KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 2003-2005 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.lang.reflect.Constructor JavaDoc;
23 import java.lang.reflect.Method JavaDoc;
24 import java.util.Collection JavaDoc;
25 import java.util.LinkedList JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.StringTokenizer JavaDoc;
28
29 import edu.umd.cs.findbugs.ba.AnalysisContext;
30
31 /**
32  * A DetectorFactory is responsible for creating instances of Detector objects
33  * and for maintaining meta-information about the detector class.
34  *
35  * @author David Hovemeyer
36  * @see Detector
37  */

38 public class DetectorFactory {
39     private static final boolean DEBUG_JAVA_VERSION = SystemProperties.getBoolean("findbugs.debug.javaversion");
40
41     private static final Class JavaDoc[] constructorArgTypes = new Class JavaDoc[]{BugReporter.class};
42
43     static class ReflectionDetectorCreator {
44         private Class JavaDoc<?> detectorClass;
45         private Method JavaDoc setAnalysisContext;
46         
47         ReflectionDetectorCreator(Class JavaDoc<?> detectorClass) {
48             this.detectorClass = detectorClass;
49
50             try {
51                 setAnalysisContext = detectorClass.getDeclaredMethod(
52                         "setAnalysisContext", new Class JavaDoc[]{AnalysisContext.class});
53             } catch (NoSuchMethodException JavaDoc e) {
54                 // Ignore
55
}
56         }
57         
58         public Detector createDetector(BugReporter bugReporter) {
59             try {
60                 Constructor JavaDoc<?> constructor =
61                     detectorClass.getConstructor(constructorArgTypes);
62                 Detector detector = (Detector) constructor.newInstance(new Object JavaDoc[]{bugReporter});
63                 if (setAnalysisContext != null) {
64                     setAnalysisContext.invoke(
65                             detector,
66                             new Object JavaDoc[]{AnalysisContext.currentAnalysisContext()});
67                 }
68                 return detector;
69             } catch (Exception JavaDoc e) {
70                 throw new RuntimeException JavaDoc("Could not instantiate " + detectorClass.getName() +
71                         " as Detector", e);
72             }
73         }
74         
75         public Detector2 createDetector2(BugReporter bugReporter) {
76             if (Detector2.class.isAssignableFrom(detectorClass)) {
77                 try {
78                     Constructor JavaDoc<?> constructor =
79                         detectorClass.getConstructor(constructorArgTypes);
80                     return (Detector2) constructor.newInstance(new Object JavaDoc[]{bugReporter});
81                 } catch (Exception JavaDoc e) {
82                     throw new RuntimeException JavaDoc("Could not instantiate " + detectorClass.getName() +
83                             " as Detector2", e);
84                 }
85             }
86             
87             if (Detector.class.isAssignableFrom(detectorClass)) {
88                 DetectorToDetector2Adapter adapter = new DetectorToDetector2Adapter(
89                         createDetector(bugReporter));
90                 return adapter;
91             }
92             
93             throw new RuntimeException JavaDoc("Class " + detectorClass.getName() + " is not a detector class");
94         }
95         
96         public Class JavaDoc<?> getDetectorClass() {
97             return detectorClass;
98         }
99     }
100     
101     private Plugin plugin;
102     private final ReflectionDetectorCreator detectorCreator;
103     private int positionSpecifiedInPluginDescriptor;
104     private boolean defEnabled;
105     private final String JavaDoc speed;
106     private final String JavaDoc reports;
107     private final String JavaDoc requireJRE;
108     private String JavaDoc detailHTML;
109     private int priorityAdjustment;
110     private boolean hidden;
111
112     /**
113      * Constructor.
114      *
115      * @param plugin the Plugin the Detector is part of
116      * @param detectorClass the Class object of the Detector
117      * @param enabled true if the Detector is enabled by default, false if disabled
118      * @param speed a string describing roughly how expensive the analysis performed
119      * by the detector is; suggested values are "fast", "moderate", and "slow"
120      * @param reports comma separated list of bug pattern codes reported
121      * by the detector; empty if unknown
122      * @param requireJRE string describing JRE version required to run the
123      * the detector: e.g., "1.5"
124      */

125     public DetectorFactory(Plugin plugin,
126                            Class JavaDoc<?> detectorClass, boolean enabled, String JavaDoc speed, String JavaDoc reports,
127                            String JavaDoc requireJRE) {
128         this.plugin = plugin;
129         this.detectorCreator = new ReflectionDetectorCreator(detectorClass);
130         this.defEnabled = enabled;
131         this.speed = speed;
132         this.reports = reports;
133         this.requireJRE = requireJRE;
134         this.priorityAdjustment = 0;
135         this.hidden = false;
136     }
137 //
138
// /**
139
// * Constructor.
140
// *
141
// * @param plugin the Plugin the detector is part of
142
// * @param detectorCreator the IDetectorCreator that will create instances of this detector
143
// * @param enabled true if the detector is enabled by default, false otherwise
144
// * @param speed speed: "fast", "moderate", or "slow"
145
// * @param reports comma separated list of bug pattern codes reported
146
// * by the detector; empty if unknown
147
// * @param requireJRE string describing JRE version required to run the
148
// * the detector: e.g., "1.5"
149
// */
150
// public DetectorFactory(Plugin plugin,
151
// IDetectorCreator detectorCreator,
152
// boolean enabled ,
153
// String speed,
154
// String reports,
155
// String requireJRE) {
156
// this.plugin = plugin;
157
// this.detectorCreator = detectorCreator;
158
// this.defEnabled = enabled;
159
// this.speed = speed;
160
// this.reports = reports;
161
// this.requireJRE = requireJRE;
162
// this.priorityAdjustment = 0;
163
// this.hidden = false;
164
// }
165

166     /**
167      * Set the overall position in which this detector was specified
168      * in the plugin descriptor.
169      *
170      * @param positionSpecifiedInPluginDescriptor position in plugin descriptor
171      */

172     public void setPositionSpecifiedInPluginDescriptor(
173             int positionSpecifiedInPluginDescriptor) {
174         this.positionSpecifiedInPluginDescriptor = positionSpecifiedInPluginDescriptor;
175     }
176     
177     /**
178      * Get the overall position in which this detector was specified
179      * in the plugin descriptor.
180      *
181      * @return position in plugin descriptor
182      */

183     public int getPositionSpecifiedInPluginDescriptor() {
184         return positionSpecifiedInPluginDescriptor;
185     }
186     
187     /**
188      * Get the Plugin that this Detector is part of.
189      *
190      * @return the Plugin this Detector is part of
191      */

192     public Plugin getPlugin() {
193         return plugin;
194     }
195     
196     /**
197      * Determine whether the detector class is a subtype of the given class (or interface).
198      *
199      * @param otherClass a class or interface
200      * @return true if the detector class is a subtype of the given class or interface
201      */

202     public boolean isDetectorClassSubtypeOf(Class JavaDoc<?> otherClass) {
203         return otherClass.isAssignableFrom(detectorCreator.getDetectorClass());
204     }
205     
206     /**
207      * Return whether or not this DetectorFactory produces detectors
208      * which report warnings.
209      *
210      * @return true if the created Detectors report warnings, false if not
211      */

212     public boolean isReportingDetector() {
213         return !isDetectorClassSubtypeOf(TrainingDetector.class)
214             && !isDetectorClassSubtypeOf(NonReportingDetector.class);
215
216     }
217     
218     /**
219      * Check to see if we are running on a recent-enough JRE for
220      * this detector to be enabled.
221      *
222      * @return true if the current JRE is recent enough to run the Detector,
223      * false if it is too old
224      */

225     public boolean isEnabledForCurrentJRE() {
226         if (requireJRE.equals(""))
227             return true;
228         try {
229             JavaVersion requiredVersion = new JavaVersion(requireJRE);
230             JavaVersion runtimeVersion = JavaVersion.getRuntimeVersion();
231
232             if (DEBUG_JAVA_VERSION) {
233                 System.out.println(
234                         "Checking JRE version for " + getShortName() +
235                         " (requires " + requiredVersion +
236                         ", running on " + runtimeVersion + ")");
237             }
238
239             
240             boolean enabledForCurrentJRE = runtimeVersion.isSameOrNewerThan(requiredVersion);
241             if (DEBUG_JAVA_VERSION) {
242                 System.out.println("\t==> " + enabledForCurrentJRE);
243             }
244             return enabledForCurrentJRE;
245         } catch (JavaVersionException e) {
246             if (DEBUG_JAVA_VERSION) {
247                 System.out.println("Couldn't check Java version: " + e.toString());
248                 e.printStackTrace(System.out);
249             }
250             return false;
251         }
252     }
253
254     /**
255      * Set visibility of the factory (to GUI dialogs to configure detectors).
256      * Invisible detectors are those that are needed behind the scenes,
257      * but shouldn't be explicitly enabled or disabled by the user.
258      *
259      * @param hidden true if this factory should be hidden, false if not
260      */

261     public void setHidden(boolean hidden) {
262         this.hidden = hidden;
263     }
264
265     /**
266      * Get visibility of the factory (to GUI dialogs to configure detectors).
267      */

268     public boolean isHidden() {
269         return hidden;
270     }
271
272     /**
273      * Is this factory enabled by default
274      */

275     public boolean isDefaultEnabled() {
276         return defEnabled;
277     }
278     
279     /**
280      * Set the priority adjustment for the detector produced by this factory.
281      *
282      * @param priorityAdjustment the priority adjustment
283      */

284     public void setPriorityAdjustment(int priorityAdjustment) {
285         this.priorityAdjustment = priorityAdjustment;
286     }
287     
288     /**
289      * Get the priority adjustment for the detector produced by this factory.
290      *
291      * @return the priority adjustment
292      */

293     public int getPriorityAdjustment() {
294         return priorityAdjustment;
295     }
296
297     /**
298      * Get the speed of the Detector produced by this factory.
299      */

300     public String JavaDoc getSpeed() {
301         return speed;
302     }
303
304     /**
305      * Get list of bug pattern codes reported by the detector: blank if unknown.
306      */

307     public String JavaDoc getReportedBugPatternCodes() {
308         return reports;
309     }
310
311     /**
312      * Get Collection of all BugPatterns this detector reports.
313      * An empty Collection means that we don't know what kind of
314      * bug patterns might be reported.
315      */

316     public Collection JavaDoc<BugPattern> getReportedBugPatterns() {
317         List JavaDoc<BugPattern> result = new LinkedList JavaDoc<BugPattern>();
318         StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(reports, ",");
319         while (tok.hasMoreTokens()) {
320             String JavaDoc type = tok.nextToken();
321             BugPattern bugPattern = I18N.instance().lookupBugPattern(type);
322             if (bugPattern != null)
323                 result.add(bugPattern);
324         }
325         return result;
326     }
327
328     /**
329      * Get an HTML document describing the Detector.
330      */

331     public String JavaDoc getDetailHTML() {
332         return detailHTML;
333     }
334
335     /**
336      * Set the HTML document describing the Detector.
337      */

338     public void setDetailHTML(String JavaDoc detailHTML) {
339         this.detailHTML = detailHTML;
340     }
341     
342     /**
343      * Create a Detector instance.
344      * This method is only guaranteed to work for
345      * old-style detectors using the BCEL bytecode framework.
346      *
347      * @param bugReporter the BugReporter to be used to report bugs
348      * @return the Detector
349      * @deprecated Use createDetector2 in new code
350      */

351     public Detector create(BugReporter bugReporter) {
352         return detectorCreator.createDetector(bugReporter);
353     }
354
355     /**
356      * Create a Detector2 instance.
357      *
358      * @param bugReporter the BugReporter to be used to report bugs
359      * @return the Detector2
360      */

361     public Detector2 createDetector2(BugReporter bugReporter) {
362         return detectorCreator.createDetector2(bugReporter);
363     }
364
365     /**
366      * Get the short name of the Detector.
367      * This is the name of the detector class without the package qualification.
368      */

369     public String JavaDoc getShortName() {
370         String JavaDoc className = detectorCreator.getDetectorClass().getName();
371         int endOfPkg = className.lastIndexOf('.');
372         if (endOfPkg >= 0)
373             className = className.substring(endOfPkg + 1);
374         return className;
375     }
376
377     /**
378      * Get the full name of the detector.
379      * This is the name of the detector class, with package qualification.
380      */

381     public String JavaDoc getFullName() {
382         return detectorCreator.getDetectorClass().getName();
383     }
384 }
385
386 // vim:ts=4
387
Popular Tags