KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * FindBugs - Find Bugs in Java programs
3  * Copyright (C) 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.FileInputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.util.Arrays JavaDoc;
25 import java.util.Collection JavaDoc;
26 import java.util.HashSet JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.LinkedList JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Set JavaDoc;
31 import java.util.TreeSet JavaDoc;
32
33 import org.apache.bcel.classfile.ClassFormatException;
34
35 import edu.umd.cs.findbugs.ba.AnalysisCacheToAnalysisContextAdapter;
36 import edu.umd.cs.findbugs.ba.AnalysisContext;
37 import edu.umd.cs.findbugs.ba.AnalysisException;
38 import edu.umd.cs.findbugs.ba.SourceInfoMap;
39 import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
40 import edu.umd.cs.findbugs.classfile.ClassDescriptor;
41 import edu.umd.cs.findbugs.classfile.Global;
42 import edu.umd.cs.findbugs.classfile.IAnalysisCache;
43 import edu.umd.cs.findbugs.classfile.IClassFactory;
44 import edu.umd.cs.findbugs.classfile.IClassObserver;
45 import edu.umd.cs.findbugs.classfile.IClassPath;
46 import edu.umd.cs.findbugs.classfile.IClassPathBuilder;
47 import edu.umd.cs.findbugs.classfile.ICodeBase;
48 import edu.umd.cs.findbugs.classfile.MissingClassException;
49 import edu.umd.cs.findbugs.classfile.ResourceNotFoundException;
50 import edu.umd.cs.findbugs.classfile.analysis.ClassInfo;
51 import edu.umd.cs.findbugs.classfile.impl.ClassFactory;
52 import edu.umd.cs.findbugs.config.AnalysisFeatureSetting;
53 import edu.umd.cs.findbugs.config.UserPreferences;
54 import edu.umd.cs.findbugs.filter.FilterException;
55 import edu.umd.cs.findbugs.plan.AnalysisPass;
56 import edu.umd.cs.findbugs.plan.ExecutionPlan;
57 import edu.umd.cs.findbugs.plan.OrderingConstraintException;
58 import edu.umd.cs.findbugs.util.ClassName;
59
60 /**
61  * FindBugs driver class.
62  * Experimental version to use the new bytecode-framework-neutral
63  * codebase/classpath/classfile infrastructure.
64  * Supports all features of the original FindBugs driver.
65  *
66  * @author David Hovemeyer
67  */

