content: /*
   * This file is part of "JTA - Telnet/SSH for the JAVA(tm) platform".
   *
   * (c) Matthias L. Jugel, Marcus Meißner 1996-2005. All Rights Reserved.
   *
   * Please visit http://javatelnet.org/ for updates and contact.
   *
   * --LICENSE NOTICE--
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   * --LICENSE NOTICE--
   *
   */
  
  package de.mud.jta;
  
  import java.lang.reflect.Constructor;
  import java.util.Enumeration;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.Vector;
  import java.util.List;
  import java.util.ArrayList;
  
  /**
   * The plugin loader tries to load the plugin by name and returns a
   * corresponding plugin object. It takes care of connecting filter
   * plugins
   * <P>
   * <B>Maintainer:</B> Matthias L. Jugel
   *
   * @version $Id: PluginLoader.java 499 2005-09-29 08:24:54Z leo $
   * @author Matthias L. Jugel, Marcus Mei�ner
   */
  public class PluginLoader implements PluginBus {
    /** holds the current version id */
    public final static String ID = "$Id: PluginLoader.java 499 2005-09-29 08:24:54Z leo $";
  
    private final static int debug = 0;
  
    /** the path to standard plugins */
    private Vector PATH = null;
  
    /** holds all the filters */
    private List filter = new ArrayList();
  
    private Map plugins;
  
    /**
     * Create new plugin loader and set up with default plugin path.
     */
    public PluginLoader() {
      this(null);
    }
  
    /**
     * Create new plugin loader and set up with specified plugin path.
     * @param path the default search path for plugins
     */
    public PluginLoader(Vector path) {
      plugins = new HashMap();
      if (path == null) {
        PATH = new Vector();
        PATH.addElement("de.mud.jta.plugin");
      } else
        PATH = path;
    }
  
    /**
     * Add a new plugin to the system and register the plugin load as its
     * communication bus. If the plugin is a filter plugin and if it is
     * not the first filter the last added filter will be set as its filter
     * source.
     * @param name the string name of the plugin
     * @return the newly created plugin or null in case of an error
     */
    public Plugin addPlugin(String name, String id) {
      Plugin plugin = loadPlugin(name, id);
  
      // if it was not found, try without a path as a last resort
      if (plugin == null)
        plugin = loadPlugin(null, name, id);
  
      // nothing found, tell the user
      if (plugin == null) {
        System.err.println("plugin loader: plugin '" + name + "' was not found!");
        return null;
      }
  
      // configure the filter plugins
      if (plugin instanceof FilterPlugin) {
        if (filter.size() > 0)
          ((FilterPlugin) plugin)
                  .setFilterSource((FilterPlugin) filter.get(filter.size() - 1));
        filter.add(plugin);
      }
  
      plugins.put(name+(id == null ? "" : "(" + id + ")"), plugin);
      return plugin;
    }
  
    /**
     * Replace a plugin with a new one, actually reloads the plugin.
     * @param name name of plugin to be replaced
     * @param id unique id
     * @return the newly loaded plugin
     */
    public Plugin replacePlugin(String name, String id) {
      Plugin plugin = loadPlugin(name, id);
  
      if(plugin != null) {
        Plugin oldPlugin = (Plugin)plugins.get(name + (id == null ? "" : "(" + id + ")"));
  
        if(filter.contains(oldPlugin)) {
          int index = filter.indexOf(oldPlugin);
          filter.set(index, plugin);
          ((FilterPlugin)plugin).setFilterSource(((FilterPlugin)oldPlugin).getFilterSource());
          if(index < filter.size() - 1) {
            ((FilterPlugin)filter.get(index + 1)).setFilterSource((FilterPlugin)plugin);
          }
        }
      }
      return plugin;
    }
  
    /**
     * Load a plugin by cycling through the plugin path.
     * @param name the class name of the plugin
     * @param id an id in case of multiple plugins of the same name
     * @return the loaded plugin or null if none was found
     */
    private Plugin loadPlugin(String name, String id) {
      Plugin plugin = null;
  
      // cycle through the PATH to load plugin
      Enumeration pathList = PATH.elements();
      while (pathList.hasMoreElements()) {
        String path = (String) pathList.nextElement();
        plugin = loadPlugin(path, name, id);
        if (plugin != null) {
          return plugin;
        }
      }
      plugin = loadPlugin(null, name, id);
      return plugin;
    }
  
    /**
     * Load a plugin using the specified path name and id.
     * @param path the package where the plugin can be found
     * @param name the class name of the plugin
     * @param id an id for multiple plugins of the same name
     * @return a loaded plugin or null if none was found
     */
    private Plugin loadPlugin(String path, String name, String id) {
      Plugin plugin = null;
      String fullClassName = (path == null) ? name : path + "." + name;
  
      // load the plugin by name and instantiate it
      try {
        Class c = Class.forName(fullClassName);
        Constructor cc = c.getConstructor(new Class[]{PluginBus.class,
                                                      String.class});
        plugin = (Plugin) cc.newInstance(new Object[]{this, id});
        return plugin;
      } catch (ClassNotFoundException ce) {
        if (debug > 0)
          System.err.println("plugin loader: plugin not found: " + fullClassName);
      } catch (Exception e) {
        System.err.println("plugin loader: can't load plugin: " + fullClassName);
        e.printStackTrace();
      }
  
      return null;
  
    }
  
    /** holds the plugin listener we serve */
    private Vector listener = new Vector();
  
    /**
     * Register a new plugin listener.
     */
    public void registerPluginListener(PluginListener l) {
      listener.addElement(l);
    }
  
    /**
     * Implementation of the plugin bus. Broadcast a message to all
     * listeners we know of. The message takes care that the right
     * methods are called in the  listeners.
     * @param message the plugin message to be sent
     * @return the answer to the sent message
     */
    public Object broadcast(PluginMessage message) {
      if (debug > 0) System.err.println("broadcast(" + message + ")");
      if (message == null || listener == null)
        return null;
      Enumeration e = listener.elements();
      Object res = null;
      while (res == null && e.hasMoreElements())
        res = message.firePluginMessage((PluginListener) e.nextElement());
      return res;
    }
  
    public Map getPlugins() {
      return plugins;
    }
  
  }
  
  