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 15:54:11 UTC

svn commit: r1767317 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/plugins/observation/filter/GlobbingPathFilter.java test/java/org/apache/jackrabbit/oak/plugins/observation/filter/GlobbingPathFilterTest.java

Author: stefanegli
Date: Mon Oct 31 15:54:11 2016
New Revision: 1767317

URL: http://svn.apache.org/viewvc?rev=1767317&view=rev
Log:
OAK-5039 : changing definition of STAR in a glob path to correspond the more classical definition of the wildcard STAR, which is any character sequence not including /

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/GlobbingPathFilter.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/filter/GlobbingPathFilterTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/GlobbingPathFilter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/GlobbingPathFilter.java?rev=1767317&r1=1767316&r2=1767317&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/GlobbingPathFilter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/filter/GlobbingPathFilter.java Mon Oct 31 15:54:11 2016
@@ -23,6 +23,10 @@ import static com.google.common.base.Obj
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.apache.jackrabbit.oak.commons.PathUtils.elements;
 
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
 import javax.annotation.Nonnull;
 
 import com.google.common.base.Joiner;
@@ -49,10 +53,12 @@ import org.apache.jackrabbit.oak.spi.sta
  * Examples:
  * <pre>
  *    q matches q only
- *    * matches every path containing a single element
+ *    * matches character matches zero or more characters of a name component without crossing path boundaries (ie without crossing /)
  *    ** matches every path
  *    a/b/c matches a/b/c only
  *    a/*&#47;c matches a/x/c for every element x
+ *    a/*.html&#47;c matches a/x.html/c for every character sequence x (that doesn't include /)
+ *    a/*.*&#47;c matches a/x.y/c for every character sequence x and y (that don't include /)
  *    **&#47;y/z match every path ending in y/z
  *    r/s/t&#47;** matches r/s/t and all its descendants
  * </pre>
@@ -62,13 +68,15 @@ public class GlobbingPathFilter implemen
     public static final String STAR_STAR = "**";
 
     private final ImmutableList<String> pattern;
+    private final Map<String, Pattern> patternMap;
 
-    private GlobbingPathFilter(@Nonnull Iterable<String> pattern) {
+    private GlobbingPathFilter(@Nonnull Iterable<String> pattern, Map<String, Pattern> patternMap) {
         this.pattern = ImmutableList.copyOf(checkNotNull(pattern));
+        this.patternMap = checkNotNull(patternMap);
     }
 
     public GlobbingPathFilter(@Nonnull String pattern) {
-        this(elements(pattern));
+        this(elements(pattern), new HashMap<String, Pattern>());
     }
 
     @Override
@@ -105,6 +113,23 @@ public class GlobbingPathFilter implemen
     public boolean includeReorder(String destName, String name, NodeState reordered) {
         return includeItem(name);
     }
+    
+    private Pattern getPattern(String wildcardStr) {
+        Pattern p = patternMap.get(wildcardStr);
+        if (p == null) {
+            p = Pattern.compile("\\Q"+wildcardStr.replace("*", "\\E[^/]*\\Q") + "\\E");
+            patternMap.put(wildcardStr, p);
+        }
+        return p;
+    }
+    
+    private boolean wildcardMatch(String pathElement, String wildcardStr) {
+        if (STAR_STAR.equals(wildcardStr) || !wildcardStr.contains(STAR)) {
+            return pathElement.equals(wildcardStr);
+        }
+        Pattern regexPattern = getPattern(wildcardStr);
+        return regexPattern.matcher(pathElement).matches();
+    }
 
     @Override
     public EventFilter create(String name, NodeState before, NodeState after) {
@@ -118,20 +143,20 @@ public class GlobbingPathFilter implemen
             return null;
         }
 
-        if (STAR.equals(head) || head.equals(name)) {
-            return new GlobbingPathFilter(pattern.subList(1, pattern.size()));
+        if (wildcardMatch(name, head)) {
+            return new GlobbingPathFilter(pattern.subList(1, pattern.size()), patternMap);
         } else if (STAR_STAR.equals(head)) {
             if (pattern.size() >= 2 && pattern.get(1).equals(name)) {
                 // ** matches empty list of elements and pattern.get(1) matches name
                 // match the rest of the pattern against the rest of the path and
                 // match the whole pattern against the rest of the path
                 return Filters.any(
-                        new GlobbingPathFilter(pattern.subList(2, pattern.size())),
-                        new GlobbingPathFilter(pattern)
+                        new GlobbingPathFilter(pattern.subList(2, pattern.size()), patternMap),
+                        new GlobbingPathFilter(pattern, patternMap)
                 );
             } else {
                 // ** matches name, match the whole pattern against the rest of the path
-                return new GlobbingPathFilter(pattern);
+                return new GlobbingPathFilter(pattern, patternMap);
             }
         } else {
             return null;
@@ -150,7 +175,7 @@ public class GlobbingPathFilter implemen
     private boolean includeItem(String name) {
         if (!pattern.isEmpty() && pattern.size() <= 2) {
             String head = pattern.get(0);
-            boolean headMatches = STAR.equals(head) || STAR_STAR.equals(head) || head.equals(name);
+            boolean headMatches = wildcardMatch(name, head) || STAR_STAR.equals(head);
             return pattern.size() == 1
                 ? headMatches
                 : headMatches && STAR_STAR.equals(pattern.get(1));

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/filter/GlobbingPathFilterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/filter/GlobbingPathFilterTest.java?rev=1767317&r1=1767316&r2=1767317&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/filter/GlobbingPathFilterTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/observation/filter/GlobbingPathFilterTest.java Mon Oct 31 15:54:11 2016
@@ -85,6 +85,27 @@ public class GlobbingPathFilterTest {
 
         assertTrue(filter.includeAdd("q", tree.getNodeState()));
     }
+    
+    @Test
+    public void wildcardMatches() {
+        EventFilter filter = new GlobbingPathFilter("*.*");
+        assertFalse(filter.includeAdd("a", tree.getNodeState()));
+        assertTrue(filter.includeAdd(".b", tree.getNodeState()));
+        assertTrue(filter.includeAdd("a.b", tree.getNodeState()));
+        assertTrue(filter.includeAdd("a.", tree.getNodeState()));
+        
+        filter = new GlobbingPathFilter("*.html");
+        assertFalse(filter.includeAdd("a.b", tree.getNodeState()));
+        assertFalse(filter.includeAdd("html", tree.getNodeState()));
+        assertTrue(filter.includeAdd(".html", tree.getNodeState()));
+        assertTrue(filter.includeAdd("a.html", tree.getNodeState()));
+
+        filter = new GlobbingPathFilter("*foo*.html");
+        assertFalse(filter.includeAdd("a.b", tree.getNodeState()));
+        assertFalse(filter.includeAdd("a.html", tree.getNodeState()));
+        assertTrue(filter.includeAdd("foo.html", tree.getNodeState()));
+        assertTrue(filter.includeAdd("my-foo-bar.html", tree.getNodeState()));
+    }
 
     /**
      * ** should match every path