package de.ugoe.cs.eventbench.jfcmonitor; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.jar.JarInputStream; import java.util.jar.Manifest; /** *

* Class that launches an executable Jar-file in the same thread and VM where * the JarLauncher instance is created. The requirements on the Jar file are: *

  • Must contain a MANIFEST.
  • *
  • The MANIFEST must define the main-class of the application ("Main-Class" * entry).
  • *
  • The MANIFEST must define the classpath of the application ("Class-Path" * entry).
  • *

    * * @author Steffen Herbold * @version 1.0 */ public class JarLauncher { /** *

    * Name of the Jar file to be executed. *

    */ private String jarfile; /** *

    * Arguments for launching the Jar file. *

    */ private String[] args; /** *

    * Helper variable with the path to the working directory. *

    */ final String workingDir = System.getProperty("user.dir") + "/"; /** *

    * Internal variable used to store the classpath extracted from the Jar * file's MANIFEST. *

    */ private String[] classPath = new String[] {}; /** *

    * Internal variable used to store the name (including package information) * of the Jar file's main function extracted from the Jar file's MANIFEST. *

    */ private String mainClassName = ""; /** *

    * Inner class that defines an exception that is thrown if launching the * application in the Jar file fails. *

    * * @author Steffen Herbold * @version 1.0 */ private class JarLaunchException extends Exception { /** *

    * Id for object serialization. *

    */ private static final long serialVersionUID = 1L; /** *

    * Constructor. Creates a new JarLaunchException. *

    * * @param string * error message of the exception */ public JarLaunchException(String string) { super(string); } /** *

    * Constructor. Creates a new JarLaunchException as a copy of an * existing exception. *

    * * @param e * exception that is copied */ public JarLaunchException(Exception e) { super(e); } } /** *

    * Constructor. Creates a new JarLauncher. *

    * * @param jarfile * file to be launched; must not be complete path but in relation * to the current working directory * @param args * arguments with which the main function of the Jar file is * called */ public JarLauncher(String jarfile, String[] args) { this.jarfile = jarfile; this.args = args; } /** *

    * Executes the main function of the Jar file associated with this launcher. *

    */ public void exec() { try { getInfoFromJar(); initClassLoader(); runMain(); } catch (JarLaunchException e) { System.err.println("Failure to launch application."); System.err.println(e.getMessage()); } } /** *

    * Retrieves the classpath and main function from the Jar file's MANIFEST. *

    * * @throws JarLaunchException * thrown if reading of Jar file or MANIFEST fails */ private void getInfoFromJar() throws JarLaunchException { JarInputStream jarInputStream; try { jarInputStream = new JarInputStream(new FileInputStream(workingDir + jarfile)); } catch (FileNotFoundException e) { throw new JarLaunchException(e); } catch (IOException e) { throw new JarLaunchException(e); } Manifest manifest = jarInputStream.getManifest(); mainClassName = manifest.getMainAttributes().getValue("Main-Class"); String jarClassPath = manifest.getMainAttributes().getValue( "Class-Path"); String[] jarClassPathElements = jarClassPath.split(" "); classPath = new String[jarClassPathElements.length]; for (int i = 0; i < jarClassPathElements.length; i++) { classPath[i] = "file:" + workingDir + jarClassPathElements[i]; } } /** *

    * Modifies the {@link ClassLoader} of the current VM such that it includes * the class path defined in the Jar file's MANIFEST. *

    * * @throws JarLaunchException * thrown if modification of {@link ClassLoader} fails. */ private void initClassLoader() throws JarLaunchException { URLClassLoader classLoader = (URLClassLoader) ClassLoader .getSystemClassLoader(); Method method; try { method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class }); } catch (SecurityException e) { throw new JarLaunchException( "addURL method of URLClassLoader not accessible via reflection."); } catch (NoSuchMethodException e) { throw new JarLaunchException( "URLClassLoader does not have addURL method. Should be impossible!!"); } method.setAccessible(true); try { method.invoke(classLoader, new Object[] { new URL("file:" + workingDir + jarfile) }); for (String element : classPath) { method.invoke(classLoader, new Object[] { new URL(element) }); } } catch (IllegalArgumentException e) { throw new JarLaunchException( "Illegal arguments for addURL method. Should be impossible!!"); } catch (MalformedURLException e) { throw new JarLaunchException(e); } catch (IllegalAccessException e) { throw new JarLaunchException( "addURL method of URLClassLoader not accessible via reflection."); } catch (InvocationTargetException e) { e.printStackTrace(); } } /** *

    * Executes the main function. *

    * * @throws JarLaunchException * thrown if execution of main function fails or the main * function itself throws an exception */ private void runMain() throws JarLaunchException { Class mainClass; try { mainClass = Class.forName(mainClassName); } catch (ClassNotFoundException e) { throw new JarLaunchException("Main class not found: " + mainClassName); } Method mainMethod; try { mainMethod = mainClass.getMethod("main", new Class[] { String[].class }); } catch (SecurityException e) { throw new JarLaunchException("Main method not accessible."); } catch (NoSuchMethodException e) { throw new JarLaunchException("Main method not found."); } try { mainMethod.invoke(null, new Object[] { args }); } catch (IllegalArgumentException e) { throw new JarLaunchException( "Illegal arguments for main method. Should be impossible!!"); } catch (IllegalAccessException e) { throw new JarLaunchException("Main method not accessible."); } catch (InvocationTargetException e) { throw new JarLaunchException(e); } } }