You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by kk...@apache.org on 2014/04/08 14:55:54 UTC
svn commit: r1585713 - in /tomcat/trunk: java/org/apache/tomcat/util/file/
java/org/apache/tomcat/util/scan/ webapps/docs/
Author: kkolinko
Date: Tue Apr 8 12:55:54 2014
New Revision: 1585713
URL: http://svn.apache.org/r1585713
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=56365
Simplify file name matching code in StandardJarScanFilter.
Removed:
tomcat/trunk/java/org/apache/tomcat/util/file/Constants.java
tomcat/trunk/java/org/apache/tomcat/util/file/LocalStrings.properties
Modified:
tomcat/trunk/java/org/apache/tomcat/util/file/Matcher.java
tomcat/trunk/java/org/apache/tomcat/util/scan/StandardJarScanFilter.java
tomcat/trunk/webapps/docs/changelog.xml
Modified: tomcat/trunk/java/org/apache/tomcat/util/file/Matcher.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/file/Matcher.java?rev=1585713&r1=1585712&r2=1585713&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/file/Matcher.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/file/Matcher.java Tue Apr 8 12:55:54 2014
@@ -18,14 +18,8 @@
package org.apache.tomcat.util.file;
-import java.io.File;
-import java.util.Locale;
import java.util.Set;
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.res.StringManager;
-
/**
* <p>This is a utility class to match file globs.
* The class has been derived from
@@ -36,44 +30,23 @@ import org.apache.tomcat.util.res.String
public final class Matcher {
/**
- * The pattern that matches an arbitrary number of directories.
- */
- public static final String DEEP_TREE_MATCH = "**";
-
- private static final String OS_NAME =
- System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
- private static final String PATH_SEP =
- System.getProperty("path.separator");
- private static final boolean ON_NETWARE = isNetware();
- private static final boolean ON_DOS = isDos();
-
- /**
- * The string resources for this package.
- */
- private static final StringManager sm =
- StringManager.getManager(Constants.Package);
-
- private static final Log log = LogFactory.getLog(Matcher.class);
-
- /**
- * Tests whether or not a given path matches any pattern in the given set.
+ * Tests whether or not a given file name matches any file name pattern in
+ * the given set. The match is performed case-sensitively.
*
- * If you need to call this method multiple times with the same
- * pattern you should rather pre parse the pattern using tokenizePathAsArray.
- *
- * @see #tokenizePathAsArray
+ * @see #match(String, String, boolean)
*
* @param patternSet The pattern set to match against. Must not be
* <code>null</code>.
- * @param str The path to match, as a String. Must not be
- * <code>null</code>.
- *
- * @return <code>true</code> if any pattern in the set matches against the string,
- * or <code>false</code> otherwise.
- */
- public static boolean matchPath(Set<String[]> patternSet, String str) {
- for (String[] patternTokens: patternSet) {
- if (matchPath(patternTokens, tokenizePathAsArray(str), true)) {
+ * @param str The file name to match, as a String. Must not be
+ * <code>null</code>. It must be just a file name, without
+ * a path.
+ *
+ * @return <code>true</code> if any pattern in the set matches against the
+ * file name, or <code>false</code> otherwise.
+ */
+ public static boolean matchName(Set<String> patternSet, String fileName) {
+ for (String pattern: patternSet) {
+ if (match(pattern, fileName, true)) {
return true;
}
}
@@ -81,177 +54,6 @@ public final class Matcher {
}
/**
- * Tests whether or not a given path matches a given pattern.
- *
- * If you need to call this method multiple times with the same
- * pattern you should rather pre parse the pattern using tokenizePathAsArray.
- *
- * @see #tokenizePathAsArray
- *
- * @param pattern The pattern to match against. Must not be
- * <code>null</code>.
- * @param str The path to match, as a String. Must not be
- * <code>null</code>.
- *
- * @return <code>true</code> if the pattern matches against the string,
- * or <code>false</code> otherwise.
- */
- public static boolean matchPath(String pattern, String str) {
- String[] patDirs = tokenizePathAsArray(pattern);
- return matchPath(patDirs, tokenizePathAsArray(str), true);
- }
-
- /**
- * Tests whether or not a given path matches a given pattern.
- *
- * If you need to call this method multiple times with the same
- * pattern you should rather pre parse the pattern using tokenizePathAsArray.
- *
- * @see #tokenizePathAsArray
- *
- * @param pattern The pattern to match against. Must not be
- * <code>null</code>.
- * @param str The path to match, as a String. Must not be
- * <code>null</code>.
- * @param isCaseSensitive Whether or not matching should be performed
- * case sensitively.
- *
- * @return <code>true</code> if the pattern matches against the string,
- * or <code>false</code> otherwise.
- */
- public static boolean matchPath(String pattern, String str,
- boolean isCaseSensitive) {
- String[] patDirs = tokenizePathAsArray(pattern);
- return matchPath(patDirs, tokenizePathAsArray(str), isCaseSensitive);
- }
-
- /**
- * Core implementation of matchPath using an already tokenized pattern.
- */
- public static boolean matchPath(String[] tokenizedPattern, String[] strDirs,
- boolean isCaseSensitive) {
- int patIdxStart = 0;
- int patIdxEnd = tokenizedPattern.length - 1;
- int strIdxStart = 0;
- int strIdxEnd = strDirs.length - 1;
-
- // up to first '**'
- while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
- String patDir = tokenizedPattern[patIdxStart];
- if (patDir.equals(DEEP_TREE_MATCH)) {
- break;
- }
- if (!match(patDir, strDirs[strIdxStart], isCaseSensitive)) {
- return false;
- }
- patIdxStart++;
- strIdxStart++;
- }
- if (strIdxStart > strIdxEnd) {
- // String is exhausted
- for (int i = patIdxStart; i <= patIdxEnd; i++) {
- if (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
- return false;
- }
- }
- return true;
- } else {
- if (patIdxStart > patIdxEnd) {
- // String not exhausted, but pattern is. Failure.
- return false;
- }
- }
-
- // up to last '**'
- while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
- String patDir = tokenizedPattern[patIdxEnd];
- if (patDir.equals(DEEP_TREE_MATCH)) {
- break;
- }
- if (!match(patDir, strDirs[strIdxEnd], isCaseSensitive)) {
- return false;
- }
- patIdxEnd--;
- strIdxEnd--;
- }
- if (strIdxStart > strIdxEnd) {
- // String is exhausted
- for (int i = patIdxStart; i <= patIdxEnd; i++) {
- if (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
- return false;
- }
- }
- return true;
- }
-
- while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
- int patIdxTmp = -1;
- for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
- if (tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
- patIdxTmp = i;
- break;
- }
- }
- if (patIdxTmp == patIdxStart + 1) {
- // '**/**' situation, so skip one
- patIdxStart++;
- continue;
- }
- // Find the pattern between padIdxStart & padIdxTmp in str between
- // strIdxStart & strIdxEnd
- int patLength = (patIdxTmp - patIdxStart - 1);
- int strLength = (strIdxEnd - strIdxStart + 1);
- int foundIdx = -1;
- strLoop:
- for (int i = 0; i <= strLength - patLength; i++) {
- for (int j = 0; j < patLength; j++) {
- String subPat = tokenizedPattern[patIdxStart + j + 1];
- String subStr = strDirs[strIdxStart + i + j];
- if (!match(subPat, subStr, isCaseSensitive)) {
- continue strLoop;
- }
- }
-
- foundIdx = strIdxStart + i;
- break;
- }
-
- if (foundIdx == -1) {
- return false;
- }
-
- patIdxStart = patIdxTmp;
- strIdxStart = foundIdx + patLength;
- }
-
- for (int i = patIdxStart; i <= patIdxEnd; i++) {
- if (!tokenizedPattern[i].equals(DEEP_TREE_MATCH)) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Tests whether or not a string matches against a pattern.
- * The pattern may contain two special characters:<br>
- * '*' means zero or more characters<br>
- * '?' means one and only one character
- *
- * @param pattern The pattern to match against.
- * Must not be <code>null</code>.
- * @param str The string which must be matched against the pattern.
- * Must not be <code>null</code>.
- *
- * @return <code>true</code> if the string matches against the pattern,
- * or <code>false</code> otherwise.
- */
- public static boolean match(String pattern, String str) {
- return match(pattern, str, true);
- }
-
- /**
* Tests whether or not a string matches against a pattern.
* The pattern may contain two special characters:<br>
* '*' means zero or more characters<br>
@@ -411,156 +213,4 @@ public final class Matcher {
: Character.toUpperCase(ch) != Character.toUpperCase(other);
}
- /**
- * Breaks a path up into a array of path elements, tokenizing on
- * <code>File.separator</code>.
- *
- * @param path Path to tokenize. Must not be <code>null</code>.
- *
- * @return a String array of path elements from the tokenized path
- */
- public static String[] tokenizePathAsArray(String path) {
- if (log.isTraceEnabled()) {
- log.trace(sm.getString("matcher.tokenize", path));
- }
- String root = null;
- if (isAbsolutePath(path)) {
- String[] s = dissect(path);
- root = s[0];
- path = s[1];
- }
- char sep = File.separatorChar;
- int start = 0;
- int len = path.length();
- int count = 0;
- for (int pos = 0; pos < len; pos++) {
- if (path.charAt(pos) == sep) {
- if (pos != start) {
- count++;
- }
- start = pos + 1;
- }
- }
- if (len != start) {
- count++;
- }
- String[] l = new String[count + ((root == null) ? 0 : 1)];
-
- if (root != null) {
- l[0] = root;
- count = 1;
- } else {
- count = 0;
- }
- start = 0;
- for (int pos = 0; pos < len; pos++) {
- if (path.charAt(pos) == sep) {
- if (pos != start) {
- String tok = path.substring(start, pos);
- l[count++] = tok;
- }
- start = pos + 1;
- }
- }
- if (len != start) {
- String tok = path.substring(start);
- l[count/*++*/] = tok;
- }
- return l;
- }
-
- /**
- * Dissect the specified absolute path.
- * @param path the path to dissect (must be absolute).
- * @return String[] {root, remaining path}.
- * @throws java.lang.NullPointerException if path is null.
- */
- private static String[] dissect(String path) {
- char sep = File.separatorChar;
- path = path.replace('/', sep).replace('\\', sep);
-
- String root = null;
- int colon = path.indexOf(':');
- if (colon > 0 && (ON_DOS || ON_NETWARE)) {
-
- int next = colon + 1;
- root = path.substring(0, next);
- char[] ca = path.toCharArray();
- root += sep;
- //remove the initial separator; the root has it.
- next = (ca[next] == sep) ? next + 1 : next;
-
- StringBuilder sbPath = new StringBuilder();
- // Eliminate consecutive slashes after the drive spec:
- for (int i = next; i < ca.length; i++) {
- if (ca[i] != sep || ca[i - 1] != sep) {
- sbPath.append(ca[i]);
- }
- }
- path = sbPath.toString();
- } else if (path.length() > 1 && path.charAt(1) == sep) {
- // UNC drive
- int nextsep = path.indexOf(sep, 2);
- nextsep = path.indexOf(sep, nextsep + 1);
- root = (nextsep > 2) ? path.substring(0, nextsep + 1) : path;
- path = path.substring(root.length());
- } else {
- root = File.separator;
- path = path.substring(1);
- }
- return new String[] {root, path};
- }
-
- /**
- * Verifies that the specified filename represents an absolute path.
- * Differs from new java.io.File("filename").isAbsolute() in that a path
- * beginning with a double file separator--signifying a Windows UNC--must
- * at minimum match "\\a\b" to be considered an absolute path.
- * @param filename the filename to be checked.
- * @return true if the filename represents an absolute path.
- * @throws java.lang.NullPointerException if filename is null.
- */
- private static boolean isAbsolutePath(String filename) {
- int len = filename.length();
- if (len == 0) {
- return false;
- }
- char sep = File.separatorChar;
- filename = filename.replace('/', sep).replace('\\', sep);
- char c = filename.charAt(0);
- if (!(ON_DOS || ON_NETWARE)) {
- return (c == sep);
- }
- if (c == sep) {
- // CheckStyle:MagicNumber OFF
- if (!(ON_DOS && len > 4 && filename.charAt(1) == sep)) {
- return false;
- }
- // CheckStyle:MagicNumber ON
- int nextsep = filename.indexOf(sep, 2);
- return nextsep > 2 && nextsep + 1 < len;
- }
- int colon = filename.indexOf(':');
- return (Character.isLetter(c) && colon == 1
- && filename.length() > 2 && filename.charAt(2) == sep)
- || (ON_NETWARE && colon > 0);
- }
-
- /**
- * Determines if our OS is Netware.
- *
- * @return true if we run on Netware
- */
- private static boolean isNetware() {
- return OS_NAME.indexOf("netware") > -1;
- }
-
- /**
- * Determines if our OS is DOS.
- *
- * @return true if we run on DOS
- */
- private static boolean isDos() {
- return PATH_SEP.equals(";") && !isNetware();
- }
}
Modified: tomcat/trunk/java/org/apache/tomcat/util/scan/StandardJarScanFilter.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/scan/StandardJarScanFilter.java?rev=1585713&r1=1585712&r2=1585713&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/scan/StandardJarScanFilter.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/scan/StandardJarScanFilter.java Tue Apr 8 12:55:54 2014
@@ -34,19 +34,19 @@ public class StandardJarScanFilter imple
private String defaultSkip;
private String defaultScan;
- private Set<String[]> defaultSkipSet = new HashSet<>();
- private Set<String[]> defaultScanSet = new HashSet<>();
+ private Set<String> defaultSkipSet = new HashSet<>();
+ private Set<String> defaultScanSet = new HashSet<>();
private String tldSkip;
private String tldScan;
- private Set<String[]> tldSkipSet = new HashSet<>();
- private Set<String[]> tldScanSet = new HashSet<>();
+ private Set<String> tldSkipSet = new HashSet<>();
+ private Set<String> tldScanSet = new HashSet<>();
private boolean defaultTldScan = true;
private String pluggabilitySkip;
private String pluggabilityScan;
- private Set<String[]> pluggabilitySkipSet = new HashSet<>();
- private Set<String[]> pluggabilityScanSet = new HashSet<>();
+ private Set<String> pluggabilitySkipSet = new HashSet<>();
+ private Set<String> pluggabilityScanSet = new HashSet<>();
private boolean defaultPluggabilityScan = true;
/**
@@ -186,8 +186,8 @@ public class StandardJarScanFilter imple
@Override
public boolean check(JarScanType jarScanType, String jarName) {
boolean defaultScan;
- Set<String[]> toSkip = new HashSet<>();
- Set<String[]> toScan = new HashSet<>();
+ Set<String> toSkip = new HashSet<>();
+ Set<String> toScan = new HashSet<>();
Lock readLock = configurationLock.readLock();
readLock.lock();
@@ -217,8 +217,8 @@ public class StandardJarScanFilter imple
}
if (defaultScan) {
- if (Matcher.matchPath(toSkip, jarName)) {
- if (Matcher.matchPath(toScan, jarName)) {
+ if (Matcher.matchName(toSkip, jarName)) {
+ if (Matcher.matchName(toScan, jarName)) {
return true;
} else {
return false;
@@ -226,8 +226,8 @@ public class StandardJarScanFilter imple
}
return true;
} else {
- if (Matcher.matchPath(toScan, jarName)) {
- if (Matcher.matchPath(toSkip, jarName)) {
+ if (Matcher.matchName(toScan, jarName)) {
+ if (Matcher.matchName(toSkip, jarName)) {
return false;
} else {
return true;
@@ -237,13 +237,15 @@ public class StandardJarScanFilter imple
}
}
- private void populateSetFromAttribute(String attribute, Set<String[]> set) {
+ private void populateSetFromAttribute(String attribute, Set<String> set) {
set.clear();
if (attribute != null) {
StringTokenizer tokenizer = new StringTokenizer(attribute, ",");
while (tokenizer.hasMoreElements()) {
String token = tokenizer.nextToken().trim();
- set.add(Matcher.tokenizePathAsArray(token));
+ if (token.length() > 0) {
+ set.add(token);
+ }
}
}
}
Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1585713&r1=1585712&r2=1585713&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Tue Apr 8 12:55:54 2014
@@ -79,6 +79,10 @@
<code>session.invalidate()</code> from the session destroyed event for
that session. (markt)
</fix>
+ <scode>
+ <bug>56365</bug>: Simplify filename pattern matching code in
+ <scode>StandardJarScanner</scode>. (kkolinko)
+ </scode>
</changelog>
</subsection>
<subsection name="Coyote">
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org