001package org.maltparser.core.plugin; 002 003import java.io.File; 004import java.lang.reflect.Constructor; 005import java.lang.reflect.InvocationTargetException; 006import java.util.HashMap; 007import java.util.Iterator; 008import java.util.TreeSet; 009import org.maltparser.core.exception.MaltChainedException; 010 011/** 012Loads MaltParser plug-ins and makes new instances of classes within these plug-ins. 013 014@author Johan Hall 015 016@since 1.0 017 */ 018public 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}