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