// Copyright 2012 Georg-August-Universität Göttingen, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package de.ugoe.cs.autoquest.plugin; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FilenameFilter; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.jar.JarInputStream; import java.util.jar.Manifest; /** *
* This class provides the functionality to load AutoQUEST plug-ins from a pre-defined folder. *
* * @author Steffen Herbold * @version 1.0 */ public class PluginLoader implements AutoCloseable { /** ** Handle of the plug-in directory. *
*/ private final File pluginDir; /** ** Collection of the loaded plug-ins. *
*/ private final Collection* the class loaders instantiated internally *
*/ private List* Constructor. Creates a new PluginLoader that can load plug-ins the defined directory. *
* * @param pluginDir * handle of the directory; in case the handle isnull
or does not
* describe a directory, an {@link IllegalArgumentException} is thrown
*/
public PluginLoader(File pluginDir) {
if (pluginDir == null) {
throw new IllegalArgumentException("Parameter pluginDir must not be null!");
}
if (!pluginDir.isDirectory()) {
throw new IllegalArgumentException("File " + pluginDir.getPath() +
" is not a directory");
}
this.pluginDir = pluginDir;
plugins = new LinkedList* Loads plug-ins from {@link #pluginDir}. *
* * @throws PluginLoaderException * thrown if there is a problem loading a plug-in or updating the classpath */ public void load() throws PluginLoaderException { File[] jarFiles = pluginDir.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return checkNameConformity(name); } }); if (jarFiles != null) { for (File jarFile : jarFiles) { ClassLoader loader = getClassLoader(jarFile); String pluginName = jarFile.getName().split("-")[2]; String pluginClassName = "de.ugoe.cs.autoquest.plugin." + pluginName + "." + pluginName.toUpperCase() + "Plugin"; Class> pluginClass = null; try { pluginClass = loader.loadClass(pluginClassName); } catch (ClassNotFoundException e) { throw new PluginLoaderException("No class '" + pluginClassName + "' found in " + pluginDir + "/" + jarFile.getName()); } try { AutoQUESTPlugin pluginObject = (AutoQUESTPlugin) pluginClass.getDeclaredConstructor().newInstance(); plugins.add(pluginObject); } catch (InstantiationException e) { throw new PluginLoaderException("Could not instantiate " + pluginClassName); } catch (IllegalAccessException e) { throw new PluginLoaderException("Could not access " + pluginClassName); } catch (ClassCastException e) { throw new PluginLoaderException("Class " + pluginClassName + " not instance of AutoQUESTPlugin"); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } /** ** Retrieves the classpath from a Jar file's MANIFEST. *
*/ protected String[] getClassPathFromJar(File jarFile) { String[] classPath; JarInputStream jarInputStream = null; Manifest manifest = null; try { FileInputStream fileStream = new FileInputStream(jarFile); try { jarInputStream = new JarInputStream(fileStream); manifest = jarInputStream.getManifest(); } finally { jarInputStream.close(); fileStream.close(); } } catch (FileNotFoundException e) { throw new AssertionError("FileNotFoundException should be impossible!"); } catch (IOException e) { throw new PluginLoaderException(e); } String jarClassPath = manifest.getMainAttributes().getValue("Class-Path"); if (jarClassPath != null) { String[] jarClassPathElements = jarClassPath.split(" "); classPath = new String[jarClassPathElements.length]; for (int i = 0; i < jarClassPathElements.length; i++) { classPath[i] = "file:" + jarFile.getParentFile().getAbsolutePath() + "/" + jarClassPathElements[i]; } try { jarInputStream.close(); } catch (IOException e) { throw new PluginLoaderException(e); } } else { classPath = new String[] { }; } return classPath; } /** *
* Updates the classpath of the {@link ClassLoader} to include the plug-in jar as well as
* further libraries required by the plug-in jar as defined in the Class-Path
* section of its manifest.
*
* Checks if the name of a file indicates that it defines a AutoQUEST plug-in. The structure of
* valid plug-in filenames is autoquest-plugin-%PLUGIN_NAME%-version.jar
, where
* %PLUGIN_NAME%
is replaced by the name of the plug-in. Note that plug-in names
* must not contain any dashes.
*