You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by st...@apache.org on 2016/10/31 16:59:32 UTC

svn commit: r1767330 - in /jackrabbit/oak/trunk/oak-jcr/src: main/java/org/apache/jackrabbit/oak/jcr/observation/ main/java/org/apache/jackrabbit/oak/jcr/observation/filter/ test/java/org/apache/jackrabbit/oak/jcr/observation/

Author: stefanegli
Date: Mon Oct 31 16:59:32 2016
New Revision: 1767330

URL: http://svn.apache.org/viewvc?rev=1767330&view=rev
Log:
OAK-5019 : introducing support for glob include paths to the OakEventFilter

Modified:
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/OakEventFilterImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/filter/OakEventFilter.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/OakEventFilterImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/OakEventFilterImpl.java?rev=1767330&r1=1767329&r2=1767330&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/OakEventFilterImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/OakEventFilterImpl.java Mon Oct 31 16:59:32 2016
@@ -54,6 +54,8 @@ public class OakEventFilterImpl extends
     /** whether or not includeSubTreeOnRemove feature is enabled */
     private boolean includeSubtreeOnRemove;
 
+    private String[] globPaths;
+
     public OakEventFilterImpl(@Nonnull JackrabbitEventFilter delegate) {
         checkNotNull(delegate);
         this.delegate = delegate;
@@ -229,11 +231,11 @@ public class OakEventFilterImpl extends
                 addAncestorsRemoveCondition(parentPaths, absPath);
             }
         }
-//        if (globPaths != null) {
-//            for (String globPath : globPaths) {
-//                addAncestorsRemoveCondition(parentPaths, globPath);
-//            }
-//        }
+        if (globPaths != null) {
+            for (String globPath : globPaths) {
+                addAncestorsRemoveCondition(parentPaths, globPath);
+            }
+        }
         if (parentPaths.size() == 0) {
             return mainCondition;
         }
@@ -262,4 +264,20 @@ public class OakEventFilterImpl extends
         return includeSubtreeOnRemove;
     }
 
+    @Override
+    public OakEventFilter withIncludeGlobPaths(String... globPaths) {
+        if (this.globPaths != null) {
+            throw new IllegalStateException("can only set globPaths once");
+        }
+//        for (String aGlobPath : globPaths) {
+//            return or(builder().path(aGlobPath));
+//        }
+        this.globPaths = globPaths;
+        return this;
+    }
+
+    String[] getIncludeGlobPaths() {
+        return globPaths;
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java?rev=1767330&r1=1767329&r2=1767330&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java Mon Oct 31 16:59:32 2016
@@ -22,11 +22,14 @@ import static com.google.common.collect.
 import static com.google.common.collect.Sets.newHashSet;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
+import static org.apache.jackrabbit.oak.commons.PathUtils.elements;
 import static org.apache.jackrabbit.oak.plugins.observation.filter.GlobbingPathFilter.STAR;
 import static org.apache.jackrabbit.oak.plugins.observation.filter.GlobbingPathFilter.STAR_STAR;
 
 import java.security.Principal;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -228,6 +231,12 @@ public class ObservationManagerImpl impl
         }
         Set<String> excludedPaths = getOakPaths(namePathMapper, filter.getExcludedPaths());
         PathUtils.unifyInExcludes(includePaths, excludedPaths);
+        if (oakEventFilter != null) {
+            String[] includeGlobPaths = oakEventFilter.getIncludeGlobPaths();
+            if (includeGlobPaths != null) {
+                includePaths.addAll(Arrays.asList(includeGlobPaths));
+            }
+        }
         if (includePaths.isEmpty()) {
             LOG.warn("The passed filter excludes all events. No event listener registered");
             return;
@@ -237,6 +246,20 @@ public class ObservationManagerImpl impl
         String depthPattern = isDeep ? STAR + '/' + STAR_STAR : STAR;
         List<Condition> includeConditions = newArrayList();
         for (String path : includePaths) {
+            final String deepenedPath;
+            if (path.endsWith(STAR)) {
+                // that's the case for a glob ending with * already, so
+                // no need to add another * or **
+                deepenedPath = path;
+            } else if (path.contains(STAR)) {
+                // for any other glob path that doesn't end with *
+                // we only add a single *, not a **
+                deepenedPath = concat (path, STAR);
+            } else {
+                // for any non-glob path we do it the traditional way
+                deepenedPath = concat(path, depthPattern);
+            }
+            includeConditions.add(filterBuilder.path(deepenedPath));
             includeConditions.add(filterBuilder.path(concat(path, depthPattern)));
             if (oakEventFilter != null && oakEventFilter.getIncludeAncestorsRemove()) {
                 // with the 'includeAncestorsRemove' extension we need
@@ -245,7 +268,8 @@ public class ObservationManagerImpl impl
                 // the subtree here as a result.
                 continue;
             }
-            filterBuilder.addSubTree(path);
+            // only register the part leading to the first STAR:
+            filterBuilder.addSubTree(pathWithoutGlob(path));
         }
 
         List<Condition> excludeConditions = createExclusions(filterBuilder, excludedPaths);
@@ -289,6 +313,23 @@ public class ObservationManagerImpl impl
         addEventListener(listener, tracker, filterBuilder.build());
     }
 
