SLING-4564 : Use a single listener registered for multiple path in JCR installer. 

git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1671760 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java b/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java
index 6931ee1..d4b57ab 100644
--- a/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java
+++ b/src/main/java/org/apache/sling/installer/provider/jcr/impl/JcrInstaller.java
@@ -213,7 +213,7 @@
                 session = repository.loginAdministrative(repository.getDefaultWorkspace());
 
                 for (final String path : cfg.getRoots()) {
-                    listeners.add(new RootFolderListener(session, path, updateFoldersListTimer));
+                    listeners.add(new RootFolderListener(session, path, updateFoldersListTimer, cfg));
                     logger.debug("Configured root folder: {}", path);
                 }
 
diff --git a/src/main/java/org/apache/sling/installer/provider/jcr/impl/RootFolderListener.java b/src/main/java/org/apache/sling/installer/provider/jcr/impl/RootFolderListener.java
index 84535fa..afce64a 100644
--- a/src/main/java/org/apache/sling/installer/provider/jcr/impl/RootFolderListener.java
+++ b/src/main/java/org/apache/sling/installer/provider/jcr/impl/RootFolderListener.java
@@ -18,6 +18,9 @@
  */
 package org.apache.sling.installer.provider.jcr.impl;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.observation.Event;
@@ -38,14 +41,18 @@
     private final RescanTimer timer;
     private final String watchedPath;
 
-    RootFolderListener(final Session session, final String path, final RescanTimer timer)
+    private final InstallerConfig cfg;
+
+    RootFolderListener(final Session session, final String path, final RescanTimer timer, final InstallerConfig cfg)
     throws RepositoryException {
         this.timer = timer;
         this.watchedPath = path;
+        this.cfg = cfg;
 
-        int eventTypes = Event.NODE_ADDED | Event.NODE_REMOVED;
-        boolean isDeep = true;
-        boolean noLocal = true;
+        final int eventTypes = Event.NODE_ADDED | Event.NODE_REMOVED
+                | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED;
+        final boolean isDeep = true;
+        final boolean noLocal = true;
         session.getWorkspace().getObservationManager().addEventListener(this, eventTypes, watchedPath,
                 isDeep, null, null, noLocal);
 
@@ -65,14 +72,32 @@
      * Schedule a scan.
      */
     public void onEvent(final EventIterator it) {
-        // we don't care about the events
-        // they are only logged if debug log level
-        if ( logger.isDebugEnabled() ) {
-            while(it.hasNext()) {
-                final Event e = it.nextEvent();
-                logger.debug("Got event {}", e);
+        // we only do the global scan for node changes
+        boolean globalScan = false;
+        // copy watched folders
+        final List<WatchedFolder> checkFolders = new ArrayList<WatchedFolder>(cfg.getWatchedFolders());
+        while(it.hasNext()) {
+            final Event e = it.nextEvent();
+            logger.debug("Got event {}", e);
+            if ( e.getType() == Event.NODE_ADDED || e.getType() == Event.NODE_REMOVED ) {
+                globalScan = true;
+            }
+            try {
+                final String path = e.getPath();
+
+                for(final WatchedFolder folder : checkFolders) {
+                    if ( path.startsWith(folder.getPathWithSlash()) ) {
+                        folder.onEvent(it);
+                        checkFolders.remove(folder);
+                        break;
+                    }
+                }
+            } catch ( final RepositoryException re ) {
+                logger.warn("Error while getting path from event", re);
             }
         }
-        timer.scheduleScan();
+        if ( globalScan ) {
+            timer.scheduleScan();
+        }
     }
 }
diff --git a/src/main/java/org/apache/sling/installer/provider/jcr/impl/WatchedFolder.java b/src/main/java/org/apache/sling/installer/provider/jcr/impl/WatchedFolder.java
index b673be1..fed3bf9 100644
--- a/src/main/java/org/apache/sling/installer/provider/jcr/impl/WatchedFolder.java
+++ b/src/main/java/org/apache/sling/installer/provider/jcr/impl/WatchedFolder.java
@@ -47,6 +47,7 @@
     private final Logger log = LoggerFactory.getLogger(getClass());
 
     private final String path;
+    private final String pathWithSlash;
     private final int priority;
     private final Session session;
     private final Collection <JcrInstaller.NodeConverter> converters;
@@ -72,6 +73,7 @@
         }
 
         this.path = path;
+        this.pathWithSlash = path.concat("/");
         this.converters = converters;
         this.priority = priority;
 
@@ -85,20 +87,20 @@
                 | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED;
         final boolean isDeep = true;
         final boolean noLocal = true;
-        session.getWorkspace().getObservationManager().addEventListener(this, eventTypes, path,
-                isDeep, null, null, noLocal);
+//        session.getWorkspace().getObservationManager().addEventListener(this, eventTypes, path,
+//                isDeep, null, null, noLocal);
         this.needsScan = true;
 
         log.info("Watching folder {} (priority {})", path, priority);
     }
 
     public void stop() {
-    	try {
+/*    	try {
 	    	session.getWorkspace().getObservationManager().removeEventListener(this);
     	} catch(RepositoryException re) {
     		log.warn("RepositoryException in stop()", re);
     	}
-    }
+*/    }
 
     @Override
     public String toString() {
@@ -109,6 +111,10 @@
         return path;
     }
 
+    public String getPathWithSlash() {
+        return this.pathWithSlash;
+    }
+
     /**
      * Update scan flag whenever an observation event occurs.
      */