org.cuberact.storage.GlobMatcher Maven / Gradle / Ivy
package org.cuberact.storage;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
* Copied from {@link sun.nio.fs.Globs} and removed isDos flag
*/
final class GlobMatcher {
private final String glob;
private final Pattern pattern;
private static final String regexMetaChars = ".^$+{[]|()";
private static final String globMetaChars = "\\*?[{";
GlobMatcher(String glob) {
this.glob = glob;
boolean inGroup = false;
StringBuilder regex = new StringBuilder("^");
int i = 0;
while (i < glob.length()) {
char c = glob.charAt(i++);
switch (c) {
case '\\':
// escape special characters
if (i == glob.length()) {
throw new PatternSyntaxException("No character to escape", glob, i - 1);
}
char next = glob.charAt(i++);
if (isGlobMeta(next) || isRegexMeta(next)) {
regex.append('\\');
}
regex.append(next);
break;
case '/':
regex.append(c);
break;
case '[':
// don't match name separator in class
regex.append("[[^/]&&[");
if (next(glob, i) == '^') {
// escape the regex negation char if it appears
regex.append("\\^");
i++;
} else {
// negation
if (next(glob, i) == '!') {
regex.append('^');
i++;
}
// hyphen allowed at start
if (next(glob, i) == '-') {
regex.append('-');
i++;
}
}
boolean hasRangeStart = false;
char last = 0;
while (i < glob.length()) {
c = glob.charAt(i++);
if (c == ']') {
break;
}
if (c == '/') {
throw new PatternSyntaxException("Explicit 'name separator' in class",
glob, i - 1);
}
// TBD: how to specify ']' in a class?
if (c == '\\' || c == '[' || c == '&' && next(glob, i) == '&') {
// escape '\', '[' or "&&" for regex class
regex.append('\\');
}
regex.append(c);
if (c == '-') {
if (!hasRangeStart) {
throw new PatternSyntaxException("Invalid range",
glob, i - 1);
}
if ((c = next(glob, i++)) == 0 || c == ']') {
break;
}
if (c < last) {
throw new PatternSyntaxException("Invalid range",
glob, i - 3);
}
regex.append(c);
hasRangeStart = false;
} else {
hasRangeStart = true;
last = c;
}
}
if (c != ']') {
throw new PatternSyntaxException("Missing ']", glob, i - 1);
}
regex.append("]]");
break;
case '{':
if (inGroup) {
throw new PatternSyntaxException("Cannot nest groups",
glob, i - 1);
}
regex.append("(?:(?:");
inGroup = true;
break;
case '}':
if (inGroup) {
regex.append("))");
inGroup = false;
} else {
regex.append('}');
}
break;
case ',':
if (inGroup) {
regex.append(")|(?:");
} else {
regex.append(',');
}
break;
case '*':
if (next(glob, i) == '*') {
// crosses directory boundaries
regex.append(".*");
i++;
} else {
// within directory boundary
regex.append("[^/]*");
}
break;
case '?':
regex.append("[^/]");
break;
default:
if (isRegexMeta(c)) {
regex.append('\\');
}
regex.append(c);
}
}
if (inGroup) {
throw new PatternSyntaxException("Missing '}", glob, i - 1);
}
regex.append('$');
this.pattern = Pattern.compile(regex.toString(), Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
}
boolean matches(String path) {
return pattern.matcher(path).matches();
}
@Override
public String toString() {
return "glob: " + glob + "\nregex: " + pattern.toString();
}
private static boolean isRegexMeta(char c) {
return regexMetaChars.indexOf(c) != -1;
}
private static boolean isGlobMeta(char c) {
return globMetaChars.indexOf(c) != -1;
}
private static char next(String glob, int i) {
if (i < glob.length()) {
return glob.charAt(i);
}
return 0;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy