Author: bdelacretaz Date: Tue Aug 25 14:06:37 2009 New Revision: 807639 URL: http://svn.apache.org/viewvc?rev=807639&view=rev Log: SLING-1078 - FindPathsToWatchTest and support classes added
Added: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/ContentHelper.java - copied, changed from r807539, sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ContentHelper.java sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/EventHelper.java - copied, changed from r807539, sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/EventHelper.java sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FindPathsToWatchTest.java - copied, changed from r807539, sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FindWatchedFoldersTest.java sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MiscUtil.java (with props) sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockInstallableResource.java - copied, changed from r807539, sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/MockInstallableData.java sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockOsgiInstaller.java (with props) Removed: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ContentHelper.java sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/EventHelper.java sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FindWatchedFoldersTest.java sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/MockInstallableData.java 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/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolderCreationListener.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=807639&r1=807638&r2=807639&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 Tue Aug 25 14:06:37 2009 @@ -18,20 +18,20 @@ */ package org.apache.sling.jcr.jcrinstall.impl; -import org.apache.sling.api.resource.ResourceResolver; -import org.apache.sling.jcr.resource.JcrResourceResolverFactory; -import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; +import java.util.Set; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.RepositoryException; import javax.jcr.Session; +import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.jcr.api.SlingRepository; +import org.apache.sling.jcr.resource.JcrResourceResolverFactory; import org.apache.sling.osgi.installer.InstallableResource; import org.apache.sling.osgi.installer.OsgiInstaller; import org.apache.sling.runmode.RunMode; @@ -56,7 +56,7 @@ * name="service.vendor" * value="The Apache Software Foundation" */ -public class JcrInstaller implements Serializable { +public class JcrInstaller implements Runnable { private static final long serialVersionUID = 1L; public static final String URL_SCHEME = "jcrinstall"; @@ -110,6 +110,12 @@ /** Session shared by all WatchedFolder */ private Session session; + /** Count cycles of our run() method, used in testing */ + private int cyclesCount; + + /** Used to stop background thread when deactivated */ + private int deactivationCounter = 1; + /** Convert Nodes to InstallableResources */ static interface NodeConverter { InstallableResource convertNode(String urlScheme, Node n) throws Exception; @@ -118,6 +124,9 @@ /** Our NodeConverters*/ private final Collection <NodeConverter> converters = new ArrayList<NodeConverter>(); + /** Detect newly created folders that we must watch */ + private final List<WatchedFolderCreationListener> listeners = new LinkedList<WatchedFolderCreationListener>(); + protected void activate(ComponentContext context) throws Exception { session = repository.loginAdministrative(repository.getDefaultWorkspace()); @@ -156,8 +165,13 @@ log.info("Using default folder name regexp '{}', not provided by {}", folderNameRegexp, FOLDER_NAME_REGEXP_PROPERTY); } + // Setup folder filtering and watching + folderNameFilter = new FolderNameFilter(roots, folderNameRegexp, runMode); + for (String path : roots) { + listeners.add(new WatchedFolderCreationListener(session, folderNameFilter, path)); + } + // Find paths to watch and create WatchedFolders to manage them - folderNameFilter = new FolderNameFilter(roots, folderNameRegexp, runMode); watchedFolders = new LinkedList<WatchedFolder>(); for(String root : roots) { findPathsToWatch(root, watchedFolders); @@ -173,16 +187,29 @@ log.info("Registering {} resources with OSGi installer", resources.size()); installer.registerResources(resources, URL_SCHEME); + + final Thread t = new Thread(this, getClass().getSimpleName() + "." + deactivationCounter); + t.setDaemon(true); + t.start(); } protected void deactivate(ComponentContext context) { - folderNameFilter = null; - watchedFolders = null; - converters.clear(); - if(session != null) { - session.logout(); - session = null; - } + try { + deactivationCounter++; + listeners.clear(); + folderNameFilter = null; + watchedFolders = null; + converters.clear(); + if(session != null) { + for(WatchedFolderCreationListener wfc : listeners) { + wfc.cleanup(session); + } + session.logout(); + session = null; + } + } catch(Exception e) { + log.warn("Exception in deactivate()", e); + } } /** Get a property value from the component context or bundle context */ @@ -206,7 +233,7 @@ } else { log.debug("Bundles root node {} found, looking for bundle folders inside it", rootPath); final Node n = s.getRootNode().getNode(relPath(rootPath)); - findAndAddPaths(n, result); + findPathsUnderNode(n, result); } } finally { if (s != null) { @@ -219,7 +246,7 @@ * Add n to result if it is a folder that we must watch, and recurse into its children * to do the same. */ - void findAndAddPaths(Node n, List<WatchedFolder> result) throws RepositoryException + void findPathsUnderNode(Node n, List<WatchedFolder> result) throws RepositoryException { final String path = n.getPath(); final int priority = folderNameFilter.getPriority(path); @@ -233,7 +260,7 @@ } else { final NodeIterator it = n.getNodes(); while (it.hasNext()) { - findAndAddPaths(it.nextNode(), result); + findPathsUnderNode(it.nextNode(), result); } } } @@ -247,5 +274,64 @@ } return path; } + + /** Add new folders to watch if any have been detected + * @return true if any WatchedFolders have been removed + */ + private boolean addAndDeleteFolders() throws RepositoryException { + 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()); + for(String path : newPaths) { + watchedFolders.add( + new WatchedFolder(session, path, folderNameFilter.getPriority(path), URL_SCHEME, converters)); + } + } + } + + 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); + wf.cleanup(); + toRemove.add(wf); + } + } + for(WatchedFolder wf : toRemove) { + watchedFolders.remove(wf); + } + + return deleted; + } + + /** Run periodic scans of our watched folders, and watch for folders creations/deletions */ + public void run() { + log.info("Background thread {} starting", Thread.currentThread().getName()); + final int savedCounter = deactivationCounter; + while(savedCounter == deactivationCounter) { + try { + // TODO rendezvous with installer if any folder has been deleted + addAndDeleteFolders(); + cyclesCount++; + + // TODO wait for events from our listeners, and/or WatchedFolder scan time + try { + Thread.sleep(500L); + } catch(InterruptedException ignore) { + } + + } catch(Exception e) { + log.warn("Exception in run()", e); + try { + Thread.sleep(1000L); + } catch(InterruptedException ignore) { + } + } + } + log.info("Background thread {} stopping", Thread.currentThread().getName()); + } } \ No newline at end of file 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=807639&r1=807638&r2=807639&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 Tue Aug 25 14:06:37 2009 @@ -70,7 +70,7 @@ session.getWorkspace().getObservationManager().addEventListener(this, eventTypes, path, isDeep, null, null, noLocal); - log.info("Watching folder " + path); + log.info("Watching folder {} (priority {})", path, priority); } void cleanup() { Modified: sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolderCreationListener.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolderCreationListener.java?rev=807639&r1=807638&r2=807639&view=diff ============================================================================== --- sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolderCreationListener.java (original) +++ sling/trunk/installer/jcr/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/impl/WatchedFolderCreationListener.java Tue Aug 25 14:06:37 2009 @@ -21,6 +21,9 @@ import java.util.HashSet; import java.util.Set; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.observation.Event; import javax.jcr.observation.EventIterator; import javax.jcr.observation.EventListener; @@ -29,11 +32,25 @@ /** Listen for JCR events to find out when new WatchedFolders * must be created. - * TODO reactivate */ class WatchedFolderCreationListener implements EventListener { protected final Logger log = LoggerFactory.getLogger(this.getClass()); private Set<String> paths = new HashSet<String>(); + private final FolderNameFilter folderNameFilter; + + WatchedFolderCreationListener(Session session, FolderNameFilter fnf, String path) throws RepositoryException { + folderNameFilter = fnf; + + int eventTypes = Event.NODE_ADDED; + boolean isDeep = true; + boolean noLocal = true; + session.getWorkspace().getObservationManager().addEventListener(this, eventTypes, path, + isDeep, null, null, noLocal); + } + + void cleanup(Session session) throws RepositoryException { + session.getWorkspace().getObservationManager().removeEventListener(this); + } /** Return our saved paths and clear the list * @return null if no paths have been saved @@ -52,11 +69,10 @@ /** Store the paths of new WatchedFolders to create */ public void onEvent(EventIterator it) { - /* try { while(it.hasNext()) { final Event e = it.nextEvent(); - if(folderNameFilter.accept(e.getPath())) { + if(folderNameFilter.getPriority(e.getPath()) > 0) { synchronized(paths) { paths.add(e.getPath()); } @@ -65,7 +81,5 @@ } catch(RepositoryException re) { log.warn("RepositoryException in onEvent", re); } - */ } - } Copied: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/ContentHelper.java (from r807539, sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ContentHelper.java) URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/ContentHelper.java?p2=sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/ContentHelper.java&p1=sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ContentHelper.java&r1=807539&r2=807639&rev=807639&view=diff ============================================================================== --- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/ContentHelper.java (original) +++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/ContentHelper.java Tue Aug 25 14:06:37 2009 @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sling.jcr.jcrinstall.jcr.impl; +package org.apache.sling.jcr.jcrinstall.impl; import java.io.InputStream; import java.util.Calendar; @@ -25,7 +25,7 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; -/** TODO adapt or remove */ +/** Utility class used to create test content */ class ContentHelper { public static final String NT_FOLDER = "nt:folder"; public static final String NT_FILE = "nt:file"; @@ -37,14 +37,14 @@ public static final String JCR_DATA = "jcr:data"; final String [] WATCHED_FOLDERS = { - "libs/foo/bar/install", - "libs/foo/wii/install", - "apps/install" + "/libs/foo/bar/install", + "/libs/foo/wii/install", + "/apps/install" }; final String [] IGNORED_FOLDERS = { - "libs/foo/bar/installed", - "apps/noninstall" + "/libs/foo/bar/installed", + "/apps/noninstall" }; private final Session session; @@ -73,7 +73,7 @@ } void createFolder(String path) throws Exception { - final String [] parts = path.split("/"); + final String [] parts = relPath(path).split("/"); Node n = session.getRootNode(); for(String part : parts) { if(n.hasNode(part)) { @@ -85,14 +85,17 @@ session.save(); } - void createOrUpdateFile(String path, MockInstallableData d) throws RepositoryException { - /* - createOrUpdateFile(path, d.adaptTo(InputStream.class), d.getLastModified()); - */ + void delete(String path) throws RepositoryException { + session.getItem(path).remove(); + session.save(); + } + + void createOrUpdateFile(String path, MockInstallableResource d) throws RepositoryException { + createOrUpdateFile(path, d.getInputStream(), System.currentTimeMillis()); } void createOrUpdateFile(String path, InputStream data, long lastModified) throws RepositoryException { - final String relPath = path.substring(1); + final String relPath = relPath(path); Node f = null; Node res = null; if(session.getRootNode().hasNode(relPath)) { @@ -111,4 +114,11 @@ f.getParent().save(); } + + String relPath(String path) { + if(path.startsWith("/")) { + return path.substring(1); + } + return path; + } } \ No newline at end of file Copied: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/EventHelper.java (from r807539, sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/EventHelper.java) URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/EventHelper.java?p2=sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/EventHelper.java&p1=sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/EventHelper.java&r1=807539&r2=807639&rev=807639&view=diff ============================================================================== --- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/EventHelper.java (original) +++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/EventHelper.java Tue Aug 25 14:06:37 2009 @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sling.jcr.jcrinstall.jcr.impl; +package org.apache.sling.jcr.jcrinstall.impl; import javax.jcr.Node; import javax.jcr.RepositoryException; @@ -28,7 +28,6 @@ /** Used by tests to wait until JCR notification events * have been delivered. */ -/** TODO remove if not needed for new tests */ class EventHelper implements EventListener { private final Session session; private int eventCount; Copied: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FindPathsToWatchTest.java (from r807539, sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FindWatchedFoldersTest.java) URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FindPathsToWatchTest.java?p2=sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FindPathsToWatchTest.java&p1=sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FindWatchedFoldersTest.java&r1=807539&r2=807639&rev=807639&view=diff ============================================================================== --- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/FindWatchedFoldersTest.java (original) +++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/FindPathsToWatchTest.java Tue Aug 25 14:06:37 2009 @@ -16,24 +16,39 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sling.jcr.jcrinstall.jcr.impl; +package org.apache.sling.jcr.jcrinstall.impl; + +import java.util.Collection; + +import javax.jcr.Session; import org.apache.sling.commons.testing.jcr.RepositoryTestBase; +import org.apache.sling.jcr.api.SlingRepository; -/** Test the "find watched folders" feature of the RepositoryObserver - * TODO adapt or remove - * */ -public class FindWatchedFoldersTest extends RepositoryTestBase { +/** Verify that the JcrInstaller finds all folders that must + * be watched, including those created after it starts + */ +public class FindPathsToWatchTest extends RepositoryTestBase { - public void testNothing() {} - - /* SlingRepository repo; Session session; private EventHelper eventHelper; private ContentHelper contentHelper; - private Mockery mockery; - private OsgiController osgiController; + private JcrInstaller installer; + private MockOsgiInstaller osgiInstaller; + + @Override + protected void setUp() throws Exception { + super.setUp(); + repo = getRepository(); + session = repo.loginAdministrative(repo.getDefaultWorkspace()); + eventHelper = new EventHelper(session); + contentHelper = new ContentHelper(session); + contentHelper.cleanupContent(); + contentHelper.setupContent(); + osgiInstaller = new MockOsgiInstaller(); + installer = MiscUtil.getJcrInstaller(repo, osgiInstaller); + } @Override protected void tearDown() throws Exception { @@ -44,56 +59,71 @@ contentHelper = null; } - @Override - protected void setUp() throws Exception { - super.setUp(); - repo = getRepository(); - session = repo.loginAdministrative(repo.getDefaultWorkspace()); - eventHelper = new EventHelper(session); - contentHelper = new ContentHelper(session); - contentHelper.cleanupContent(); - mockery = new Mockery(); - osgiController = mockery.mock(OsgiController.class); - final Set<String> installedUri = new HashSet<String>(); - mockery.checking(new Expectations() {{ - allowing(osgiController).setResourceOverrideRules(with(any(ResourceOverrideRules.class))); - allowing(osgiController).getInstalledUris(); will(returnValue(installedUri)); - allowing(osgiController).executeScheduledOperations(); - }}); + private boolean isWatched(String path, Collection<WatchedFolder> wfList) { + for(WatchedFolder wf : wfList ) { + if(wf.getPath().equals(path)) { + return true; + } + } + return false; } public void testInitialFind() throws Exception { - - contentHelper.setupContent(); - final MockRepositoryObserver ro = new MockRepositoryObserver(repo, osgiController); - ro.activate(null); - - final Set<WatchedFolder> wfSet = ro.getWatchedFolders(); - assertEquals("activate() must find all watched folders", contentHelper.WATCHED_FOLDERS.length, wfSet.size()); + final Collection<WatchedFolder> wf = MiscUtil.getWatchedFolders(installer); + assertEquals("activate() must find all watched folders", contentHelper.WATCHED_FOLDERS.length, wf.size()); for(String folder : contentHelper.WATCHED_FOLDERS) { - assertTrue("Folder " + folder + " must be watched (watched=" + wfSet + ")", - ro.folderIsWatched(folder)); + assertTrue("Folder " + folder + " must be watched (watched=" + wf + ")", + isWatched(folder, wf)); } } public void testNewWatchedFolderDetection() throws Exception { - contentHelper.setupContent(); - final MockRepositoryObserver ro = new MockRepositoryObserver(repo, osgiController); - ro.activate(null); - - final String newPaths [] = { "libs/tnwf/install", "apps/tnwf/install" }; + final String newPaths [] = { + "/libs/tnwf/install", + "/libs/tnwf/install.dev", + "/apps/tnwf/install", + "/apps/tnwf/install.staging", + "/apps/tnwf/install.staging.dev", + "/NOT/foo/nothing" + }; for(String newPath : newPaths) { - assertFalse(newPath + " must not be watched before test", ro.folderIsWatched(newPath)); + assertFalse(newPath + " must not be watched before test", isWatched(newPath, + MiscUtil.getWatchedFolders(installer))); // Create folder, wait for observation event and check that // it is detected contentHelper.createFolder(newPath); eventHelper.waitForEvents(5000L); - assertFalse(newPath + " must not be watched before calling addNewWatchedFolders()", ro.folderIsWatched(newPath)); - ro.addNewWatchedFolders(); - assertTrue(newPath + " must be watched before calling addNewWatchedFolders()", ro.folderIsWatched(newPath)); + MiscUtil.waitForCycles(installer, 2, 5000L); + + if(newPath.contains("NOT")) { + assertFalse(newPath + " must not be watched after test", isWatched(newPath, + MiscUtil.getWatchedFolders(installer))); + } else { + assertTrue(newPath + " must be watched after calling addNewWatchedFolders()", isWatched(newPath, + MiscUtil.getWatchedFolders(installer))); + } } + + // Delete a single folder and verify that it's gone + final String folder = newPaths[1]; + final int nBefore = MiscUtil.getWatchedFolders(installer).size(); + contentHelper.delete(folder); + eventHelper.waitForEvents(5000L); + MiscUtil.waitForCycles(installer, 2, 5000L); + assertFalse(folder + " must not be watched anymore after deleting", isWatched(folder, + MiscUtil.getWatchedFolders(installer))); + assertEquals("Expecting only one WatchedFolder to be deleted", nBefore - 1, + MiscUtil.getWatchedFolders(installer).size()); + } + + public void testDeleteWatchedFolders() throws Exception { + final Collection<WatchedFolder> wf = MiscUtil.getWatchedFolders(installer); + assertEquals("activate() must find all watched folders", contentHelper.WATCHED_FOLDERS.length, wf.size()); + contentHelper.cleanupContent(); + eventHelper.waitForEvents(5000L); + MiscUtil.waitForCycles(installer, 2, 5000L); + assertEquals("After deleting content, no more folders must be watched", 0, wf.size()); } - */ } \ No newline at end of file Added: 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=807639&view=auto ============================================================================== --- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MiscUtil.java (added) +++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MiscUtil.java Tue Aug 25 14:06:37 2009 @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sling.jcr.jcrinstall.impl; + +import java.lang.reflect.Field; +import java.util.Collection; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; + +import javax.jcr.Session; +import javax.servlet.http.HttpServletRequest; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.jcr.api.SlingRepository; +import org.apache.sling.jcr.resource.JcrResourceResolverFactory; +import org.apache.sling.osgi.installer.OsgiInstaller; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; + +/** JcrInstall test utilities */ +class MiscUtil { + + public static String SEARCH_PATHS [] = { "/libs/", "/apps/" }; + public static String RUN_MODES [] = { "dev", "staging" }; + + static class MockResourceResolver implements ResourceResolver { + + public Iterator<Resource> findResources(String arg0, String arg1) { + return null; + } + + public Resource getResource(Resource arg0, String arg1) { + return null; + } + + public Resource getResource(String arg0) { + return null; + } + + public String[] getSearchPath() { + return SEARCH_PATHS; + } + + public Iterator<Resource> listChildren(Resource arg0) { + return null; + } + + public String map(String arg0) { + return null; + } + + public Iterator<Map<String, Object>> queryResources(String arg0, + String arg1) { + return null; + } + + public Resource resolve(HttpServletRequest arg0) { + return null; + } + + public Resource resolve(String arg0) { + return null; + } + + public <AdapterType> AdapterType adaptTo(Class<AdapterType> arg0) { + return null; + } + } + + static class MockJcrResourceResolverFactory implements JcrResourceResolverFactory { + + public ResourceResolver getResourceResolver(Session arg0) { + return new MockResourceResolver(); + } + } + + /** Set a non-public Field */ + static void setField(Object target, String fieldName, Object value) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { + final Field f = target.getClass().getDeclaredField(fieldName); + f.setAccessible(true); + f.set(target, value); + } + + /** Return a JcrInstaller setup for testing */ + static JcrInstaller getJcrInstaller(SlingRepository repository, OsgiInstaller osgiInstaller) throws Exception { + // 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 Dictionary<String, Object> emptyDict = new Hashtable<String, Object>(); + m.checking(new Expectations() {{ + allowing(cc).getProperties(); + will(returnValue(emptyDict)); + allowing(cc).getBundleContext(); + will(returnValue(bc)); + 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; + } + + static void waitForCycles(JcrInstaller installer, int nCycles, long timeoutMsec) throws Exception { + final Field f = installer.getClass().getDeclaredField("cyclesCount"); + f.setAccessible(true); + final int endCycles = ((Integer)f.get(installer)).intValue() + nCycles; + final long endTime = System.currentTimeMillis() + timeoutMsec; + while(System.currentTimeMillis() < endTime) { + if(((Integer)f.get(installer)).intValue() > endCycles) { + return; + } + } + throw new Exception("did not get " + nCycles + " installer cycles in " + timeoutMsec + " msec"); + } + + /** Get the WatchedFolders of supplied JcrInstaller */ + @SuppressWarnings({ "unchecked"}) + static Collection<WatchedFolder> getWatchedFolders(JcrInstaller installer) throws Exception { + final Field f = installer.getClass().getDeclaredField("watchedFolders"); + f.setAccessible(true); + return (Collection<WatchedFolder>)f.get(installer); + } +} Propchange: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MiscUtil.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MiscUtil.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev URL Copied: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockInstallableResource.java (from r807539, sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/MockInstallableData.java) URL: http://svn.apache.org/viewvc/sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockInstallableResource.java?p2=sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockInstallableResource.java&p1=sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/MockInstallableData.java&r1=807539&r2=807639&rev=807639&view=diff ============================================================================== --- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/jcr/impl/MockInstallableData.java (original) +++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockInstallableResource.java Tue Aug 25 14:06:37 2009 @@ -16,65 +16,30 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sling.jcr.jcrinstall.jcr.impl; +package org.apache.sling.jcr.jcrinstall.impl; +import java.io.ByteArrayInputStream; -/** TODO adapt or remove */ -public class MockInstallableData /* implements InstallableData */ { +import org.apache.sling.osgi.installer.InstallableResource; - /* - private final InputStream inputStream; - private long lastModified; - private String digest; - private static int counter; - - public MockInstallableData(String uri) { - this(uri, uri); +public class MockInstallableResource extends InstallableResource { + + private static int counter; + + public MockInstallableResource(String uri) { + this(uri, "", null); } - public MockInstallableData(String uri, String data) { - inputStream = new ByteArrayInputStream(data.getBytes()); - lastModified = System.currentTimeMillis() + counter; - counter++; - digest = String.valueOf(lastModified); - } - - @Override - public boolean equals(Object obj) { - if(obj instanceof MockInstallableData) { - final MockInstallableData other = (MockInstallableData)obj; - return digest.equals(other.digest); - } - return false; - } - - public long getLastModified() { - return lastModified; - } - - @Override - public int hashCode() { - return digest.hashCode(); - } - - @SuppressWarnings("unchecked") - public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) { - if(type.equals(InputStream.class)) { - return (AdapterType)inputStream; - } - return null; - } - - void setDigest(String d) { - digest = d; - } - - public String getDigest() { - return digest; - } - - public int getBundleStartLevel() { - return 0; + public MockInstallableResource(String uri, String data, String digest) { + super(uri, new ByteArrayInputStream(data.getBytes()), getNextDigest(digest)); } - */ + + static String getNextDigest(String digest) { + if(digest != null) { + return digest; + } + synchronized (MockInstallableResource.class) { + return String.valueOf(System.currentTimeMillis() + (counter++)); + } + } } Added: 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=807639&view=auto ============================================================================== --- sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockOsgiInstaller.java (added) +++ sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockOsgiInstaller.java Tue Aug 25 14:06:37 2009 @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sling.jcr.jcrinstall.impl; + +import java.io.IOException; +import java.util.Collection; + +import org.apache.sling.osgi.installer.InstallableResource; +import org.apache.sling.osgi.installer.OsgiInstaller; + +class MockOsgiInstaller implements OsgiInstaller { + + public void addResource(InstallableResource d) throws IOException { + } + + public long[] getCounters() { + return null; + } + + public void registerResources(Collection<InstallableResource> data, + String urlScheme) throws IOException { + } + + public void removeResource(InstallableResource d) throws IOException { + } +} Propchange: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockOsgiInstaller.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/installer/jcr/jcrinstall/src/test/java/org/apache/sling/jcr/jcrinstall/impl/MockOsgiInstaller.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev URL