package eis; import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.jar.JarFile; import java.util.jar.Manifest; /** * Loads an environment-interface from a file and instantiates it. Uses * java-reflection to load the environment-interface from the respective * jar-file. Also checks the required version for compatibility. * * @author tristanbehrens * */ public class EILoader { private static String version = "0.5"; /** * Loads an environment-interface from a jar-file. Firstly, the jar-file is * added to the classpath. Secondly, the main-class is determined by * inspecting the manifest. And finally, an instance of that very main-class * is created and returned. * * @param file * the file to be loaded * @return an instance of the environment-interface contained in the * jar-file * @throws IOException * is thrown if loading was not successfull */ public static EnvironmentInterfaceStandard fromJarFile(File file) throws IOException { // 1. locate file, check for existence, check for being a jar if (file.exists() == false) throw new IOException("\"" + file.getAbsolutePath() + "\" does not exist."); if (file.getName().endsWith(".jar") == false) throw new IOException("\"" + file.getAbsolutePath() + "\" is not a jar-file."); // 2. read manifest and get main class JarFile jarFile = new JarFile(file); Manifest manifest = jarFile.getManifest(); String mainClass = manifest.getMainAttributes().getValue("Main-Class"); if (mainClass == null || mainClass.equals("")) throw new IOException(file + "does not specify a main-class"); // 3. add the jar file to the classpath URLClassLoader sysloader = (URLClassLoader) ClassLoader .getSystemClassLoader(); Class<URLClassLoader> sysclass = URLClassLoader.class; URL url = file.toURI().toURL(); try { Method method = sysclass.getDeclaredMethod("addURL", new Class[] { URL.class }); method.setAccessible(true); method.invoke(sysloader, new Object[] { url }); } catch (Throwable t) { t.printStackTrace(); throw new IOException( "Error, could not add URL to system classloader", t); } // 4. load the class URLClassLoader loader = new URLClassLoader(new URL[] { url }); Class<?> envInterfaceClass = null; try { envInterfaceClass = loader.loadClass(mainClass); } catch (ClassNotFoundException e) { throw new IOException("Class \"" + mainClass + "\" could not be loaded from \"" + file + "\"", e); } // 5. get an instance of the class Constructor<?> c = null; EnvironmentInterfaceStandard ei = null; try { c = envInterfaceClass.getConstructor(); ei = (EnvironmentInterfaceStandard) (c.newInstance()); } catch (Exception e) { System.out.println(e); throw new IOException("Class \"" + mainClass + "\" could not be loaded from \"" + file + "\"", e); } // check version if (version.equals(ei.requiredVersion()) == false) throw new IOException( "Loaded environment interface version does not match the required one \"" + version + "\" vs. \"" + ei.requiredVersion() + "\""); return ei; } /** * Instantiates an environment-interface from a given class-name. Assumes * that all required classes are already in the classpath. * * @param className * the className to load * @return given class name, verified as implementing * EnvironmentInterfaceStandard * @throws IOException */ public static EnvironmentInterfaceStandard fromClassName(String className) throws IOException { // 4. load the class ClassLoader loader = EnvironmentInterfaceStandard.class .getClassLoader(); Class<?> envInterfaceClass = null; try { envInterfaceClass = loader.loadClass(className); } catch (ClassNotFoundException e) { throw new IOException("Class \"" + className + "\" could not be loaded", e); } // 5. get an instance of the class Constructor<?> c = null; EnvironmentInterfaceStandard ei = null; try { c = envInterfaceClass.getConstructor(); ei = (EnvironmentInterfaceStandard) (c.newInstance()); } catch (Exception e) { System.out.println(e); throw new IOException("Class \"" + className + "\" could not be loaded", e); } // check version if (version.equals(ei.requiredVersion()) == false) throw new IOException( "Loaded environment interface version does not match the required one \"" + version + "\" vs. \"" + ei.requiredVersion() + "\""); return ei; } /** * Loads an environment-interface. * * @param args * the first string has to be a path to a jar-file containing an * environment-interface * @throws IOException * thrown if the file could not be loaded */ public static void main(String[] args) throws IOException { if (args.length == 0) { System.out.println("You have to provide a filename."); } else { EnvironmentInterfaceStandard ei = EILoader.fromJarFile(new File( args[0])); } } }