KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * FindBugs - Find Bugs in Java programs
3  * Copyright (C) 2003-2006, 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.io.BufferedOutputStream JavaDoc;
23 import java.io.BufferedReader JavaDoc;
24 import java.io.File JavaDoc;
25 import java.io.FileOutputStream JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStreamReader JavaDoc;
28 import java.io.PrintStream JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.Set JavaDoc;
31 import java.util.StringTokenizer JavaDoc;
32
33 import edu.umd.cs.findbugs.annotations.SuppressWarnings;
34 import edu.umd.cs.findbugs.config.UserPreferences;
35 import edu.umd.cs.findbugs.filter.FilterException;
36
37 /**
38  * Helper class to parse the command line and configure
39  * the IFindBugsEngine object.
40  * As a side-effect it also configures a DetectorFactoryCollection
41  * (to enable and disable detectors as requested).
42  */

43 public class TextUICommandLine extends FindBugsCommandLine {
44     /**
45      * Handling callback for choose() method,
46      * used to implement the -chooseVisitors and -choosePlugins options.
47      */

48     private interface Chooser {
49         /**
50          * Choose a detector, plugin, etc.
51          *
52          * @param enable whether or not the item should be enabled
53          * @param what the item
54          */

55         public void choose(boolean enable, String JavaDoc what);
56     }
57
58     private static final int PRINTING_REPORTER = 0;
59     private static final int SORTING_REPORTER = 1;
60     private static final int XML_REPORTER = 2;
61     private static final int EMACS_REPORTER = 3;
62     private static final int HTML_REPORTER = 4;
63     private static final int XDOCS_REPORTER = 5;
64
65     private int bugReporterType = PRINTING_REPORTER;
66     private boolean relaxedReportingMode = false;
67     private boolean useLongBugCodes = false;
68     private boolean xmlWithMessages = false;
69     private String JavaDoc stylesheet = null;
70     private boolean quiet = false;
71     private ClassScreener classScreener = new ClassScreener();
72     private String JavaDoc includeFilterFile = null;
73     private String JavaDoc excludeFilterFile = null;
74     private boolean setExitCode = false;
75     private int priorityThreshold = Detector.NORMAL_PRIORITY;
76     private PrintStream JavaDoc outputStream = null;
77     private Set JavaDoc<String JavaDoc> bugCategorySet = null;
78     private UserPreferences userPreferences;
79     private String JavaDoc trainingOutputDir;
80     private String JavaDoc trainingInputDir;
81     private String JavaDoc releaseName = "";
82     private String JavaDoc sourceInfoFile = null;
83     private boolean xargs = false;
84     private boolean scanNestedArchives = false;
85
86     /**
87      * Constructor.
88      */

89     public TextUICommandLine() {
90         
91         addSwitch("-showPlugins", "show list of available plugins");
92         addSwitch("-timestampNow", "set timestamp of results to be current time");
93
94         addSwitch("-quiet", "suppress error messages");
95         addSwitch("-longBugCodes", "report long bug codes");
96         addOption("-release", "release name", "set the release name of the analyzed application");
97         addSwitch("-experimental", "report all warnings including experimental bug patterns");
98         addSwitch("-low", "report all warnings");
99         addSwitch("-medium", "report only medium and high priority warnings [default]");
100         addSwitch("-high", "report only high priority warnings");
101         addSwitch("-sortByClass", "sort warnings by class");
102         addSwitchWithOptionalExtraPart("-xml", "withMessages",
103                 "XML output (optionally with messages)");
104         addSwitch("-xdocs", "xdoc XML output to use with Apache Maven");
105         addSwitchWithOptionalExtraPart("-html", "stylesheet",
106                 "Generate HTML output (default stylesheet is default.xsl)");
107         addSwitch("-emacs", "Use emacs reporting format");
108         addSwitch("-relaxed", "Relaxed reporting mode (more false positives!)");
109         addSwitchWithOptionalExtraPart("-train", "outputDir",
110                 "Save training data (experimental); output dir defaults to '.'");
111         addSwitchWithOptionalExtraPart("-useTraining", "inputDir",
112                 "Use training data (experimental); input dir defaults to '.'");
113         addOption("-sourceInfo", "filename",
114                 "Specify source info file (line numbers for fields/classes)");
115         addOption("-outputFile", "filename", "Save output in named file");
116         addOption("-visitors", "v1[,v2...]", "run only named visitors");
117         addOption("-omitVisitors", "v1[,v2...]", "omit named visitors");
118         addOption("-chooseVisitors", "+v1,-v2,...", "selectively enable/disable detectors");
119         addOption("-choosePlugins", "+p1,-p2,...", "selectively enable/disable plugins");
120         addOption("-adjustPriority", "v1=(raise|lower)[,...]",
121                 "raise/lower priority of warnings for given visitor(s)");
122         addOption("-bugCategories", "cat1[,cat2...]", "only report bugs in given categories");
123         addOption("-onlyAnalyze", "classes/packages", "only analyze given classes and packages");
124         addOption("-exclude", "filter file", "exclude bugs matching given filter");
125         addOption("-include", "filter file", "include only bugs matching given filter");
126         addSwitchWithOptionalExtraPart("-nested", "true|false",
127                 "analyze nested jar/zip archives (default=true)");
128         addOption("-auxclasspath", "classpath", "set aux classpath for analysis");
129         addOption("-sourcepath", "source path", "set source path for analyzed classes");
130         addSwitch("-exitcode", "set exit code of process");
131         addSwitch("-xargs", "get list of classfiles/jarfiles from standard input rather than command line");
132     }
133
134     @Override JavaDoc
135     public Project getProject() {
136         return project;
137     }
138     public boolean getXargs() {
139         return xargs;
140     }
141     public boolean setExitCode() {
142         return setExitCode;
143     }
144
145     public boolean quiet() {
146         return quiet;
147     }
148
149     @SuppressWarnings JavaDoc("DM_EXIT")
150     @Override JavaDoc
151     protected void handleOption(String JavaDoc option, String JavaDoc optionExtraPart) {
152         if (option.equals("-showPlugins")) {
153             System.out.println("Available plugins:");
154             int count = 0;
155             for (Iterator JavaDoc<Plugin> i = DetectorFactoryCollection.instance().pluginIterator(); i.hasNext(); ) {
156                 Plugin plugin = i.next();
157                 System.out.println(" " + plugin.getPluginId() + " (default: " +
158                         (plugin.isEnabled() ? "enabled" : "disabled") + ")");
159                 if (plugin.getShortDescription() != null)
160                     System.out.println(" Description: " + plugin.getShortDescription());
161                 if (plugin.getProvider() != null)
162                     System.out.println(" Provider: " + plugin.getProvider());
163                 if (plugin.getWebsite() != null)
164                     System.out.println(" Website: " + plugin.getWebsite());
165                 ++count;
166             }
167             if (count == 0) {
168                 System.out.println(" No plugins are available (FindBugs installed incorrectly?)");
169             }
170             System.exit(0);
171         } else if (option.equals("-experimental"))
172             priorityThreshold = Detector.EXP_PRIORITY;
173         else if (option.equals("-longBugCodes"))
174             useLongBugCodes = true;
175         else if (option.equals("-timestampNow"))
176             project.setTimestamp(System.currentTimeMillis());
177         else if (option.equals("-low"))
178             priorityThreshold = Detector.LOW_PRIORITY;
179         else if (option.equals("-medium"))
180             priorityThreshold = Detector.NORMAL_PRIORITY;
181         else if (option.equals("-high"))
182             priorityThreshold = Detector.HIGH_PRIORITY;
183         else if (option.equals("-sortByClass"))
184             bugReporterType = SORTING_REPORTER;
185         else if (option.equals("-xml")) {
186             bugReporterType = XML_REPORTER;
187             if (!optionExtraPart.equals("")) {
188                 if (optionExtraPart.equals("withMessages"))
189                     xmlWithMessages = true;
190                 else
191                     throw new IllegalArgumentException JavaDoc("Unknown option: -xml:" + optionExtraPart);
192             }
193         } else if (option.equals("-emacs")) {
194             bugReporterType = EMACS_REPORTER;
195         } else if (option.equals("-relaxed")) {
196             relaxedReportingMode = true;
197         } else if (option.equals("-train")) {
198             trainingOutputDir = !optionExtraPart.equals("") ? optionExtraPart : ".";
199         } else if (option.equals("-useTraining")) {
200             trainingInputDir = !optionExtraPart.equals("") ? optionExtraPart : ".";
201         } else if (option.equals("-html")) {
202             bugReporterType = HTML_REPORTER;
203             if (!optionExtraPart.equals("")) {
204                 stylesheet = optionExtraPart;
205             } else {
206                 stylesheet = "default.xsl";
207             }
208         } else if (option.equals("-xdocs")) {
209             bugReporterType = XDOCS_REPORTER;
210         } else if (option.equals("-quiet")) {
211             quiet = true;
212         } else if (option.equals("-nested")) {
213             scanNestedArchives =
214                 optionExtraPart.equals("") || Boolean.valueOf(optionExtraPart).booleanValue();
215         } else if (option.equals("-exitcode")) {
216             setExitCode = true;
217         } else if (option.equals("-xargs"))
218             xargs = true;
219         else {
220             super.handleOption(option, optionExtraPart);
221         }
222     }
223
224     @SuppressWarnings JavaDoc("DM_EXIT")
225     @Override JavaDoc
226     protected void handleOptionWithArgument(String JavaDoc option, String JavaDoc argument) throws IOException JavaDoc {
227         if (option.equals("-outputFile")) {
228             String JavaDoc outputFile = argument;
229
230             try {
231                 outputStream = new PrintStream JavaDoc(new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(outputFile)));
232             } catch (IOException JavaDoc e) {
233                 System.err.println("Couldn't open " + outputFile + " for output: " + e.toString());
234                 System.exit(1);
235             }
236         } else if (option.equals("-release")) {
237             this.releaseName = argument;
238         } else if (option.equals("-sourceInfo")) {
239             sourceInfoFile = argument;
240         } else if (option.equals("-visitors") || option.equals("-omitVisitors")) {
241             boolean omit = option.equals("-omitVisitors");
242
243             if (!omit) {
244                 // Selecting detectors explicitly, so start out by
245
// disabling all of them. The selected ones will
246
// be re-enabled.
247
getUserPreferences().enableAllDetectors(false);
248             }
249
250             // Explicitly enable or disable the selected detectors.
251
StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(argument, ",");
252             while (tok.hasMoreTokens()) {
253                 String JavaDoc visitorName = tok.nextToken();
254                 DetectorFactory factory = DetectorFactoryCollection.instance().getFactory(visitorName);
255                 if (factory == null)
256                     throw new IllegalArgumentException JavaDoc("Unknown detector: " + visitorName);
257                 getUserPreferences().enableDetector(factory, !omit);
258             }
259         } else if (option.equals("-chooseVisitors")) {
260             // This is like -visitors and -omitVisitors, but
261
// you can selectively enable and disable detectors,
262
// starting from the default set (or whatever set
263
// happens to be in effect).
264
choose(argument, "Detector choices", new Chooser() {
265                 public void choose(boolean enabled, String JavaDoc what) {
266                     DetectorFactory factory = DetectorFactoryCollection.instance().getFactory(what);
267                     if (factory == null)
268                         throw new IllegalArgumentException JavaDoc("Unknown detector: " + what);
269                     if (FindBugs.DEBUG) {
270                         System.err.println("Detector " + factory.getShortName() + " " +
271                                 (enabled ? "enabled" : "disabled") +
272                                 ", userPreferences="+System.identityHashCode(getUserPreferences()));
273                     }
274                     getUserPreferences().enableDetector(factory, enabled);
275                 }
276             });
277         } else if (option.equals("-choosePlugins")) {
278             // Selectively enable/disable plugins
279
choose(argument, "Plugin choices", new Chooser() {
280                 public void choose(boolean enabled, String JavaDoc what) {
281                     Plugin plugin = DetectorFactoryCollection.instance().getPluginById(what);
282                     if (plugin == null)
283                         throw new IllegalArgumentException JavaDoc("Unknown plugin: " + what);
284                     plugin.setEnabled(enabled);
285                 }
286             });
287         } else if (option.equals("-adjustPriority")) {
288             // Selectively raise or lower the priority of warnings
289
// produced by specified detectors.
290

291             StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(argument, ",");
292             while (tok.hasMoreTokens()) {
293                 String JavaDoc token = tok.nextToken();
294                 int eq = token.indexOf('=');
295                 if (eq < 0)
296                     throw new IllegalArgumentException JavaDoc("Illegal priority adjustment: " + token);
297
298                 String JavaDoc visitorName = token.substring(0, eq);
299
300                 DetectorFactory factory = DetectorFactoryCollection.instance().getFactory(visitorName);
301                 if (factory == null)
302                     throw new IllegalArgumentException JavaDoc("Unknown detector: " + visitorName);
303
304                 String JavaDoc adjustment = token.substring(eq + 1);
305                 if (!(adjustment.equals("raise") || adjustment.equals("lower")))
306                     throw new IllegalArgumentException JavaDoc("Illegal priority adjustment value: " +
307                             adjustment);
308
309                 // Recall that lower values are higher priorities
310
factory.setPriorityAdjustment(adjustment.equals("raise") ? -1 : +1);
311             }
312         } else if (option.equals("-bugCategories")) {
313             this.bugCategorySet = FindBugs.handleBugCategories(getUserPreferences(), argument);
314         } else if (option.equals("-onlyAnalyze")) {
315             // The argument is a comma-separated list of classes and packages
316
// to select to analyze. (If a list item ends with ".*",
317
// it specifies a package, otherwise it's a class.)
318
StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(argument, ",");
319             while (tok.hasMoreTokens()) {
320                 String JavaDoc item = tok.nextToken();
321                 if (item.endsWith(".-"))
322                     classScreener.addAllowedPrefix(item.substring(0, item.length() - 1));
323                 else if (item.endsWith(".*"))
324                     classScreener.addAllowedPackage(item.substring(0, item.length() - 1));
325                 else
326                     classScreener.addAllowedClass(item);
327             }
328         } else if (option.equals("-exclude")) {
329             if (excludeFilterFile != null)
330                 throw new IllegalArgumentException JavaDoc("Can specify one exclude filter file");
331             excludeFilterFile = argument;
332         } else if (option.equals("-include")) {
333             if (includeFilterFile != null)
334                 throw new IllegalArgumentException JavaDoc("Can specify one include filter file");
335             includeFilterFile = argument;
336         } else if (option.equals("-auxclasspath")) {
337             StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(argument, File.pathSeparator);
338             while (tok.hasMoreTokens())
339                 project.addAuxClasspathEntry(tok.nextToken());
340         } else if (option.equals("-sourcepath")) {
341             StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(argument, File.pathSeparator);
342             while (tok.hasMoreTokens())
343                 project.addSourceDir(new File JavaDoc(tok.nextToken()).getAbsolutePath());
344         } else {
345             super.handleOptionWithArgument(option, argument);
346         }
347     }
348
349     /**
350      * Common handling code for -chooseVisitors and -choosePlugins options.
351      *
352      * @param argument the list of visitors or plugins to be chosen
353      * @param desc String describing what is being chosen
354      * @param chooser callback object to selectively choose list members
355      */

