Clover coverage report - classworlds - 1.1-alpha-1
Coverage timestamp: Sun Sep 19 2004 14:08:44 EDT
file stats: LOC: 452   Methods: 17
NCLOC: 203   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
Launcher.java 33.3% 55.3% 88.2% 55.6%
coverage coverage
 1   
 package org.codehaus.classworlds;
 2   
 
 3   
 /*
 4   
  $Id: Launcher.java,v 1.5 2004/09/19 17:41:44 dandiep 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   
 import java.net.URL;
 57   
 
 58   
 /**
 59   
  * Command-line invokable application launcher.
 60   
  * <p/>
 61   
  * <p/>
 62   
  * This launcher class assists in the creation of classloaders and <code>ClassRealm</code>s
 63   
  * from a configuration file and the launching of the application's <code>main</code>
 64   
  * method from the correct class loaded through the correct classloader.
 65   
  * </p>
 66   
  * <p/>
 67   
  * <p/>
 68   
  * The path to the configuration file is specified using the <code>classworlds.conf</code>
 69   
  * system property, typically specified using the <code>-D</code> switch to
 70   
  * <code>java</code>.
 71   
  * </p>
 72   
  *
 73   
  * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a>
 74   
  * @version $Id: Launcher.java,v 1.5 2004/09/19 17:41:44 dandiep Exp $
 75   
  */
 76   
 public class Launcher
 77   
 {
 78   
     protected static final String CLASSWORLDS_CONF = "classworlds.conf";
 79   
 
 80   
     protected static final String UBERJAR_CONF_DIR = "WORLDS-INF/conf/";
 81   
 
 82   
     protected String mainClassName;
 83   
 
 84   
     protected String mainRealmName;
 85   
 
 86   
     protected ClassWorld world;
 87   
 
 88   
     private int exitCode = 0;
 89   
 
 90  68
     public Launcher()
 91   
     {
 92   
     }
 93   
 
 94  4
     public int getExitCode()
 95   
     {
 96  4
         return exitCode;
 97   
     }
 98   
 
 99  44
     public void setAppMain( String mainClassName, String mainRealmName )
 100   
     {
 101  44
         this.mainClassName = mainClassName;
 102   
 
 103  44
         this.mainRealmName = mainRealmName;
 104   
     }
 105   
 
 106  82
     public String getMainRealmName()
 107   
     {
 108  82
         return this.mainRealmName;
 109   
     }
 110   
 
 111  52
     public String getMainClassName()
 112   
     {
 113  52
         return this.mainClassName;
 114   
     }
 115   
 
 116  42
     public void setWorld( ClassWorld world )
 117   
     {
 118  42
         this.world = world;
 119   
     }
 120   
 
 121  90
     public ClassWorld getWorld()
 122   
     {
 123  90
         return this.world;
 124   
     }
 125   
 
 126   
     /**
 127   
      * Configure from a file.
 128   
      *
 129   
      * @param is The config input stream.
 130   
      * @throws IOException             If an error occurs reading the config file.
 131   
      * @throws MalformedURLException   If the config file contains invalid URLs.
 132   
      * @throws ConfigurationException  If the config file is corrupt.
 133   
      * @throws DuplicateRealmException If the config file defines two realms
 134   
      *                                 with the same id.
 135   
      * @throws NoSuchRealmException    If the config file defines a main entry
 136   
      *                                 point in a non-existent realm.
 137   
      */
 138  14
     public void configure( InputStream is )
 139   
         throws IOException, MalformedURLException, ConfigurationException,
 140   
         DuplicateRealmException, NoSuchRealmException
 141   
     {
 142  14
         Configurator configurator = new Configurator( this );
 143   
 
 144  14
         configurator.configure( is );
 145   
     }
 146   
 
 147   
     /**
 148   
      * Retrieve the main entry class.
 149   
      *
 150   
      * @return The main entry class.
 151   
      * @throws ClassNotFoundException If the class cannot be found.
 152   
      * @throws NoSuchRealmException   If the specified main entry realm does not exist.
 153   
      */
 154  46
     public Class getMainClass()
 155   
         throws ClassNotFoundException, NoSuchRealmException
 156   
     {
 157  46
         return getMainRealm().loadClass( getMainClassName() );
 158   
     }
 159   
 
 160   
     /**
 161   
      * Retrieve the main entry realm.
 162   
      *
 163   
      * @return The main entry realm.
 164   
      * @throws NoSuchRealmException If the specified main entry realm does not exist.
 165   
      */
 166  76
     public ClassRealm getMainRealm()
 167   
         throws NoSuchRealmException
 168   
     {
 169  76
         return getWorld().getRealm( getMainRealmName() );
 170   
     }
 171   
 
 172   
     /**
 173   
      * Retrieve the enhanced main entry method.
 174   
      *
 175   
      * @return The enhanced main entry method.
 176   
      * @throws ClassNotFoundException If the main entry class cannot be found.
 177   
      * @throws NoSuchMethodException  If the main entry method cannot be found.
 178   
      * @throws NoSuchRealmException   If the main entry realm cannot be found.
 179   
      */
 180  10
     protected Method getEnhancedMainMethod()
 181   
         throws ClassNotFoundException, NoSuchMethodException, NoSuchRealmException
 182   
     {
 183  10
         Method[] methods = getMainClass().getMethods();
 184  10
         Class cwClass = getMainRealm().loadClass( ClassWorld.class.getName() );
 185   
 
 186  10
         Method m = getMainClass().getMethod( "main", new Class[] { String[].class, cwClass } );
 187   
 
 188  4
         int modifiers = m.getModifiers();
 189   
 
 190  4
         if ( Modifier.isStatic( modifiers ) && Modifier.isPublic( modifiers ) )
 191   
         {
 192  4
             if ( m.getReturnType() == Integer.TYPE || m.getReturnType() == Void.TYPE )
 193   
             {
 194  4
                 return m;
 195   
             }
 196   
         }
 197   
 
 198  0
         throw new NoSuchMethodException( "public static void main(String[] args, ClassWorld world)" );
 199   
     }
 200   
 
 201   
     /**
 202   
      * Retrieve the main entry method.
 203   
      *
 204   
      * @return The main entry method.
 205   
      * @throws ClassNotFoundException If the main entry class cannot be found.
 206   
      * @throws NoSuchMethodException  If the main entry method cannot be found.
 207   
      * @throws NoSuchRealmException   If the main entry realm cannot be found.
 208   
      */
 209  6
     protected Method getMainMethod()
 210   
         throws ClassNotFoundException, NoSuchMethodException, NoSuchRealmException
 211   
     {
 212  6
         Method m = getMainClass().getMethod( "main", new Class[] { String[].class } );
 213   
 
 214  4
         int modifiers = m.getModifiers();
 215   
 
 216  4
         if ( Modifier.isStatic( modifiers ) && Modifier.isPublic( modifiers ) )
 217   
         {
 218  4
             if ( m.getReturnType() == Integer.TYPE || m.getReturnType() == Void.TYPE )
 219   
             {
 220  4
                 return m;
 221   
             }
 222   
         }
 223   
 
 224  0
         throw new NoSuchMethodException( "public static void main(String[] args) in " + getMainClass() );
 225   
     }
 226   
 
 227   
     /**
 228   
      * Launch the application.
 229   
      *
 230   
      * @param args The application args.
 231   
      * @throws ClassNotFoundException    If the main entry class cannot be found.
 232   
      * @throws IllegalAccessException    If the method cannot be accessed.
 233   
      * @throws InvocationTargetException If the target of the invokation is invalid.
 234   
      * @throws NoSuchMethodException     If the main entry method cannot be found.
 235   
      * @throws NoSuchRealmException      If the main entry realm cannot be found.
 236   
      */
 237  12
     public void launch( String[] args )
 238   
         throws ClassNotFoundException, IllegalAccessException,
 239   
         InvocationTargetException, NoSuchMethodException, NoSuchRealmException
 240   
     {
 241  12
         try
 242   
         {
 243  12
             launchEnhanced( args );
 244   
 
 245  4
             return;
 246   
         }
 247   
         catch ( NoSuchMethodException e )
 248   
         {
 249   
             // ignore
 250   
         }
 251   
 
 252  6
         launchStandard( args );
 253   
     }
 254   
 
 255   
     /**
 256   
      * Attempt to launch the application through the enhanced main method.
 257   
      * <p/>
 258   
      * <p/>
 259   
      * This will seek a method with the exact signature of:
 260   
      * </p>
 261   
      * <p/>
 262   
      * <pre>
 263   
      *  public static void main(String[] args, ClassWorld world)
 264   
      *  </pre>
 265   
      *
 266   
      * @param args The application args.
 267   
      * @throws ClassNotFoundException    If the main entry class cannot be found.
 268   
      * @throws IllegalAccessException    If the method cannot be accessed.
 269   
      * @throws InvocationTargetException If the target of the invokation is
 270   
      *                                   invalid.
 271   
      * @throws NoSuchMethodException     If the main entry method cannot be found.
 272   
      * @throws NoSuchRealmException      If the main entry realm cannot be found.
 273   
      */
 274  12
     protected void launchEnhanced( String[] args )
 275   
         throws ClassNotFoundException, IllegalAccessException,
 276   
         InvocationTargetException, NoSuchMethodException, NoSuchRealmException
 277   
     {
 278  12
         ClassRealm mainRealm = getMainRealm();
 279   
 
 280  12
         Class mainClass = getMainClass();
 281   
 
 282  10
         Method mainMethod = getEnhancedMainMethod();
 283   
 
 284  4
         ClassLoader cl = mainRealm.getClassLoader();
 285   
 
 286   
         // ----------------------------------------------------------------------
 287   
         // This is what the classloader for the main realm looks like when we
 288   
         // boot from the command line:
 289   
         // ----------------------------------------------------------------------
 290   
         // [ AppLauncher$AppClassLoader ] : $CLASSPATH envar
 291   
         //           ^
 292   
         //           |
 293   
         //           |
 294   
         // [ AppLauncher$ExtClassLoader ] : ${java.home}/jre/lib/ext/*.jar
 295   
         //           ^
 296   
         //           |
 297   
         //           |
 298   
         // [ RealmClassLoader ]
 299   
         // ----------------------------------------------------------------------
 300   
 
 301  4
         Thread.currentThread().setContextClassLoader( cl );
 302   
 
 303  4
         Object ret = mainMethod.invoke( mainClass, new Object[]{args, getWorld()} );
 304  4
         if ( ret instanceof Integer )
 305   
         {
 306  2
             exitCode = ( ( Integer ) ret ).intValue();
 307   
         }
 308   
     }
 309   
 
 310   
     /**
 311   
      * Attempt to launch the application through the standard main method.
 312   
      * <p/>
 313   
      * <p/>
 314   
      * This will seek a method with the exact signature of:
 315   
      * </p>
 316   
      * <p/>
 317   
      * <pre>
 318   
      *  public static void main(String[] args)
 319   
      *  </pre>
 320   
      *
 321   
      * @param args The application args.
 322   
      * @throws ClassNotFoundException    If the main entry class cannot be found.
 323   
      * @throws IllegalAccessException    If the method cannot be accessed.
 324   
      * @throws InvocationTargetException If the target of the invokation is
 325   
      *                                   invalid.
 326   
      * @throws NoSuchMethodException     If the main entry method cannot be found.
 327   
      * @throws NoSuchRealmException      If the main entry realm cannot be found.
 328   
      */
 329  6
     protected void launchStandard( String[] args )
 330   
         throws ClassNotFoundException, IllegalAccessException,
 331   
         InvocationTargetException, NoSuchMethodException, NoSuchRealmException
 332   
     {
 333  6
         ClassRealm mainRealm = getMainRealm();
 334   
 
 335  6
         Class mainClass = getMainClass();
 336   
 
 337  6
         Method mainMethod = getMainMethod();
 338   
 
 339  4
         Thread.currentThread().setContextClassLoader( mainRealm.getClassLoader() );
 340   
 
 341  4
         Object ret = mainMethod.invoke( mainClass, new Object[]{args} );
 342  4
         if ( ret instanceof Integer )
 343   
         {
 344  2
             exitCode = ( ( Integer ) ret ).intValue();
 345   
         }
 346   
     }
 347   
 
 348   
     // ------------------------------------------------------------
 349   
     //     Class methods
 350   
     // ------------------------------------------------------------
 351   
 
 352   
     /**
 353   
      * Launch the launcher from the command line.
 354   
      * Will exit using System.exit with an exit code of 0 for success, 100 if there was an unknown exception,
 355   
      * or some other code for an application error.
 356   
      *
 357   
      * @param args The application command-line arguments.
 358   
      */
 359  0
     public static void main( String[] args )
 360   
     {
 361  0
         try
 362   
         {
 363  0
             int exitCode = mainWithExitCode( args );
 364  0
             System.exit( exitCode );
 365   
         }
 366   
         catch ( Exception e )
 367   
         {
 368  0
             e.printStackTrace();
 369  0
             System.exit( 100 );
 370   
         }
 371   
     }
 372   
 
 373   
     /**
 374   
      * Launch the launcher.
 375   
      *
 376   
      * @param args The application command-line arguments.
 377   
      * @return an integer exit code
 378   
      * @throws Exception If an error occurs.
 379   
      */
 380  0
     public static int mainWithExitCode( String[] args )
 381   
         throws Exception
 382   
     {
 383  0
         String classworldsConf = System.getProperty( CLASSWORLDS_CONF );
 384   
 
 385  0
         InputStream is = null;
 386   
 
 387  0
         Launcher launcher = new Launcher();
 388   
 
 389  0
         if ( classworldsConf != null )
 390   
         {
 391  0
             is = new FileInputStream( classworldsConf );
 392   
         }
 393   
         else
 394   
         {
 395  0
             ClassLoader cl = Thread.currentThread().getContextClassLoader();
 396   
 
 397  0
             if ( "true".equals( System.getProperty( "classworlds.bootstrapped" ) ) )
 398   
             {
 399  0
                 is = cl.getResourceAsStream( UBERJAR_CONF_DIR + CLASSWORLDS_CONF );
 400   
             }
 401   
             else
 402   
             {
 403  0
                 is = cl.getResourceAsStream( CLASSWORLDS_CONF );
 404   
             }
 405   
         }
 406   
 
 407  0
         if ( is == null )
 408   
         {
 409  0
             throw new Exception( "classworlds configuration not specified nor found in the classpath" );
 410   
         }
 411   
 
 412  0
         launcher.configure( is );
 413   
 
 414  0
         try
 415   
         {
 416  0
             launcher.launch( args );
 417   
         }
 418   
         catch ( InvocationTargetException e )
 419   
         {
 420  0
             ClassRealm realm = launcher.getWorld().getRealm( launcher.getMainRealmName() );
 421   
 
 422  0
             URL[] constituents = realm.getConstituents();
 423   
 
 424  0
             System.out.println( "---------------------------------------------------" );
 425   
 
 426  0
             for ( int i = 0; i < constituents.length; i++ )
 427   
             {
 428  0
                 System.out.println( "constituent[" + i + "]: " + constituents[i] );
 429   
             }
 430   
 
 431  0
             System.out.println( "---------------------------------------------------" );
 432   
 
 433   
             // Decode ITE (if we can)
 434  0
             Throwable t = e.getTargetException();
 435   
 
 436  0
             if ( t instanceof Exception )
 437   
             {
 438  0
                 throw (Exception) t;
 439   
             }
 440  0
             if ( t instanceof Error )
 441   
             {
 442  0
                 throw (Error) t;
 443   
             }
 444   
 
 445   
             // Else just toss the ITE
 446  0
             throw e;
 447   
         }
 448   
 
 449  0
         return launcher.getExitCode();
 450   
     }
 451   
 }
 452