View Javadoc
1 package org.codehaus.classworlds; 2 3 /* 4 $Id: Launcher.java,v 1.4 2003/09/22 16:12:54 jvanzyl Exp $ 5 6 Copyright 2002 (C) The Werken Company. All Rights Reserved. 7 8 Redistribution and use of this software and associated documentation 9 ("Software"), with or without modification, are permitted provided 10 that the following conditions are met: 11 12 1. Redistributions of source code must retain copyright 13 statements and notices. Redistributions must also contain a 14 copy of this document. 15 16 2. Redistributions in binary form must reproduce the 17 above copyright notice, this list of conditions and the 18 following disclaimer in the documentation and/or other 19 materials provided with the distribution. 20 21 3. The name "classworlds" must not be used to endorse or promote 22 products derived from this Software without prior written 23 permission of The Werken Company. For written permission, 24 please contact bob@werken.com. 25 26 4. Products derived from this Software may not be called "classworlds" 27 nor may "classworlds" appear in their names without prior written 28 permission of The Werken Company. "classworlds" is a registered 29 trademark of The Werken Company. 30 31 5. Due credit should be given to The Werken Company. 32 (http://classworlds.werken.com/). 33 34 THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS 35 ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 36 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 37 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 38 THE WERKEN COMPANY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 39 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 40 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 41 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 42 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 43 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 44 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 45 OF THE POSSIBILITY OF SUCH DAMAGE. 46 47 */ 48 49 import java.io.IOException; 50 import java.io.InputStream; 51 import java.io.FileInputStream; 52 import java.lang.reflect.Method; 53 import java.lang.reflect.Modifier; 54 import java.lang.reflect.InvocationTargetException; 55 import java.net.MalformedURLException; 56 57 /*** Command-line invokable application launcher. 58 * 59 * <p> 60 * This launcher class assists in the creation of classloaders and <code>ClassRealm</code>s 61 * from a configuration file and the launching of the application's <code>main</code> 62 * method from the correct class loaded through the correct classloader. 63 * </p> 64 * 65 * <p> 66 * The path to the configuration file is specified using the <code>classworlds.conf</code> 67 * system property, typically specified using the <code>-D</code> switch to 68 * <code>java</code>. 69 * </p> 70 * 71 * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a> 72 * 73 * @version $Id: Launcher.java,v 1.4 2003/09/22 16:12:54 jvanzyl Exp $ 74 */ 75 public class Launcher 76 { 77 // ------------------------------------------------------------ 78 // Constants 79 // ------------------------------------------------------------ 80 81 /*** Default config file name. */ 82 private static final String CLASSWORLDS_CONF = "classworlds.conf"; 83 84 /*** Default config dir name. */ 85 private static final String UBERJAR_CONF_DIR = "WORLDS-INF/conf/"; 86 87 // ------------------------------------------------------------ 88 // Instance members 89 // ------------------------------------------------------------ 90 91 /*** Main class name. */ 92 private String mainClassName; 93 94 /*** Main realm name. */ 95 private String mainRealmName; 96 97 /*** App's world. */ 98 private ClassWorld world; 99 100 // ------------------------------------------------------------ 101 // Constructors 102 // ------------------------------------------------------------ 103 104 /*** Construct. 105 */ 106 public Launcher() 107 { 108 // intentionally left blank 109 } 110 111 // ------------------------------------------------------------ 112 // Instance methods 113 // ------------------------------------------------------------ 114 115 /*** Set the application's main entrypoint. 116 * 117 * @param mainClassName The main class name. 118 * @param mainRealmName The realm to load the class from. 119 */ 120 public void setAppMain(String mainClassName, 121 String mainRealmName) 122 { 123 this.mainClassName = mainClassName; 124 this.mainRealmName = mainRealmName; 125 } 126 127 /*** Retrieve the main entry realm name. 128 * 129 * @return The main entry realm name. 130 */ 131 public String getMainRealmName() 132 { 133 return this.mainRealmName; 134 } 135 136 /*** Retrieve the main entry class name. 137 * 138 * @return The main entry class name. 139 */ 140 public String getMainClassName() 141 { 142 return this.mainClassName; 143 } 144 145 /*** Set this launcher's <code>ClassWorld</code>. 146 * 147 * @param world The world. 148 */ 149 public void setWorld(ClassWorld world) 150 { 151 this.world = world; 152 } 153 154 /*** Retrieve this launcher's <code>ClassWorld</code>. 155 * 156 * @return The world. 157 */ 158 public ClassWorld getWorld() 159 { 160 return this.world; 161 } 162 163 /*** Configure from a file. 164 * 165 * @param is The config input stream. 166 * 167 * @throws IOException If an error occurs reading the config file. 168 * @throws MalformedURLException If the config file contains invalid URLs. 169 * @throws ConfigurationException If the config file is corrupt. 170 * @throws DuplicateRealmException If the config file defines two realms 171 * with the same id. 172 * @throws NoSuchRealmException If the config file defines a main entry 173 * point in a non-existent realm. 174 */ 175 public void configure(InputStream is) 176 throws IOException, MalformedURLException, ConfigurationException, 177 DuplicateRealmException, NoSuchRealmException 178 { 179 Configurator configurator = new Configurator(this); 180 181 configurator.configure(is); 182 } 183 184 /*** Retrieve the main entry class. 185 * 186 * @return The main entry class. 187 * 188 * @throws ClassNotFoundException If the class cannot be found. 189 * @throws NoSuchRealmException If the specified main entry realm does not exist. 190 */ 191 public Class getMainClass() 192 throws ClassNotFoundException, NoSuchRealmException 193 { 194 return getMainRealm().loadClass(getMainClassName()); 195 } 196 197 /*** Retrieve the main entry realm. 198 * 199 * @return The main entry realm. 200 * 201 * @throws NoSuchRealmException If the specified main entry realm does not exist. 202 */ 203 public ClassRealm getMainRealm() 204 throws NoSuchRealmException 205 { 206 return getWorld().getRealm(getMainRealmName()); 207 } 208 209 /*** Retrieve the enhanced main entry method. 210 * 211 * @return The enhanced main entry method. 212 * 213 * @throws ClassNotFoundException If the main entry class cannot be found. 214 * @throws NoSuchMethodException If the main entry method cannot be found. 215 * @throws NoSuchRealmException If the main entry realm cannot be found. 216 */ 217 protected Method getEnhancedMainMethod() 218 throws ClassNotFoundException, NoSuchMethodException, NoSuchRealmException 219 { 220 Method[] methods = getMainClass().getMethods(); 221 222 for (int i = 0; i < methods.length; ++i) 223 { 224 final Method method = methods[i]; 225 226 if (!"main".equals(method.getName())) 227 { 228 continue; 229 } 230 231 int modifiers = method.getModifiers(); 232 233 if (!(Modifier.isStatic(modifiers) 234 && 235 Modifier.isPublic(modifiers))) 236 { 237 continue; 238 } 239 240 if (method.getReturnType() != Void.TYPE) 241 { 242 continue; 243 } 244 245 Class[] paramTypes = method.getParameterTypes(); 246 247 if (paramTypes.length != 2) 248 { 249 continue; 250 } 251 252 if (paramTypes[0] != String[].class) 253 { 254 continue; 255 } 256 257 if (paramTypes[1] != ClassWorld.class) 258 { 259 continue; 260 } 261 262 return method; 263 } 264 265 throw new NoSuchMethodException("public static void main(String[] args, ClassWorld world)"); 266 } 267 268 /*** Retrieve the main entry method. 269 * 270 * @return The main entry method. 271 * 272 * @throws ClassNotFoundException If the main entry class cannot be found. 273 * @throws NoSuchMethodException If the main entry method cannot be found. 274 * @throws NoSuchRealmException If the main entry realm cannot be found. 275 */ 276 protected Method getMainMethod() 277 throws ClassNotFoundException, NoSuchMethodException, NoSuchRealmException 278 { 279 Method[] methods = getMainClass().getMethods(); 280 281 for (int i = 0; i < methods.length; ++i) 282 { 283 if (!"main".equals(methods[i].getName())) 284 { 285 continue; 286 } 287 288 int modifiers = methods[i].getModifiers(); 289 290 if (!(Modifier.isStatic(modifiers) 291 && 292 Modifier.isPublic(modifiers))) 293 { 294 continue; 295 } 296 297 if (methods[i].getReturnType() != Void.TYPE) 298 { 299 continue; 300 } 301 302 Class[] paramTypes = methods[i].getParameterTypes(); 303 304 if (paramTypes.length != 1) 305 { 306 continue; 307 } 308 309 if (paramTypes[0] != String[].class) 310 { 311 continue; 312 } 313 314 return methods[i]; 315 } 316 317 throw new NoSuchMethodException("public static void main(String[] args) in " + getMainClass() ); 318 } 319 320 /*** Launch the application. 321 * 322 * @param args The application args. 323 * 324 * @throws ClassNotFoundException If the main entry class cannot be found. 325 * @throws IllegalAccessException If the method cannot be accessed. 326 * @throws InvocationTargetException If the target of the invokation is invalid. 327 * @throws NoSuchMethodException If the main entry method cannot be found. 328 * @throws NoSuchRealmException If the main entry realm cannot be found. 329 */ 330 public void launch(String[] args) 331 throws ClassNotFoundException, IllegalAccessException, 332 InvocationTargetException, NoSuchMethodException, NoSuchRealmException 333 { 334 try 335 { 336 launchEnhanced(args); 337 return; 338 } 339 catch (NoSuchMethodException e) 340 { 341 // ignore 342 } 343 344 launchStandard(args); 345 } 346 347 /*** Attempt to launch the application through the enhanced main method. 348 * 349 * <p> 350 * This will seek a method with the exact signature of: 351 * </p> 352 * 353 * <pre> 354 * public static void main(String[] args, ClassWorld world) 355 * </pre> 356 * 357 * @param args The application args. 358 * 359 * @throws ClassNotFoundException If the main entry class cannot be found. 360 * @throws IllegalAccessException If the method cannot be accessed. 361 * @throws InvocationTargetException If the target of the invokation is 362 * invalid. 363 * @throws NoSuchMethodException If the main entry method cannot be found. 364 * @throws NoSuchRealmException If the main entry realm cannot be found. 365 */ 366 protected void launchEnhanced(String[] args) 367 throws ClassNotFoundException, IllegalAccessException, 368 InvocationTargetException, NoSuchMethodException, NoSuchRealmException 369 { 370 ClassRealm mainRealm = getMainRealm(); 371 Class mainClass = getMainClass(); 372 Method mainMethod = getEnhancedMainMethod(); 373 374 Thread.currentThread().setContextClassLoader(mainRealm.getClassLoader()); 375 376 mainMethod.invoke(mainClass, 377 new Object[]{args, 378 getWorld()}); 379 } 380 381 /*** Attempt to launch the application through the standard main method. 382 * 383 * <p> 384 * This will seek a method with the exact signature of: 385 * </p> 386 * 387 * <pre> 388 * public static void main(String[] args) 389 * </pre> 390 * 391 * @param args The application args. 392 * 393 * @throws ClassNotFoundException If the main entry class cannot be found. 394 * @throws IllegalAccessException If the method cannot be accessed. 395 * @throws InvocationTargetException If the target of the invokation is 396 * invalid. 397 * @throws NoSuchMethodException If the main entry method cannot be found. 398 * @throws NoSuchRealmException If the main entry realm cannot be found. 399 */ 400 protected void launchStandard(String[] args) 401 throws ClassNotFoundException, IllegalAccessException, 402 InvocationTargetException, NoSuchMethodException, NoSuchRealmException 403 { 404 ClassRealm mainRealm = getMainRealm(); 405 Class mainClass = getMainClass(); 406 Method mainMethod = getMainMethod(); 407 408 Thread.currentThread().setContextClassLoader(mainRealm.getClassLoader()); 409 410 mainMethod.invoke( mainClass, 411 new Object[] { args } ); 412 } 413 414 // ------------------------------------------------------------ 415 // Class methods 416 // ------------------------------------------------------------ 417 418 /*** Launch the launcher. 419 * 420 * @param args The application command-line arguments. 421 * 422 * @throws Exception If an error occurs. 423 */ 424 public static void main(String[] args) 425 throws Exception 426 { 427 String classworldsConf = System.getProperty(CLASSWORLDS_CONF); 428 429 InputStream is = null; 430 431 Launcher launcher = new Launcher(); 432 433 if ( classworldsConf != null ) 434 { 435 is = new FileInputStream( classworldsConf ); 436 } 437 else 438 { 439 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 440 441 if ( "true".equals( System.getProperty( "classworlds.bootstrapped" ) ) ) 442 { 443 is = cl.getResourceAsStream( UBERJAR_CONF_DIR + CLASSWORLDS_CONF ); 444 } 445 else 446 { 447 is = cl.getResourceAsStream(CLASSWORLDS_CONF); 448 } 449 } 450 451 if (is == null) 452 { 453 throw new Exception( "classworlds configuration not specified nor found " 454 + "in the classpath" ); 455 } 456 457 launcher.configure( is ); 458 459 try 460 { 461 launcher.launch(args); 462 } 463 catch (InvocationTargetException e) 464 { 465 // Decode ITE (if we can) 466 Throwable t = e.getTargetException(); 467 if (t instanceof Exception) 468 { 469 throw (Exception)t; 470 } 471 if (t instanceof Error) 472 { 473 throw (Error)t; 474 } 475 476 // Else just toss the ITE 477 throw e; 478 } 479 } 480 }

This page was automatically generated by Maven