356     private void choose(String JavaDoc argument, String JavaDoc desc, Chooser chooser) {
357         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(argument, ",");
358         while (tok.hasMoreTokens()) {
359             String JavaDoc what = tok.nextToken();
360             if (!what.startsWith("+") && !what.startsWith("-"))
361                 throw new IllegalArgumentException JavaDoc(desc + " must start with " +
362                         "\"+\" or \"-\" (saw " + what + ")");
363             boolean enabled = what.startsWith("+");
364             chooser.choose(enabled, what.substring(1));
365         }
366     }
367
368     public void configureEngine(IFindBugsEngine findBugs) throws IOException JavaDoc, FilterException {
369         // Load plugins
370
DetectorFactoryCollection.instance().ensureLoaded();
371         
372         // Set the DetectorFactoryCollection (that has been configured
373
// by command line parsing)
374
findBugs.setDetectorFactoryCollection(DetectorFactoryCollection.instance());
375         
376         TextUIBugReporter textuiBugReporter;
377         switch (bugReporterType) {
378         case PRINTING_REPORTER:
379             textuiBugReporter = new PrintingBugReporter();
380             break;
381         case SORTING_REPORTER:
382             textuiBugReporter = new SortingBugReporter();
383             break;
384         case XML_REPORTER:
385             {
386                 XMLBugReporter xmlBugReporter = new XMLBugReporter(project);
387                 xmlBugReporter.setAddMessages(xmlWithMessages);
388                 textuiBugReporter = xmlBugReporter;
389             }
390             break;
391         case EMACS_REPORTER:
392             textuiBugReporter = new EmacsBugReporter();
393             break;
394         case HTML_REPORTER:
395             textuiBugReporter = new HTMLBugReporter(project, stylesheet);
396             break;
397         case XDOCS_REPORTER:
398             textuiBugReporter = new XDocsBugReporter(project);
399             break;
400         default:
401             throw new IllegalStateException JavaDoc();
402         }
403
404         if (quiet)
405             textuiBugReporter.setErrorVerbosity(BugReporter.SILENT);
406
407         textuiBugReporter.setPriorityThreshold(priorityThreshold);
408         textuiBugReporter.setUseLongBugCodes(useLongBugCodes);
409
410         if (outputStream != null)
411             textuiBugReporter.setOutputStream(outputStream);
412
413         BugReporter bugReporter = textuiBugReporter;
414
415         if (bugCategorySet != null) {
416             bugReporter = new CategoryFilteringBugReporter(bugReporter, bugCategorySet);
417         }
418
419         findBugs.setBugReporter(bugReporter);
420         findBugs.setProject(project);
421
422         findBugs.setUserPreferences(getUserPreferences());
423
424         if (includeFilterFile != null)
425             findBugs.addFilter(includeFilterFile, true);
426         if (excludeFilterFile != null)
427             findBugs.addFilter(excludeFilterFile, false);
428
429         findBugs.setClassScreener(classScreener);
430
431         findBugs.setRelaxedReportingMode(relaxedReportingMode);
432
433         if (trainingOutputDir != null) {
434             findBugs.enableTrainingOutput(trainingOutputDir);
435         }
436         if (trainingInputDir != null) {
437             findBugs.enableTrainingInput(trainingInputDir);
438         }
439
440         if (sourceInfoFile != null) {
441             findBugs.setSourceInfoFile(sourceInfoFile);
442         }
443
444         findBugs.setAnalysisFeatureSettings(settingList);
445
446         findBugs.setReleaseName(releaseName);
447         
448         findBugs.setScanNestedArchives(scanNestedArchives);
449     }
450
451     /**
452      * Handle -xargs command line option by reading
453      * jar file names from standard input and adding them
454      * to the project.
455      *
456      * @throws IOException
457      */

458     public void handleXArgs() throws IOException JavaDoc {
459         if (getXargs()) {
460             BufferedReader JavaDoc in = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(System.in));
461             while (true) {
462                 String JavaDoc s = in.readLine();
463                 if (s == null) break;
464                 project.addFile(s);
465             }
466         }
467     }
468
469     /**
470      * @param userPreferences The userPreferences to set.
471      */

472     private void setUserPreferences(UserPreferences userPreferences) {
473         this.userPreferences = userPreferences;
474     }
475
476     /**
477      * @return Returns the userPreferences.
478      */

479     private UserPreferences getUserPreferences() {
480         if (userPreferences == null)
481             userPreferences = UserPreferences.createDefaultUserPreferences();
482         return userPreferences;
483     }
484 }
485
Popular Tags