001: package net.sourceforge.squirrel_sql.client.plugin;
002:
003: /*
004: * Copyright (C) 2001-2004 Colin Bell
005: * colbell@users.sourceforge.net
006: *
007: * Modifications Copyright (c) 2004 Jason Height.
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022: */
023: import java.io.File;
024: import java.io.IOException;
025: import java.lang.reflect.InvocationHandler;
026: import java.lang.reflect.Method;
027: import java.lang.reflect.Proxy;
028: import java.net.URL;
029: import java.util.ArrayList;
030: import java.util.Arrays;
031: import java.util.Collections;
032: import java.util.Comparator;
033: import java.util.HashMap;
034: import java.util.Iterator;
035: import java.util.List;
036: import java.util.Map;
037:
038: import javax.swing.JInternalFrame;
039: import javax.swing.event.InternalFrameAdapter;
040: import javax.swing.event.InternalFrameEvent;
041:
042: import net.sourceforge.squirrel_sql.client.IApplication;
043: import net.sourceforge.squirrel_sql.client.gui.db.SQLAlias;
044: import net.sourceforge.squirrel_sql.client.gui.db.aliasproperties.IAliasPropertiesPanelController;
045: import net.sourceforge.squirrel_sql.client.gui.session.BaseSessionInternalFrame;
046: import net.sourceforge.squirrel_sql.client.gui.session.ObjectTreeInternalFrame;
047: import net.sourceforge.squirrel_sql.client.gui.session.SQLInternalFrame;
048: import net.sourceforge.squirrel_sql.client.session.ISession;
049: import net.sourceforge.squirrel_sql.client.util.ApplicationFiles;
050: import net.sourceforge.squirrel_sql.fw.gui.GUIUtils;
051: import net.sourceforge.squirrel_sql.fw.id.IIdentifier;
052: import net.sourceforge.squirrel_sql.fw.util.ClassLoaderListener;
053: import net.sourceforge.squirrel_sql.fw.util.MyURLClassLoader;
054: import net.sourceforge.squirrel_sql.fw.util.StringManager;
055: import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
056: import net.sourceforge.squirrel_sql.fw.util.Utilities;
057: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
058: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
059:
060: /**
061: * Manages plugins for the application.
062: *
063: * @author <A HREF="mailto:colbell@users.sourceforge.net">Colin Bell</A>
064: */
065: public class PluginManager {
066: /** Internationalized strings for this class. */
067: private static final StringManager s_stringMgr = StringManagerFactory
068: .getStringManager(PluginManager.class);
069:
070: /** Logger for this class. */
071: private static final ILogger s_log = LoggerController
072: .createLogger(PluginManager.class);
073:
074: /** Application API object. */
075: private IApplication _app;
076:
077: /** Classloader used for plugins. */
078: private MyURLClassLoader _pluginsClassLoader;
079:
080: /**
081: * Contains a <TT>PluginInfo</TT> object for every plugin that we
082: * attempted to load.
083: */
084: private final List<PluginInfo> _plugins = new ArrayList<PluginInfo>();
085:
086: /**
087: * Contains all plugins (<TT>IPlugin</TT>) successfully loaded. Keyed by
088: * <TT>IPlugin.getInternalName()</TT>.
089: */
090: private final Map<String, IPlugin> _loadedPlugins = new HashMap<String, IPlugin>();
091:
092: /**
093: * Contains a <TT>SessionPluginInfo</TT> object for evey object in
094: * <TT>_loadedPlugins<TT> that is an instance of <TT>ISessionPlugin</TT>.
095: */
096: private final List<SessionPluginInfo> _sessionPlugins = new ArrayList<SessionPluginInfo>();
097:
098: /**
099: * Collection of active sessions. Keyed by <TT>ISession.getIdentifier()</TT>
100: * and contains a <TT>List</TT> of active <TT>ISessionPlugin</TT>
101: * objects for the session.
102: */
103: private final Map<IIdentifier, List<SessionPluginInfo>> _activeSessions = new HashMap<IIdentifier, List<SessionPluginInfo>>();
104:
105: /**
106: * Collection of <TT>PluginLoadInfo</TT> objects for the plugins. Stores
107: * info about how long it took to load each plugin.
108: */
109: private final Map<String, PluginLoadInfo> _pluginLoadInfoColl = new HashMap<String, PluginLoadInfo>();
110:
111: private HashMap<IIdentifier, List<PluginSessionCallback>> _pluginSessionCallbacksBySessionID = new HashMap<IIdentifier, List<PluginSessionCallback>>();
112:
113: /** The class that listens for notifications as archives are being loaded */
114: private ClassLoaderListener classLoaderListener = null;
115:
116: /**
117: * Ctor.
118: *
119: * @param app
120: * Application API.
121: *
122: * @throws IllegalArgumentException.
123: * Thrown if <TT>null</TT> <TT>IApplication</TT> passed.
124: */
125: public PluginManager(IApplication app) {
126: super ();
127: if (app == null) {
128: throw new IllegalArgumentException("IApplication == null");
129: }
130:
131: _app = app;
132: }
133:
134: /**
135: * A new session has been created. At this point the <TT>SessionPanel</TT>
136: * does not exist for the new session.
137: *
138: * @param session
139: * The new session.
140: *
141: * @throws IllegalArgumentException
142: * Thrown if a <TT>null</TT> ISession</TT> passed.
143: */
144: public synchronized void sessionCreated(ISession session) {
145: if (session == null) {
146: throw new IllegalArgumentException("ISession == null");
147: }
148:
149: for (Iterator<SessionPluginInfo> it = _sessionPlugins
150: .iterator(); it.hasNext();) {
151: SessionPluginInfo spi = it.next();
152: try {
153: spi.getSessionPlugin().sessionCreated(session);
154: } catch (Throwable th) {
155: String msg = s_stringMgr.getString(
156: "PluginManager.error.sessioncreated", spi
157: .getPlugin().getDescriptiveName());
158: s_log.error(msg, th);
159: _app.showErrorDialog(msg, th);
160: }
161: }
162: }
163:
164: /**
165: * A new session is starting.
166: *
167: * @param session
168: * The new session.
169: *
170: * @throws IllegalArgumentException
171: * Thrown if a <TT>null</TT> ISession</TT> passed.
172: */
173: public synchronized void sessionStarted(final ISession session) {
174: if (session == null) {
175: throw new IllegalArgumentException("ISession == null");
176: }
177: final List<SessionPluginInfo> plugins = new ArrayList<SessionPluginInfo>();
178: _activeSessions.put(session.getIdentifier(), plugins);
179:
180: ArrayList<SessionPluginInfo> startInFG = new ArrayList<SessionPluginInfo>();
181: final ArrayList<SessionPluginInfo> startInBG = new ArrayList<SessionPluginInfo>();
182: for (Iterator<SessionPluginInfo> it = _sessionPlugins
183: .iterator(); it.hasNext();) {
184: SessionPluginInfo spi = it.next();
185: if (spi.getSessionPlugin()
186: .allowsSessionStartedInBackground()) {
187: startInBG.add(spi);
188: } else {
189: startInFG.add(spi);
190: }
191:
192: }
193: session.setPluginsfinishedLoading(true);
194:
195: for (Iterator<SessionPluginInfo> it = startInFG.iterator(); it
196: .hasNext();) {
197: SessionPluginInfo spi = it.next();
198: sendSessionStarted(session, spi, plugins);
199: }
200:
201: session.getApplication().getThreadPool().addTask(
202: new Runnable() {
203: public void run() {
204: for (Iterator<SessionPluginInfo> it = startInBG
205: .iterator(); it.hasNext();) {
206: SessionPluginInfo spi = it.next();
207: sendSessionStarted(session, spi, plugins);
208: }
209: session.setPluginsfinishedLoading(true);
210: }
211: });
212: }
213:
214: private void sendSessionStarted(ISession session,
215: SessionPluginInfo spi, List<SessionPluginInfo> plugins) {
216: try {
217: PluginSessionCallback pluginSessionCallback = spi
218: .getSessionPlugin().sessionStarted(session);
219:
220: if (null != pluginSessionCallback) {
221: List<PluginSessionCallback> list = _pluginSessionCallbacksBySessionID
222: .get(session.getIdentifier());
223: if (null == list) {
224: list = new ArrayList<PluginSessionCallback>();
225: _pluginSessionCallbacksBySessionID.put(session
226: .getIdentifier(), list);
227: }
228: list.add(pluginSessionCallback);
229:
230: plugins.add(spi);
231: }
232: } catch (final Throwable th) {
233: final String msg = s_stringMgr.getString(
234: "PluginManager.error.sessionstarted", spi
235: .getPlugin().getDescriptiveName());
236: s_log.error(msg, th);
237: GUIUtils.processOnSwingEventThread(new Runnable() {
238: public void run() {
239: _app.showErrorDialog(msg, th);
240: }
241: });
242:
243: }
244: }
245:
246: /**
247: * A session is ending.
248: *
249: * @param session
250: * The session ending.
251: *
252: * @throws IllegalArgumentException
253: * Thrown if a <TT>null</TT> ISession</TT> passed.
254: */
255: public synchronized void sessionEnding(ISession session) {
256: if (session == null) {
257: throw new IllegalArgumentException("ISession == null");
258: }
259:
260: List<SessionPluginInfo> plugins = _activeSessions
261: .remove(session.getIdentifier());
262: if (plugins != null) {
263: for (Iterator<SessionPluginInfo> it = plugins.iterator(); it
264: .hasNext();) {
265: SessionPluginInfo spi = it.next();
266: try {
267: spi.getSessionPlugin().sessionEnding(session);
268: } catch (Throwable th) {
269: String msg = s_stringMgr.getString(
270: "PluginManager.error.sessionended", spi
271: .getPlugin().getDescriptiveName());
272: s_log.error(msg, th);
273: _app.showErrorDialog(msg, th);
274: }
275: }
276:
277: _pluginSessionCallbacksBySessionID.remove(session
278: .getIdentifier());
279: }
280: }
281:
282: public synchronized void unloadPlugin(String pluginInternalName) {
283: for (Iterator<IPlugin> it = _loadedPlugins.values().iterator(); it
284: .hasNext();) {
285: IPlugin plugin = it.next();
286: if (plugin.getInternalName().equals(pluginInternalName)) {
287: plugin.unload();
288: it.remove();
289: }
290: }
291: }
292:
293: /**
294: * Unload all plugins.
295: */
296: public synchronized void unloadPlugins() {
297: for (Iterator<IPlugin> it = _loadedPlugins.values().iterator(); it
298: .hasNext();) {
299: IPlugin plugin = it.next();
300: try {
301: plugin.unload();
302: } catch (Throwable th) {
303: String msg = s_stringMgr.getString(
304: "PluginManager.error.unloading", plugin
305: .getInternalName());
306: s_log.error(msg, th);
307: _app.showErrorDialog(msg, th);
308: }
309: }
310: }
311:
312: public synchronized PluginInfo[] getPluginInformation() {
313: return _plugins.toArray(new PluginInfo[_plugins.size()]);
314: }
315:
316: public synchronized SessionPluginInfo[] getPluginInformation(
317: ISession session) {
318: if (session == null) {
319: throw new IllegalArgumentException("Null ISession passed");
320: }
321: List<SessionPluginInfo> list = _activeSessions.get(session
322: .getIdentifier());
323: if (list != null) {
324: return list.toArray(new SessionPluginInfo[list.size()]);
325: }
326: return new SessionPluginInfo[0];
327: }
328:
329: public synchronized IPluginDatabaseObjectType[] getDatabaseObjectTypes(
330: ISession session) {
331: List<IPluginDatabaseObjectType> objTypesList = new ArrayList<IPluginDatabaseObjectType>();
332: List<SessionPluginInfo> plugins = _activeSessions.get(session
333: .getIdentifier());
334: if (plugins != null) {
335: for (Iterator<SessionPluginInfo> it = plugins.iterator(); it
336: .hasNext();) {
337: SessionPluginInfo spi = it.next();
338: IPluginDatabaseObjectType[] objTypes = spi
339: .getSessionPlugin().getObjectTypes(session);
340: if (objTypes != null) {
341: for (int i = 0; i < objTypes.length; ++i) {
342: objTypesList.add(objTypes[i]);
343: }
344: }
345: }
346: }
347:
348: return objTypesList
349: .toArray(new IPluginDatabaseObjectType[objTypesList
350: .size()]);
351: }
352:
353: /**
354: * Retrieve an array of all the <TT>URL</TT> objects that are used to find
355: * plugin classes.
356: *
357: * @return <TT>URL[]</TT>.
358: */
359: public URL[] getPluginURLs() {
360: return _pluginsClassLoader.getURLs();
361: }
362:
363: public PluginStatus[] getPluginStatuses() {
364: return _app.getSquirrelPreferences().getPluginStatuses();
365: }
366:
367: public synchronized void setPluginStatuses(PluginStatus[] values) {
368: _app.getSquirrelPreferences().setPluginStatuses(values);
369: }
370:
371: /**
372: * Retrieve loaded session plugins
373: *
374: * @return <TT>Iterator</TT> over a collection of <TT>ISessionPlugin</TT>
375: * objects.
376: */
377: public Iterator<SessionPluginInfo> getSessionPluginIterator() {
378: return _sessionPlugins.iterator();
379: }
380:
381: /**
382: * TODO: Clean this mess up!!!! Load plugins. Load all plugin jars into
383: * class loader.
384: */
385: public void loadPlugins() {
386: List<URL> pluginUrls = new ArrayList<URL>();
387: File dir = new ApplicationFiles().getPluginsDirectory();
388: boolean isMac = System.getProperty("os.name").toLowerCase()
389: .startsWith("mac");
390: if (dir.isDirectory()) {
391: final Map<String, PluginStatus> pluginStatuses = new HashMap<String, PluginStatus>();
392: {
393: final PluginStatus[] ar = getPluginStatuses();
394: for (int i = 0; i < ar.length; ++i) {
395: pluginStatuses.put(ar[i].getInternalName(), ar[i]);
396: }
397: }
398: File[] files = dir.listFiles();
399: for (int i = 0; i < files.length; ++i) {
400: if (files[i].isFile()) {
401: checkPlugin(files[i], pluginStatuses, pluginUrls,
402: isMac);
403: }
404: }
405: }
406:
407: URL[] urls = pluginUrls.toArray(new URL[pluginUrls.size()]);
408: if (s_log.isDebugEnabled()) {
409: for (int i = 0; i < urls.length; ++i) {
410: s_log.debug("Plugin class loader URL[" + i + "] = "
411: + urls[i]);
412: }
413: }
414:
415: loadPluginInfoCache();
416:
417: _pluginsClassLoader = new MyURLClassLoader(urls);
418: _pluginsClassLoader.addClassLoaderListener(classLoaderListener);
419: Class<?>[] classes = _pluginsClassLoader.getAssignableClasses(
420: IPlugin.class, s_log);
421: for (int i = 0; i < classes.length; ++i) {
422: try {
423: loadPlugin(classes[i]);
424: } catch (Throwable th) {
425: String msg = s_stringMgr.getString(
426: "PluginManager.error.loadpluginclass",
427: classes[i].getName());
428: th.printStackTrace();
429: s_log.error(msg, th);
430: _app.showErrorDialog(msg, th);
431: }
432: }
433: Collections.sort(_plugins, new Comparator<PluginInfo>() {
434: public int compare(PluginInfo arg0, PluginInfo arg1) {
435: if (arg0 == null || arg1 == null) {
436: throw new NullPointerException(
437: "arg1 and arg2 must not be null");
438: }
439: return arg0.getInternalName().compareTo(
440: arg1.getInternalName());
441: }
442:
443: });
444: }
445:
446: private void checkPlugin(File pluginFile,
447: Map<String, PluginStatus> pluginStatuses,
448: List<URL> pluginUrls, boolean isMac) {
449: final String fileName = pluginFile.getAbsolutePath();
450: if (!fileName.toLowerCase().endsWith("src.jar")
451: && (fileName.toLowerCase().endsWith(".zip") || fileName
452: .toLowerCase().endsWith(".jar"))) {
453: try {
454: if (fileName.toLowerCase().endsWith("jedit.jar")) {
455: String msg = s_stringMgr
456: .getString("PluginManager.error.jedit");
457: _app.showErrorDialog(msg);
458: return;
459: }
460:
461: final String fullFilePath = pluginFile
462: .getAbsolutePath();
463: final String internalName = Utilities
464: .removeFileNameSuffix(pluginFile.getName());
465: final PluginStatus ps = pluginStatuses
466: .get(internalName);
467: if (!isMac && internalName.startsWith("macosx")) {
468: s_log
469: .info("Detected MacOS X plugin on non-Mac platform - skipping");
470: return;
471: }
472: if (ps != null && !ps.isLoadAtStartup()) {
473: // We need this in order to allow the user to see this
474: // plugin - which isn't loaded - in the plugin summary
475: // dialog, so that they can enable it.
476: PluginInfo pi = new PluginInfo();
477: pi.setPlugin(new MyPlaceHolderPlugin(internalName));
478: _plugins.add(pi);
479:
480: } else {
481: pluginUrls.add(pluginFile.toURL());
482:
483: // See if plugin has any jars in lib dir.
484: final String pluginDirName = Utilities
485: .removeFileNameSuffix(fullFilePath);
486: final File libDir = new File(pluginDirName, "lib");
487: addPluginLibraries(libDir, pluginUrls);
488:
489: }
490: } catch (IOException ex) {
491: String msg = s_stringMgr.getString(
492: "PluginManager.error.loadplugin", fileName);
493: s_log.error(msg, ex);
494: _app.showErrorDialog(msg, ex);
495: }
496: }
497: }
498:
499: private void loadPluginInfoCache() {
500:
501: }
502:
503: private void addPluginLibraries(File libDir, List<URL> pluginUrls) {
504: if (libDir.exists() && libDir.isDirectory()) {
505: File[] libDirFiles = libDir.listFiles();
506: for (int j = 0; j < libDirFiles.length; ++j) {
507: if (libDirFiles[j].isFile()) {
508: final String fn = libDirFiles[j].getAbsolutePath();
509: if (fn.toLowerCase().endsWith(".zip")
510: || fn.toLowerCase().endsWith(".jar")) {
511: try {
512: pluginUrls.add(libDirFiles[j].toURL());
513: } catch (IOException ex) {
514: String msg = s_stringMgr.getString(
515: "PluginManager.error.loadlib", fn);
516: s_log.error(msg, ex);
517: _app.showErrorDialog(msg, ex);
518: }
519: }
520: }
521: }
522: }
523:
524: }
525:
526: /**
527: * Initialize plugins.
528: */
529: public void initializePlugins() {
530: _app.getWindowManager().addSessionSheetListener(
531: new InternalFrameAdapter() {
532: public void internalFrameOpened(InternalFrameEvent e) {
533: onInternalFrameOpened(e);
534: }
535: });
536:
537: for (Iterator<IPlugin> it = _loadedPlugins.values().iterator(); it
538: .hasNext();) {
539: IPlugin plugin = it.next();
540: try {
541: final PluginLoadInfo pli = getPluginLoadInfo(plugin);
542: pli.startInitializing();
543: plugin.initialize();
544: pli.endInitializing();
545: } catch (Throwable th) {
546: String msg = s_stringMgr.getString(
547: "PluginManager.error.initplugin", plugin
548: .getInternalName());
549: s_log.error(msg, th);
550: _app.showErrorDialog(msg, th);
551: }
552: }
553: }
554:
555: /**
556: * Sets the ClassLoaderListener to notify when archive files containing
557: * classes are loaded.
558: *
559: * @param listener
560: * a ClassLoaderListener implementation
561: */
562: public void setClassLoaderListener(ClassLoaderListener listener) {
563: classLoaderListener = listener;
564: }
565:
566: private void onInternalFrameOpened(InternalFrameEvent e) {
567: JInternalFrame frame = e.getInternalFrame();
568:
569: if (frame instanceof BaseSessionInternalFrame) {
570: ISession session = ((BaseSessionInternalFrame) frame)
571: .getSession();
572:
573: List<PluginSessionCallback> list = _pluginSessionCallbacksBySessionID
574: .get(session.getIdentifier());
575:
576: if (null != list) {
577: for (int i = 0; i < list.size(); i++) {
578: PluginSessionCallback psc = list.get(i);
579:
580: if (frame instanceof SQLInternalFrame) {
581: psc.sqlInternalFrameOpened(
582: (SQLInternalFrame) frame, session);
583: } else if (frame instanceof ObjectTreeInternalFrame) {
584: psc.objectTreeInternalFrameOpened(
585: (ObjectTreeInternalFrame) frame,
586: session);
587: }
588: }
589: }
590: }
591: }
592:
593: /**
594: * Retrieve information about plugin load times
595: *
596: * @return <TT>Iterator</TT> over a collection of <TT>PluginLoadInfo</TT>
597: * objects.
598: */
599: public Iterator<PluginLoadInfo> getPluginLoadInfoIterator() {
600: return _pluginLoadInfoColl.values().iterator();
601: }
602:
603: private void loadPlugin(Class<?> pluginClass) {
604: PluginInfo pi = new PluginInfo(pluginClass.getName());
605: try {
606: final PluginLoadInfo pli = new PluginLoadInfo();
607: final IPlugin plugin = (IPlugin) pluginClass.newInstance();
608: pli.pluginCreated(plugin);
609: _pluginLoadInfoColl.put(plugin.getInternalName(), pli);
610: pi.setPlugin(plugin);
611: _plugins.add(pi);
612: if (validatePlugin(plugin)) {
613: pli.startLoading();
614: plugin.load(_app);
615: pi.setLoaded(true);
616: _loadedPlugins.put(plugin.getInternalName(), plugin);
617: if (ISessionPlugin.class.isAssignableFrom(pluginClass)) {
618: _sessionPlugins.add(new SessionPluginInfo(pi));
619: }
620: }
621: pli.endLoading();
622: } catch (Throwable th) {
623: String msg = s_stringMgr.getString(
624: "PluginManager.error.loadpluginclass", pluginClass
625: .getName());
626: th.printStackTrace();
627: s_log.error(msg, th);
628: _app.showErrorDialog(msg, th);
629: }
630: }
631:
632: private boolean validatePlugin(IPlugin plugin) {
633: String pluginInternalName = plugin.getInternalName();
634: if (pluginInternalName == null
635: || pluginInternalName.trim().length() == 0) {
636: s_log.error("Plugin " + plugin.getClass().getName()
637: + "doesn't return a valid getInternalName()");
638: return false;
639: }
640:
641: if (_loadedPlugins.get(pluginInternalName) != null) {
642: s_log.error("A Plugin with the internal name "
643: + pluginInternalName + " has already been loaded");
644: return false;
645: }
646:
647: return true;
648: }
649:
650: private PluginLoadInfo getPluginLoadInfo(IPlugin plugin) {
651: return _pluginLoadInfoColl.get(plugin.getInternalName());
652: }
653:
654: /**
655: * Allows plugins to access each other without imports.
656: *
657: * @param internalNameOfPlugin
658: * Is the accessed plugins internal name returned by
659: * IPlugin.getInternalName().
660: *
661: * @param toBindTo
662: * Is an interface that is to bind against the object that the
663: * accessed plugin returns by its getExternalService() method.
664: *
665: * @return An Object that may be cast to the toBindTo interface and
666: * delegates all calls to the object returned by the accessed
667: * plugin's getExternalService() method. The method signature of the
668: * methods in the toBintTo interface and external service object
669: * must be identical. This method returns null if the plugin can not
670: * be found / is not loaded.
671: */
672: public Object bindExternalPluginService(
673: String internalNameOfPlugin, Class<?> toBindTo) {
674: IPlugin plugin = _loadedPlugins.get(internalNameOfPlugin);
675:
676: if (null == plugin) {
677: return null;
678: }
679:
680: final Object obj = plugin.getExternalService();
681:
682: if (null == obj) {
683: throw new RuntimeException("The plugin "
684: + internalNameOfPlugin
685: + " doesn't provide any external service.");
686: }
687:
688: InvocationHandler ih = new InvocationHandler() {
689: public Object invoke(Object proxy, Method method,
690: Object[] args) throws Throwable {
691: Method m = obj.getClass().getMethod(method.getName(),
692: method.getParameterTypes());
693: return m.invoke(obj, args);
694: }
695: };
696:
697: return Proxy.newProxyInstance(_pluginsClassLoader,
698: new Class[] { toBindTo }, ih);
699: }
700:
701: public IAliasPropertiesPanelController[] getAliasPropertiesPanelControllers(
702: SQLAlias alias) {
703: ArrayList<IAliasPropertiesPanelController> ret = new ArrayList<IAliasPropertiesPanelController>();
704: for (Iterator<IPlugin> i = _loadedPlugins.values().iterator(); i
705: .hasNext();) {
706: IPlugin plugin = i.next();
707:
708: IAliasPropertiesPanelController[] ctrls = plugin
709: .getAliasPropertiesPanelControllers(alias);
710: if (null != ctrls) {
711: ret.addAll(Arrays.asList(ctrls));
712: }
713: }
714:
715: return ret.toArray(new IAliasPropertiesPanelController[ret
716: .size()]);
717: }
718:
719: public void aliasCopied(SQLAlias source, SQLAlias target) {
720: for (Iterator<IPlugin> i = _loadedPlugins.values().iterator(); i
721: .hasNext();) {
722: IPlugin plugin = i.next();
723: plugin.aliasCopied(source, target);
724: }
725: }
726:
727: public void aliasRemoved(SQLAlias alias) {
728: for (Iterator<IPlugin> i = _loadedPlugins.values().iterator(); i
729: .hasNext();) {
730: IPlugin plugin = i.next();
731: plugin.aliasRemoved(alias);
732: }
733: }
734:
735: /**
736: * A plugin implementation that serves only to identify plugins that aren't
737: * being loaded, but which are still installed, and available to load on
738: * startup if the user changes the isLoadedOnStartup attribute.
739: *
740: * @author rmmannin
741: */
742: private static class MyPlaceHolderPlugin extends DefaultPlugin {
743: private String _internalName = null;
744:
745: public MyPlaceHolderPlugin(String internalName) {
746: _internalName = internalName;
747: }
748:
749: /*
750: * (non-Javadoc)
751: *
752: * @see net.sourceforge.squirrel_sql.client.plugin.IPlugin#getAuthor()
753: */
754: public String getAuthor() {
755: return "";
756: }
757:
758: /*
759: * (non-Javadoc)
760: *
761: * @see net.sourceforge.squirrel_sql.client.plugin.IPlugin#getDescriptiveName()
762: */
763: public String getDescriptiveName() {
764: return "";
765: }
766:
767: /*
768: * (non-Javadoc)
769: *
770: * @see net.sourceforge.squirrel_sql.client.plugin.IPlugin#getInternalName()
771: */
772: public String getInternalName() {
773: return _internalName;
774: }
775:
776: /*
777: * (non-Javadoc)
778: *
779: * @see net.sourceforge.squirrel_sql.client.plugin.IPlugin#getVersion()
780: */
781: public String getVersion() {
782: return "";
783: }
784:
785: }
786: }
|