Author: cziegeler
Date: Tue Oct 18 13:12:14 2016
New Revision: 1765435

URL: http://svn.apache.org/viewvc?rev=1765435&view=rev
Log:
SLING-6056 : achieve 1:1 mapping between observation and resource change 
listener

Modified:
    
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrListenerBaseConfig.java
    
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java

Modified: 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrListenerBaseConfig.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrListenerBaseConfig.java?rev=1765435&r1=1765434&r2=1765435&view=diff
==============================================================================
--- 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrListenerBaseConfig.java
 (original)
+++ 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrListenerBaseConfig.java
 Tue Oct 18 13:12:14 2016
@@ -25,10 +25,13 @@ 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;
 import javax.jcr.observation.ObservationManager;
 
 import org.apache.jackrabbit.api.observation.JackrabbitEventFilter;
 import org.apache.jackrabbit.api.observation.JackrabbitObservationManager;
+import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.resource.observation.ResourceChange.ChangeType;
 import org.apache.sling.api.resource.path.Path;
 import org.apache.sling.jcr.api.SlingRepository;
@@ -83,11 +86,93 @@ public class JcrListenerBaseConfig imple
             final String[] pathArray = new String[paths.size()];
             int i=0;
             // remove global prefix
+            boolean hasGlob = false;
             for(final String p : paths) {
+                if ( p.startsWith(Path.GLOB_PREFIX )) {
+                    hasGlob = true;
+                }
                 pathArray[i] = (p.startsWith(Path.GLOB_PREFIX) ? 
p.substring(Path.GLOB_PREFIX.length()) : p);
                 i++;
             }
-            filter.setAdditionalPaths(pathArray);
+            final EventListener regListener;
+            if ( hasGlob ) {
+                // TODO we can't use glob patterns directly here
+                filter.setAbsPath("/");
+                regListener = new EventListener() {
+
+                    @Override
+                    public void onEvent(final EventIterator events) {
+                        listener.onEvent(new EventIterator() {
+
+                            Event next = seek();
+
+                            private Event seek() {
+                                while ( events.hasNext() ) {
+                                    final Event e = events.nextEvent();
+                                    String path = null;
+                                    try {
+                                        path = e.getPath();
+                                        if ( e.getType() == 
Event.PROPERTY_ADDED
+                                                || e.getType() == 
Event.PROPERTY_CHANGED
+                                                || e.getType() == 
Event.PROPERTY_REMOVED ) {
+                                                  path = 
ResourceUtil.getParent(path);
+                                        }
+                                        if ( config.getPaths().matches(path) 
!= null ) {
+                                            return e;
+                                        }
+                                    } catch (RepositoryException e1) {
+                                        // ignore
+                                    }
+                                }
+                                return null;
+                            }
+
+                            @Override
+                            public void remove() {
+                                // we don't support this -> NOP
+                            }
+
+                            @Override
+                            public Object next() {
+                                return nextEvent();
+                            }
+
+                            @Override
+                            public boolean hasNext() {
+                                return next != null;
+                            }
+
+                            @Override
+                            public void skip(long skipNum) {
+                                // we don't support this -> NOP
+                            }
+
+                            @Override
+                            public long getSize() {
+                                // we don't support this -> 0
+                                return 0;
+                            }
+
+                            @Override
+                            public long getPosition() {
+                                // we don't support this -> 0
+                                return 0;
+                            }
+
+                            @Override
+                            public Event nextEvent() {
+                                final Event result = next;
+                                next = seek();
+                                return result;
+                            }
+                        });
+                    }
+                };
+
+            } else {
+                filter.setAdditionalPaths(pathArray);
+                regListener = listener;
+            }
             filter.setIsDeep(true);
 
             // exclude paths
@@ -102,7 +187,7 @@ public class JcrListenerBaseConfig imple
             // types
             filter.setEventTypes(this.getTypes(config));
 
-            ((JackrabbitObservationManager)mgr).addEventListener(listener, 
filter);
+            ((JackrabbitObservationManager)mgr).addEventListener(regListener, 
filter);
         } else {
             throw new RepositoryException("Observation manager is not a 
JackrabbitObservationManager");
         }

Modified: 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java?rev=1765435&r1=1765434&r2=1765435&view=diff
==============================================================================
--- 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java
 (original)
+++ 
sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java
 Tue Oct 18 13:12:14 2016
@@ -241,9 +241,27 @@ public class JcrResourceProvider extends
             this.unregisterListeners();
             this.registerListeners();
         } else {
-            // TODO this can be optimized
-            this.unregisterListeners();
-            this.registerListeners();
+            final Map<ObserverConfiguration, Closeable> oldMap = new 
HashMap<>(this.listeners);
+            this.listeners.clear();
+            try {
+                for(final ObserverConfiguration config : 
this.getProviderContext().getObservationReporter().getObserverConfigurations()) 
{
+                    // check if such a listener already exists
+                    Closeable listener = oldMap.remove(config);
+                    if ( listener == null ) {
+                        listener = new 
JcrResourceListener(this.listenerConfig, config);
+                    }
+                    this.listeners.put(config, listener);
+                }
+            } catch (final RepositoryException e) {
+                throw new SlingException("Can't create the JCR event 
listener.", e);
+            }
+            for(final Closeable c : oldMap.values()) {
+                try {
+                    c.close();
+                } catch (final IOException e) {
+                    // ignore this as the method above does not throw it
+                }
+            }
         }
     }
 


Reply via email to