You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2016/10/17 16:16:02 UTC
svn commit: r1765329 - in /sling/trunk/bundles/api/src:
main/java/org/apache/sling/api/resource/path/Path.java
test/java/org/apache/sling/api/resource/path/PathTest.java
Author: cziegeler
Date: Mon Oct 17 16:16:02 2016
New Revision: 1765329
URL: http://svn.apache.org/viewvc?rev=1765329&view=rev
Log:
SLING-6161 : Correctly implement Path.matches
Modified:
sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/path/Path.java
sling/trunk/bundles/api/src/test/java/org/apache/sling/api/resource/path/PathTest.java
Modified: sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/path/Path.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/path/Path.java?rev=1765329&r1=1765328&r2=1765329&view=diff
==============================================================================
--- sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/path/Path.java (original)
+++ sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/path/Path.java Mon Oct 17 16:16:02 2016
@@ -46,7 +46,9 @@ public class Path implements Comparable<
* <li>The {@code **} characters match zero or more characters crossing directory boundaries.</li>
* </ul>
*
- * @param path the resource path or a glob pattern.
+ * @param path The resource path or a glob pattern.
+ * @throws NullPointerException If {@code otherPath} is {@code null}
+ * @throws IllegalArgumentException If the provided path is not absolute, or if the glob pattern does not start with a slash.
*/
public Path(@Nonnull final String path) {
if ( path.equals("/") ) {
@@ -56,23 +58,42 @@ public class Path implements Comparable<
} else {
this.path = path;
}
- if (path.startsWith(GLOB_PREFIX)) {
- isPattern = true;
- regexPattern = Pattern.compile(toRegexPattern(path.substring(5)));
- String patternPath = path.substring(GLOB_PREFIX.length());
- this.prefix = patternPath.equals("/") ? "/" : patternPath.concat("/");
+ if (this.path.startsWith(GLOB_PREFIX)) {
+ final String patternPath = path.substring(GLOB_PREFIX.length());
+ this.isPattern = true;
+ this.regexPattern = Pattern.compile(toRegexPattern(patternPath));
+ int lastSlash = 0;
+ int pos = 1;
+ while ( patternPath.length() > pos ) {
+ final char c = patternPath.charAt(pos);
+ if ( c == '/') {
+ lastSlash = pos;
+ } else if ( c == '*') {
+ break;
+ }
+ pos++;
+ }
+
+ this.prefix = (pos == patternPath.length() ? patternPath : patternPath.substring(0, lastSlash + 1));
} else {
- isPattern = false;
- regexPattern = null;
+ this.isPattern = false;
+ this.regexPattern = null;
this.prefix = this.path.equals("/") ? "/" : this.path.concat("/");
}
+ if ( !this.prefix.startsWith("/") ) {
+ throw new IllegalArgumentException("Path must be absolute: " + path);
+ }
}
/**
* If this {@code Path} object holds a path (and not a pattern), this method
- * check whether the provided path is equal to this path or a sub path of it.
+ * checks whether the provided path is equal to this path or a sub path of it.
+ * If a glob pattern is provided as the argument, it performs the same check
+ * and respects the provided pattern.
* If this {@code Path} object holds a pattern, it checks whether the
- * provided path matches the pattern.
+ * provided path matches the pattern. If this path object holds a pattern
+ * and a pattern is provided as the argument, it returns only {@code true}
+ * if the pattern is the same.
* If the provided argument is not an absolute path (e.g. if it is a relative
* path or a pattern), this method returns {@code false}.
*
@@ -80,11 +101,57 @@ public class Path implements Comparable<
* @return {@code true} If other path is within the sub tree of this path
* or matches the pattern.
* @see Path#isPattern()
+ * @throws NullPointerException If {@code otherPath} is {@code null}
+ * @throws IllegalArgumentException If the provided path is not absolute, or if the glob pattern does not start with a slash.
*/
public boolean matches(final String otherPath) {
- if (isPattern) {
+ if ( otherPath.startsWith(GLOB_PREFIX) ) {
+ if ( this.isPattern ) {
+ // both are patterns, then they must be equal
+ final Path oPath = new Path(otherPath);
+ return this.regexPattern.equals(oPath.regexPattern);
+ }
+
+ // this is path, provided argument is a pattern
+ // simplest case - the prefix of the glob pattern matches already
+ // for example: this path = /apps
+ // glob = /apps/**
final Path oPath = new Path(otherPath);
- return this.regexPattern.equals(oPath.regexPattern) || this.regexPattern.matcher(otherPath).matches();
+ if ( this.matches(oPath.prefix) ) {
+ return true;
+ }
+ // count slashes in path
+ int count = 0;
+ for (int i=0; i < this.path.length(); i++) {
+ if (this.path.charAt(i) == '/') {
+ count++;
+ }
+ }
+ // now create the substring of the glob pattern with the same amount of slashes
+ int start = GLOB_PREFIX.length();
+ while ( start < otherPath.length() ) {
+ if ( otherPath.charAt(start) == '/') {
+ if ( count == 0 ) {
+ break;
+ }
+ count--;
+ }
+ start++;
+ }
+ if ( count > 0 ) {
+ return false;
+ }
+ final String globPattern = otherPath.substring(0, start);
+ final Path globPatternPath = new Path(globPattern);
+ return globPatternPath.matches(this.path);
+ }
+
+ // provided argument is a path
+ if ( !otherPath.startsWith("/") ) {
+ throw new IllegalArgumentException("Path must be absolute: " + otherPath);
+ }
+ if (isPattern) {
+ return this.regexPattern.matcher(otherPath).matches();
}
return this.path.equals(otherPath) || otherPath.startsWith(this.prefix);
}
@@ -92,7 +159,7 @@ public class Path implements Comparable<
/**
* Return the path if this {@code Path} object holds a path,
* returns the pattern otherwise.
- * @return The path.
+ * @return The path or pattern.
* @see #isPattern()
*/
public String getPath() {
Modified: sling/trunk/bundles/api/src/test/java/org/apache/sling/api/resource/path/PathTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/test/java/org/apache/sling/api/resource/path/PathTest.java?rev=1765329&r1=1765328&r2=1765329&view=diff
==============================================================================
--- sling/trunk/bundles/api/src/test/java/org/apache/sling/api/resource/path/PathTest.java (original)
+++ sling/trunk/bundles/api/src/test/java/org/apache/sling/api/resource/path/PathTest.java Mon Oct 17 16:16:02 2016
@@ -20,6 +20,7 @@ package org.apache.sling.api.resource.pa
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import org.junit.Test;
@@ -70,8 +71,33 @@ public class PathTest {
@Test public void testPatternRootMatching() {
final Path path = new Path("/");
- assertFalse(path.matches("glob:/apps/myproject/components/**/*.html"));
- assertFalse(path.matches("glob:/apps/**/*.html"));
+ assertTrue(path.matches("glob:/apps/myproject/components/**/*.html"));
+ assertTrue(path.matches("glob:/apps/**/*.html"));
+ }
+
+ @Test public void testMatchesWithGlobPattern() {
+ final Path path = new Path("/apps/myproject");
+ assertTrue(path.matches("glob:/apps/myproject/components/**/*.html"));
+ assertTrue(path.matches("glob:/apps/**/components/**/*.html"));
+ assertFalse(path.matches("glob:/*/foo"));
+ assertTrue(path.matches("glob:/*/myproject"));
+ assertTrue(path.matches("glob:/*/*project"));
+ assertTrue(path.matches("glob:/*/*project/**.html"));
+ }
+
+ @Test public void testIllegalArgumentException() {
+ try {
+ new Path("foo");
+ fail();
+ } catch ( final IllegalArgumentException iae) {
+ // this should happen!
+ }
+ try {
+ new Path("glob:foo");
+ fail();
+ } catch ( final IllegalArgumentException iae) {
+ // this should happen!
+ }
}
@Test public void testPathMatchingTrailingSlash() {