package org.maltparser.core.plugin;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeSet;
import org.maltparser.core.exception.MaltChainedException;
/**
* Loads MaltParser plug-ins and makes new instances of classes within these
* plug-ins. *
* @author Johan Hall
*
* @since 1.0
*/
public class PluginLoader implements Iterable<Plugin> {
private HashMap<String, Plugin> plugins;
private TreeSet<String> pluginNames;
private File[] directories;
private JarLoader jarLoader;
private static PluginLoader uniqueInstance = new PluginLoader();
/**
* Creates a PluginLoader
*
* @throws PluginException
*/
private PluginLoader() {
pluginNames = new TreeSet<String>();
plugins = new HashMap<String, Plugin>();
jarLoader = null;
}
/**
* Returns a reference to the single instance.
*/
public static PluginLoader instance() {
return uniqueInstance;
}
/**
* Loads plug-ins from one directory
*
* @param pluginDirectory The directory that contains all plug-ins
* @throws MaltChainedException
*/
public void loadPlugins(File pluginDirectory) throws MaltChainedException {
this.loadPlugins(new File[]{pluginDirectory});
}
/**
* Loads plug-ins from one or more directories
*
* @param pluginDirectories An array of directories that contains all
* plug-ins
* @throws MaltChainedException
*/
public void loadPlugins(File[] pluginDirectories) throws MaltChainedException {
directories = new File[pluginDirectories.length];
for (int i = 0; i < directories.length; i++) {
directories[i] = pluginDirectories[i];
}
try {
Class<?> self = Class.forName("org.maltparser.core.plugin.PluginLoader");
jarLoader = new JarLoader(self.getClassLoader());
} catch (ClassNotFoundException e) {
throw new PluginException("The class 'org.maltparser.core.plugin.PluginLoader' not found. ", e);
}
traverseDirectories();
}
/**
* Traverse all the plug-in directories
*
* @throws MaltChainedException
*/
private void traverseDirectories() throws MaltChainedException {
for (int i = 0; i < directories.length; i++) {
traverseDirectory(directories[i]);
}
}
/**
* Traverse all plug-ins and sub-directories within one plug-in directory.
*
* @param directory The directory that contains plug-ins
* @throws MaltChainedException
*/
private void traverseDirectory(File directory) throws MaltChainedException {
if (!directory.isDirectory() && directory.getName().endsWith(".jar")) {
pluginNames.add(directory.getAbsolutePath());
Plugin plugin = new Plugin(directory);
plugins.put(directory.getAbsolutePath(), plugin);
if (jarLoader.readJarFile(plugin.getUrl()) == false) {
plugins.remove(directory.getAbsolutePath());
}
}
if (directory.isDirectory()) {
String[] children = directory.list();
for (int i = 0; i < children.length; i++) {
traverseDirectory(new File(directory, children[i]));
}
}
}
/**
* Returns the Class object for the class with the specified name.
*
* @param classname the fully qualified name of the desired class
* @return the Class object for the class with the specified name.
*/
public Class<?> getClass(String classname) {
if (jarLoader != null) {
return jarLoader.getClass(classname);
} else {
return null;
}
}
/**
* Creates a new instance of a class within one of the plug-ins
*
* @param classname The fully qualified name of the desired class
* @param argTypes An array of classes (fully qualified name) that specify
* the arguments to the constructor
* @param args An array of objects that will be the actual parameters to the
* constructor (the type should corresponds to the argTypes).
* @return a reference to the created instance.
* @throws MaltChainedException
*/
public Object newInstance(String classname, Class<?>[] argTypes, Object[] args) throws MaltChainedException {
try {
if (jarLoader == null) {
return null;
}
Class<?> clazz = jarLoader.getClass(classname);
Object o;
if (clazz == null) {
return null;
}
if (argTypes != null) {
Constructor<?> constructor = clazz.getConstructor(argTypes);
o = constructor.newInstance(args);
} else {
o = clazz.newInstance();
}
return o;
} catch (NoSuchMethodException e) {
throw new PluginException("The plugin loader was not able to create an instance of the class '" + classname + "'. ", e);
} catch (InstantiationException e) {
throw new PluginException("The plugin loader was not able to create an instance of the class '" + classname + "'. ", e);
} catch (IllegalAccessException e) {
throw new PluginException("The plugin loader was not able to create an instance of the class '" + classname + "'. ", e);
} catch (InvocationTargetException e) {
throw new PluginException("The plugin loader was not able to create an instance of the class '" + classname + "'. ", e);
}
}
public Iterator<Plugin> iterator() {
return plugins.values().iterator();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (Plugin plugin : this) {
sb.append(plugin.toString()).append("\n");
}
return sb.toString();
}
}