    001    package org.maltparser.core.plugin;
    002
    003    import java.io.File;
    004    import java.lang.reflect.Constructor;
    005    import java.lang.reflect.InvocationTargetException;
    006    import java.util.HashMap;
    007    import java.util.Iterator;
    008    import java.util.TreeSet;
    009    import org.maltparser.core.exception.MaltChainedException;
    010
    011    /**
    012    Loads MaltParser plug-ins and makes new instances of classes within these plug-ins.
    013
    014    @author Johan Hall
    015
    016    @since 1.0
    017     */
    018    public class PluginLoader implements Iterable<Plugin> {
    019            private HashMap<String, Plugin> plugins;
    020            private TreeSet<String> pluginNames;
    021            private File[] directories;
    022            private JarLoader jarLoader;
    023            private static PluginLoader uniqueInstance = new PluginLoader();
    024
    025            /**
    026             * Creates a PluginLoader
    027             *
    028             * @throws PluginException
    029             */
    030            private PluginLoader() {
    031                    pluginNames = new TreeSet<String>();
    032                    plugins = new HashMap<String, Plugin>();
    033                    jarLoader = null;
    034            }
    035
    036            /**
    037            * Returns a reference to the single instance.
    038            */
    039            public static PluginLoader instance() {
    040                    return uniqueInstance;
    041            }
    042
    043            /**
    044             * Loads plug-ins from one directory
    045             *
    046             * @param pluginDirectory The directory that contains all plug-ins
    047             * @throws MaltChainedException
    048             */
    049            public void loadPlugins(File pluginDirectory) throws MaltChainedException {
    050                    this.loadPlugins(new File[] {pluginDirectory});
    051            }
    052
    053            /**
    054             * Loads plug-ins from one or more directories
    055             *
    056             * @param pluginDirectories An array of directories that contains all plug-ins
    057             * @throws MaltChainedException
    058             */
    059            public void loadPlugins(File[] pluginDirectories) throws MaltChainedException {
    060                    directories = new File[pluginDirectories.length];
    061                    for (int i = 0; i < directories.length; i++) {
    062                            directories[i] = pluginDirectories[i];
    063                    }
    064
    065                    try {
    066                            Class<?> self = Class.forName("org.maltparser.core.plugin.PluginLoader");
    067                            jarLoader = new JarLoader(self.getClassLoader());
    068                    } catch (ClassNotFoundException e) {
    069                            throw new PluginException("The class 'org.maltparser.core.plugin.PluginLoader' not found. ", e);
    070                    }
    071                    traverseDirectories();
    072            }
    073
    074            /**
    075             * Traverse all the plug-in directories
    076             *
    077             * @throws MaltChainedException
    078             */
    079            private void traverseDirectories() throws MaltChainedException {
    080                    for (int i = 0; i < directories.length; i++) {
    081                            traverseDirectory(directories[i]);
    082                    }
    083            }
    084
    085            /**
    086             * Traverse all plug-ins and sub-directories within one plug-in directory.
    087             *
    088             * @param directory The directory that contains plug-ins
    089             * @throws MaltChainedException
    090             */
    091            private void traverseDirectory(File directory) throws MaltChainedException {
    092                    if (!directory.isDirectory() && directory.getName().endsWith(".jar")) {
    093                            pluginNames.add(directory.getAbsolutePath());
    094                            Plugin plugin = new Plugin(directory);
    095                            plugins.put(directory.getAbsolutePath(), plugin);
    096                            if (jarLoader.readJarFile(plugin.getUrl()) == false) {
    097                                    plugins.remove(directory.getAbsolutePath());
    098                            }
    099                    }
    100
    101            if (directory.isDirectory()) {
    102                String[] children = directory.list();
    103                for (int i=0; i<children.length; i++) {
    104                    traverseDirectory(new File(directory, children[i]));
    105                }
    106            }
    107            }
    108
    109            /**
    110             * Returns the Class object for the class with the specified name.
    111             *
    112             * @param classname the fully qualified name of the desired class
    113             * @return the Class object for the class with the specified name.
    114             */
    115            public Class<?> getClass(String classname) {
    116                    if (jarLoader != null) {
    117                            return jarLoader.getClass(classname);
    118                    } else {
    119                            return null;
    120                    }
    121            }
    122
    123            /**
    124             * Creates a new instance of a class within one of the plug-ins
    125             *
    126             * @param classname The fully qualified name of the desired class
    127             * @param argTypes An array of classes (fully qualified name) that specify the arguments to the constructor
    128             * @param args An array of objects that will be the actual parameters to the constructor (the type should corresponds to the argTypes).
    129             * @return a reference to the created instance.
    130             * @throws MaltChainedException
    131             */
    132            public Object newInstance(String classname, Class<?>[] argTypes, Object[] args) throws MaltChainedException {
    133                    try {
    134                            if (jarLoader == null) {
    135                                    return null;
    136                            }
    137                            Class<?> clazz = jarLoader.getClass(classname);
    138                            Object o = null;
    139                            if (clazz == null)
    140                                    return null;
    141                            if (argTypes != null) {
    142                                    Constructor<?> constructor = clazz.getConstructor(argTypes);
    143                                    o = constructor.newInstance(args);
    144                            } else {
    145                                    o = clazz.newInstance();
    146                            }
    147                            return o;
    148                    } catch (NoSuchMethodException e) {
    149                            throw new PluginException("The plugin loader was not able to create an instance of the class '"+classname+"'. ", e);
    150                    } catch (InstantiationException e) {
    151                            throw new PluginException("The plugin loader was not able to create an instance of the class '"+classname+"'. ", e);
    152                    } catch (IllegalAccessException e) {
    153                            throw new PluginException("The plugin loader was not able to create an instance of the class '"+classname+"'. ", e);
    154                    } catch (InvocationTargetException e) {
    155                            throw new PluginException("The plugin loader was not able to create an instance of the class '"+classname+"'. ", e);
    156                    }
    157            }
    158
    159            public Iterator<Plugin> iterator() {
    160                    return plugins.values().iterator();
    161            }
    162
    163
    164            public String toString() {
    165                    StringBuilder sb = new StringBuilder();
    166                    for (Plugin plugin : this) {
    167                            sb.append(plugin.toString() + "\n");
    168                    }
    169                    return sb.toString();
    170            }
    171    }