Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FIXED JENKINS-37218] Use String.startsWith() for simple patterns
  • Loading branch information
stephenc committed Aug 5, 2016
1 parent 62aad35 commit c2f1e5d
Showing 1 changed file with 38 additions and 12 deletions.
50 changes: 38 additions & 12 deletions src/main/java/hudson/remoting/ClassFilter.java
Expand Up @@ -83,10 +83,10 @@ public final Class check(Class c) {
*/
/*package*/ static ClassFilter createDefaultInstance() {
try {
List<Pattern> patternOverride = loadPatternOverride();
List<String> patternOverride = loadPatternOverride();
if (patternOverride != null) {
LOGGER.log(Level.FINE, "Using user specified overrides for class blacklisting");
return new RegExpClassFilter(patternOverride);
return new RegExpClassFilter(patternOverride.toArray(new String[patternOverride.size()]));
} else {
LOGGER.log(Level.FINE, "Using default in built class blacklisting");
return new RegExpClassFilter(DEFAULT_PATTERNS);
Expand All @@ -100,7 +100,7 @@ public final Class check(Class c) {
}

@CheckForNull
private static List<Pattern> loadPatternOverride() {
private static List<String> loadPatternOverride() {
String prop = System.getProperty(FILE_OVERRIDE_LOCATION_PROPERTY);
if (prop==null) {
return null;
Expand All @@ -115,10 +115,11 @@ private static List<Pattern> loadPatternOverride() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(prop), Charset.defaultCharset()));
ArrayList<Pattern> patterns = new ArrayList<Pattern>();
ArrayList<String> patterns = new ArrayList<String>();
for (String line = br.readLine(); line != null; line = br.readLine()) {
try {
patterns.add(Pattern.compile(line));
Pattern.compile(line);
patterns.add(line);
} catch (PatternSyntaxException pex) {
throw new Error("Error compiling blacklist expressions - '" + line + "' is not a valid regular expression.", pex);
}
Expand All @@ -142,23 +143,48 @@ private static List<Pattern> loadPatternOverride() {
*/
private static final class RegExpClassFilter extends ClassFilter {

private final List<Pattern> blacklistPatterns;
/**
* Any regex that is {@code ^some[.]package[.]name[.].*} or {@code ^some\.package\.name\.*} is really just a
* {@link String#startsWith(String)} test and we can reduce CPU usage by performing that test explicitly as
* well as reduce GC pressure.
*/
private static final Pattern OPTIMIZE1 = Pattern.compile(
"^\\^(([\\p{L}_$][\\p{L}\\p{N}_$]*(\\.|\\[\\.\\])?)+)\\.\\*$");

/**
* Any regex that is {@code ^\Qsome.package.name\E.*} is really just a {@link String#startsWith(String)}
* test and we can reduce CPU usage by performing that test explicitly as well as reduce GC pressure.
*/
private static final Pattern OPTIMIZE2 = Pattern.compile("^\\^\\Q[^\\\\]+\\\\E\\.\\*$");

private final Object[] blacklistPatterns;

public RegExpClassFilter(List<Pattern> blacklistPatterns) {
this.blacklistPatterns = blacklistPatterns;
this.blacklistPatterns = blacklistPatterns.toArray(new Pattern[blacklistPatterns.size()]);
}

RegExpClassFilter(String[] patterns) {
blacklistPatterns = new ArrayList<Pattern>(patterns.length);
for (String pattern : patterns) {
blacklistPatterns.add(Pattern.compile(pattern));
blacklistPatterns = new Object[patterns.length];
for (int i = 0, patternsLength = patterns.length; i < patternsLength; i++) {
if (OPTIMIZE1.matcher(patterns[i]).matches()) {
// this is a simple startsWith test, no need to slow things down with a regex
blacklistPatterns[i] = patterns[i].substring(1,patterns[i].length()-2).replace("[.]",".");
} else if (OPTIMIZE2.matcher(patterns[i]).matches()) {
// this is a simple startsWith test, no need to slow things down with a regex
blacklistPatterns[i] = patterns[i].substring(3,patterns[i].length()-4);
} else {
blacklistPatterns[i] = Pattern.compile(patterns[i]);
}
}
}

@Override
protected boolean isBlacklisted(String name) {
for (Pattern p : blacklistPatterns) {
if (p.matcher(name).matches()) {
for (int i = 0; i < blacklistPatterns.length; i++) {
Object p = blacklistPatterns[i];
if (p instanceof Pattern && ((Pattern)p).matcher(name).matches()) {
return true;
} else if (p instanceof String && name.startsWith((String)p)) {
return true;
}
}
Expand Down

0 comments on commit c2f1e5d

Please sign in to comment.