001: /*
002: * FindBugs - Find bugs in Java programs
003: * Copyright (C) 2003-2005 University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package edu.umd.cs.findbugs;
021:
022: import java.io.File;
023: import java.net.MalformedURLException;
024: import java.net.URL;
025: import java.security.AccessController;
026: import java.security.PrivilegedActionException;
027: import java.security.PrivilegedExceptionAction;
028: import java.util.ArrayList;
029: import java.util.HashMap;
030: import java.util.Iterator;
031:
032: /**
033: * The DetectorFactoryCollection stores all of the DetectorFactory objects
034: * used to create the Detectors which implement the various analyses.
035: * It is a singleton class.
036: *
037: * @author David Hovemeyer
038: * @see DetectorFactory
039: */
040: public class DetectorFactoryCollection {
041: private HashMap<String, Plugin> pluginByIdMap = new HashMap<String, Plugin>();
042: private ArrayList<DetectorFactory> factoryList = new ArrayList<DetectorFactory>();
043: private HashMap<String, DetectorFactory> factoriesByName = new HashMap<String, DetectorFactory>();
044: private HashMap<String, DetectorFactory> factoriesByDetectorClassName = new HashMap<String, DetectorFactory>();
045:
046: private static DetectorFactoryCollection theInstance;
047: private static final Object lock = new Object();
048: private boolean loaded = false;
049:
050: private URL[] pluginList;
051:
052: /**
053: * Constructor.
054: * loadPlugins() method must be called before
055: * any detector factories can be accessed.
056: */
057: DetectorFactoryCollection() {
058: }
059:
060: /**
061: * Set the list of plugins to load explicitly.
062: * This must be done before the instance of DetectorFactoryCollection
063: * is created.
064: *
065: * @param pluginList list of plugin Jar files to load
066: */
067: public void setPluginList(URL[] pluginList) {
068: if (loaded)
069: throw new IllegalStateException();
070: this .pluginList = new URL[pluginList.length];
071: System.arraycopy(pluginList, 0, this .pluginList, 0,
072: pluginList.length);
073: }
074:
075: /**
076: * Set the instance that should be retured as the singleton instance.
077: *
078: * @param instance the singleton instance to be set
079: */
080: static void setInstance(DetectorFactoryCollection instance) {
081: synchronized (lock) {
082: if (theInstance != null) {
083: throw new IllegalStateException();
084: }
085: theInstance = instance;
086: }
087: }
088:
089: static void resetInstance(DetectorFactoryCollection instance) {
090: synchronized (lock) {
091: theInstance = instance;
092: }
093: }
094:
095: /**
096: * Get the single instance of DetectorFactoryCollection.
097: */
098: public static DetectorFactoryCollection instance() {
099: synchronized (lock) {
100: if (theInstance == null) {
101: theInstance = new DetectorFactoryCollection();
102: }
103: theInstance.ensureLoaded();
104: return theInstance;
105: }
106: }
107:
108: /**
109: * Get the single instance of DetectorFactoryCollection.
110: */
111: public static DetectorFactoryCollection rawInstance() {
112: synchronized (lock) {
113: if (theInstance == null) {
114: theInstance = new DetectorFactoryCollection();
115: }
116: return theInstance;
117: }
118: }
119:
120: /**
121: * Return an Iterator over all available Plugin objects.
122: */
123: public Iterator<Plugin> pluginIterator() {
124: ensureLoaded();
125: return pluginByIdMap.values().iterator();
126: }
127:
128: /**
129: * Get a Plugin by its unique id.
130: *
131: * @param pluginId the unique id
132: * @return the Plugin with that id, or null if no such Plugin is found
133: */
134: public Plugin getPluginById(String pluginId) {
135: ensureLoaded();
136: return pluginByIdMap.get(pluginId);
137: }
138:
139: /**
140: * Return an Iterator over the DetectorFactory objects for all
141: * registered Detectors.
142: */
143: public Iterator<DetectorFactory> factoryIterator() {
144: ensureLoaded();
145: return factoryList.iterator();
146: }
147:
148: /**
149: * Look up a DetectorFactory by its short name.
150: *
151: * @param name the short name
152: * @return the DetectorFactory, or null if there is no factory with that short name
153: */
154: public DetectorFactory getFactory(String name) {
155: ensureLoaded();
156: return factoriesByName.get(name);
157: }
158:
159: /**
160: * Look up a DetectorFactory by its class name.
161: *
162: * @param className the class name
163: * @return the DetectoryFactory, or null if there is no factory with
164: * that class name
165: */
166: public DetectorFactory getFactoryByClassName(String className) {
167: ensureLoaded();
168: return factoriesByDetectorClassName.get(className);
169: }
170:
171: /**
172: * Register a DetectorFactory.
173: */
174: void registerDetector(DetectorFactory factory) {
175: if (FindBugs.DEBUG)
176: System.out.println("Registering detector: "
177: + factory.getFullName());
178: String detectorName = factory.getShortName();
179: factoryList.add(factory);
180: factoriesByName.put(detectorName, factory);
181: factoriesByDetectorClassName
182: .put(factory.getFullName(), factory);
183: }
184:
185: private void determinePlugins() {
186: if (pluginList != null)
187: return;
188: String homeDir = FindBugs.getHome();
189: if (homeDir == null) {
190: System.err
191: .println("Error: FindBugs home directory is not set");
192: return;
193: }
194:
195: File pluginDir = new File(homeDir + File.separator + "plugin");
196: File[] contentList = pluginDir.listFiles();
197: if (contentList == null) {
198: System.err.println("Error: The path " + pluginDir.getPath()
199: + " does not seem to be a directory!");
200: System.err.println("No FindBugs plugins could be loaded");
201: pluginList = new URL[0];
202: return;
203: }
204:
205: ArrayList<URL> arr = new ArrayList<URL>();
206: for (File aContentList : contentList) {
207: if (aContentList.getName().endsWith(".jar")) {
208:
209: try {
210: arr.add(aContentList.toURL());
211: if (FindBugs.DEBUG)
212: System.out.println("Found plugin: "
213: + aContentList.toString());
214: } catch (MalformedURLException e) {
215:
216: }
217:
218: }
219: }
220: pluginList = arr.toArray(new URL[arr.size()]);
221:
222: }
223:
224: public void ensureLoaded() {
225: if (loaded)
226: return;
227: loadPlugins();
228: }
229:
230: /**
231: * Directly set the collection of Plugins from which to load DetectorFactories.
232: * May be called instead of loadPlugins().
233: *
234: * @param plugins array of Plugins to register
235: */
236: void setPlugins(Plugin[] plugins) {
237: if (loaded) {
238: throw new IllegalStateException();
239: }
240: for (Plugin plugin : plugins) {
241: pluginByIdMap.put(plugin.getPluginId(), plugin);
242: }
243: loaded = true;
244: }
245:
246: /**
247: * Load all plugins. If a setPluginList() has been called, then those
248: * plugins are loaded. Otherwise, the "findbugs.home" property is checked to
249: * determine where FindBugs is installed, and the plugin files are
250: * dynamically loaded from the plugin directory.
251: */
252: void loadPlugins() {
253: if (loaded)
254: throw new IllegalStateException();
255:
256: //If we are running under jaws, just use the loaded plugin
257: if (SystemProperties.getBoolean("findbugs.jaws")) {
258: URL u = DetectorFactoryCollection.class
259: .getResource("/findbugs.xml");
260: // JOptionPane.showMessageDialog(null, "Loading plugin from " + u);
261: URL[] plugins = new URL[1];
262: if (u != null) {
263: String path = u.toString();
264: path = path.substring(0, path.length()
265: - "findbugs.xml".length());
266: if (FindBugs.DEBUG)
267: System.out.println("Jaws uses plugin: " + path);
268: try {
269: plugins[0] = new URL(path);
270:
271: } catch (MalformedURLException e) {
272: throw new RuntimeException(e);
273: }
274: setPluginList(plugins);
275:
276: }
277: }
278:
279: // Load all detector plugins.
280: loaded = true;
281: determinePlugins();
282:
283: int numLoaded = 0;
284: for (final URL url : pluginList) {
285: try {
286: if (FindBugs.DEBUG)
287: System.out.println("Loading plugin: "
288: + url.toString());
289: PluginLoader pluginLoader = AccessController
290: .doPrivileged(new PrivilegedExceptionAction<PluginLoader>() {
291:
292: public PluginLoader run()
293: throws PluginException {
294: return new PluginLoader(url, this
295: .getClass().getClassLoader());
296: }
297:
298: });
299:
300: Plugin plugin = pluginLoader.getPlugin();
301: pluginByIdMap.put(plugin.getPluginId(), plugin);
302:
303: // Register all of the detectors that this plugin contains
304: for (Iterator<DetectorFactory> j = plugin
305: .detectorFactoryIterator(); j.hasNext();) {
306: DetectorFactory factory = j.next();
307: registerDetector(factory);
308: }
309:
310: I18N i18n = I18N.instance();
311:
312: // Register the BugPatterns
313: for (Iterator<BugPattern> j = plugin
314: .bugPatternIterator(); j.hasNext();) {
315: BugPattern bugPattern = j.next();
316: i18n.registerBugPattern(bugPattern);
317: }
318:
319: // Register the BugCodes
320: for (Iterator<BugCode> j = plugin.bugCodeIterator(); j
321: .hasNext();) {
322: BugCode bugCode = j.next();
323: i18n.registerBugCode(bugCode);
324: }
325:
326: ++numLoaded;
327: } catch (PluginException e) {
328: System.err.println("Warning: could not load plugin "
329: + url + ": " + e.toString());
330: if (FindBugs.DEBUG)
331: e.printStackTrace();
332: } catch (PrivilegedActionException e) {
333: System.err.println("Warning: could not load plugin "
334: + url + ": " + e.toString());
335: if (FindBugs.DEBUG)
336: e.printStackTrace();
337: }
338: }
339:
340: //System.out.println("Loaded " + numLoaded + " plugins");
341: }
342: }
343:
344: // vim:ts=4
|