blob: 71f4b31a47a11f0dce38c877f520b07bd1682664 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2010 VMware Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware Inc. - initial contribution
*******************************************************************************/
package org.eclipse.virgo.repository.internal.watched;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanInfo;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.osgi.framework.Version;
import org.eclipse.virgo.medic.test.eventlog.MockEventLogger;
import org.eclipse.virgo.repository.ArtifactBridge;
import org.eclipse.virgo.repository.ArtifactDescriptor;
import org.eclipse.virgo.repository.ArtifactGenerationException;
import org.eclipse.virgo.repository.IndexFormatException;
import org.eclipse.virgo.repository.RepositoryAwareArtifactDescriptor;
import org.eclipse.virgo.repository.RepositoryCreationException;
import org.eclipse.virgo.repository.builder.ArtifactDescriptorBuilder;
import org.eclipse.virgo.repository.builder.AttributeBuilder;
import org.eclipse.virgo.repository.configuration.WatchedStorageRepositoryConfiguration;
import org.eclipse.virgo.repository.internal.LocalRepository;
import org.eclipse.virgo.repository.internal.watched.WatchedStorageRepository;
import org.eclipse.virgo.util.io.FileCopyUtils;
import org.eclipse.virgo.util.osgi.manifest.VersionRange;
/**
* Test the {@link WatchedStorageRepository} extension of the {@link LocalRepository} class.
* <p />
*
* <strong>Concurrent Semantics</strong><br />
* Thread-safe
*
*/
public class WatchedStorageRepositoryTests {
private static final String LOCATIONS_TEST_FILENAME = "a.jar";
private static final String MBEAN_DOMAIN_VIRGO_WEB_SERVER = "org.eclipse.virgo.server";
private static MockEventLogger mockEventLogger = new MockEventLogger();
private static final String ARTIFACT_FILE_NAME = "org.eclipse.virgo.sample.configuration.properties.core.jar";
private static final String WATCHED_REPO_NAME = "Test-Watched-Repo";
private static final int WATCH_INTERVAL = 5; // seconds
private static final int MIN_WATCH_INTERVAL = 1; // seconds
private static final int LONG_WATCH_INTERVAL = 50; // seconds
private static final int BAD_WATCH_INTERVAL = 0; // seconds
private static final File testArtefactFile1 = new File("src/test/resources/artifacts/" + ARTIFACT_FILE_NAME);
private WatchedStorageRepositoryConfiguration wsrConfiguration;
private WatchedStorageRepository wsRepository;
private final File watchDir = new File("build/watchedDir");
private Set<ArtifactBridge> artefactBridgeDefinitions;
@Before
public void setUp() {
mockEventLogger.reinitialise();
this.watchDir.mkdirs();
this.artefactBridgeDefinitions = new HashSet<ArtifactBridge>(4);
this.artefactBridgeDefinitions.add(new StaticBridge());
assertTrue("Need jar artifact for tests.", testArtefactFile1.exists());
}
@Test
public void testConstructor() throws RepositoryCreationException, IndexFormatException {
this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("build/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
WATCH_INTERVAL, null);
this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, new MockEventLogger());
assertFalse("Didn't create a repository!", null == this.wsRepository);
}
@Test
public void testConstructLongWaiter() throws RepositoryCreationException, IndexFormatException {
this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("build/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
LONG_WATCH_INTERVAL, null);
this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
assertFalse("Didn't create a repository!", null == this.wsRepository);
}
@Test(expected = IllegalArgumentException.class)
public void testConstructorBadWaiter() throws RepositoryCreationException, IndexFormatException {
this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("build/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
BAD_WATCH_INTERVAL, null);
this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
assertTrue("Created a repository after exception!", null == this.wsRepository);
}
@Test
public void testGetArtifactLocations() throws Exception {
this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("build/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
WATCH_INTERVAL, null);
this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
assertFalse("Didn't create a repository!", null == this.wsRepository);
Set<String> locations = this.wsRepository.getArtifactLocations(LOCATIONS_TEST_FILENAME);
Set<String> expectedLocations = new HashSet<String>(1);
expectedLocations.add(new File(this.watchDir,LOCATIONS_TEST_FILENAME).getCanonicalPath());
assertNotNull("null locations set returned.", locations);
assertEquals("set of locations not expected", expectedLocations, locations);
}
@Test
public void testGetOnEmptyRepository() throws RepositoryCreationException, IOException {
this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("build/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
WATCH_INTERVAL, null);
this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
assertFalse("Didn't create a repository!", null == this.wsRepository);
this.wsRepository.start(); // must start it to see things
VersionRange maxRange = new VersionRange("0");
ArtifactDescriptor aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
assertTrue("A descriptor returned, when it shouldn't!", null == aD);
this.wsRepository.stop(); // tidy up after one!
}
@Test
public void testGetInitialArtefact() throws RepositoryCreationException, IOException {
this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("build/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
MIN_WATCH_INTERVAL, null);
putArtifactFile(testArtefactFile1);
this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
assertFalse("Didn't create a repository!", null == this.wsRepository);
this.wsRepository.start(); // must start it to see things
testDelay(MIN_WATCH_INTERVAL);
VersionRange maxRange = new VersionRange("0");
ArtifactDescriptor aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
assertTrue("Wrong or null descriptor returned!", (null == aD ? false : aD.getName().equals(testArtefactFile1.getName())));
this.wsRepository.stop(); // tidy up after one!
}
@Test
public void testGetInitialArtefactWithCheck() throws Exception {
this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("build/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
MIN_WATCH_INTERVAL, null);
putArtifactFile(testArtefactFile1);
this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
assertFalse("Didn't create a repository!", null == this.wsRepository);
this.wsRepository.start(); // must start it to see things
this.wsRepository.forceCheck();
VersionRange maxRange = new VersionRange("0");
ArtifactDescriptor aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
assertTrue("Wrong or null descriptor returned!", (null == aD ? false : aD.getName().equals(testArtefactFile1.getName())));
this.wsRepository.stop(); // tidy up after one!
}
/**
* Short delay (of seconds) in test
*/
private void testDelay(long secs) {
try {
Thread.sleep(secs * 1000);
} catch (InterruptedException e) {
// continue
}
}
@Test
public void testGetAddAndDeleteArtefact() throws RepositoryCreationException, IOException {
this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("build/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
MIN_WATCH_INTERVAL, null);
this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, new MockEventLogger());
assertFalse("Didn't create a repository!", null == this.wsRepository);
this.wsRepository.start(); // must start it to see things
putArtifactFile(testArtefactFile1);
testDelay(3 * MIN_WATCH_INTERVAL);
VersionRange maxRange = new VersionRange("0");
RepositoryAwareArtifactDescriptor aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
assertNotNull("Null descriptor returned.", aD);
assertEquals(testArtefactFile1.getName(), aD.getName());
assertEquals("static", aD.getType());
assertEquals(new Version(0, 1, 0), aD.getVersion());
removeArtifactFile(testArtefactFile1);
testDelay(2 * MIN_WATCH_INTERVAL);
aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
assertTrue("A descriptor returned, when it shouldn't!", null == aD);
this.wsRepository.stop(); // tidy up after one!
}
@Test
public void testGetAddAndDeleteArtefactWithCheck() throws RepositoryCreationException, IOException, ArtifactGenerationException, Exception {
this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("build/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
MIN_WATCH_INTERVAL, null);
this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, new MockEventLogger());
assertFalse("Didn't create a repository!", null == this.wsRepository);
this.wsRepository.start(); // watcher needs to be created
putArtifactFile(testArtefactFile1);
this.wsRepository.forceCheck();
VersionRange maxRange = new VersionRange("0");
RepositoryAwareArtifactDescriptor aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
assertNotNull("Null descriptor returned.", aD);
assertEquals(testArtefactFile1.getName(), aD.getName());
assertEquals("static", aD.getType());
assertEquals(new Version(0, 1, 0), aD.getVersion());
removeArtifactFile(testArtefactFile1);
this.wsRepository.forceCheck();
aD = this.wsRepository.get("static", testArtefactFile1.getName(), maxRange);
assertTrue("A descriptor returned, when it shouldn't!", null == aD);
this.wsRepository.stop(); // tidy up after one!
}
@Test
public void mBeanPublication() throws Exception {
this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("build/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
WATCH_INTERVAL, MBEAN_DOMAIN_VIRGO_WEB_SERVER);
this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
ObjectName objectName = new ObjectName(MBEAN_DOMAIN_VIRGO_WEB_SERVER + ":type=Repository,name=" + WATCHED_REPO_NAME);
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
try {
platformMBeanServer.getMBeanInfo(objectName);
fail("MBean should not be present until repository has been started");
} catch (InstanceNotFoundException infe) {
}
this.wsRepository.start();
MBeanInfo mBeanInfo = platformMBeanServer.getMBeanInfo(objectName);
Object type = mBeanInfo.getDescriptor().getFieldValue("type");
assertNotNull(type);
assertEquals("watched", type);
this.wsRepository.stop();
try {
platformMBeanServer.getMBeanInfo(objectName);
fail("MBean should not be present once repository has been stopped");
} catch (InstanceNotFoundException infe) {
}
}
@Test
public void mBeanNonPublication() throws Exception {
this.wsrConfiguration = new WatchedStorageRepositoryConfiguration(WATCHED_REPO_NAME, new File("build/watchedIndex"), this.artefactBridgeDefinitions, this.watchDir.getAbsolutePath(),
WATCH_INTERVAL, null);
this.wsRepository = new WatchedStorageRepository(this.wsrConfiguration, mockEventLogger);
ObjectName objectName = new ObjectName(MBEAN_DOMAIN_VIRGO_WEB_SERVER + ":type=Repository,name=" + WATCHED_REPO_NAME);
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
try {
platformMBeanServer.getMBeanInfo(objectName);
fail("MBean should not be present before start");
} catch (InstanceNotFoundException infe) {
}
this.wsRepository.start();
try {
platformMBeanServer.getMBeanInfo(objectName);
fail("MBean should not be present after start");
} catch (InstanceNotFoundException infe) {
}
this.wsRepository.stop();
try {
platformMBeanServer.getMBeanInfo(objectName);
fail("MBean should not be present once repository has been stopped");
} catch (InstanceNotFoundException infe) {
}
}
/**
* Put artefact file copy into watched directory
*
* @throws IOException
*/
private File putArtifactFile(File artifactFile) throws IOException {
File toFile = new File(this.watchDir, artifactFile.getName());
FileCopyUtils.copy(artifactFile, toFile);
assertTrue("Failed to copy file into watched directory", toFile.exists());
return toFile;
}
/**
* Remove artefact file copy from watched directory
*
* @throws IOException
*/
private void removeArtifactFile(File artifactFile) throws IOException {
File fileToRemove = new File(this.watchDir, artifactFile.getName());
fileToRemove.delete();
assertFalse("Failed to delete file from watched directory", fileToRemove.exists());
}
@After
public void stop() {
if (null != this.wsRepository) {
this.wsRepository.stop();
}
if (this.watchDir.isDirectory()) {
if (this.watchDir.exists()) {
for (File file : this.watchDir.listFiles()) {
file.delete();
}
this.watchDir.delete();
}
}
}
/**
* <p>
* Implementation of <code>ArtefactBridge</code> that understands how to create a minimal Artefact from any given
* file. The Artefact name will be that of the file including any extension and the version will always be '0'. The
* number of bytes in the file, as reported by the operating system will be added as the sole Attribute with a name
* of size.
* </p>
*
* <strong>Concurrent Semantics</strong><br />
*
* This class is Threadsafe
*
*/
private class StaticBridge implements ArtifactBridge {
public static final String STATIC_ARTIFACT_TYPE = "static";
public static final String ARTEFACT_ATTRIBUTE_SIZE = "size";
/**
* {@inheritDoc}
*/
public ArtifactDescriptor generateArtifactDescriptor(File artifact) throws ArtifactGenerationException {
if (!artifact.exists()) {
throw new ArtifactGenerationException("Artifact must exist at the specified location: " + artifact.getAbsolutePath(),
STATIC_ARTIFACT_TYPE);
}
ArtifactDescriptorBuilder builder = new ArtifactDescriptorBuilder();
builder.setUri(artifact.toURI());
builder.setType(STATIC_ARTIFACT_TYPE);
builder.setName(artifact.getName());
builder.setVersion("0.1.0");
//Exercise the Attribute builder class a bit
AttributeBuilder attrBuilder = new AttributeBuilder().setName(ARTEFACT_ATTRIBUTE_SIZE);
attrBuilder.setValue(String.valueOf(artifact.length()));
attrBuilder.putProperties("key1","value1");
ArrayList<String> valueList = new ArrayList<String>(1);
valueList.add("value2");
attrBuilder.putProperties("key2",valueList);
builder.addAttribute(attrBuilder.build());
return builder.build();
}
}
}