- Timestamp:
- 09/19/12 10:46:39 (12 years ago)
- Location:
- trunk/JFCMonitor
- Files:
-
- 2 added
- 2 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/JFCMonitor
-
Property
svn:ignore
set to
.settings
-
Property
svn:ignore
set to
-
trunk/JFCMonitor/src/main/java/de/ugoe/cs/eventbench/jfcmonitor/JarLauncher.java
r286 r822 1 1 2 package de.ugoe.cs.eventbench.jfcmonitor; 2 3 … … 15 16 /** 16 17 * <p> 17 * Class that launches an executable Jar-file in the same thread and VM where 18 * the JarLauncherinstance is created. The requirements on the Jar file are:18 * Class that launches an executable Jar-file in the same thread and VM where the JarLauncher 19 * instance is created. The requirements on the Jar file are: 19 20 * <li>Must contain a MANIFEST.</li> 20 * <li>The MANIFEST must define the main-class of the application ("Main-Class" 21 * entry).</li> 22 * <li>The MANIFEST must define the classpath of the application ("Class-Path" 23 * entry).</li> 21 * <li>The MANIFEST must define the main-class of the application ("Main-Class" entry).</li> 22 * <li>The MANIFEST must define the classpath of the application ("Class-Path" entry).</li> 24 23 * </p> 25 24 * … … 29 28 public class JarLauncher { 30 29 31 /** 32 * <p> 33 * Name of the Jar file to be executed. 34 * </p> 35 */ 36 private String jarfile; 37 38 /** 39 * <p> 40 * Arguments for launching the Jar file. 41 * </p> 42 */ 43 private String[] args; 44 45 /** 46 * <p> 47 * Helper variable with the path to the working directory. 48 * </p> 49 */ 50 final String workingDir = System.getProperty("user.dir") + "/"; 51 52 /** 53 * <p> 54 * Internal variable used to store the classpath extracted from the Jar 55 * file's MANIFEST. 56 * </p> 57 */ 58 private String[] classPath = new String[] {}; 59 60 /** 61 * <p> 62 * Internal variable used to store the name (including package information) 63 * of the Jar file's main function extracted from the Jar file's MANIFEST. 64 * </p> 65 */ 66 private String mainClassName = ""; 67 68 /** 69 * <p> 70 * Inner class that defines an exception that is thrown if launching the 71 * application in the Jar file fails. 72 * </p> 73 * 74 * @author Steffen Herbold 75 * @version 1.0 76 */ 77 private static class JarLaunchException extends Exception { 78 79 /** 80 * <p> 81 * Id for object serialization. 82 * </p> 83 */ 84 private static final long serialVersionUID = 1L; 85 86 /** 87 * <p> 88 * Constructor. Creates a new JarLaunchException. 89 * </p> 90 * 91 * @param string 92 * error message of the exception 93 */ 94 public JarLaunchException(String string) { 95 super(string); 96 } 97 98 /** 99 * <p> 100 * Constructor. Creates a new JarLaunchException as a copy of an 101 * existing exception. 102 * </p> 103 * 104 * @param e 105 * exception that is copied 106 */ 107 public JarLaunchException(Exception e) { 108 super(e); 109 } 110 111 } 112 113 /** 114 * <p> 115 * Constructor. Creates a new JarLauncher. 116 * </p> 117 * 118 * @param jarfile 119 * file to be launched; must not be complete path but in relation 120 * to the current working directory 121 * @param args 122 * arguments with which the main function of the Jar file is 123 * called 124 */ 125 public JarLauncher(String jarfile, String[] args) { 126 this.jarfile = jarfile; 127 this.args = Arrays.copyOf(args, args.length); 128 } 129 130 /** 131 * <p> 132 * Executes the main function of the Jar file associated with this launcher. 133 * </p> 134 */ 135 public void exec() { 136 try { 137 getInfoFromJar(); 138 initClassLoader(); 139 runMain(); 140 } catch (JarLaunchException e) { 141 System.err.println("Failure to launch application."); 142 System.err.println(e.getMessage()); 143 } 144 } 145 146 /** 147 * <p> 148 * Retrieves the classpath and main function from the Jar file's MANIFEST. 149 * </p> 150 * 151 * @throws JarLaunchException 152 * thrown if reading of Jar file or MANIFEST fails 153 */ 154 private void getInfoFromJar() throws JarLaunchException { 155 JarInputStream jarInputStream; 156 try { 157 jarInputStream = new JarInputStream(new FileInputStream(workingDir 158 + jarfile)); 159 } catch (FileNotFoundException e) { 160 throw new JarLaunchException(e); 161 } catch (IOException e) { 162 throw new JarLaunchException(e); 163 } 164 Manifest manifest = jarInputStream.getManifest(); 165 mainClassName = manifest.getMainAttributes().getValue("Main-Class"); 166 String jarClassPath = manifest.getMainAttributes().getValue( 167 "Class-Path"); 168 String[] jarClassPathElements = jarClassPath.split(" "); 169 classPath = new String[jarClassPathElements.length]; 170 for (int i = 0; i < jarClassPathElements.length; i++) { 171 classPath[i] = "file:" + workingDir + jarClassPathElements[i]; 172 } 173 try { 174 jarInputStream.close(); 175 } catch (IOException e) { 176 e.printStackTrace(); 177 } 178 } 179 180 /** 181 * <p> 182 * Modifies the {@link ClassLoader} of the current VM such that it includes 183 * the class path defined in the Jar file's MANIFEST. 184 * </p> 185 * 186 * @throws JarLaunchException 187 * thrown if modification of {@link ClassLoader} fails. 188 */ 189 private void initClassLoader() throws JarLaunchException { 190 URLClassLoader classLoader = (URLClassLoader) ClassLoader 191 .getSystemClassLoader(); 192 Method method; 193 try { 194 method = URLClassLoader.class.getDeclaredMethod("addURL", 195 new Class[] { URL.class }); 196 } catch (SecurityException e) { 197 throw new JarLaunchException( 198 "addURL method of URLClassLoader not accessible via reflection."); 199 } catch (NoSuchMethodException e) { 200 throw new JarLaunchException( 201 "URLClassLoader does not have addURL method. Should be impossible!!"); 202 } 203 method.setAccessible(true); 204 205 try { 206 method.invoke(classLoader, new Object[] { new URL("file:" 207 + workingDir + jarfile) }); 208 for (String element : classPath) { 209 method.invoke(classLoader, new Object[] { new URL(element) }); 210 } 211 } catch (IllegalArgumentException e) { 212 throw new JarLaunchException( 213 "Illegal arguments for addURL method. Should be impossible!!"); 214 } catch (MalformedURLException e) { 215 throw new JarLaunchException(e); 216 } catch (IllegalAccessException e) { 217 throw new JarLaunchException( 218 "addURL method of URLClassLoader not accessible via reflection."); 219 } catch (InvocationTargetException e) { 220 e.printStackTrace(); 221 } 222 } 223 224 /** 225 * <p> 226 * Executes the main function. 227 * </p> 228 * 229 * @throws JarLaunchException 230 * thrown if execution of main function fails or the main 231 * function itself throws an exception 232 */ 233 private void runMain() throws JarLaunchException { 234 Class<?> mainClass; 235 try { 236 mainClass = Class.forName(mainClassName); 237 } catch (ClassNotFoundException e) { 238 throw new JarLaunchException("Main class not found: " 239 + mainClassName); 240 } 241 Method mainMethod; 242 try { 243 mainMethod = mainClass.getMethod("main", 244 new Class[] { String[].class }); 245 } catch (SecurityException e) { 246 throw new JarLaunchException("Main method not accessible."); 247 } catch (NoSuchMethodException e) { 248 throw new JarLaunchException("Main method not found."); 249 } 250 try { 251 mainMethod.invoke(null, new Object[] { args }); 252 } catch (IllegalArgumentException e) { 253 throw new JarLaunchException( 254 "Illegal arguments for main method. Should be impossible!!"); 255 } catch (IllegalAccessException e) { 256 throw new JarLaunchException("Main method not accessible."); 257 } catch (InvocationTargetException e) { 258 throw new JarLaunchException(e); 259 } 260 } 30 /** 31 * <p> 32 * Name of the Jar file to be executed. 33 * </p> 34 */ 35 private String jarfile; 36 37 /** 38 * <p> 39 * Arguments for launching the Jar file. 40 * </p> 41 */ 42 private String[] args; 43 44 /** 45 * <p> 46 * Helper variable with the path to the working directory. 47 * </p> 48 */ 49 final String workingDir = System.getProperty("user.dir") + "/"; 50 51 /** 52 * <p> 53 * Internal variable used to store the classpath extracted from the Jar file's MANIFEST. 54 * </p> 55 */ 56 private String[] classPath = new String[] { }; 57 58 /** 59 * <p> 60 * Internal variable used to store the name (including package information) of the Jar file's 61 * main function extracted from the Jar file's MANIFEST. 62 * </p> 63 */ 64 private String mainClassName = ""; 65 66 /** 67 * <p> 68 * Inner class that defines an exception that is thrown if launching the application in the Jar 69 * file fails. 70 * </p> 71 * 72 * @author Steffen Herbold 73 * @version 1.0 74 */ 75 private static class JarLaunchException extends Exception { 76 77 /** 78 * <p> 79 * Id for object serialization. 80 * </p> 81 */ 82 private static final long serialVersionUID = 1L; 83 84 /** 85 * <p> 86 * Constructor. Creates a new JarLaunchException. 87 * </p> 88 * 89 * @param string 90 * error message of the exception 91 */ 92 public JarLaunchException(String string) { 93 super(string); 94 } 95 96 /** 97 * <p> 98 * Constructor. Creates a new JarLaunchException as a copy of an existing exception. 99 * </p> 100 * 101 * @param e 102 * exception that is copied 103 */ 104 public JarLaunchException(Exception e) { 105 super(e); 106 } 107 108 } 109 110 /** 111 * <p> 112 * Constructor. Creates a new JarLauncher. 113 * </p> 114 * 115 * @param jarfile 116 * file to be launched; must not be complete path but in relation to the current 117 * working directory 118 * @param args 119 * arguments with which the main function of the Jar file is called 120 */ 121 public JarLauncher(String jarfile, String[] args) { 122 this.jarfile = jarfile; 123 this.args = Arrays.copyOf(args, args.length); 124 } 125 126 /** 127 * <p> 128 * Executes the main function of the Jar file associated with this launcher. 129 * </p> 130 */ 131 public void exec() { 132 try { 133 getInfoFromJar(); 134 initClassLoader(); 135 runMain(); 136 } 137 catch (JarLaunchException e) { 138 System.err.println("Failure to launch application."); 139 System.err.println(e.getMessage()); 140 } 141 } 142 143 /** 144 * <p> 145 * Retrieves the classpath and main function from the Jar file's MANIFEST. 146 * </p> 147 * 148 * @throws JarLaunchException 149 * thrown if reading of Jar file or MANIFEST fails 150 */ 151 private void getInfoFromJar() throws JarLaunchException { 152 JarInputStream jarInputStream; 153 try { 154 jarInputStream = new JarInputStream(new FileInputStream(workingDir + jarfile)); 155 } 156 catch (FileNotFoundException e) { 157 throw new JarLaunchException(e); 158 } 159 catch (IOException e) { 160 throw new JarLaunchException(e); 161 } 162 Manifest manifest = jarInputStream.getManifest(); 163 mainClassName = manifest.getMainAttributes().getValue("Main-Class"); 164 String jarClassPath = manifest.getMainAttributes().getValue("Class-Path"); 165 String[] jarClassPathElements = jarClassPath.split(" "); 166 classPath = new String[jarClassPathElements.length]; 167 for (int i = 0; i < jarClassPathElements.length; i++) { 168 classPath[i] = "file:" + workingDir + jarClassPathElements[i]; 169 } 170 try { 171 jarInputStream.close(); 172 } 173 catch (IOException e) { 174 e.printStackTrace(); 175 } 176 } 177 178 /** 179 * <p> 180 * Modifies the {@link ClassLoader} of the current VM such that it includes the class path 181 * defined in the Jar file's MANIFEST. 182 * </p> 183 * 184 * @throws JarLaunchException 185 * thrown if modification of {@link ClassLoader} fails. 186 */ 187 private void initClassLoader() throws JarLaunchException { 188 URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); 189 Method method; 190 try { 191 method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] 192 { URL.class }); 193 } 194 catch (SecurityException e) { 195 throw new JarLaunchException( 196 "addURL method of URLClassLoader not accessible via reflection."); 197 } 198 catch (NoSuchMethodException e) { 199 throw new JarLaunchException( 200 "URLClassLoader does not have addURL method. Should be impossible!!"); 201 } 202 method.setAccessible(true); 203 204 try { 205 method.invoke(classLoader, new Object[] 206 { new URL("file:" + workingDir + jarfile) }); 207 for (String element : classPath) { 208 method.invoke(classLoader, new Object[] 209 { new URL(element) }); 210 } 211 } 212 catch (IllegalArgumentException e) { 213 throw new JarLaunchException( 214 "Illegal arguments for addURL method. Should be impossible!!"); 215 } 216 catch (MalformedURLException e) { 217 throw new JarLaunchException(e); 218 } 219 catch (IllegalAccessException e) { 220 throw new JarLaunchException( 221 "addURL method of URLClassLoader not accessible via reflection."); 222 } 223 catch (InvocationTargetException e) { 224 e.printStackTrace(); 225 } 226 } 227 228 /** 229 * <p> 230 * Executes the main function. 231 * </p> 232 * 233 * @throws JarLaunchException 234 * thrown if execution of main function fails or the main function itself throws an 235 * exception 236 */ 237 private void runMain() throws JarLaunchException { 238 Class<?> mainClass; 239 try { 240 mainClass = Class.forName(mainClassName); 241 } 242 catch (ClassNotFoundException e) { 243 throw new JarLaunchException("Main class not found: " + mainClassName); 244 } 245 Method mainMethod; 246 try { 247 mainMethod = mainClass.getMethod("main", new Class[] 248 { String[].class }); 249 } 250 catch (SecurityException e) { 251 throw new JarLaunchException("Main method not accessible."); 252 } 253 catch (NoSuchMethodException e) { 254 throw new JarLaunchException("Main method not found."); 255 } 256 try { 257 mainMethod.invoke(null, new Object[] 258 { args }); 259 } 260 catch (IllegalArgumentException e) { 261 throw new JarLaunchException( 262 "Illegal arguments for main method. Should be impossible!!"); 263 } 264 catch (IllegalAccessException e) { 265 throw new JarLaunchException("Main method not accessible."); 266 } 267 catch (InvocationTargetException e) { 268 throw new JarLaunchException(e); 269 } 270 } 261 271 }
Note: See TracChangeset
for help on using the changeset viewer.