68 public class FindBugs2 implements IFindBugsEngine {
69     private static final boolean VERBOSE = SystemProperties.getBoolean("findbugs.verbose");
70     private static final boolean DEBUG = VERBOSE || SystemProperties.getBoolean("findbugs.debug");
71     
72     private List JavaDoc<IClassObserver> classObserverList;
73     private ErrorCountingBugReporter bugReporter;
74     private Project project;
75     private IClassFactory classFactory;
76     private IClassPath classPath;
77     private IAnalysisCache analysisCache;
78     private List JavaDoc<ClassDescriptor> appClassList;
79     private Set JavaDoc<ClassDescriptor> referencedClassSet;
80     private DetectorFactoryCollection detectorFactoryCollection;
81     private ExecutionPlan executionPlan;
82     private UserPreferences userPreferences;
83     private String JavaDoc currentClassName;
84     private String JavaDoc releaseName;
85     private String JavaDoc sourceInfoFileName;
86     private AnalysisFeatureSetting[] analysisFeatureSettingList;
87     private boolean relaxedReportingMode;
88     private String JavaDoc trainingInputDir;
89     private String JavaDoc trainingOutputDir;
90     private FindBugsProgress progress;
91     private IClassScreener classScreener;
92     private boolean scanNestedArchives;
93     
94     /**
95      * Constructor.
96      */

97     public FindBugs2() {
98         this.classObserverList = new LinkedList JavaDoc<IClassObserver>();
99         this.analysisFeatureSettingList = FindBugs.DEFAULT_EFFORT;
100         this.progress = new NoOpFindBugsProgress();
101         
102         // By default, do not exclude any classes via the class screener
103
this.classScreener = new IClassScreener() {
104             /* (non-Javadoc)
105              * @see edu.umd.cs.findbugs.IClassScreener#matches(java.lang.String)
106              */

107             public boolean matches(String JavaDoc fileName) {
108                 return true;
109             }
110         };
111         
112         // By default, we do want to scan nested archives
113
this.scanNestedArchives = false;
114     }
115     
116     /**
117      * Set the detector factory collection to be used by this
118      * FindBugs2 engine. This method should be called before
119      * the execute() method is called.
120      *
121      * @param detectorFactoryCollection The detectorFactoryCollection to set.
122      */

123     public void setDetectorFactoryCollection(
124             DetectorFactoryCollection detectorFactoryCollection) {
125         this.detectorFactoryCollection = detectorFactoryCollection;
126     }
127
128     /**
129      * Execute the analysis.
130      * For obscure reasons, CheckedAnalysisExceptions are re-thrown
131      * as IOExceptions. However, these can only happen during the
132      * setup phase where we scan codebases for classes.
133      *
134      * @throws IOException
135      * @throws InterruptedException
136      */

137     public void execute() throws IOException JavaDoc, InterruptedException JavaDoc {
138         // Get the class factory for creating classpath/codebase/etc.
139
classFactory = ClassFactory.instance();
140         
141         // The class path object
142
createClassPath();
143         
144         // The analysis cache object
145
createAnalysisCache();
146         
147         progress.reportNumberOfArchives(project.getFileCount());
148         
149         try {
150             // Discover all codebases in classpath and
151
// enumerate all classes (application and non-application)
152
buildClassPath();
153             
154             // Build set of classes referenced by application classes
155
buildReferencedClassSet();
156             
157             // Create BCEL compatibility layer
158
createAnalysisContext();
159             
160             // Configure the BugCollection (if we are generating one)
161
FindBugs.configureBugCollection(this);
162
163             // Enable/disabled relaxed reporting mode
164
FindBugsAnalysisFeatures.setRelaxedMode(relaxedReportingMode);
165             
166             // Configure training databases
167
FindBugs.configureTrainingDatabases(this);
168             
169             // Configure analysis features
170
configureAnalysisFeatures();
171             
172             // Create the execution plan (which passes/detectors to execute)
173
createExecutionPlan();
174             
175             // Analyze the application
176
analyzeApplication();
177         } catch (CheckedAnalysisException e) {
178             IOException JavaDoc ioe = new IOException JavaDoc("IOException while scanning codebases");
179             ioe.initCause(e);
180             throw ioe;
181         } finally {
182             // Make sure the codebases on the classpath are closed
183
classPath.close();
184         }
185     }
186     
187     /* (non-Javadoc)
188      * @see edu.umd.cs.findbugs.IFindBugsEngine#getBugReporter()
189      */

190     public BugReporter getBugReporter() {
191         return bugReporter;
192     }
193     
194     /* (non-Javadoc)
195      * @see edu.umd.cs.findbugs.IFindBugsEngine#getProject()
196      */

197     public Project getProject() {
198         return project;
199     }
200
201     /* (non-Javadoc)
202      * @see edu.umd.cs.findbugs.IFindBugsEngine#addClassObserver(edu.umd.cs.findbugs.classfile.IClassObserver)
203      */

204     public void addClassObserver(IClassObserver classObserver) {
205         classObserverList.add(classObserver);
206     }
207     
208     /* (non-Javadoc)
209      * @see edu.umd.cs.findbugs.IFindBugsEngine#addFilter(java.lang.String, boolean)
210      */

211     public void addFilter(String JavaDoc filterFileName, boolean include) throws IOException JavaDoc, FilterException {
212         FindBugs.configureFilter(bugReporter, filterFileName, include);
213     }
214     
215     /* (non-Javadoc)
216      * @see edu.umd.cs.findbugs.IFindBugsEngine#enableTrainingInput(java.lang.String)
217      */

218     public void enableTrainingInput(String JavaDoc trainingInputDir) {
219         this.trainingInputDir = trainingInputDir;
220     }
221     
222     /* (non-Javadoc)
223      * @see edu.umd.cs.findbugs.IFindBugsEngine#enableTrainingOutput(java.lang.String)
224      */

225     public void enableTrainingOutput(String JavaDoc trainingOutputDir) {
226         this.trainingOutputDir = trainingOutputDir;
227     }
228     
229     /* (non-Javadoc)
230      * @see edu.umd.cs.findbugs.IFindBugsEngine#getBugCount()
231      */

232     public int getBugCount() {
233         return bugReporter.getBugCount();
234     }
235     
236     /* (non-Javadoc)
237      * @see edu.umd.cs.findbugs.IFindBugsEngine#getCurrentClass()
238      */

239     public String JavaDoc getCurrentClass() {
240         return currentClassName;
241     }
242     
243     /* (non-Javadoc)
244      * @see edu.umd.cs.findbugs.IFindBugsEngine#getErrorCount()
245      */

246     public int getErrorCount() {
247         return bugReporter.getErrorCount();
248     }
249     
250     /* (non-Javadoc)
251      * @see edu.umd.cs.findbugs.IFindBugsEngine#getMissingClassCount()
252      */

253     public int getMissingClassCount() {
254         return bugReporter.getMissingClassCount();
255     }
256     
257     /* (non-Javadoc)
258      * @see edu.umd.cs.findbugs.IFindBugsEngine#getReleaseName()
259      */

260     public String JavaDoc getReleaseName() {
261         return releaseName;
262     }
263     
264     /* (non-Javadoc)
265      * @see edu.umd.cs.findbugs.IFindBugsEngine#setAnalysisFeatureSettings(edu.umd.cs.findbugs.config.AnalysisFeatureSetting[])
266      */

267     public void setAnalysisFeatureSettings(AnalysisFeatureSetting[] settingList) {
268         this.analysisFeatureSettingList = settingList;
269     }
270     
271     /* (non-Javadoc)
272      * @see edu.umd.cs.findbugs.IFindBugsEngine#setBugReporter(edu.umd.cs.findbugs.BugReporter)
273      */

274     public void setBugReporter(BugReporter bugReporter) {
275         this.bugReporter = new ErrorCountingBugReporter(bugReporter);
276         addClassObserver(bugReporter);
277     }
278     
279     /* (non-Javadoc)
280      * @see edu.umd.cs.findbugs.IFindBugsEngine#setClassScreener(edu.umd.cs.findbugs.ClassScreener)
281      */

282     public void setClassScreener(IClassScreener classScreener) {
283         this.classScreener = classScreener;
284     }
285     
286     /* (non-Javadoc)
287      * @see edu.umd.cs.findbugs.IFindBugsEngine#setProgressCallback(edu.umd.cs.findbugs.FindBugsProgress)
288      */

289     public void setProgressCallback(FindBugsProgress progressCallback) {
290         this.progress = progressCallback;
291     }
292     
293     /* (non-Javadoc)
294      * @see edu.umd.cs.findbugs.IFindBugsEngine#setProject(edu.umd.cs.findbugs.Project)
295      */

296     public void setProject(Project project) {
297         this.project = project;
298     }
299     
300     /* (non-Javadoc)
301      * @see edu.umd.cs.findbugs.IFindBugsEngine#setRelaxedReportingMode(boolean)
302      */

303     public void setRelaxedReportingMode(boolean relaxedReportingMode) {
304         this.relaxedReportingMode = relaxedReportingMode;
305     }
306     
307     /* (non-Javadoc)
308      * @see edu.umd.cs.findbugs.IFindBugsEngine#setReleaseName(java.lang.String)
309      */

310     public void setReleaseName(String JavaDoc releaseName) {
311         this.releaseName = releaseName;
312     }
313     
314     /* (non-Javadoc)
315      * @see edu.umd.cs.findbugs.IFindBugsEngine#setSourceInfoFile(java.lang.String)
316      */

317     public void setSourceInfoFile(String JavaDoc sourceInfoFile) {
318         this.sourceInfoFileName = sourceInfoFile;
319     }
320     
321     /* (non-Javadoc)
322      * @see edu.umd.cs.findbugs.IFindBugsEngine#setUserPreferences(edu.umd.cs.findbugs.config.UserPreferences)
323      */

324     public void setUserPreferences(UserPreferences userPreferences) {
325         this.userPreferences = userPreferences;
326     }
327     
328     /* (non-Javadoc)
329      * @see edu.umd.cs.findbugs.IFindBugsEngine#emitTrainingOutput()
330      */

331     public boolean emitTrainingOutput() {
332         return trainingOutputDir != null;
333     }
334     
335     /* (non-Javadoc)
336      * @see edu.umd.cs.findbugs.IFindBugsEngine#getUserPreferences()
337      */

338     public UserPreferences getUserPreferences() {
339         return userPreferences;
340     }
341
342     /**
343      * Create the classpath object.
344      */

345     private void createClassPath() {
346         classPath = classFactory.createClassPath();
347     }
348     
349     /* (non-Javadoc)
350      * @see edu.umd.cs.findbugs.IFindBugsEngine#getTrainingInputDir()
351      */

352     public String JavaDoc getTrainingInputDir() {
353         return trainingInputDir;
354     }
355     
356     /* (non-Javadoc)
357      * @see edu.umd.cs.findbugs.IFindBugsEngine#getTrainingOutputDir()
358      */

359     public String JavaDoc getTrainingOutputDir() {
360         return trainingOutputDir;
361     }
362     
363     /* (non-Javadoc)
364      * @see edu.umd.cs.findbugs.IFindBugsEngine#useTrainingInput()
365      */

366     public boolean useTrainingInput() {
367         return trainingInputDir != null;
368     }
369     
370     /* (non-Javadoc)
371      * @see edu.umd.cs.findbugs.IFindBugsEngine#setScanNestedArchives(boolean)
372      */

373     public void setScanNestedArchives(boolean scanNestedArchives) {
374         this.scanNestedArchives = scanNestedArchives;
375     }
376
377     /**
378      * Create the analysis cache object.
379      */

380     private void createAnalysisCache() {
381         analysisCache = ClassFactory.instance().createAnalysisCache(classPath, bugReporter);
382         
383         // TODO: this would be a good place to load "analysis plugins" which could
384
// add additional analysis engines. Or, perhaps when we load
385
// detector plugins we should check for analysis engines.
386
// Either way, allowing plugins to add new analyses would be nice.
387
new edu.umd.cs.findbugs.classfile.engine.EngineRegistrar().registerAnalysisEngines(analysisCache);
388         new edu.umd.cs.findbugs.classfile.engine.asm.EngineRegistrar().registerAnalysisEngines(analysisCache);
389         new edu.umd.cs.findbugs.classfile.engine.bcel.EngineRegistrar().registerAnalysisEngines(analysisCache);
390         
391         Global.setAnalysisCacheForCurrentThread(analysisCache);
392     }
393
394     /**
395      * Build the classpath from project codebases and system codebases.
396      *
397      * @throws InterruptedException if the analysis thread is interrupted
398      * @throws IOException if an I/O error occurs
399      * @throws ResourceNotFoundException
400      */

401     private void buildClassPath() throws InterruptedException JavaDoc, IOException JavaDoc, CheckedAnalysisException {
402         IClassPathBuilder builder = classFactory.createClassPathBuilder(bugReporter);
403         
404         for (String JavaDoc path : project.getFileArray()) {
405             builder.addCodeBase(classFactory.createFilesystemCodeBaseLocator(path), true);
406         }
407         for (String JavaDoc path : project.getAuxClasspathEntryList()) {
408             builder.addCodeBase(classFactory.createFilesystemCodeBaseLocator(path), false);
409         }
410         
411         builder.scanNestedArchives(scanNestedArchives);
412         
413         builder.build(classPath, progress);
414         
415         appClassList = builder.getAppClassList();
416         
417         // If any of the application codebases contain source code,
418
// add them to the source path.
419
// Also, use the last modified time of application codebases
420
// to set the project timestamp.
421
for (Iterator JavaDoc<? extends ICodeBase> i = classPath.appCodeBaseIterator(); i.hasNext(); ){
422             ICodeBase appCodeBase = i.next();
423             
424             if (appCodeBase.containsSourceFiles()) {
425                 String JavaDoc pathName = appCodeBase.getPathName();
426                 if (pathName != null) {
427                     project.addSourceDir(pathName);
428                 }
429             }
430             
431             project.addTimestamp(appCodeBase.getLastModifiedTime());
432         }
433         
434     }
435     
436     private void buildReferencedClassSet() throws CheckedAnalysisException, InterruptedException JavaDoc {
437         // XXX: should drive progress dialog (scanning phase)?
438

439         referencedClassSet = new TreeSet JavaDoc<ClassDescriptor>();
440         
441         LinkedList JavaDoc<ClassDescriptor> workList = new LinkedList JavaDoc<ClassDescriptor>();
442         workList.addAll(appClassList);
443
444         Set JavaDoc<ClassDescriptor> seen = new HashSet JavaDoc<ClassDescriptor>();
445         Set JavaDoc<ClassDescriptor> appClassSet = new HashSet JavaDoc<ClassDescriptor>(appClassList);
446         
447         Set JavaDoc<ClassDescriptor> badAppClassSet = new HashSet JavaDoc<ClassDescriptor>();
448         
449         while (!workList.isEmpty()) {
450             if (Thread.interrupted())
451                 throw new InterruptedException JavaDoc();
452             ClassDescriptor classDesc = workList.removeFirst();
453             
454             if (seen.contains(classDesc)) {
455                 continue;
456             }
457             seen.add(classDesc);
458             
459             referencedClassSet.add(classDesc);
460             
461             // Get list of referenced classes and add them to set.
462
// Add superclasses and superinterfaces to worklist.
463
try {
464                 ClassInfo classInfo = Global.getAnalysisCache().getClassAnalysis(ClassInfo.class, classDesc);
465                 referencedClassSet.addAll(Arrays.asList(classInfo.getReferencedClassDescriptorList()));
466                 
467                 if (classInfo.getSuperclassDescriptor() != null) {
468                     workList.addLast(classInfo.getSuperclassDescriptor());
469                 }
470                 
471                 for (ClassDescriptor ifaceDesc : classInfo.getInterfaceDescriptorList()) {
472                     workList.addLast(ifaceDesc);
473                 }
474             } catch (MissingClassException e) {
475                 // Just log it as a missing class
476
bugReporter.reportMissingClass(e.getClassDescriptor());
477                 if (appClassSet.contains(classDesc)) {
478                     badAppClassSet.add(classDesc);
479                 }
480             } catch (CheckedAnalysisException e) {
481                 // Failed to scan a referenced class --- just log the error and continue
482
bugReporter.logError("Error scanning " + classDesc + " for referenced classes", e);
483                 if (appClassSet.contains(classDesc)) {
484                     badAppClassSet.add(classDesc);
485                 }
486             }
487         }
488         
489         // Delete any application classes that could not be read
490
appClassList.removeAll(badAppClassSet);
491     }
492     
493     /**
494      * Create the AnalysisContext that will serve as the BCEL-compatibility
495      * layer over the AnalysisCache.
496      */

497     private void createAnalysisContext() throws CheckedAnalysisException, IOException JavaDoc {
498         AnalysisCacheToAnalysisContextAdapter analysisContext =
499             new AnalysisCacheToAnalysisContextAdapter();
500         
501         // Make the AnalysisCache the backing store for
502
// the BCEL Repository
503
analysisContext.clearRepository();
504
505         // Specify which classes are application classes
506
analysisContext.setAppClassList(appClassList);
507         
508         // If needed, load SourceInfoMap
509
if (sourceInfoFileName != null) {
510             SourceInfoMap sourceInfoMap = analysisContext.getSourceInfoMap();
511             sourceInfoMap.read(new FileInputStream JavaDoc(sourceInfoFileName));
512         }
513
514         // Make this the current analysis context
515
AnalysisContext.setCurrentAnalysisContext(analysisContext);
516     }
517     
518     /**
519      * Configure analysis feature settings.
520      */

521     private void configureAnalysisFeatures() {
522         for (AnalysisFeatureSetting setting : analysisFeatureSettingList) {
523             setting.configure(AnalysisContext.currentAnalysisContext());
524         }
525     }
526
527     /**
528      * Create an execution plan.
529      *
530      * @throws OrderingConstraintException if the detector ordering constraints are inconsistent
531      */

532     private void createExecutionPlan() throws OrderingConstraintException {
533         executionPlan = new ExecutionPlan();
534         
535         // Use user preferences to decide which detectors are enabled.
536
DetectorFactoryChooser detectorFactoryChooser = new DetectorFactoryChooser() {
537             /* (non-Javadoc)
538              * @see edu.umd.cs.findbugs.DetectorFactoryChooser#choose(edu.umd.cs.findbugs.DetectorFactory)
539              */

540             public boolean choose(DetectorFactory factory) {
541                 return FindBugs.isDetectorEnabled(FindBugs2.this, factory);
542             }
543         };
544         executionPlan.setDetectorFactoryChooser(detectorFactoryChooser);
545         
546         // Add plugins
547
for (Iterator JavaDoc<Plugin> i = detectorFactoryCollection.pluginIterator(); i.hasNext(); ) {
548             Plugin plugin = i.next();
549             if (DEBUG) {
550                 System.out.println("Adding plugin " + plugin.getPluginId() + " to execution plan");
551             }
552             executionPlan.addPlugin(plugin);
553         }
554         
555         // Build the execution plan
556
executionPlan.build();
557         
558         if (DEBUG) {
559             System.out.println(executionPlan.getNumPasses() + " passes in execution plan");
560         }
561     }
562
563     /**
564      * Analyze the classes in the application codebase.
565      */

566     private void analyzeApplication() throws InterruptedException JavaDoc {
567         int passCount = 0;
568         boolean multiplePasses = executionPlan.getNumPasses() > 1;
569         int [] classesPerPass = new int[executionPlan.getNumPasses()];
570         classesPerPass[0] = referencedClassSet .size();
571         for(int i = 0; i < classesPerPass.length; i++)
572             classesPerPass[i] = i == 0 ? referencedClassSet.size() : appClassList.size();
573         progress.predictPassCount(classesPerPass);
574         for (Iterator JavaDoc<AnalysisPass> i = executionPlan.passIterator(); i.hasNext(); ) {
575             AnalysisPass pass = i.next();
576
577             // Instantiate the detectors
578
Detector2[] detectorList = pass.instantiateDetector2sInPass(bugReporter);
579
580             // If there are multiple passes, then on the first pass,
581
// we apply detectors to all classes referenced by the application classes.
582
// On subsequent passes, we apply detector only to application classes.
583
Collection JavaDoc<ClassDescriptor> classCollection = (multiplePasses && passCount == 0)
584                     ? referencedClassSet
585                     : appClassList;
586             if (DEBUG) {
587                 System.out.println("Pass " + (passCount) + ": " + classCollection.size() + " classes");
588             }
589             
590             progress.startAnalysis(classCollection.size());
591             
592             for (ClassDescriptor classDescriptor : classCollection) {
593                 if (DEBUG) {
594                     System.out.println("Class " + classDescriptor);
595                 }
596                 
597                 if (!classScreener.matches(classDescriptor.toResourceName())) {
598                     if (DEBUG) {
599                         System.out.println("*** Excluded by class screener");
600                     }
601                     continue;
602                 }
603                 
604                 currentClassName = ClassName.toDottedClassName(classDescriptor.getClassName());
605                 notifyClassObservers(classDescriptor);
606                 
607                 for (Detector2 detector : detectorList) {
608                     if (Thread.interrupted())
609                         throw new InterruptedException JavaDoc();
610                     if (DEBUG) {
611                         System.out.println("Applying " + detector.getDetectorClassName() + " to " + classDescriptor);
612                     }
613                     try {
614                         detector.visitClass(classDescriptor);
615                     } catch (ClassFormatException e) {
616                         logRecoverableException(classDescriptor, detector, e);
617                     } catch (MissingClassException e) {
618                         Global.getAnalysisCache().getErrorLogger().reportMissingClass(e.getClassDescriptor());
619                     } catch (CheckedAnalysisException e) {
620                         logRecoverableException(classDescriptor, detector, e);
621                     } catch (AnalysisException e) {
622                         logRecoverableException(classDescriptor, detector, e);
623                     } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
624                         logRecoverableException(classDescriptor, detector, e);
625                     } catch (ClassCastException JavaDoc e) {
626                         logRecoverableException(classDescriptor, detector, e);
627                     }
628                 }
629                 
630                 progress.finishClass();
631             }
632             
633             // Call finishPass on each detector
634
for (Detector2 detector : detectorList) {
635                 detector.finishPass();
636             }
637             
638             AnalysisContext.currentAnalysisContext().updateDatabases(passCount);
639             progress.finishPerClassAnalysis();
640             
641             passCount++;
642         }
643
644         // Flush any queued bug reports
645
bugReporter.finish();
646
647         // Flush any queued error reports
648
bugReporter.reportQueuedErrors();
649     }
650
651     /**
652      * Notify all IClassObservers that we are visiting given class.
653      *
654      * @param classDescriptor the class being visited
655      */

656     private void notifyClassObservers(ClassDescriptor classDescriptor) {
657         for (IClassObserver observer : classObserverList) {
658             observer.observeClass(classDescriptor);
659         }
660     }
661
662     /**
663      * Report an exception that occurred while analyzing a class
664      * with a detector.
665      *
666      * @param classDescriptor class being analyzed
667      * @param detector detector doing the analysis
668      * @param e the exception
669      */

670     private void logRecoverableException(
671             ClassDescriptor classDescriptor, Detector2 detector, Throwable JavaDoc e) {
672         bugReporter.logError("Exception analyzing " + classDescriptor.toDottedClassName() +
673                 " using detector " + detector.getDetectorClassName(), e);
674     }
675
676     public static void main(String JavaDoc[] args) throws Exception JavaDoc {
677         // Create FindBugs2 engine
678
FindBugs2 findBugs = new FindBugs2();
679         
680         // Parse command line and configure the engine
681
TextUICommandLine commandLine = new TextUICommandLine();
682         FindBugs.processCommandLine(commandLine, args, findBugs);
683         
684         // Away we go!
685
FindBugs.runMain(findBugs, commandLine);
686     }
687 }
688
Popular Tags