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


Reply via email to