KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > java > plugin > standard > StandardPluginManager


1 /*****************************************************************************
2  * Java Plug-in Framework (JPF)
3  * Copyright (C) 2004-2006 Dmitry Olshansky
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 package org.java.plugin.standard;
20
21 import java.net.URL JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collections JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.LinkedList JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.Set JavaDoc;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.java.plugin.JpfException;
35 import org.java.plugin.PathResolver;
36 import org.java.plugin.Plugin;
37 import org.java.plugin.PluginClassLoader;
38 import org.java.plugin.PluginLifecycleException;
39 import org.java.plugin.PluginManager;
40 import org.java.plugin.registry.PluginDescriptor;
41 import org.java.plugin.registry.PluginFragment;
42 import org.java.plugin.registry.PluginPrerequisite;
43 import org.java.plugin.registry.PluginRegistry;
44 import org.java.plugin.registry.PluginRegistry.RegistryChangeData;
45 import org.java.plugin.registry.PluginRegistry.RegistryChangeListener;
46
47 /**
48  * Standard implementation of plug-in manager.
49  * @version $Id: StandardPluginManager.java,v 1.13 2006/09/07 18:16:57 ddimon Exp $
50  */

51 public final class StandardPluginManager extends PluginManager {
52     Log log = LogFactory.getLog(getClass());
53
54     private final PathResolver pathResolver;
55     private final PluginRegistry registry;
56     private final PluginLifecycleHandler lifecycleHandler;
57     private final Map JavaDoc activePlugins = new HashMap JavaDoc(); // <plugin-id, Plugin>
58
private final Set JavaDoc activatingPlugins = new HashSet JavaDoc(); // <plugin-id>
59
private final Set JavaDoc badPlugins = new HashSet JavaDoc(); // <plugin-id>
60
private final List JavaDoc activationLog = new LinkedList JavaDoc(); // <plugin-id>
61
private final Map JavaDoc classLoaders =
62         new HashMap JavaDoc(); // <plugin-id, PluginClassLoader>
63
private final Set JavaDoc disabledPlugins = new HashSet JavaDoc(); // <plugin-id>
64
private final List JavaDoc listeners =
65         Collections.synchronizedList(new LinkedList JavaDoc()); // <EventListener>
66
private RegistryChangeListener registryChangeListener;
67     private Map JavaDoc notRegisteredPluginLocations = new HashMap JavaDoc(); //<URL, URL>
68

69     /**
70      * Creates instance of plug-in manager for given registry, path resolver
71      * and life cycle handler.
72      * @param aRegistry some implementation of plug-in registry interface
73      * @param aPathResolver some implementation of path resolver interface
74      * @param aLifecycleHandler an implementation of plug-in life cycle handler
75      *
76      * @see StandardObjectFactory
77      */

78     protected StandardPluginManager(final PluginRegistry aRegistry,
79             final PathResolver aPathResolver,
80             final PluginLifecycleHandler aLifecycleHandler) {
81         registry = aRegistry;
82         pathResolver = aPathResolver;
83         lifecycleHandler = aLifecycleHandler;
84         lifecycleHandler.init(this);
85         registryChangeListener = new RegistryChangeListener() {
86             public void registryChanged(final RegistryChangeData data) {
87                 registryChangeHandler(data);
88             }
89         };
90         registry.registerListener(registryChangeListener);
91     }
92
93     /**
94      * @see org.java.plugin.PluginManager#getRegistry()
95      */

96     public PluginRegistry getRegistry() {
97         return registry;
98     }
99
100     /**
101      * @see org.java.plugin.PluginManager#getPathResolver()
102      */

103     public PathResolver getPathResolver() {
104         return pathResolver;
105     }
106     
107     /**
108      * Method to handle plug-in registry change events.
109      * @param data registry change data holder
110      */

111     synchronized void registryChangeHandler(
112             final RegistryChangeData data) {
113         badPlugins.clear();
114         for (Iterator JavaDoc it = data.removedPlugins().iterator(); it.hasNext();) {
115             String JavaDoc id = (String JavaDoc) it.next();
116             deactivatePlugin(id);
117             pathResolver.unregisterContext(id);
118         }
119         for (Iterator JavaDoc it = registry.getPluginDescriptors().iterator();
120                 it.hasNext();) {
121             PluginDescriptor idt = (PluginDescriptor) it.next();
122             URL JavaDoc location =
123                 (URL JavaDoc) notRegisteredPluginLocations.remove(idt.getLocation());
124             if (location != null) {
125                 pathResolver.registerContext(idt, location);
126             }
127         }
128         for (Iterator JavaDoc it = registry.getPluginFragments().iterator();
129                 it.hasNext();) {
130             PluginFragment idt = (PluginFragment) it.next();
131             URL JavaDoc location =
132                 (URL JavaDoc) notRegisteredPluginLocations.remove(idt.getLocation());
133             if (location != null) {
134                 pathResolver.registerContext(idt, location);
135             }
136         }
137         for (Iterator JavaDoc it = data.modifiedPlugins().iterator(); it.hasNext();) {
138             String JavaDoc id = (String JavaDoc) it.next();
139             if (activePlugins.containsKey(id)) {
140                 deactivatePlugin(id);
141                 try {
142                     activatePlugin(id);
143                 } catch (Exception JavaDoc e) {
144                     log.error("failed activating modified plug-in " + id, e); //$NON-NLS-1$
145
}
146             } else {
147                 PluginClassLoader clsLoader =
148                     (PluginClassLoader) classLoaders.get(id);
149                 if (clsLoader != null) {
150                     notifyClassLoader(clsLoader);
151                 }
152             }
153         }
154     }
155     
156     /**
157      * Registers plug-ins and their locations with this plug-in manager. You
158      * should use this method to register new plug-ins to make them available
159      * for activation with this manager instance (compare this to
160      * {@link PluginRegistry#register(URL[])} method that just makes plug-in's
161      * meta-data available for reading and doesn't "know" where are things
162      * actually located).
163      * @param locations plug-in locations data
164      * @return map where keys are manifest URL's and values are registered
165      * plug-ins or plug-in fragments, URL's for unprocessed manifests
166      * are not included
167      * @throws JpfException if given plug-ins can't be registered or published
168      * (optional behavior)
169      */

170     public Map JavaDoc publishPlugins(final PluginLocation[] locations)
171             throws JpfException {
172         URL JavaDoc[] manifests = new URL JavaDoc[locations.length];
173         for (int i = 0; i < manifests.length; i++) {
174             manifests[i] = locations[i].getManifestLocation();
175             notRegisteredPluginLocations.put(manifests[i],
176                     locations[i].getContextLocation());
177         }
178         return registry.register(manifests);
179     }
180     
181     /**
182      * Looks for plug-in with given ID and activates it if it is not activated
183      * yet. Note that this method will never return <code>null</code>.
184      * @param id plug-in ID
185      * @return found plug-in
186      * @throws PluginLifecycleException if plug-in can't be found or activated
187      */

188     public Plugin getPlugin(final String JavaDoc id) throws PluginLifecycleException {
189         Plugin result = (Plugin) activePlugins.get(id);
190         if (result != null) {
191             return result;
192         }
193         if (badPlugins.contains(id)) {
194             throw new IllegalArgumentException JavaDoc("plug-in " + id //$NON-NLS-1$
195
+ " disabled internally as it wasn't properly initialized"); //$NON-NLS-1$
196
}
197         if (disabledPlugins.contains(id)) {
198             throw new IllegalArgumentException JavaDoc("plug-in " + id //$NON-NLS-1$
199
+ " disabled externally"); //$NON-NLS-1$
200
}
201         PluginDescriptor descr = registry.getPluginDescriptor(id);
202         if (descr == null) {
203             throw new IllegalArgumentException JavaDoc("unknown plug-in ID - " + id); //$NON-NLS-1$
204
}
205         return activatePlugin(descr);
206     }
207
208     /**
209      * Activates plug-in with given ID if it is not activated yet.
210      * @param id plug-in ID
211      * @throws PluginLifecycleException if plug-in can't be found or activated
212      */

213     public void activatePlugin(final String JavaDoc id)
214             throws PluginLifecycleException {
215         if (activePlugins.containsKey(id)) {
216             return;
217         }
218         if (badPlugins.contains(id)) {
219             throw new IllegalArgumentException JavaDoc("plug-in " + id //$NON-NLS-1$
220
+ " disabled internally as it wasn't properly initialized"); //$NON-NLS-1$
221
}
222         if (disabledPlugins.contains(id)) {
223             throw new IllegalArgumentException JavaDoc("plug-in " + id //$NON-NLS-1$
224
+ " disabled externally"); //$NON-NLS-1$
225
}
226         PluginDescriptor descr = registry.getPluginDescriptor(id);
227         if (descr == null) {
228             throw new IllegalArgumentException JavaDoc("unknown plug-in ID - " + id); //$NON-NLS-1$
229
}
230         activatePlugin(descr);
231     }
232
233     /**
234      * Looks for plug-in, given object belongs to.
235      * @param obj any object that maybe belongs to some plug-in
236      * @return plug-in or <code>null</code> if given object doesn't belong
237      * to any plug-in (possibly it is part of "host" application)
238      * and thus doesn't managed by the Framework directly
239      * or indirectly
240      */

241     public Plugin getPluginFor(final Object JavaDoc obj) {
242         if (obj == null) {
243             return null;
244         }
245         ClassLoader JavaDoc clsLoader;
246         if (obj instanceof Class JavaDoc) {
247             clsLoader = ((Class JavaDoc) obj).getClassLoader();
248         } else if (obj instanceof ClassLoader JavaDoc) {
249             clsLoader = (ClassLoader JavaDoc) obj;
250         } else {
251             clsLoader = obj.getClass().getClassLoader();
252         }
253         if (!(clsLoader instanceof PluginClassLoader)) {
254             return null;
255         }
256         PluginDescriptor descr =
257             ((PluginClassLoader) clsLoader).getPluginDescriptor();
258         Plugin result = (Plugin) activePlugins.get(descr.getId());
259         if (result != null) {
260             return result;
261         }
262         throw new IllegalStateException JavaDoc("can't get plug-in " + descr); //$NON-NLS-1$
263
}
264
265     /**
266      * @param descr plug-in descriptor
267      * @return <code>true</code> if plug-in with given descriptor is activated
268      */

269     public boolean isPluginActivated(final PluginDescriptor descr) {
270         return activePlugins.containsKey(descr.getId());
271     }
272
273     /**
274      * @param descr plug-in descriptor
275      * @return <code>true</code> if plug-in disabled as it's activation fails
276      */

277     public boolean isBadPlugin(final PluginDescriptor descr) {
278         return badPlugins.contains(descr.getId());
279     }
280
281     /**
282      * @param descr plug-in descriptor
283      * @return <code>true</code> if plug-in is currently activating
284      */

285     public boolean isPluginActivating(final PluginDescriptor descr) {
286         return activatingPlugins.contains(descr.getId());
287     }
288     
289     /**
290      * Returns instance of plug-in's class loader and not tries to activate
291      * plug-in. Use this method if you need to get access to plug-in resources
292      * and don't want to cause plug-in activation.
293      * @param descr plug-in descriptor
294      * @return class loader instance for plug-in with given descriptor
295      */

296     public PluginClassLoader getPluginClassLoader(
297             final PluginDescriptor descr) {
298         if (badPlugins.contains(descr.getId())) {
299             throw new IllegalArgumentException JavaDoc("plug-in " + descr.getId() //$NON-NLS-1$
300
+ " disabled internally as it wasn't properly initialized"); //$NON-NLS-1$
301
}
302         if (disabledPlugins.contains(descr.getId())) {
303             throw new IllegalArgumentException JavaDoc("plug-in " + descr.getId() //$NON-NLS-1$
304
+ " disabled externally"); //$NON-NLS-1$
305
}
306         PluginClassLoader result =
307             (PluginClassLoader) classLoaders.get(descr.getId());
308         if (result != null) {
309             return result;
310         }
311         synchronized (this) {
312             result = (PluginClassLoader) classLoaders.get(descr.getId());
313             if (result != null) {
314                 return result;
315             }
316             result = lifecycleHandler.createPluginClassLoader(descr);
317             classLoaders.put(descr.getId(), result);
318         }
319         return result;
320     }
321     
322     /**
323      * Shuts down the framework.
324      * <br>
325      * Calling this method will deactivate all active plug-ins in order,
326      * reverse to the order they was activated. It also releases all resources
327      * allocated by this manager (class loaders, plug-in descriptors etc.).
328      * All disabled plug-ins will be marked as "enabled", all registered event
329      * listeners will be unregistered.
330      */

331     public synchronized void shutdown() {
332         log.debug("shutting down..."); //$NON-NLS-1$
333
dump();
334         registry.unregisterListener(registryChangeListener);
335         List JavaDoc reversedLog = new ArrayList JavaDoc(activationLog);
336         Collections.reverse(reversedLog);
337         for (Iterator JavaDoc it = reversedLog.iterator(); it.hasNext();) {
338             String JavaDoc id = (String JavaDoc) it.next();
339             PluginDescriptor descr = registry.getPluginDescriptor(id);
340             if (descr == null) {
341                 log.warn("can't find descriptor for plug-in " + id //$NON-NLS-1$
342
+ " to deactivate plug-in", new Exception JavaDoc( //$NON-NLS-1$
343
"fake exception to view stack trace")); //$NON-NLS-1$
344
continue;
345             }
346             deactivatePlugin(descr);
347         }
348         dump();
349         classLoaders.clear();
350         disabledPlugins.clear();
351         listeners.clear();
352         lifecycleHandler.dispose();
353         log.info("shutdown done"); //$NON-NLS-1$
354
}
355     
356     private synchronized Plugin activatePlugin(final PluginDescriptor descr)
357             throws PluginLifecycleException {
358         Plugin result = (Plugin) activePlugins.get(descr.getId());
359         if (result != null) {
360             return result;
361         }
362         if (badPlugins.contains(descr.getId())) {
363             throw new IllegalArgumentException JavaDoc("plug-in " + descr.getId() //$NON-NLS-1$
364
+ " disabled as it wasn't properly initialized"); //$NON-NLS-1$
365
}
366         if (activatingPlugins.contains(descr.getId())) {
367             throw new PluginLifecycleException(
368                     StandardObjectFactory.PACKAGE_NAME,
369                     "pluginActivating", descr.getId()); //$NON-NLS-1$
370
}
371         activatingPlugins.add(descr.getId());
372         try {
373             try {
374                 checkPrerequisites(descr);
375                 String JavaDoc pluginClassName = descr.getPluginClassName();
376                 if ((pluginClassName == null)
377                         || (pluginClassName.trim().length() == 0)) {
378                     result = new EmptyPlugin();
379                 } else {
380                     result = lifecycleHandler.createPluginInstance(descr);
381                 }
382                 initPlugin(result, descr);
383                 lifecycleHandler.beforePluginStart(result);
384                 startPlugin(result);
385             } catch (PluginLifecycleException ple) {
386                 badPlugins.add(descr.getId());
387                 classLoaders.remove(descr.getId());
388                 throw ple;
389             } catch (Exception JavaDoc e) {
390                 badPlugins.add(descr.getId());
391                 classLoaders.remove(descr.getId());
392                 throw new PluginLifecycleException(
393                         StandardObjectFactory.PACKAGE_NAME,
394                         "pluginStartFailed", descr.getUniqueId(), e); //$NON-NLS-1$
395
}
396             activePlugins.put(descr.getId(), result);
397             activationLog.add(descr.getId());
398             log.info("plug-in started - " + descr.getUniqueId()); //$NON-NLS-1$
399
fireEvent(result, true);
400             return result;
401         } finally {
402             activatingPlugins.remove(descr.getId());
403         }
404     }
405     
406     private void checkPrerequisites(final PluginDescriptor descr)
407             throws PluginLifecycleException {
408         for (Iterator JavaDoc it = descr.getPrerequisites().iterator(); it.hasNext();) {
409             PluginPrerequisite pre = (PluginPrerequisite) it.next();
410             if (activatingPlugins.contains(pre.getPluginId())) {
411                 log.warn("dependencies loop detected during " //$NON-NLS-1$
412
+ "activation of plug-in " + descr, new Exception JavaDoc( //$NON-NLS-1$
413
"fake exception to view stack trace")); //$NON-NLS-1$
414
continue;
415             }
416             if (badPlugins.contains(pre.getPluginId())) {
417                 if (pre.isOptional()) {
418                     continue;
419                 }
420                 throw new PluginLifecycleException(
421                         StandardObjectFactory.PACKAGE_NAME,
422                         "pluginPrerequisiteBad", //$NON-NLS-1$
423
new Object JavaDoc[] {descr.getId(), pre.getPluginId()});
424             }
425             if (disabledPlugins.contains(pre.getPluginId())) {
426                 if (pre.isOptional()) {
427                     continue;
428                 }
429                 throw new PluginLifecycleException(
430                         StandardObjectFactory.PACKAGE_NAME,
431                         "pluginPrerequisiteDisabled", //$NON-NLS-1$
432
new Object JavaDoc[] {descr.getId(), pre.getPluginId()});
433             }
434             if (!pre.matches()) {
435                 if (pre.isOptional()) {
436                     continue;
437                 }
438                 throw new PluginLifecycleException(
439                         StandardObjectFactory.PACKAGE_NAME,
440                         "pluginPrerequisiteNotMatches", //$NON-NLS-1$
441
new Object JavaDoc[] {descr.getId(), pre.getPluginId()});
442             }
443             try {
444                 activatePlugin(registry.getPluginDescriptor(
445                         pre.getPluginId()));
446             } catch (PluginLifecycleException ple) {
447                 if (pre.isOptional()) {
448                     log.warn("failed activating optional plug-in from" //$NON-NLS-1$
449
+ " prerequisite " + pre, ple); //$NON-NLS-1$
450
continue;
451                 }
452                 throw ple;
453             }
454         }
455     }
456     
457     /**
458      * Deactivates plug-in with given ID if it has been successfully activated
459      * before. Note that this method will effectively deactivate all plug-ins
460      * that depend on the given plug-in.
461      * @param id plug-in ID
462      */

463     public void deactivatePlugin(final String JavaDoc id) {
464         if (!activePlugins.containsKey(id)) {
465             return;
466         }
467         PluginDescriptor descr = registry.getPluginDescriptor(id);
468         if (descr == null) {
469             throw new IllegalArgumentException JavaDoc("unknown plug-in ID - " + id); //$NON-NLS-1$
470
}
471         // Collect depending plug-ins
472
Map JavaDoc dependingPluginsMap = new HashMap JavaDoc();
473         for (Iterator JavaDoc it = registry.getDependingPlugins(descr).iterator();
474                 it.hasNext();) {
475             PluginDescriptor dependingPlugin = (PluginDescriptor) it.next();
476             dependingPluginsMap.put(dependingPlugin.getId(), dependingPlugin);
477         }
478         // Prepare list of plug-ins to be deactivated in correct order
479
List JavaDoc tobeDeactivated = new LinkedList JavaDoc();
480         List JavaDoc reversedLog = new ArrayList JavaDoc(activationLog);
481         Collections.reverse(reversedLog);
482         for (Iterator JavaDoc it = reversedLog.iterator(); it.hasNext();) {
483             String JavaDoc pluginId = (String JavaDoc) it.next();
484             if (pluginId.equals(descr.getId())) {
485                 tobeDeactivated.add(descr);
486             } else if (dependingPluginsMap.containsKey(pluginId)) {
487                 tobeDeactivated.add(dependingPluginsMap.get(pluginId));
488             }
489         }
490         // Deactivate plug-ins
491
for (Iterator JavaDoc it = tobeDeactivated.iterator(); it.hasNext();) {
492             deactivatePlugin((PluginDescriptor) it.next());
493         }
494         dump();
495     }
496
497     private synchronized void deactivatePlugin(final PluginDescriptor descr) {
498         Plugin plugin = (Plugin) activePlugins.remove(descr.getId());
499         if (plugin != null) {
500             try {
501                 if (plugin.isActive()) {
502                     fireEvent(plugin, false);
503                     stopPlugin(plugin);
504                     lifecycleHandler.afterPluginStop(plugin);
505                     log.info("plug-in stopped - " + descr.getUniqueId()); //$NON-NLS-1$
506
} else {
507                     log.warn("plug-in " + descr.getUniqueId() //$NON-NLS-1$
508
+ " is not active although present in active " //$NON-NLS-1$
509
+ "plug-ins list", new Exception JavaDoc( //$NON-NLS-1$
510
"fake exception to view stack trace")); //$NON-NLS-1$
511
}
512             } catch (Exception JavaDoc e) {
513                 log.error("error while stopping plug-in " //$NON-NLS-1$
514
+ descr.getUniqueId(), e);
515             }
516         }
517         PluginClassLoader clsLoader =
518             (PluginClassLoader) classLoaders.remove(descr.getId());
519         if (clsLoader != null) {
520             disposeClassLoader(clsLoader);
521         }
522         badPlugins.remove(descr.getId());
523         activationLog.remove(descr.getId());
524     }
525     
526     private void dump() {
527         if (!log.isDebugEnabled()) {
528             return;
529         }
530         StringBuffer JavaDoc buf = new StringBuffer JavaDoc("PLUGIN MANAGER DUMP:\r\n"); //$NON-NLS-1$
531
buf.append("-------------- DUMP BEGIN -----------------\r\n"); //$NON-NLS-1$
532
buf.append("\tActive plug-ins: " + activePlugins.size()) //$NON-NLS-1$
533
.append("\r\n"); //$NON-NLS-1$
534
for (Iterator JavaDoc it = activePlugins.values().iterator(); it.hasNext();) {
535             buf.append("\t\t") //$NON-NLS-1$
536
.append(it.next())
537                 .append("\r\n"); //$NON-NLS-1$
538
}
539         buf.append("\tActivating plug-ins: " //$NON-NLS-1$
540
+ activatingPlugins.size()).append("\r\n"); //$NON-NLS-1$
541
for (Iterator JavaDoc it = activatingPlugins.iterator(); it.hasNext();) {
542             buf.append("\t\t") //$NON-NLS-1$
543
.append(it.next())
544                 .append("\r\n"); //$NON-NLS-1$
545
}
546         buf.append("\tPlug-ins with instantiated class loaders: " //$NON-NLS-1$
547
+ classLoaders.size()).append("\r\n"); //$NON-NLS-1$
548
for (Iterator JavaDoc it = classLoaders.keySet().iterator(); it.hasNext();) {
549             buf.append("\t\t") //$NON-NLS-1$
550
.append(it.next())
551                 .append("\r\n"); //$NON-NLS-1$
552
}
553         buf.append("\tDisabled plug-ins: " + disabledPlugins.size()) //$NON-NLS-1$
554
.append("\r\n"); //$NON-NLS-1$
555
for (Iterator JavaDoc it = disabledPlugins.iterator(); it.hasNext();) {
556             buf.append("\t\t") //$NON-NLS-1$
557
.append(it.next())
558                 .append("\r\n"); //$NON-NLS-1$
559
}
560         buf.append("\tBad plug-ins: " + badPlugins.size()) //$NON-NLS-1$
561
.append("\r\n"); //$NON-NLS-1$
562
for (Iterator JavaDoc it = badPlugins.iterator(); it.hasNext();) {
563             buf.append("\t\t") //$NON-NLS-1$
564
.append(it.next())
565                 .append("\r\n"); //$NON-NLS-1$
566
}
567         buf.append("\tActivation log: " + activationLog.size()) //$NON-NLS-1$
568
.append("\r\n"); //$NON-NLS-1$
569
for (Iterator JavaDoc it = activationLog.iterator(); it.hasNext();) {
570             buf.append("\t\t") //$NON-NLS-1$
571
.append(it.next())
572                 .append("\r\n"); //$NON-NLS-1$
573
}
574         buf.append("Memory TOTAL/FREE/MAX: ") //$NON-NLS-1$
575
.append(Runtime.getRuntime().totalMemory())
576             .append("/") //$NON-NLS-1$
577
.append(Runtime.getRuntime().freeMemory())
578             .append("/") //$NON-NLS-1$
579
.append(Runtime.getRuntime().maxMemory())
580             .append("\r\n"); //$NON-NLS-1$
581
buf.append("-------------- DUMP END -----------------"); //$NON-NLS-1$
582
log.debug(buf.toString());
583     }
584     
585     /**
586      * Disables plug-in (with dependencies) in this manager instance.
587      * Disabled plug-in can't be activated although it may be valid and
588      * successfully registered with plug-in registry. Before disabling,
589      * plug-in will be deactivated if it was successfully activated.
590      * <br>
591      * Be careful with this method as it can effectively disable large set
592      * of inter-depending plug-ins and your application may become unstable
593      * or even disabled as whole.
594      * @param descr descriptor of plug-in to be disabled
595      * @return descriptors of plug-ins that was actually disabled
596      */

597     public PluginDescriptor[] disablePlugin(final PluginDescriptor descr) {
598         List JavaDoc result = new LinkedList JavaDoc();
599         if (!disabledPlugins.contains(descr.getId())) {
600             deactivatePlugin(descr);
601             fireEvent(descr, false);
602             disabledPlugins.add(descr.getId());
603             result.add(descr);
604         }
605         for (Iterator JavaDoc it = registry.getDependingPlugins(descr).iterator();
606                 it.hasNext();) {
607             PluginDescriptor dependedPlugin = (PluginDescriptor) it.next();
608             if (!disabledPlugins.contains(dependedPlugin.getId())) {
609                 deactivatePlugin(dependedPlugin);
610                 fireEvent(dependedPlugin, false);
611                 disabledPlugins.add(dependedPlugin.getId());
612                 result.add(dependedPlugin);
613             }
614         }
615         return (PluginDescriptor[]) result.toArray(
616                 new PluginDescriptor[result.size()]);
617     }
618     
619     /**
620      * Enables plug-in (or plug-ins) in this manager instance.
621      * @param descr descriptor of plug-in to be enabled
622      * @param includeDependings if <code>true</code>, depending plug-ins will
623      * be also enabled
624      * @return descriptors of plug-ins that was actually enabled
625      * @see #disablePlugin(PluginDescriptor)
626      */

627     public PluginDescriptor[] enablePlugin(final PluginDescriptor descr,
628             final boolean includeDependings) {
629         List JavaDoc result = new LinkedList JavaDoc();
630         if (disabledPlugins.contains(descr.getId())) {
631             disabledPlugins.remove(descr.getId());
632             fireEvent(descr, true);
633             result.add(descr);
634         }
635         if (includeDependings) {
636             for (Iterator JavaDoc it = registry.getDependingPlugins(descr).iterator();
637                     it.hasNext();) {
638                 PluginDescriptor dependedPlugin = (PluginDescriptor) it.next();
639                 if (disabledPlugins.contains(dependedPlugin.getId())) {
640                     disabledPlugins.remove(dependedPlugin.getId());
641                     fireEvent(dependedPlugin, true);
642                     result.add(dependedPlugin);
643                 }
644             }
645         }
646         return (PluginDescriptor[]) result.toArray(
647                 new PluginDescriptor[result.size()]);
648     }
649     
650     /**
651      * @param descr plug-in descriptor
652      * @return <code>true</code> if given plug-in is disabled in this manager
653      */

654     public boolean isPluginEnabled(final PluginDescriptor descr) {
655         return !disabledPlugins.contains(descr.getId());
656     }
657     
658     /**
659      * Registers plug-in manager event listener. If given listener has been
660      * registered before, this method will throw an
661      * {@link IllegalArgumentException}.
662      * @param listener new manager event listener
663      */

664     public void registerListener(final EventListener listener) {
665         if (listeners.contains(listener)) {
666             throw new IllegalArgumentException JavaDoc("listener " + listener //$NON-NLS-1$
667
+ " already registered"); //$NON-NLS-1$
668
}
669         listeners.add(listener);
670     }
671     
672     /**
673      * Unregisters manager event listener. If given listener hasn't been
674      * registered before, this method will throw an
675      * {@link IllegalArgumentException}.
676      * @param listener registered listener
677      */

678     public void unregisterListener(final EventListener listener) {
679         if (!listeners.remove(listener)) {
680             log.warn("unknown listener " + listener); //$NON-NLS-1$
681
}
682     }
683     
684     private void fireEvent(final Object JavaDoc data, final boolean on) {
685         if (listeners.isEmpty()) {
686             return;
687         }
688         // make local copy
689
EventListener[] arr = (EventListener[]) listeners.toArray(
690                 new EventListener[listeners.size()]);
691         // propagate event basing on given data type and on/off flag
692
//NB: revise this logic if EventListener members are changed
693
if (data instanceof PluginDescriptor) {
694             PluginDescriptor descr = (PluginDescriptor) data;
695             if (on) {
696                 if (log.isDebugEnabled()) {
697                     log.debug("propagating \"pluginEnabled\" event for " //$NON-NLS-1$
698
+ descr);
699                 }
700                 for (int i = 0; i < arr.length; i++) {
701                     arr[i].pluginEnabled(descr);
702                 }
703             } else {
704                 if (log.isDebugEnabled()) {
705                     log.debug("propagating \"pluginDisabled\" event for " //$NON-NLS-1$
706
+ descr);
707                 }
708                 for (int i = 0; i < arr.length; i++) {
709                     arr[i].pluginDisabled(descr);
710                 }
711             }
712         } else {
713             Plugin plugin = (Plugin) data;
714             if (on) {
715                 if (log.isDebugEnabled()) {
716                     log.debug("propagating \"pluginActivated\" event for " //$NON-NLS-1$
717
+ plugin);
718                 }
719                 for (int i = 0; i < arr.length; i++) {
720                     arr[i].pluginActivated(plugin);
721                 }
722             } else {
723                 if (log.isDebugEnabled()) {
724                     log.debug("propagating \"pluginDeactivated\" event for " //$NON-NLS-1$
725
+ plugin);
726                 }
727                 for (int i = 0; i < arr.length; i++) {
728                     arr[i].pluginDeactivated(plugin);
729                 }
730             }
731         }
732     }
733     
734     static final class EmptyPlugin extends Plugin {
735         /**
736          * @see org.java.plugin.Plugin#doStart()
737          */

738         protected void doStart() throws Exception JavaDoc {
739             // no-op
740
}
741         
742         /**
743          * @see org.java.plugin.Plugin#doStop()
744          */

745         protected void doStop() throws Exception JavaDoc {
746             // no-op
747
}
748     }
749 }
750
Popular Tags