KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > ClassScreener


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 2004, University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19
20 package edu.umd.cs.findbugs;
21
22 import java.util.LinkedList JavaDoc;
23 import java.util.regex.Matcher JavaDoc;
24 import java.util.regex.Pattern JavaDoc;
25
26 import static edu.umd.cs.findbugs.util.Strings.replace;
27
28 /**
29  * Class to pre-screen class files, so that only a subset are
30  * analyzed. This supports the -onlyAnalyze command line option.
31  *
32  * Modified February 2006 in four ways:
33  * a) don't break windows platform by hard-coding '/' as the directory separator
34  * b) store list of Matchers, not Patterns, so we don't keep instantiating Matchers
35  * c) fix suffix bug, so FooBar and Foo$Bar no longer match Bar
36  * d) addAllowedPackage() can now handle unicode chars in filenames, though we
37  * still may not be handling every case mentioned in section 7.2.1 of the JLS
38  *
39  * @see FindBugs
40  * @author David Hovemeyer
41  */

42 public class ClassScreener implements IClassScreener {
43     private static final boolean DEBUG = SystemProperties.getBoolean("findbugs.classscreener.debug");
44     
45     /** regular expression fragment to match a directory separator. note: could use
46      * File.separatorChar instead, but that could be argued to be not general enough */

47     private static final String JavaDoc SEP = "[/\\\\]"; // could include ':' for classic macOS
48
private static final String JavaDoc START = "(?:^|"+SEP+")"; // (?:) is a non-capturing group
49

50     /** regular expression fragment to match a char of a class or package name.
51      * Actually, we just allow any char except a dot or a directory separator. */

52     private static final String JavaDoc JAVA_IDENTIFIER_PART = "[^./\\\\]";
53
54     private LinkedList JavaDoc<Matcher JavaDoc> patternList;
55
56     /**
57      * Constructor.
58      * By default, the ClassScreener will match <em>all</em> class files.
59      * Once addAllowedClass() and addAllowedPackage() are called,
60      * the ClassScreener will only match the explicitly specified classes
61      * and packages.
62      */

63     public ClassScreener() {
64         this.patternList = new LinkedList JavaDoc<Matcher JavaDoc>();
65     }
66
67     /** replace the dots in a fully-qualified class/package name to a
68      * regular expression fragment that will match file names.
69      * @param dotsName such as "java.io" or "java.io.File"
70      * @return regex fragment such as "java[/\\\\]io" (single backslash escaped twice)
71      */

72     private static String JavaDoc dotsToRegex(String JavaDoc dotsName) {
73         /* oops, next line requires JDK 1.5
74         return dotsName.replace("$", "\\$").replace(".", SEP);
75          * could use String.replaceAll(regex, repl) but that can be problematic--javadoc says
76          * "Note that backslashes (\) and dollar signs ($) in the replacement string may cause
77          * the results to be different than if it were being treated as a literal replacement" */

78         return replace(replace(dotsName, "$", "\\$"), ".", SEP);
79         // note: The original code used the \Q and \E regex quoting constructs to escape $.
80
}
81     
82     /**
83      * Add the name of a class to be matched by the screener.
84      *
85      * @param className name of a class to be matched
86      */

87     public void addAllowedClass(String JavaDoc className) {
88         String JavaDoc classRegex = START+dotsToRegex(className)+".class$";
89         if (DEBUG) System.out.println("Class regex: " + classRegex);
90         patternList.add(Pattern.compile(classRegex).matcher(""));
91     }
92
93     /**
94      * Add the name of a package to be matched by the screener.
95      * All class files that appear to be in the package should be matched.
96      *
97      * @param packageName name of the package to be matched
98      */

99     public void addAllowedPackage(String JavaDoc packageName) {
100         if (packageName.endsWith(".")) {
101             packageName = packageName.substring(0, packageName.length() - 1);
102         }
103         
104         String JavaDoc packageRegex = START+dotsToRegex(packageName)+SEP+JAVA_IDENTIFIER_PART+"+.class$";
105         if (DEBUG) System.out.println("Package regex: " + packageRegex);
106         patternList.add(Pattern.compile(packageRegex).matcher(""));
107     }
108
109     /**
110      * Add the name of a prefix to be matched by the screener.
111      * All class files that appear to be in the package specified
112      * by the prefix, or a more deeply nested package, should be matched.
113      *
114      * @param prefix name of the prefix to be matched
115      */

116     public void addAllowedPrefix(String JavaDoc prefix) {
117         if (prefix.endsWith(".")) {
118             prefix = prefix.substring(0, prefix.length()-1);
119         }
120         if (DEBUG) System.out.println("Allowed prefix: " + prefix);
121         String JavaDoc packageRegex = START+dotsToRegex(prefix)+SEP;
122         if (DEBUG) System.out.println("Prefix regex: " + packageRegex);
123         patternList.add(Pattern.compile(packageRegex).matcher(""));
124     }
125
126     /* (non-Javadoc)
127      * @see edu.umd.cs.findbugs.IClassScreener#matches(java.lang.String)
128      */

129     public boolean matches(String JavaDoc fileName) {
130         // Special case: if no classes or packages have been defined,
131
// then the screener matches all class files.
132
if (patternList.isEmpty())
133             return true;
134
135         if (DEBUG) System.out.println("Matching: " + fileName);
136
137         // Scan through list of regexes
138
for (Matcher JavaDoc matcher : patternList) {
139             if (DEBUG) System.out.print("\tTrying [" + matcher.pattern());
140             matcher.reset(fileName);
141             if (matcher.find()) {
142                 if (DEBUG) System.out.println("]: yes!");
143                 return true;
144             }
145             if (DEBUG) System.out.println("]: no");
146         }
147         return false;
148     }
149 }
150
151 // vim:ts=4
152
Popular Tags