All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.plexus.classworlds.launcher.Launcher Maven / Gradle / Ivy

There is a newer version: 2.8.0
Show newest version
package org.codehaus.plexus.classworlds.launcher;

/*
 * Copyright 2001-2006 Codehaus Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;

import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;

/**
 * 

Command-line invokable application launcher.

* *

This launcher class assists in the creation of classloaders and ClassRealms * from a configuration file and the launching of the application's main * method from the correct class loaded through the correct classloader.

* *

The path to the configuration file is specified using the classworlds.conf * system property, typically specified using the -D switch to * java.

* * @author bob mcwhirter */ public class Launcher { protected static final String CLASSWORLDS_CONF = "classworlds.conf"; protected static final String UBERJAR_CONF_DIR = "WORLDS-INF/conf/"; protected ClassLoader systemClassLoader; protected String mainClassName; protected String mainRealmName; protected ClassWorld world; private int exitCode = 0; public Launcher() { this.systemClassLoader = Thread.currentThread().getContextClassLoader(); } public void setSystemClassLoader( ClassLoader loader ) { this.systemClassLoader = loader; } public ClassLoader getSystemClassLoader() { return this.systemClassLoader; } public int getExitCode() { return exitCode; } public void setAppMain( String mainClassName, String mainRealmName ) { this.mainClassName = mainClassName; this.mainRealmName = mainRealmName; } public String getMainRealmName() { return this.mainRealmName; } public String getMainClassName() { return this.mainClassName; } public void setWorld( ClassWorld world ) { this.world = world; } public ClassWorld getWorld() { return this.world; } /** * Configure from a file. * * @param is The config input stream. * @throws IOException If an error occurs reading the config file. * @throws MalformedURLException If the config file contains invalid URLs. * @throws ConfigurationException If the config file is corrupt. * @throws org.codehaus.plexus.classworlds.realm.DuplicateRealmException If the config file defines two realms * with the same id. * @throws org.codehaus.plexus.classworlds.realm.NoSuchRealmException If the config file defines a main entry * point in a non-existent realm. */ public void configure( InputStream is ) throws IOException, ConfigurationException, DuplicateRealmException, NoSuchRealmException { Configurator configurator = new Configurator( this ); configurator.configure( is ); } /** * Retrieve the main entry class. * * @return The main entry class. * @throws ClassNotFoundException If the class cannot be found. * @throws NoSuchRealmException If the specified main entry realm does not exist. */ public Class getMainClass() throws ClassNotFoundException, NoSuchRealmException { return getMainRealm().loadClass( getMainClassName() ); } /** * Retrieve the main entry realm. * * @return The main entry realm. * @throws NoSuchRealmException If the specified main entry realm does not exist. */ public ClassRealm getMainRealm() throws NoSuchRealmException { return getWorld().getRealm( getMainRealmName() ); } /** * Retrieve the enhanced main entry method. * * @return The enhanced main entry method. * @throws ClassNotFoundException If the main entry class cannot be found. * @throws NoSuchMethodException If the main entry method cannot be found. * @throws NoSuchRealmException If the main entry realm cannot be found. */ protected Method getEnhancedMainMethod() throws ClassNotFoundException, NoSuchMethodException, NoSuchRealmException { Class cwClass = getMainRealm().loadClass( ClassWorld.class.getName() ); Method m = getMainClass().getMethod( "main", new Class[]{String[].class, cwClass} ); int modifiers = m.getModifiers(); if ( Modifier.isStatic( modifiers ) && Modifier.isPublic( modifiers ) ) { if ( m.getReturnType() == Integer.TYPE || m.getReturnType() == Void.TYPE ) { return m; } } throw new NoSuchMethodException( "public static void main(String[] args, ClassWorld world)" ); } /** * Retrieve the main entry method. * * @return The main entry method. * @throws ClassNotFoundException If the main entry class cannot be found. * @throws NoSuchMethodException If the main entry method cannot be found. * @throws NoSuchRealmException If the main entry realm cannot be found. */ protected Method getMainMethod() throws ClassNotFoundException, NoSuchMethodException, NoSuchRealmException { Method m = getMainClass().getMethod( "main", new Class[]{String[].class} ); int modifiers = m.getModifiers(); if ( Modifier.isStatic( modifiers ) && Modifier.isPublic( modifiers ) ) { if ( m.getReturnType() == Integer.TYPE || m.getReturnType() == Void.TYPE ) { return m; } } throw new NoSuchMethodException( "public static void main(String[] args) in " + getMainClass() ); } /** * Launch the application. * * @param args The application args. * @throws ClassNotFoundException If the main entry class cannot be found. * @throws IllegalAccessException If the method cannot be accessed. * @throws InvocationTargetException If the target of the invokation is invalid. * @throws NoSuchMethodException If the main entry method cannot be found. * @throws NoSuchRealmException If the main entry realm cannot be found. */ public void launch( String[] args ) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchRealmException { try { launchEnhanced( args ); return; } catch ( NoSuchMethodException e ) { // ignore } launchStandard( args ); } /** *

Attempt to launch the application through the enhanced main method.

* *

This will seek a method with the exact signature of:

*
     *  public static void main(String[] args, ClassWorld world)
     *  
* * @param args The application args. * @throws ClassNotFoundException If the main entry class cannot be found. * @throws IllegalAccessException If the method cannot be accessed. * @throws InvocationTargetException If the target of the invokation is * invalid. * @throws NoSuchMethodException If the main entry method cannot be found. * @throws NoSuchRealmException If the main entry realm cannot be found. */ protected void launchEnhanced( String[] args ) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchRealmException { ClassRealm mainRealm = getMainRealm(); Class mainClass = getMainClass(); Method mainMethod = getEnhancedMainMethod(); ClassLoader cl = mainRealm; // ---------------------------------------------------------------------- // This is what the classloader for the main realm looks like when we // boot from the command line: // ---------------------------------------------------------------------- // [ AppLauncher$AppClassLoader ] : $CLASSPATH envar // ^ // | // | // [ AppLauncher$ExtClassLoader ] : ${java.home}/jre/lib/ext/*.jar // ^ // | // | // [ Strategy ] // ---------------------------------------------------------------------- Thread.currentThread().setContextClassLoader( cl ); Object ret = mainMethod.invoke( mainClass, new Object[]{args, getWorld()} ); if ( ret instanceof Integer ) { exitCode = ( (Integer) ret ).intValue(); } Thread.currentThread().setContextClassLoader( systemClassLoader ); } /** *

Attempt to launch the application through the standard main method.

* *

This will seek a method with the exact signature of:

*
     *  public static void main(String[] args)
     *  
* * @param args The application args. * @throws ClassNotFoundException If the main entry class cannot be found. * @throws IllegalAccessException If the method cannot be accessed. * @throws InvocationTargetException If the target of the invokation is * invalid. * @throws NoSuchMethodException If the main entry method cannot be found. * @throws NoSuchRealmException If the main entry realm cannot be found. */ protected void launchStandard( String[] args ) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, NoSuchRealmException { ClassRealm mainRealm = getMainRealm(); Class mainClass = getMainClass(); Method mainMethod = getMainMethod(); Thread.currentThread().setContextClassLoader( mainRealm ); Object ret = mainMethod.invoke( mainClass, new Object[]{args} ); if ( ret instanceof Integer ) { exitCode = ( (Integer) ret ).intValue(); } Thread.currentThread().setContextClassLoader( systemClassLoader ); } // ------------------------------------------------------------ // Class methods // ------------------------------------------------------------ /** * Launch the launcher from the command line. * Will exit using System.exit with an exit code of 0 for success, 100 if there was an unknown exception, * or some other code for an application error. * * @param args The application command-line arguments. */ public static void main( String[] args ) { try { int exitCode = mainWithExitCode( args ); System.exit( exitCode ); } catch ( Exception e ) { e.printStackTrace(); System.exit( 100 ); } } /** * Launch the launcher. * * @param args The application command-line arguments. * @return an integer exit code * @throws Exception If an error occurs. */ public static int mainWithExitCode( String[] args ) throws Exception { String classworldsConf = System.getProperty( CLASSWORLDS_CONF ); InputStream is; Launcher launcher = new Launcher(); ClassLoader cl = Thread.currentThread().getContextClassLoader(); launcher.setSystemClassLoader( cl ); if ( classworldsConf != null ) { is = new FileInputStream( classworldsConf ); } else { if ( "true".equals( System.getProperty( "classworlds.bootstrapped" ) ) ) { is = cl.getResourceAsStream( UBERJAR_CONF_DIR + CLASSWORLDS_CONF ); } else { is = cl.getResourceAsStream( CLASSWORLDS_CONF ); } } if ( is == null ) { throw new Exception( "classworlds configuration not specified nor found in the classpath" ); } launcher.configure( is ); is.close(); try { launcher.launch( args ); } catch ( InvocationTargetException e ) { ClassRealm realm = launcher.getWorld().getRealm( launcher.getMainRealmName() ); URL[] constituents = realm.getURLs(); System.out.println( "---------------------------------------------------" ); for ( int i = 0; i < constituents.length; i++ ) { System.out.println( "constituent[" + i + "]: " + constituents[i] ); } System.out.println( "---------------------------------------------------" ); // Decode ITE (if we can) Throwable t = e.getTargetException(); if ( t instanceof Exception ) { throw (Exception) t; } if ( t instanceof Error ) { throw (Error) t; } // Else just toss the ITE throw e; } return launcher.getExitCode(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy