package barrysoft.plugins;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import barrysoft.logs.Logger;
import barrysoft.utils.FileUtils;
import barrysoft.utils.JarClassLoader;
import barrysoft.utils.OSSpecific;
public class PluginsManager <PluginType extends Plugin> {
public static final String DEF_PLUGINS_EXTENSION = ".spi";
public static final String DEF_LANGUAGE = "English";
private String pluginsExtension = DEF_PLUGINS_EXTENSION;
private String pluginsDirectory;
private ArrayList<PluginType> pluginsList;
private String pluginsLanguage = DEF_LANGUAGE;
public PluginsManager() {
pluginsList = new ArrayList<PluginType>();
}
/**
* Constructor for the plugin manager class
* @param pluginsDirectory Plugins directory
*/
public PluginsManager(String pluginsDirectory) {
this();
setPluginsDirectory(OSSpecific.formatDirectory(pluginsDirectory));
}
/**
* Load the plugins from the specified plugins directory
*/
public void loadPlugins() throws IllegalArgumentException {
String[] pluginsFiles = scanDirectory(getPluginsDirectory());
if (pluginsFiles == null)
throw new IllegalArgumentException("Listing for directory "+
getPluginsDirectory()+" was null, probably wrong path.");
// Process the plugin info
for (String file : pluginsFiles) {
try {
addPlugin(new File(getPluginsDirectory() + File.separator + file));
} catch (PluginLoadingException e) {
Logger.warning(e.getMessage()+"\n\tCause: ("+
e.getCause().getClass().getCanonicalName()+") "+
e.getCause().getMessage());
}
}
}
/**
* Get the number of loaded plugins
* @return Number of loaded plugins
*/
public int getPluginsCount() {
return this.pluginsList.size();
}
/**
* Scan the plugins directory looking for plugins
* configurations file
*
* @param directory Directory to scan
*
* @return Filenames of plugins configuration files
*/
private String[] scanDirectory(String directory) {
File dir = new File(directory);
// Create a filter for the plugin config file
FilenameFilter pluginsFilter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(getPluginsExtension());
}
};
return dir.list(pluginsFilter);
}
public PluginType getPlugin(int number) {
return this.pluginsList.get(number);
}
public ArrayList<PluginType> getPluginsList() {
return this.pluginsList;
}
public PluginType getPluginByName(String name) {
for (Iterator<PluginType> i = this.pluginsList.iterator(); i.hasNext(); ) {
PluginType cur = i.next();
if (cur.getInfo().getName().equals(name)) return cur;
}
return null;
}
/**
* Adds a plugin to this plugin manager
* by loading it from its specification
* file.
*
* @param file The plugin's specification file
* @throws PluginLoadingException If there was an
* error while loading the plugin
*/
public void addPlugin(File file)
throws PluginLoadingException
{
if (file == null)
throw new NullPointerException("Null plugin configuration file");
try {
PluginInfo pluginInfo = PluginInfo.loadFromFile(file);
PluginType plugin = loadPlugin(pluginInfo,file);
plugin.setFile(file);
plugin.load();
plugin.getLocalization().setCurrentLocalization(getPluginsLanguage());
addPlugin(plugin);
} catch (FileNotFoundException e) {
throw new PluginLoadingException(file, e);
} catch (ParserConfigurationException e) {
throw new PluginLoadingException(file, e);
} catch (SAXException e) {
throw new PluginLoadingException(file, e);
} catch (IOException e) {
throw new PluginLoadingException(file, e);
} catch (ClassNotFoundException e) {
throw new PluginLoadingException(file, e);
} catch (InstantiationException e) {
throw new PluginLoadingException(file, e);
} catch (IllegalAccessException e) {
throw new PluginLoadingException(file, e);
}
}
public void addPlugin(PluginType plugin) {
pluginsList.add(plugin);
}
public PluginType loadPlugin(PluginInfo pluginInfo, File pluginFile)
throws ClassNotFoundException,
InstantiationException,
IllegalAccessException,
IOException
{
if (pluginInfo == null)
throw new IllegalArgumentException("Null plugin info");
Class<?> pluginClass = loadPluginClass(pluginInfo, pluginFile);
PluginType plugin = loadPlugin(pluginClass);
plugin.setInfo(pluginInfo);
return plugin;
}
public Class<?> loadPluginClass(PluginInfo infos, File f)
throws FileNotFoundException,
IOException,
ClassNotFoundException
{
Class<?> pluginClass;
if (infos.getJarName() != null && !infos.getJarName().isEmpty()) {
String jarPath = FileUtils.getJarPath(f.getParentFile().getName()+
File.separator+infos.getJarName(), getClass());
File jarFile = new File(jarPath);
if (!jarFile.exists())
throw new FileNotFoundException("Can't find jar file for plugin: "+
jarFile.getAbsolutePath());
JarClassLoader loader = new JarClassLoader(jarFile.getAbsolutePath());
pluginClass = loader.loadClass(infos.getJarClass());
} else {
pluginClass = getClass().getClassLoader().
loadClass(infos.getJarClass());
}
return pluginClass;
}
@SuppressWarnings("unchecked")
public PluginType loadPlugin(Class<?> pluginClass)
throws InstantiationException,
IllegalAccessException
{
PluginType plugin = (PluginType)pluginClass.newInstance();
return plugin;
}
public String getPluginsExtension() {
return pluginsExtension;
}
public void setPluginsExtension(String pluginsExtension) {
this.pluginsExtension = pluginsExtension;
}
public String getPluginsDirectory() {
return pluginsDirectory;
}
public void setPluginsDirectory(String pluginsDirectory) {
this.pluginsDirectory = pluginsDirectory;
Logger.debug("Plugins directory: "+this.pluginsDirectory, Logger.MEDIUM_VERBOSITY);
}
public String getPluginsLanguage() {
return pluginsLanguage;
}
public void setPluginsLanguage(String pluginsLanguage) {
this.pluginsLanguage = pluginsLanguage;
for (PluginType p : pluginsList)
p.getLocalization().setCurrentLocalization(pluginsLanguage);
}
}