package main;
import interfaces.IPlugin;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
/**
* Load the plugins from a folder (all the classes implementing interfaces.IPlugin)
*/
public class PluginLoader {
/** Plugin folder */
private String pluginFolder;
/** Plugins loaded */
private Map<String, Class<?>> plugins;
public PluginLoader(String pluginFolder)
{
System.out.println("Loading plugins from folder " + pluginFolder);
plugins = new HashMap<String, Class<?>>();
this.pluginFolder = pluginFolder;
}
/**
* Get the files that may be plugins (files which name ends with "jar" or "class")
* @throws IOException folder not found
*/
public void load() throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException
{
load(pluginFolder);
}
/**
* Get the files that may be plugins (files which name ends with "jar" or "class") in the folder given
* @throws IOException folder not found
*/
private void load(String pluginFolder) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException
{
List<String> out = new ArrayList<String>();
File folder = new File(pluginFolder);
File[] files = folder.listFiles();
if (files == null)
return;
for (File file : files)
{
String fileName = file.getName();
if (file.isDirectory())
{
/* Continue the search in subfolders */
System.out.println("Entering " + fileName);
load(pluginFolder + "/" + file.getName());
System.out.println("Exiting " + fileName);
}
if (fileName.endsWith(".jar"))
{
System.out.println("Opening archive " + fileName);
loadJar(pluginFolder + "/" + fileName, file);
}
}
}
/**
* Browse a jar archive looking for a class implementing the interfaces.IPlugin interface
* @param jarName the jar archive file name
* @throws IOException archive not found
* @throws ClassNotFoundException can't find class
*/
private void loadJar(String jarName, File file) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException
{
JarInputStream jarFile = new JarInputStream(new FileInputStream(jarName));
JarEntry jarEntry;
while(true)
{
jarEntry=jarFile.getNextJarEntry ();
if(jarEntry == null)
break;
URLClassLoader cl = new URLClassLoader (new URL[] {file.toURI().toURL()});
if(jarEntry.getName().endsWith (".class") && !jarEntry.getName().startsWith("interfaces.IPlugin"))
{
String className = jarEntry.getName ().replaceAll(".class", "").replaceAll("/", ".");
//System.out.println("Found class " + className);
Class<?> c = cl.loadClass(className);
String class_name = c.getName ();
for (Class<?> i : c.getInterfaces ())
{
// get the interface implemented name
String interf = i.getName ();
if (interf.equals("interfaces.IPlugin"))
{
// plugin ! \o/
class_name = class_name.substring (class_name.lastIndexOf (".") + 1);
System.out.println(">>> Found class " + class_name + " in archive");
String pluginName = file.getName().substring(0, file.getName().lastIndexOf("."));
plugins.put(pluginName, c);
System.out.println(">>> Registered with name " + pluginName);
}
}
}
}
}
/**
* Get a plugin by its name (the jar archive name)
* @param name the plugin name
* @return the corresponding plugin (if loaded successfully before), or null
*/
public IPlugin getPlugin(String name)
{
IPlugin result = null;
Class<?> c = plugins.get(name);
if (c != null)
{
try
{
result = (IPlugin) c.newInstance();
}
catch (IllegalAccessException iae)
{
iae.printStackTrace();
result = null;
}
catch (InstantiationException ie)
{
ie.printStackTrace();
result = null;
}
}
return result;
}
/**
* Test method
*/
public static void main(String[] args)
{
PluginLoader loader = new PluginLoader("/tmp/plugin");
try
{
loader.load();
System.out.println("Yay !");
}
catch (Exception e)
{
System.err.println(":(");
e.printStackTrace();
}
}
}