1 19 20 package edu.umd.cs.findbugs; 21 22 import java.io.BufferedOutputStream ; 23 import java.io.BufferedReader ; 24 import java.io.File ; 25 import java.io.FileOutputStream ; 26 import java.io.IOException ; 27 import java.io.InputStreamReader ; 28 import java.io.PrintStream ; 29 import java.util.Iterator ; 30 import java.util.Set ; 31 import java.util.StringTokenizer ; 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 43 public class TextUICommandLine extends FindBugsCommandLine { 44 48 private interface Chooser { 49 55 public void choose(boolean enable, String 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 stylesheet = null; 70 private boolean quiet = false; 71 private ClassScreener classScreener = new ClassScreener(); 72 private String includeFilterFile = null; 73 private String excludeFilterFile = null; 74 private boolean setExitCode = false; 75 private int priorityThreshold = Detector.NORMAL_PRIORITY; 76 private PrintStream outputStream = null; 77 private Set <String > bugCategorySet = null; 78 private UserPreferences userPreferences; 79 private String trainingOutputDir; 80 private String trainingInputDir; 81 private String releaseName = ""; 82 private String sourceInfoFile = null; 83 private boolean xargs = false; 84 private boolean scanNestedArchives = false; 85 86 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 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 ("DM_EXIT") 150 @Override 151 protected void handleOption(String option, String optionExtraPart) { 152 if (option.equals("-showPlugins")) { 153 System.out.println("Available plugins:"); 154 int count = 0; 155 for (Iterator <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 ("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 ("DM_EXIT") 225 @Override 226 protected void handleOptionWithArgument(String option, String argument) throws IOException { 227 if (option.equals("-outputFile")) { 228 String outputFile = argument; 229 230 try { 231 outputStream = new PrintStream (new BufferedOutputStream (new FileOutputStream (outputFile))); 232 } catch (IOException 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 getUserPreferences().enableAllDetectors(false); 248 } 249 250 StringTokenizer tok = new StringTokenizer (argument, ","); 252 while (tok.hasMoreTokens()) { 253 String visitorName = tok.nextToken(); 254 DetectorFactory factory = DetectorFactoryCollection.instance().getFactory(visitorName); 255 if (factory == null) 256 throw new IllegalArgumentException ("Unknown detector: " + visitorName); 257 getUserPreferences().enableDetector(factory, !omit); 258 } 259 } else if (option.equals("-chooseVisitors")) { 260 choose(argument, "Detector choices", new Chooser() { 265 public void choose(boolean enabled, String what) { 266 DetectorFactory factory = DetectorFactoryCollection.instance().getFactory(what); 267 if (factory == null) 268 throw new IllegalArgumentException ("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 choose(argument, "Plugin choices", new Chooser() { 280 public void choose(boolean enabled, String what) { 281 Plugin plugin = DetectorFactoryCollection.instance().getPluginById(what); 282 if (plugin == null) 283 throw new IllegalArgumentException ("Unknown plugin: " + what); 284 plugin.setEnabled(enabled); 285 } 286 }); 287 } else if (option.equals("-adjustPriority")) { 288 291 StringTokenizer tok = new StringTokenizer (argument, ","); 292 while (tok.hasMoreTokens()) { 293 String token = tok.nextToken(); 294 int eq = token.indexOf('='); 295 if (eq < 0) 296 throw new IllegalArgumentException ("Illegal priority adjustment: " + token); 297 298 String visitorName = token.substring(0, eq); 299 300 DetectorFactory factory = DetectorFactoryCollection.instance().getFactory(visitorName); 301 if (factory == null) 302 throw new IllegalArgumentException ("Unknown detector: " + visitorName); 303 304 String adjustment = token.substring(eq + 1); 305 if (!(adjustment.equals("raise") || adjustment.equals("lower"))) 306 throw new IllegalArgumentException ("Illegal priority adjustment value: " + 307 adjustment); 308 309 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 StringTokenizer tok = new StringTokenizer (argument, ","); 319 while (tok.hasMoreTokens()) { 320 String 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 ("Can specify one exclude filter file"); 331 excludeFilterFile = argument; 332 } else if (option.equals("-include")) { 333 if (includeFilterFile != null) 334 throw new IllegalArgumentException ("Can specify one include filter file"); 335 includeFilterFile = argument; 336 } else if (option.equals("-auxclasspath")) { 337 StringTokenizer tok = new StringTokenizer (argument, File.pathSeparator); 338 while (tok.hasMoreTokens()) 339 project.addAuxClasspathEntry(tok.nextToken()); 340 } else if (option.equals("-sourcepath")) { 341 StringTokenizer tok = new StringTokenizer (argument, File.pathSeparator); 342 while (tok.hasMoreTokens()) 343 project.addSourceDir(new File (tok.nextToken()).getAbsolutePath()); 344 } else { 345 super.handleOptionWithArgument(option, argument); 346 } 347 } 348 349 356 private void choose(String argument, String desc, Chooser chooser) { 357 StringTokenizer tok = new StringTokenizer (argument, ","); 358 while (tok.hasMoreTokens()) { 359 String what = tok.nextToken(); 360 if (!what.startsWith("+") && !what.startsWith("-")) 361 throw new IllegalArgumentException (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 , FilterException { 369 DetectorFactoryCollection.instance().ensureLoaded(); 371 372 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 (); 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 458 public void handleXArgs() throws IOException { 459 if (getXargs()) { 460 BufferedReader in = new BufferedReader (new InputStreamReader (System.in)); 461 while (true) { 462 String s = in.readLine(); 463 if (s == null) break; 464 project.addFile(s); 465 } 466 } 467 } 468 469 472 private void setUserPreferences(UserPreferences userPreferences) { 473 this.userPreferences = userPreferences; 474 } 475 476 479 private UserPreferences getUserPreferences() { 480 if (userPreferences == null) 481 userPreferences = UserPreferences.createDefaultUserPreferences(); 482 return userPreferences; 483 } 484 } 485 | Popular Tags |