+    private String pathWithoutGlob(String path) {
+        if (!path.contains("*")) {
+            return path;
+        }
+        Iterator<String> it = elements(path).iterator();
+        String result = "/";
+        while(it.hasNext()) {
+            String next = it.next();
+            if (next.contains("*")) {
+                // then stop here
+                break;
+            }
+            result = concat(result, next);
+        }
+        return result;
+    }
+
     private static List<Condition> createExclusions(FilterBuilder filterBuilder, Iterable<String> excludedPaths) {
         List<Condition> conditions = newArrayList();
         for (String path : excludedPaths) {

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/filter/OakEventFilter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/filter/OakEventFilter.java?rev=1767330&r1=1767329&r2=1767330&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/filter/OakEventFilter.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/filter/OakEventFilter.java Mon Oct 31 16:59:32 2016
@@ -75,4 +75,23 @@ public abstract class OakEventFilter ext
      * @return this filter with the filter change applied
      */
     public abstract OakEventFilter withIncludeSubtreeOnRemove();
+
+    /**
+     * Adds the provided glob paths to the set of include paths.
+     * <p>
+     * The definition of a glob path is
+     * <a href="https://jackrabbit.apache.org/oak/docs/apidocs/org/apache/jackrabbit/oak/plugins/observation/filter/GlobbingPathFilter.html">here</a>
+     * <p>
+     * Note that unlike 'normal' include and exclude paths, this variant
+     * doesn't apply Oak's NamePathMapper.
+     * <p>
+     * This filter property is added in 'or' mode.
+     * 
+     * @param globPath
+     *            glob path that should be added as include path pattern. Note
+     *            that the NamePathMapper is not applied on this globPath.
+     * @return this filter with the filter change applied
+     */
+    public abstract OakEventFilter withIncludeGlobPaths(String... globPaths);
+
 }

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java?rev=1767330&r1=1767329&r2=1767330&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/observation/ObservationTest.java Mon Oct 31 16:59:32 2016
@@ -1375,5 +1375,52 @@ public class ObservationTest extends Abs
         assertTrue("Unexpected events: " + unexpected, unexpected.isEmpty());
     }
     
+    @Test
+    public void includeGlobPaths() throws Exception {
+        
+        Node testNode = getNode(TEST_PATH);
+        testNode.addNode("a1").addNode("b").addNode("c");
+        testNode.addNode("a2").addNode("b").addNode("c");
+        testNode.getSession().save();
+
+        ObservationManagerImpl oManager = (ObservationManagerImpl) observationManager;
+        ExpectationListener listener = new ExpectationListener();
+        
+        JackrabbitEventFilter filter = new JackrabbitEventFilter();
+        filter.setEventTypes(ALL_EVENTS);
+        filter = FilterFactory.wrap(filter).withIncludeGlobPaths(TEST_PATH + "/a2/**");
+
+        oManager.addEventListener(listener, filter);
+
+        testNode.getNode("a1").getNode("b").remove();
+        listener.expectRemove(testNode.getNode("a2").getNode("b")).remove();
+        testNode.getSession().save();
+        
+        Thread.sleep(1000);
+        List<Expectation> missing = listener.getMissing(TIME_OUT, TimeUnit.SECONDS);
+        assertTrue("Missing events: " + missing, missing.isEmpty());
+        List<Event> unexpected = listener.getUnexpected();
+        assertTrue("Unexpected events: " + unexpected, unexpected.isEmpty());
+        
+        Node a3 = testNode.addNode("a3");
+        Node foo = a3.addNode("bar").addNode("foo");
+        testNode.getSession().save();
+
+        filter = new JackrabbitEventFilter();
+        filter.setEventTypes(ALL_EVENTS);
+//        filter.setAbsPath(TEST_PATH + "/a3/bar/foo/x");
+        filter = FilterFactory.wrap(filter).withIncludeGlobPaths(TEST_PATH + "/a3/**/x");
+        oManager.addEventListener(listener, filter);
+        
+        Node x = foo.addNode("x");
+        listener.expect(x.getPath() + "/jcr:primaryType", PROPERTY_ADDED);
+        testNode.getSession().save();
+
+        Thread.sleep(1000);
+        missing = listener.getMissing(TIME_OUT, TimeUnit.SECONDS);
+        assertTrue("Missing events: " + missing, missing.isEmpty());
+        unexpected = listener.getUnexpected();
+        assertTrue("Unexpected events: " + unexpected, unexpected.isEmpty());
+    }
 
 }