You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2009/08/26 14:15:34 UTC
svn commit: r807976 - in /sling/trunk/installer/jcr/jcrinstall/src:
main/java/org/apache/sling/jcr/jcrinstall/impl/
test/java/org/apache/sling/jcr/jcrinstall/impl/
Author: bdelacretaz
Date: Wed Aug 26 12:15:34 2009
New Revision: 807976
URL: http://svn.apache.org/viewvc?rev=807976&view=rev
Log:
SLING-1078 - ResourceDetectionTest: test deletion of resources
Modified:
sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/JcrInstaller.java
sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolder.java
sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MiscUtil.java
sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockOsgiInstaller.java
sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/ResourceDetectionTest.java
Modified: sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/JcrInstaller.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/JcrInstaller.java?rev=807976&r1=807975&r2=807976&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/JcrInstaller.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/JcrInstaller.java Wed Aug 26 12:15:34 2009
@@ -57,7 +57,7 @@
* value="The Apache Software Foundation"
*/
public class JcrInstaller implements Runnable {
- private static final long serialVersionUID = 1L;
+ public static final long RUN_LOOP_DELAY_MSEC = 500L;
public static final String URL_SCHEME = "jcrinstall";
private final Logger log = LoggerFactory.getLogger(getClass());
@@ -129,6 +129,8 @@
protected void activate(ComponentContext context) throws Exception {
+ log.info("activate()");
+
session = repository.loginAdministrative(repository.getDefaultWorkspace());
// Setup converters
@@ -194,9 +196,10 @@
}
protected void deactivate(ComponentContext context) {
+ log.info("deactivate()");
+
try {
deactivationCounter++;
- listeners.clear();
folderNameFilter = null;
watchedFolders = null;
converters.clear();
@@ -207,6 +210,7 @@
session.logout();
session = null;
}
+ listeners.clear();
} catch(Exception e) {
log.warn("Exception in deactivate()", e);
}
@@ -276,13 +280,15 @@
}
/** Add new folders to watch if any have been detected
- * @return true if any WatchedFolders have been removed
+ * @return a list of InstallableResource that must be unregistered,
+ * for folders that have been removed
*/
- private boolean addAndDeleteFolders() throws RepositoryException {
+ private List<InstallableResource> addAndDeleteFolders() throws Exception {
+ final List<InstallableResource> result = new LinkedList<InstallableResource>();
for(WatchedFolderCreationListener wfc : listeners) {
final Set<String> newPaths = wfc.getAndClearPaths();
if(newPaths != null && newPaths.size() > 0) {
- log.info("Detected {} new folder(s to watch", newPaths.size());
+ log.info("Detected {} new folder(s) to watch", newPaths.size());
for(String path : newPaths) {
watchedFolders.add(
new WatchedFolder(session, path, folderNameFilter.getPriority(path), URL_SCHEME, converters));
@@ -290,12 +296,11 @@
}
}
- boolean deleted = false;
final List<WatchedFolder> toRemove = new ArrayList<WatchedFolder>();
for(WatchedFolder wf : watchedFolders) {
if(!session.itemExists(wf.getPath())) {
- deleted = true;
log.info("Deleting {}, path does not exist anymore", wf);
+ result.addAll(wf.scan().toRemove);
wf.cleanup();
toRemove.add(wf);
}
@@ -304,7 +309,7 @@
watchedFolders.remove(wf);
}
- return deleted;
+ return result;
}
/** Run periodic scans of our watched folders, and watch for folders creations/deletions */
@@ -313,8 +318,11 @@
final int savedCounter = deactivationCounter;
while(savedCounter == deactivationCounter) {
try {
- // TODO rendezvous with installer if any folder has been deleted
- addAndDeleteFolders();
+ final List<InstallableResource> toRemove = addAndDeleteFolders();
+ for(InstallableResource r : toRemove) {
+ log.info("Removing resource from OSGi installer (folder deleted): {}",r);
+ installer.removeResource(r);
+ }
// Rescan WatchedFolders if needed
if(System.currentTimeMillis() > WatchedFolder.getNextScanTime()) {
@@ -334,14 +342,14 @@
// TODO wait for events from our listeners, and/or WatchedFolder scan time
try {
- Thread.sleep(500L);
+ Thread.sleep(RUN_LOOP_DELAY_MSEC);
} catch(InterruptedException ignore) {
}
} catch(Exception e) {
log.warn("Exception in run()", e);
try {
- Thread.sleep(1000L);
+ Thread.sleep(RUN_LOOP_DELAY_MSEC);
} catch(InterruptedException ignore) {
}
}
Modified: sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolder.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolder.java?rev=807976&r1=807975&r2=807976&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolder.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolder.java Wed Aug 26 12:15:34 2009
@@ -128,30 +128,27 @@
}
}
- if(folder == null) {
- log.info("Folder {} does not exist (or not anymore), cannot scan", path);
- return null;
- }
-
// Return an InstallableResource for all child nodes for which we have a NodeConverter
final ScanResult result = new ScanResult();
- final NodeIterator it = folder.getNodes();
- while(it.hasNext()) {
- final Node n = it.nextNode();
- for(JcrInstaller.NodeConverter nc : converters) {
- final InstallableResource r = nc.convertNode(urlScheme, n);
- if(r != null) {
- final String oldDigest = digests.get(r.getUrl());
- if(r.getDigest().equals(oldDigest)) {
- // Already returned that resource, ignore
- digests.remove(r.getUrl());
- } else {
- r.setPriority(priority);
- result.toAdd.add(r);
- }
- break;
- }
- }
+ if(folder != null) {
+ final NodeIterator it = folder.getNodes();
+ while(it.hasNext()) {
+ final Node n = it.nextNode();
+ for(JcrInstaller.NodeConverter nc : converters) {
+ final InstallableResource r = nc.convertNode(urlScheme, n);
+ if(r != null) {
+ final String oldDigest = digests.get(r.getUrl());
+ if(r.getDigest().equals(oldDigest)) {
+ // Already returned that resource, ignore
+ digests.remove(r.getUrl());
+ } else {
+ r.setPriority(priority);
+ result.toAdd.add(r);
+ }
+ break;
+ }
+ }
+ }
}
// Resources left in the digests map have been deleted since last scan,
Modified: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MiscUtil.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MiscUtil.java?rev=807976&r1=807975&r2=807976&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MiscUtil.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MiscUtil.java Wed Aug 26 12:15:34 2009
@@ -41,6 +41,8 @@
/** JcrInstall test utilities */
class MiscUtil {
+ static final Mockery mockery = new Mockery();
+
public static String SEARCH_PATHS [] = { "/libs/", "/apps/" };
public static String RUN_MODES [] = { "dev", "staging" };
@@ -104,13 +106,23 @@
/** Return a JcrInstaller setup for testing */
static JcrInstaller getJcrInstaller(SlingRepository repository, OsgiInstaller osgiInstaller) throws Exception {
+ final JcrInstaller installer = new JcrInstaller();
+ setField(installer, "repository", repository);
+ setField(installer, "resourceResolverFactory", new MockJcrResourceResolverFactory());
+ setField(installer, "installer", osgiInstaller);
+ setField(installer, "runMode", new MockRunMode(RUN_MODES));
+
+ installer.activate(getMockComponentContext());
+ return installer;
+ }
+
+ static ComponentContext getMockComponentContext() {
// Setup fake ComponentContext to allow JcrInstaller to start
- final Mockery m = new Mockery();
- final ComponentContext cc = m.mock(ComponentContext.class);
- final BundleContext bc = m.mock(BundleContext.class);
+ final ComponentContext cc = mockery.mock(ComponentContext.class);
+ final BundleContext bc = mockery.mock(BundleContext.class);
final Dictionary<String, Object> emptyDict = new Hashtable<String, Object>();
- m.checking(new Expectations() {{
+ mockery.checking(new Expectations() {{
allowing(cc).getProperties();
will(returnValue(emptyDict));
allowing(cc).getBundleContext();
@@ -118,15 +130,7 @@
allowing(bc).getProperty(with(any(String.class)));
will(returnValue(null));
}});
-
- final JcrInstaller installer = new JcrInstaller();
- setField(installer, "repository", repository);
- setField(installer, "resourceResolverFactory", new MockJcrResourceResolverFactory());
- setField(installer, "installer", osgiInstaller);
- setField(installer, "runMode", new MockRunMode(RUN_MODES));
-
- installer.activate(cc);
- return installer;
+ return cc;
}
static void waitForCycles(JcrInstaller installer, int nCycles, long timeoutMsec) throws Exception {
Modified: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockOsgiInstaller.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockOsgiInstaller.java?rev=807976&r1=807975&r2=807976&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockOsgiInstaller.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockOsgiInstaller.java Wed Aug 26 12:15:34 2009
@@ -22,8 +22,10 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Set;
import org.apache.sling.osgi.installer.InstallableResource;
import org.apache.sling.osgi.installer.OsgiInstaller;
@@ -42,7 +44,11 @@
/** Keep track of our method calls, for verification */
private final List<String> recordedCalls = new LinkedList<String>();
+ /** Keep track of registered URLS */
+ private final Set<String> urls = new HashSet<String>();
+
public void addResource(InstallableResource d) throws IOException {
+ urls.add(d.getUrl());
recordCall("add", d);
}
@@ -56,11 +62,13 @@
sorted.addAll(data);
Collections.sort(sorted, new InstallableResourceComparator());
for(InstallableResource r : data) {
+ urls.add(r.getUrl());
recordCall("register", r);
}
}
public void removeResource(InstallableResource d) throws IOException {
+ urls.remove(d.getUrl());
recordCall("remove", d);
}
@@ -75,4 +83,8 @@
List<String> getRecordedCalls() {
return recordedCalls;
}
+
+ boolean isRegistered(String urlScheme, String path) {
+ return urls.contains(urlScheme + ":" + path);
+ }
}
Modified: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/ResourceDetectionTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/ResourceDetectionTest.java?rev=807976&r1=807975&r2=807976&view=diff
==============================================================================
--- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/ResourceDetectionTest.java (original)
+++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/ResourceDetectionTest.java Wed Aug 26 12:15:34 2009
@@ -18,17 +18,15 @@
*/
package org.apache.sling.jcr.jcrinstall.impl;
-import java.util.List;
-
import javax.jcr.Session;
import org.apache.sling.commons.testing.jcr.RepositoryTestBase;
import org.apache.sling.jcr.api.SlingRepository;
+import org.osgi.service.component.ComponentContext;
/** Test that added/updated/removed resources are
* correctly translated to OsgiInstaller registration
* calls.
- * TODO: test deleting resources while JcrInstaller is stopped
*/
public class ResourceDetectionTest extends RepositoryTestBase {
public static final long TIMEOUT = 5000L;
@@ -62,24 +60,33 @@
}
private void assertRegisteredPaths(String [] paths) {
- final List<String> recorded = osgiInstaller.getRecordedCalls();
for(String path : paths) {
- boolean found = false;
- for(String rec : recorded) {
- if(rec.contains(path)) {
- found = true;
- break;
- }
- }
-
- boolean expectFound = !path.contains("NOT");
- assertEquals(
- (expectFound ? "Expected " : "Did not expect ")
- + path + " to be registered (" + recorded + ")",
- expectFound, found);
+ assertRegistered(path, !path.contains("NOT"));
}
}
+ private void assertRegistered(String path, boolean registered) {
+ if(registered) {
+ assertTrue("Expected " + path + " to be registered",
+ osgiInstaller.isRegistered(JcrInstaller.URL_SCHEME, path));
+ } else {
+ assertFalse("Expected " + path + " to be unregistered",
+ osgiInstaller.isRegistered(JcrInstaller.URL_SCHEME, path));
+ }
+ }
+
+ private void assertRecordedCall(String action, String path) {
+ final String callStr = action + ":" + JcrInstaller.URL_SCHEME + ":" + path;
+ boolean found = false;
+ for(String call : osgiInstaller.getRecordedCalls()) {
+ if(call.startsWith(callStr)) {
+ found = true;
+ break;
+ }
+ }
+ assertTrue("Expecting '" + callStr + "' in recorded calls (" + osgiInstaller.getRecordedCalls() + ")", found);
+ }
+
public void testInitialResourceDetection() throws Exception {
assertRegisteredPaths(contentHelper.FAKE_RESOURCES);
assertRegisteredPaths(contentHelper.FAKE_CONFIGS);
@@ -122,4 +129,97 @@
assertRegisteredPaths(paths);
}
+ public void testDeleteResources() throws Exception {
+ assertRegisteredPaths(contentHelper.FAKE_RESOURCES);
+ assertRegisteredPaths(contentHelper.FAKE_CONFIGS);
+
+ osgiInstaller.clearRecordedCalls();
+ assertTrue("Expecting recorded calls to be empty", osgiInstaller.getRecordedCalls().isEmpty());
+
+ final int toRemove = 1;
+ contentHelper.delete(contentHelper.FAKE_RESOURCES[toRemove]);
+ contentHelper.delete(contentHelper.FAKE_CONFIGS[toRemove]);
+ eventHelper.waitForEvents(TIMEOUT);
+ MiscUtil.waitForCycles(installer, 2, TIMEOUT);
+
+ for(int i=0; i < contentHelper.FAKE_RESOURCES.length; i++) {
+ assertRegistered(contentHelper.FAKE_RESOURCES[i], i != toRemove);
+ }
+ for(int i=0; i < contentHelper.FAKE_CONFIGS.length; i++) {
+ assertRegistered(contentHelper.FAKE_CONFIGS[i], i != toRemove);
+ }
+
+ final int nCalls = contentHelper.FAKE_RESOURCES.length + contentHelper.FAKE_CONFIGS.length;
+ assertEquals("Expecting both remove and add calls when resources are deleted",
+ nCalls, osgiInstaller.getRecordedCalls().size());
+ }
+
+ public void testStopAndRestart() throws Exception {
+ assertRegisteredPaths(contentHelper.FAKE_RESOURCES);
+ assertRegisteredPaths(contentHelper.FAKE_CONFIGS);
+ final ComponentContext cc = MiscUtil.getMockComponentContext();
+
+ // With the installer deactivated, remove two resources and add some new ones
+ osgiInstaller.clearRecordedCalls();
+ installer.deactivate(cc);
+ assertEquals("Expected no calls to OsgiInstaller when deactivating JcrInstaller",
+ 0, osgiInstaller.getRecordedCalls().size());
+ final int toRemove = 2;
+ contentHelper.delete(contentHelper.FAKE_RESOURCES[toRemove]);
+ contentHelper.delete(contentHelper.FAKE_CONFIGS[toRemove]);
+ final String [] toAdd = {
+ "/libs/foo/bar/install/" + System.currentTimeMillis() + ".jar",
+ "/libs/foo/wii/install/" + + System.currentTimeMillis() + ".properties",
+ "/libs/foo/wii/install/" + + System.currentTimeMillis() + ".cfg",
+ };
+ for(String path : toAdd) {
+ contentHelper.createOrUpdateFile(path);
+ }
+
+ // Verify that no calls have been made to OSGi installer
+ eventHelper.waitForEvents(TIMEOUT);
+ Thread.sleep(JcrInstaller.RUN_LOOP_DELAY_MSEC * 3);
+ assertEquals("Expected no calls to OsgiInstaller while JcrInstaller is stopped",
+ 0, osgiInstaller.getRecordedCalls().size());
+
+ // Restart JcrInstaller and verify that all remaining resources are re-registered
+ installer.activate(cc);
+ MiscUtil.waitForCycles(installer, 2, TIMEOUT);
+
+ for(int i=0; i < contentHelper.FAKE_RESOURCES.length; i++) {
+ final String path = contentHelper.FAKE_RESOURCES[i];
+ if(i == toRemove) {
+ assertFalse("Path should be absent from recorded calls", osgiInstaller.getRecordedCalls().contains(path));
+ } else {
+ assertRecordedCall("register",path);
+ }
+ }
+ for(int i=0; i < contentHelper.FAKE_CONFIGS.length; i++) {
+ final String path = contentHelper.FAKE_CONFIGS[i];
+ if(i == toRemove) {
+ assertFalse("Path should be absent from recorded calls", osgiInstaller.getRecordedCalls().contains(path));
+ } else {
+ assertRecordedCall("register",path);
+ }
+ }
+ for(String path : toAdd) {
+ assertRecordedCall("register",path);
+ }
+ }
+
+ public void testFolderRemoval() throws Exception {
+ assertRegisteredPaths(contentHelper.FAKE_RESOURCES);
+ assertRegisteredPaths(contentHelper.FAKE_CONFIGS);
+
+ // Removing a folder, all resources that it contains must be unregistered
+ contentHelper.delete("/libs");
+ eventHelper.waitForEvents(TIMEOUT);
+ MiscUtil.waitForCycles(installer, 2, TIMEOUT);
+ for(String path : contentHelper.FAKE_RESOURCES) {
+ assertRegistered(path, !path.startsWith("/libs"));
+ }
+ for(String path : contentHelper.FAKE_CONFIGS) {
+ assertRegistered(path, !path.startsWith("/libs"));
+ }
+ }
}
\ No newline at end of file