than using the container classloader. * DefaultWorkspace and ExecManagerFactory figure out myrmidon.home using their parameters, rather than using system properties. * Split embeddor/workspace/project handling code out of CLIMain into a new EmbeddedAnt helper class. CLIMain is now responsible for setting up the logger, and command-line option handling. EmbeddedAnt is responsible for starting the embeddor, building the project, and executing targets (and cleaning-up). Should make it considerably simpler to embed myrmidon. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271987 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -74,6 +74,7 @@ public class DefaultEmbeddor | |||||
| private File m_homeDir; | private File m_homeDir; | ||||
| private File m_taskLibDir; | private File m_taskLibDir; | ||||
| private static final String MYRMIDON_HOME = "myrmidon.home"; | |||||
| /** | /** | ||||
| * Setup basic properties of engine. | * Setup basic properties of engine. | ||||
| @@ -133,6 +134,9 @@ public class DefaultEmbeddor | |||||
| { | { | ||||
| final Workspace workspace = | final Workspace workspace = | ||||
| (Workspace)createService( Workspace.class, PREFIX + "workspace.DefaultWorkspace" ); | (Workspace)createService( Workspace.class, PREFIX + "workspace.DefaultWorkspace" ); | ||||
| // TODO - don't do this; need some way to pass separate sets of defines and config | |||||
| // to the workspace | |||||
| parameters.setParameter( MYRMIDON_HOME, m_parameters.getParameter( MYRMIDON_HOME ) ); | |||||
| setupObject( workspace, m_workspaceServiceManager, parameters ); | setupObject( workspace, m_workspaceServiceManager, parameters ); | ||||
| return workspace; | return workspace; | ||||
| } | } | ||||
| @@ -186,7 +190,7 @@ public class DefaultEmbeddor | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| // Deploy all type libraries found in the classpath | // Deploy all type libraries found in the classpath | ||||
| final ClassLoader libClassloader = Thread.currentThread().getContextClassLoader(); | |||||
| final ClassLoader libClassloader = getClass().getClassLoader(); | |||||
| final TypeDeployer typeDeployer = m_deployer.createDeployer( libClassloader ); | final TypeDeployer typeDeployer = m_deployer.createDeployer( libClassloader ); | ||||
| typeDeployer.deployAll(); | typeDeployer.deployAll(); | ||||
| @@ -297,7 +301,7 @@ public class DefaultEmbeddor | |||||
| { | { | ||||
| String filepath = null; | String filepath = null; | ||||
| filepath = getParameter( "myrmidon.home" ); | |||||
| filepath = getParameter( MYRMIDON_HOME ); | |||||
| m_homeDir = ( new File( filepath ) ).getAbsoluteFile(); | m_homeDir = ( new File( filepath ) ).getAbsoluteFile(); | ||||
| checkDirectory( m_homeDir, "home-dir.name" ); | checkDirectory( m_homeDir, "home-dir.name" ); | ||||
| @@ -147,7 +147,7 @@ public class DefaultWorkspace | |||||
| } | } | ||||
| private File findTypeLib( final String libraryName ) | private File findTypeLib( final String libraryName ) | ||||
| throws TaskException | |||||
| throws Exception | |||||
| { | { | ||||
| //TODO: In future this will be expanded to allow | //TODO: In future this will be expanded to allow | ||||
| //users to specify search path or automagically | //users to specify search path or automagically | ||||
| @@ -155,7 +155,7 @@ public class DefaultWorkspace | |||||
| //workspace specific) | //workspace specific) | ||||
| final String name = libraryName.replace( '/', File.separatorChar ) + ".atl"; | final String name = libraryName.replace( '/', File.separatorChar ) + ".atl"; | ||||
| final String home = System.getProperty( "myrmidon.home" ); | |||||
| final String home = m_parameters.getParameter( "myrmidon.home" ); | |||||
| final File homeDir = new File( home + File.separatorChar + "ext" ); | final File homeDir = new File( home + File.separatorChar + "ext" ); | ||||
| final File library = new File( homeDir, name ); | final File library = new File( homeDir, name ); | ||||
| @@ -178,7 +178,7 @@ public class DefaultWorkspace | |||||
| } | } | ||||
| private void deployTypeLib( final Deployer deployer, final Project project ) | private void deployTypeLib( final Deployer deployer, final Project project ) | ||||
| throws TaskException | |||||
| throws Exception | |||||
| { | { | ||||
| final TypeLib[] typeLibs = project.getTypeLibs(); | final TypeLib[] typeLibs = project.getTypeLibs(); | ||||
| @@ -213,7 +213,7 @@ public class DefaultWorkspace | |||||
| * Creates an execution frame for a project. | * Creates an execution frame for a project. | ||||
| */ | */ | ||||
| private ExecutionFrame createExecutionFrame( final Project project ) | private ExecutionFrame createExecutionFrame( final Project project ) | ||||
| throws TaskException, ServiceException | |||||
| throws Exception | |||||
| { | { | ||||
| //Create per frame ComponentManager | //Create per frame ComponentManager | ||||
| final DefaultServiceManager serviceManager = | final DefaultServiceManager serviceManager = | ||||
| @@ -12,6 +12,9 @@ import org.apache.aut.nativelib.ExecException; | |||||
| import org.apache.aut.nativelib.impl.DefaultExecManager; | import org.apache.aut.nativelib.impl.DefaultExecManager; | ||||
| import org.apache.avalon.excalibur.i18n.ResourceManager; | import org.apache.avalon.excalibur.i18n.ResourceManager; | ||||
| import org.apache.avalon.excalibur.i18n.Resources; | import org.apache.avalon.excalibur.i18n.Resources; | ||||
| import org.apache.avalon.framework.parameters.Parameterizable; | |||||
| import org.apache.avalon.framework.parameters.Parameters; | |||||
| import org.apache.avalon.framework.parameters.ParameterException; | |||||
| import org.apache.myrmidon.interfaces.service.AntServiceException; | import org.apache.myrmidon.interfaces.service.AntServiceException; | ||||
| import org.apache.myrmidon.interfaces.service.ServiceFactory; | import org.apache.myrmidon.interfaces.service.ServiceFactory; | ||||
| @@ -22,23 +25,31 @@ import org.apache.myrmidon.interfaces.service.ServiceFactory; | |||||
| * @version $Revision$ $Date$ | * @version $Revision$ $Date$ | ||||
| */ | */ | ||||
| public class ExecManagerFactory | public class ExecManagerFactory | ||||
| implements ServiceFactory | |||||
| implements ServiceFactory, Parameterizable | |||||
| { | { | ||||
| private final static Resources REZ = | private final static Resources REZ = | ||||
| ResourceManager.getPackageResources( ExecManagerFactory.class ); | ResourceManager.getPackageResources( ExecManagerFactory.class ); | ||||
| private Parameters m_parameters; | |||||
| public void parameterize( final Parameters parameters ) | |||||
| throws ParameterException | |||||
| { | |||||
| m_parameters = parameters; | |||||
| } | |||||
| /** | /** | ||||
| * Create the ExecManager Service. | * Create the ExecManager Service. | ||||
| */ | */ | ||||
| public Object createService() | public Object createService() | ||||
| throws AntServiceException | throws AntServiceException | ||||
| { | { | ||||
| final File home = getHomeDirectory(); | |||||
| try | try | ||||
| { | { | ||||
| final File home = getHomeDirectory(); | |||||
| return new DefaultExecManager( home ); | return new DefaultExecManager( home ); | ||||
| } | } | ||||
| catch( final ExecException ee ) | |||||
| catch( final Exception ee ) | |||||
| { | { | ||||
| throw new AntServiceException( ee.getMessage(), ee ); | throw new AntServiceException( ee.getMessage(), ee ); | ||||
| } | } | ||||
| @@ -47,10 +58,10 @@ public class ExecManagerFactory | |||||
| /** | /** | ||||
| * Utility method to retrieve home directory. | * Utility method to retrieve home directory. | ||||
| */ | */ | ||||
| private static File getHomeDirectory() | |||||
| throws AntServiceException | |||||
| private File getHomeDirectory() | |||||
| throws Exception | |||||
| { | { | ||||
| final String home = System.getProperty( "myrmidon.home" ); | |||||
| final String home = m_parameters.getParameter( "myrmidon.home" ); | |||||
| if( null == home ) | if( null == home ) | ||||
| { | { | ||||
| final String message = REZ.getString( "missing-home-dir.error" ); | final String message = REZ.getString( "missing-home-dir.error" ); | ||||
| @@ -8,10 +8,12 @@ | |||||
| package org.apache.myrmidon.frontends; | package org.apache.myrmidon.frontends; | ||||
| import java.io.BufferedReader; | import java.io.BufferedReader; | ||||
| import java.io.File; | |||||
| import java.io.InputStreamReader; | import java.io.InputStreamReader; | ||||
| import java.io.File; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Map; | |||||
| import java.util.HashMap; | |||||
| import org.apache.avalon.excalibur.cli.CLArgsParser; | import org.apache.avalon.excalibur.cli.CLArgsParser; | ||||
| import org.apache.avalon.excalibur.cli.CLOption; | import org.apache.avalon.excalibur.cli.CLOption; | ||||
| import org.apache.avalon.excalibur.cli.CLOptionDescriptor; | import org.apache.avalon.excalibur.cli.CLOptionDescriptor; | ||||
| @@ -20,15 +22,9 @@ import org.apache.avalon.excalibur.i18n.ResourceManager; | |||||
| import org.apache.avalon.excalibur.i18n.Resources; | import org.apache.avalon.excalibur.i18n.Resources; | ||||
| import org.apache.avalon.framework.CascadingException; | import org.apache.avalon.framework.CascadingException; | ||||
| import org.apache.avalon.framework.ExceptionUtil; | import org.apache.avalon.framework.ExceptionUtil; | ||||
| import org.apache.avalon.framework.logger.AbstractLogEnabled; | |||||
| import org.apache.avalon.framework.parameters.Parameters; | |||||
| import org.apache.myrmidon.Constants; | import org.apache.myrmidon.Constants; | ||||
| import org.apache.myrmidon.api.TaskException; | import org.apache.myrmidon.api.TaskException; | ||||
| import org.apache.myrmidon.interfaces.embeddor.Embeddor; | |||||
| import org.apache.myrmidon.interfaces.executor.Executor; | import org.apache.myrmidon.interfaces.executor.Executor; | ||||
| import org.apache.myrmidon.interfaces.model.Project; | |||||
| import org.apache.myrmidon.interfaces.workspace.Workspace; | |||||
| import org.apache.myrmidon.listeners.ProjectListener; | |||||
| /** | /** | ||||
| * The class to kick the tires and light the fires. | * The class to kick the tires and light the fires. | ||||
| @@ -39,14 +35,10 @@ import org.apache.myrmidon.listeners.ProjectListener; | |||||
| * @version $Revision$ $Date$ | * @version $Revision$ $Date$ | ||||
| */ | */ | ||||
| public class CLIMain | public class CLIMain | ||||
| extends AbstractLogEnabled | |||||
| { | { | ||||
| private final static Resources REZ = | private final static Resources REZ = | ||||
| ResourceManager.getPackageResources( CLIMain.class ); | ResourceManager.getPackageResources( CLIMain.class ); | ||||
| private static final String DEFAULT_EMBEDDOR_CLASS = | |||||
| "org.apache.myrmidon.components.embeddor.DefaultEmbeddor"; | |||||
| //defines for the Command Line options | //defines for the Command Line options | ||||
| private final static int HELP_OPT = 'h'; | private final static int HELP_OPT = 'h'; | ||||
| private final static int QUIET_OPT = 'q'; | private final static int QUIET_OPT = 'q'; | ||||
| @@ -84,23 +76,19 @@ public class CLIMain | |||||
| LISTENER_OPT, NO_PREFIX_OPT | LISTENER_OPT, NO_PREFIX_OPT | ||||
| }; | }; | ||||
| ///Parameters for run of myrmidon | |||||
| private Parameters m_parameters = new Parameters(); | |||||
| ///List of targets supplied on command line to execute | ///List of targets supplied on command line to execute | ||||
| private ArrayList m_targets = new ArrayList(); | private ArrayList m_targets = new ArrayList(); | ||||
| ///List of user supplied defines | |||||
| private Parameters m_defines = new Parameters(); | |||||
| ///List of user supplied parameters for builder | |||||
| private Parameters m_builderParameters = new Parameters(); | |||||
| ///Determine whether tasks are actually executed | ///Determine whether tasks are actually executed | ||||
| private boolean m_dryRun = false; | private boolean m_dryRun = false; | ||||
| ///Enables incremental mode | |||||
| private boolean m_incremental; | |||||
| ///The launcher | |||||
| private EmbeddedAnt m_embedded = new EmbeddedAnt(); | |||||
| ///Log level to use | ///Log level to use | ||||
| //private static Priority m_priority = Priority.WARN; | |||||
| private static int m_priority = BasicLogger.LEVEL_WARN; | private static int m_priority = BasicLogger.LEVEL_WARN; | ||||
| /** | /** | ||||
| @@ -109,12 +97,24 @@ public class CLIMain | |||||
| * @param args the args | * @param args the args | ||||
| */ | */ | ||||
| public static void main( final String[] args ) | public static void main( final String[] args ) | ||||
| { | |||||
| final Map properties = new HashMap(); | |||||
| properties.put( "myrmidon.home", new File( "." ) ); | |||||
| main( properties, args ); | |||||
| } | |||||
| /** | |||||
| * Main entry point called to run standard Myrmidon. | |||||
| * | |||||
| * @param args the args | |||||
| */ | |||||
| public static void main( final Map properties, final String[] args ) | |||||
| { | { | ||||
| int exitCode = 0; | int exitCode = 0; | ||||
| final CLIMain main = new CLIMain(); | final CLIMain main = new CLIMain(); | ||||
| try | try | ||||
| { | { | ||||
| main.execute( args ); | |||||
| main.execute( properties, args ); | |||||
| } | } | ||||
| catch( final Throwable throwable ) | catch( final Throwable throwable ) | ||||
| { | { | ||||
| @@ -243,10 +243,10 @@ public class CLIMain | |||||
| return false; | return false; | ||||
| case HOME_DIR_OPT: | case HOME_DIR_OPT: | ||||
| m_parameters.setParameter( "myrmidon.home", option.getArgument() ); | |||||
| m_embedded.setEmbeddorProperty( "myrmidon.home", option.getArgument() ); | |||||
| break; | break; | ||||
| case TASKLIB_DIR_OPT: | case TASKLIB_DIR_OPT: | ||||
| m_parameters.setParameter( "myrmidon.lib.path", option.getArgument() ); | |||||
| m_embedded.setEmbeddorProperty( "myrmidon.lib.path", option.getArgument() ); | |||||
| break; | break; | ||||
| case LOG_LEVEL_OPT: | case LOG_LEVEL_OPT: | ||||
| @@ -260,26 +260,26 @@ public class CLIMain | |||||
| break; | break; | ||||
| case INCREMENTAL_OPT: | case INCREMENTAL_OPT: | ||||
| m_parameters.setParameter( "incremental", "true" ); | |||||
| m_incremental = true; | |||||
| break; | break; | ||||
| case FILE_OPT: | case FILE_OPT: | ||||
| m_parameters.setParameter( "filename", option.getArgument() ); | |||||
| m_embedded.setProjectFile( option.getArgument() ); | |||||
| break; | break; | ||||
| case LISTENER_OPT: | case LISTENER_OPT: | ||||
| m_parameters.setParameter( "listener", option.getArgument() ); | |||||
| m_embedded.setListener( option.getArgument() ); | |||||
| break; | break; | ||||
| case NO_PREFIX_OPT: | case NO_PREFIX_OPT: | ||||
| m_parameters.setParameter( "listener", "noprefix" ); | |||||
| m_embedded.setListener( "noprefix" ); | |||||
| break; | break; | ||||
| case DEFINE_OPT: | case DEFINE_OPT: | ||||
| m_defines.setParameter( option.getArgument( 0 ), option.getArgument( 1 ) ); | |||||
| m_embedded.setWorkspaceProperty( option.getArgument( 0 ), option.getArgument( 1 ) ); | |||||
| break; | break; | ||||
| case BUILDER_PARAM_OPT: | case BUILDER_PARAM_OPT: | ||||
| m_builderParameters.setParameter( option.getArgument( 0 ), option.getArgument( 1 ) ); | |||||
| m_embedded.setBuilderProperty( option.getArgument( 0 ), option.getArgument( 1 ) ); | |||||
| break; | break; | ||||
| case DRY_RUN_OPT: | case DRY_RUN_OPT: | ||||
| @@ -295,61 +295,42 @@ public class CLIMain | |||||
| return true; | return true; | ||||
| } | } | ||||
| private void setupDefaultParameters() | |||||
| { | |||||
| //System property set up by launcher | |||||
| m_parameters.setParameter( "myrmidon.home", System.getProperty( "myrmidon.home", "." ) ); | |||||
| m_parameters.setParameter( "filename", "build.ant" ); | |||||
| m_parameters.setParameter( "log.level", "WARN" ); | |||||
| m_parameters.setParameter( "listener", "default" ); | |||||
| m_parameters.setParameter( "incremental", "false" ); | |||||
| } | |||||
| private void execute( final String[] args ) | |||||
| private void execute( final Map properties, final String[] args ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| setupDefaultParameters(); | |||||
| if( !parseCommandLineOptions( args ) ) | |||||
| try | |||||
| { | { | ||||
| return; | |||||
| } | |||||
| prepareLogging(); | |||||
| checkHomeDir(); | |||||
| final File buildFile = getBuildFile(); | |||||
| //getLogger().debug( "Ant Bin Directory: " + m_binDir ); | |||||
| //getLogger().debug( "Ant Lib Directory: " + m_libDir ); | |||||
| //getLogger().debug( "Ant Task Lib Directory: " + m_taskLibDir ); | |||||
| // Set system properties set up by launcher | |||||
| m_embedded.setEmbeddorProperty( "myrmidon.home", properties.get( "myrmidon.home" ) ); | |||||
| if( m_dryRun ) | |||||
| { | |||||
| m_parameters.setParameter( Executor.ROLE, | |||||
| "org.apache.myrmidon.components.executor.PrintingExecutor" ); | |||||
| } | |||||
| // Command line | |||||
| if( !parseCommandLineOptions( args ) ) | |||||
| { | |||||
| return; | |||||
| } | |||||
| final Embeddor embeddor = prepareEmbeddor(); | |||||
| // Setup logging | |||||
| final BasicLogger logger = new BasicLogger( "[myrmidon] ", m_priority ); | |||||
| m_embedded.setLogger( logger ); | |||||
| try | |||||
| { | |||||
| final ProjectListener listener = prepareListener( embeddor ); | |||||
| if( m_dryRun ) | |||||
| { | |||||
| m_embedded.setEmbeddorProperty( Executor.ROLE, | |||||
| "org.apache.myrmidon.components.executor.PrintingExecutor" ); | |||||
| } | |||||
| //create the project | |||||
| final Project project = | |||||
| embeddor.createProject( buildFile.toString(), null, m_builderParameters ); | |||||
| // Set the common classloader | |||||
| final ClassLoader sharedClassLoader = (ClassLoader)properties.get( "myrmidon.shared.classloader" ); | |||||
| m_embedded.setSharedClassLoader( sharedClassLoader ); | |||||
| //loop over build if we are in incremental mode.. | //loop over build if we are in incremental mode.. | ||||
| final boolean incremental = m_parameters.getParameterAsBoolean( "incremental", false ); | |||||
| if( !incremental ) | |||||
| if( !m_incremental ) | |||||
| { | { | ||||
| executeBuild( embeddor, project, listener ); | |||||
| executeBuild(); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| executeIncrementalBuild( embeddor, project, listener ); | |||||
| executeIncrementalBuild(); | |||||
| } | } | ||||
| } | } | ||||
| catch( final Exception e ) | catch( final Exception e ) | ||||
| @@ -359,13 +340,11 @@ public class CLIMain | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| shutdownEmbeddor( embeddor ); | |||||
| m_embedded.stop(); | |||||
| } | } | ||||
| } | } | ||||
| private void executeIncrementalBuild( final Embeddor embeddor, | |||||
| final Project project, | |||||
| final ProjectListener listener ) | |||||
| private void executeIncrementalBuild() | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| BufferedReader reader = null; | BufferedReader reader = null; | ||||
| @@ -374,7 +353,7 @@ public class CLIMain | |||||
| { | { | ||||
| try | try | ||||
| { | { | ||||
| executeBuild( embeddor, project, listener ); | |||||
| executeBuild(); | |||||
| } | } | ||||
| catch( final TaskException te ) | catch( final TaskException te ) | ||||
| { | { | ||||
| @@ -398,6 +377,13 @@ public class CLIMain | |||||
| } | } | ||||
| } | } | ||||
| private void executeBuild() throws Exception | |||||
| { | |||||
| //actually do the build ... | |||||
| final String[] targets = (String[])m_targets.toArray( new String[m_targets.size() ] ); | |||||
| m_embedded.executeTargets( targets ); | |||||
| } | |||||
| /** | /** | ||||
| * Builds the error message for an exception | * Builds the error message for an exception | ||||
| */ | */ | ||||
| @@ -426,131 +412,7 @@ public class CLIMain | |||||
| } | } | ||||
| // Write the message out | // Write the message out | ||||
| if( getLogger() == null ) | |||||
| { | |||||
| System.err.println( message ); | |||||
| } | |||||
| else | |||||
| { | |||||
| getLogger().error( message ); | |||||
| } | |||||
| } | |||||
| private void executeBuild( final Embeddor embeddor, | |||||
| final Project project, | |||||
| final ProjectListener listener ) | |||||
| throws Exception | |||||
| { | |||||
| //actually do the build ... | |||||
| final Workspace workspace = embeddor.createWorkspace( m_defines ); | |||||
| workspace.addProjectListener( listener ); | |||||
| doBuild( workspace, project, m_targets ); | |||||
| } | |||||
| private File getBuildFile() throws Exception | |||||
| { | |||||
| final String filename = m_parameters.getParameter( "filename", null ); | |||||
| final File buildFile = ( new File( filename ) ).getCanonicalFile(); | |||||
| if( !buildFile.isFile() ) | |||||
| { | |||||
| final String message = REZ.getString( "bad-file.error", buildFile ); | |||||
| throw new Exception( message ); | |||||
| } | |||||
| if( getLogger().isInfoEnabled() ) | |||||
| { | |||||
| final String message = REZ.getString( "buildfile.notice", buildFile ); | |||||
| getLogger().info( message ); | |||||
| } | |||||
| return buildFile; | |||||
| } | |||||
| private void checkHomeDir() throws Exception | |||||
| { | |||||
| final String home = m_parameters.getParameter( "myrmidon.home" ); | |||||
| final File homeDir = ( new File( home ) ).getAbsoluteFile(); | |||||
| if( !homeDir.isDirectory() ) | |||||
| { | |||||
| final String message = REZ.getString( "home-not-dir.error", homeDir ); | |||||
| throw new Exception( message ); | |||||
| } | |||||
| if( getLogger().isInfoEnabled() ) | |||||
| { | |||||
| final String message = REZ.getString( "homedir.notice", homeDir ); | |||||
| getLogger().info( message ); | |||||
| } | |||||
| } | |||||
| private void prepareLogging() throws Exception | |||||
| { | |||||
| //handle logging... | |||||
| final BasicLogger logger = new BasicLogger( "[myrmidon] ", m_priority ); | |||||
| enableLogging( logger ); | |||||
| } | |||||
| private void shutdownEmbeddor( final Embeddor embeddor ) | |||||
| throws Exception | |||||
| { | |||||
| embeddor.stop(); | |||||
| embeddor.dispose(); | |||||
| } | |||||
| private ProjectListener prepareListener( final Embeddor embeddor ) | |||||
| throws Exception | |||||
| { | |||||
| //create the listener | |||||
| final String listenerName = m_parameters.getParameter( "listener", null ); | |||||
| final ProjectListener listener = embeddor.createListener( listenerName ); | |||||
| return listener; | |||||
| } | |||||
| private Embeddor prepareEmbeddor() | |||||
| throws Exception | |||||
| { | |||||
| final Embeddor embeddor = createEmbeddor(); | |||||
| setupLogger( embeddor ); | |||||
| embeddor.parameterize( m_parameters ); | |||||
| embeddor.initialize(); | |||||
| embeddor.start(); | |||||
| return embeddor; | |||||
| } | |||||
| private Embeddor createEmbeddor() | |||||
| throws Exception | |||||
| { | |||||
| final Class clazz = Class.forName( DEFAULT_EMBEDDOR_CLASS ); | |||||
| return (Embeddor)clazz.newInstance(); | |||||
| } | |||||
| /** | |||||
| * Actually do the build. | |||||
| * | |||||
| * @param workspace the workspace | |||||
| * @param project the project | |||||
| * @param targets the targets to build as passed by CLI | |||||
| */ | |||||
| private void doBuild( final Workspace workspace, | |||||
| final Project project, | |||||
| final ArrayList targets ) | |||||
| throws TaskException | |||||
| { | |||||
| final int targetCount = targets.size(); | |||||
| //if we didn't specify a target on CLI then choose default | |||||
| if( 0 == targetCount ) | |||||
| { | |||||
| workspace.executeProject( project, project.getDefaultTargetName() ); | |||||
| } | |||||
| else | |||||
| { | |||||
| for( int i = 0; i < targetCount; i++ ) | |||||
| { | |||||
| workspace.executeProject( project, (String)targets.get( i ) ); | |||||
| } | |||||
| } | |||||
| System.err.println( message ); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -0,0 +1,295 @@ | |||||
| /* | |||||
| * Copyright (C) The Apache Software Foundation. All rights reserved. | |||||
| * | |||||
| * This software is published under the terms of the Apache Software License | |||||
| * version 1.1, a copy of which has been included with this distribution in | |||||
| * the LICENSE.txt file. | |||||
| */ | |||||
| package org.apache.myrmidon.frontends; | |||||
| import java.io.File; | |||||
| import org.apache.avalon.excalibur.i18n.ResourceManager; | |||||
| import org.apache.avalon.excalibur.i18n.Resources; | |||||
| import org.apache.avalon.framework.logger.AbstractLogEnabled; | |||||
| import org.apache.avalon.framework.logger.Logger; | |||||
| import org.apache.avalon.framework.parameters.Parameters; | |||||
| import org.apache.myrmidon.api.TaskException; | |||||
| import org.apache.myrmidon.interfaces.embeddor.Embeddor; | |||||
| import org.apache.myrmidon.interfaces.model.Project; | |||||
| import org.apache.myrmidon.interfaces.workspace.Workspace; | |||||
| import org.apache.myrmidon.listeners.ProjectListener; | |||||
| /** | |||||
| * A utility class, that takes care of launching Myrmidon, and building and | |||||
| * executing a project. | |||||
| * | |||||
| * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a> | |||||
| * @version $Revision$ $Date$ | |||||
| */ | |||||
| public class EmbeddedAnt | |||||
| extends AbstractLogEnabled | |||||
| { | |||||
| private final static Resources REZ | |||||
| = ResourceManager.getPackageResources( EmbeddedAnt.class ); | |||||
| private static final String DEFAULT_EMBEDDOR_CLASS = | |||||
| "org.apache.myrmidon.components.embeddor.DefaultEmbeddor"; | |||||
| private String m_projectFile = "build.ant"; | |||||
| private Project m_project; | |||||
| private String m_listenerName = "default"; | |||||
| private ProjectListener m_listener; | |||||
| private Parameters m_workspaceProps = new Parameters(); | |||||
| private Parameters m_builderProps = new Parameters(); | |||||
| private Parameters m_embeddorProps = new Parameters(); | |||||
| private ClassLoader m_sharedClassLoader; | |||||
| private Embeddor m_embeddor; | |||||
| /** | |||||
| * Sets the logger to use. | |||||
| */ | |||||
| public void setLogger( final Logger logger ) | |||||
| { | |||||
| enableLogging( logger ); | |||||
| } | |||||
| /** | |||||
| * Sets the project file to execute. Default is 'build.ant'. | |||||
| */ | |||||
| public void setProjectFile( final String projectFile ) | |||||
| { | |||||
| m_projectFile = projectFile; | |||||
| m_project = null; | |||||
| } | |||||
| /** | |||||
| * Sets the project to execute. This method can be used instead of | |||||
| * {@link #setProjectFile}, for projects models that are built | |||||
| * programmatically. | |||||
| */ | |||||
| public void setProject( final Project project ) | |||||
| { | |||||
| m_projectFile = null; | |||||
| m_project = project; | |||||
| } | |||||
| /** | |||||
| * Sets the name of the project listener to use. | |||||
| */ | |||||
| public void setListener( final String listener ) | |||||
| { | |||||
| m_listenerName = listener; | |||||
| m_listener = null; | |||||
| } | |||||
| /** | |||||
| * Sets the project listener to use. | |||||
| */ | |||||
| public void setListener( final ProjectListener listener ) | |||||
| { | |||||
| m_listenerName = null; | |||||
| m_listener = listener; | |||||
| } | |||||
| /** | |||||
| * Sets a workspace property. These are inherited by all projects executed | |||||
| * by this embeddor. | |||||
| */ | |||||
| public void setWorkspaceProperty( final String name, final Object value ) | |||||
| { | |||||
| // TODO - Make properties Objects, not Strings | |||||
| m_workspaceProps.setParameter( name, (String)value ); | |||||
| } | |||||
| /** | |||||
| * Sets a project builder property. These are used by the project builder | |||||
| * when it is parsing the project file. | |||||
| */ | |||||
| public void setBuilderProperty( final String name, final Object value ) | |||||
| { | |||||
| // TODO - Make properties Objects, not Strings | |||||
| m_builderProps.setParameter( name, (String)value ); | |||||
| } | |||||
| /** | |||||
| * Sets a task engine property. These are used to configure the task engine. | |||||
| */ | |||||
| public void setEmbeddorProperty( final String name, final Object value ) | |||||
| { | |||||
| // TODO - Make properties Objects, not Strings | |||||
| m_embeddorProps.setParameter( name, (String)value ); | |||||
| } | |||||
| /** | |||||
| * Sets the shared classloader, which is used as the parent classloader | |||||
| * for all antlibs. Default is to use the context classloader. | |||||
| */ | |||||
| public void setSharedClassLoader( final ClassLoader classLoader ) | |||||
| { | |||||
| m_sharedClassLoader = classLoader; | |||||
| } | |||||
| /** | |||||
| * Executes a set of targets in the project. This method may be called | |||||
| * multiple times. | |||||
| */ | |||||
| public void executeTargets( final String[] targets ) throws Exception | |||||
| { | |||||
| if( m_sharedClassLoader != null ) | |||||
| { | |||||
| Thread.currentThread().setContextClassLoader( m_sharedClassLoader ); | |||||
| } | |||||
| checkHomeDir(); | |||||
| // Prepare the embeddor, project listener and project model | |||||
| final Embeddor embeddor = prepareEmbeddor(); | |||||
| final ProjectListener listener = prepareListener( embeddor ); | |||||
| final Project project = prepareProjectModel( embeddor ); | |||||
| // Create a new workspace | |||||
| final Workspace workspace = embeddor.createWorkspace( m_workspaceProps ); | |||||
| workspace.addProjectListener( listener ); | |||||
| //execute the project | |||||
| executeTargets( workspace, project, targets ); | |||||
| } | |||||
| /** | |||||
| * Shuts down the task engine, after the project has been executed. | |||||
| */ | |||||
| public void stop() throws Exception | |||||
| { | |||||
| try | |||||
| { | |||||
| if( m_embeddor != null ) | |||||
| { | |||||
| m_embeddor.stop(); | |||||
| m_embeddor.dispose(); | |||||
| } | |||||
| } | |||||
| finally | |||||
| { | |||||
| m_embeddor = null; | |||||
| m_project = null; | |||||
| m_listener = null; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Actually do the build. | |||||
| */ | |||||
| private void executeTargets( final Workspace workspace, | |||||
| final Project project, | |||||
| final String[] targets ) | |||||
| throws TaskException | |||||
| { | |||||
| //if we didn't specify a target, then choose default | |||||
| if( targets == null || targets.length == 0 ) | |||||
| { | |||||
| workspace.executeProject( project, project.getDefaultTargetName() ); | |||||
| } | |||||
| else | |||||
| { | |||||
| for( int i = 0; i < targets.length; i++ ) | |||||
| { | |||||
| workspace.executeProject( project, targets[ i ] ); | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Make sure myrmidon home directory has been specified, and is a | |||||
| * directory. | |||||
| */ | |||||
| private void checkHomeDir() throws Exception | |||||
| { | |||||
| final String home = m_embeddorProps.getParameter( "myrmidon.home" ); | |||||
| final File homeDir = ( new File( home ) ).getAbsoluteFile(); | |||||
| if( !homeDir.isDirectory() ) | |||||
| { | |||||
| final String message = REZ.getString( "home-not-dir.error", homeDir ); | |||||
| throw new Exception( message ); | |||||
| } | |||||
| if( getLogger().isInfoEnabled() ) | |||||
| { | |||||
| final String message = REZ.getString( "homedir.notice", homeDir ); | |||||
| getLogger().info( message ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Prepares and returns the embeddor to use. | |||||
| */ | |||||
| private Embeddor prepareEmbeddor() | |||||
| throws Exception | |||||
| { | |||||
| if( m_embeddor == null ) | |||||
| { | |||||
| m_embeddor = createEmbeddor(); | |||||
| setupLogger( m_embeddor ); | |||||
| m_embeddor.parameterize( m_embeddorProps ); | |||||
| m_embeddor.initialize(); | |||||
| m_embeddor.start(); | |||||
| } | |||||
| return m_embeddor; | |||||
| } | |||||
| /** | |||||
| * Creates the embeddor. | |||||
| */ | |||||
| private Embeddor createEmbeddor() | |||||
| throws Exception | |||||
| { | |||||
| final Class clazz = Class.forName( DEFAULT_EMBEDDOR_CLASS ); | |||||
| return (Embeddor)clazz.newInstance(); | |||||
| } | |||||
| /** | |||||
| * Prepares and returns the project listener to use. | |||||
| */ | |||||
| private ProjectListener prepareListener( final Embeddor embeddor ) | |||||
| throws Exception | |||||
| { | |||||
| if( m_listener == null ) | |||||
| { | |||||
| m_listener = embeddor.createListener( m_listenerName ); | |||||
| } | |||||
| return m_listener; | |||||
| } | |||||
| /** | |||||
| * Prepares and returns the project model. | |||||
| */ | |||||
| private Project prepareProjectModel( final Embeddor embeddor ) throws Exception | |||||
| { | |||||
| if( m_project == null ) | |||||
| { | |||||
| final File buildFile = getProjectFile(); | |||||
| m_project = embeddor.createProject( buildFile.toString(), null, m_builderProps ); | |||||
| } | |||||
| return m_project; | |||||
| } | |||||
| /** | |||||
| * Locates the project file | |||||
| */ | |||||
| private File getProjectFile() throws Exception | |||||
| { | |||||
| final File projectFile = ( new File( m_projectFile ) ).getCanonicalFile(); | |||||
| if( !projectFile.isFile() ) | |||||
| { | |||||
| final String message = REZ.getString( "bad-file.error", projectFile ); | |||||
| throw new Exception( message ); | |||||
| } | |||||
| if( getLogger().isInfoEnabled() ) | |||||
| { | |||||
| final String message = REZ.getString( "buildfile.notice", projectFile ); | |||||
| getLogger().info( message ); | |||||
| } | |||||
| return projectFile; | |||||
| } | |||||
| } | |||||
| @@ -14,6 +14,8 @@ import java.net.URL; | |||||
| import java.net.URLClassLoader; | import java.net.URLClassLoader; | ||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.StringTokenizer; | import java.util.StringTokenizer; | ||||
| import java.util.Map; | |||||
| import java.util.HashMap; | |||||
| /** | /** | ||||
| * Basic Loader that is responsible for all the hackery to get classloader to work. | * Basic Loader that is responsible for all the hackery to get classloader to work. | ||||
| @@ -34,16 +36,26 @@ public final class Main | |||||
| { | { | ||||
| try | try | ||||
| { | { | ||||
| //actually try to discover the install directory based on where | |||||
| // the myrmidon.jar is | |||||
| final Map properties = new HashMap(); | |||||
| // Try to discover the install directory based on where the | |||||
| // launcher Jar is | |||||
| final File installDirectory = findInstallDir(); | final File installDirectory = findInstallDir(); | ||||
| System.setProperty( "myrmidon.home", installDirectory.toString() ); | |||||
| properties.put( "myrmidon.home", installDirectory ); | |||||
| // Build the shared classloader | |||||
| final URL[] sharedClassPath = getSharedClassPath( installDirectory ); | |||||
| properties.put( "myrmidon.shared.classpath", sharedClassPath ); | |||||
| final URLClassLoader sharedClassLoader = new URLClassLoader( sharedClassPath ); | |||||
| properties.put( "myrmidon.shared.classloader", sharedClassLoader ); | |||||
| final URLClassLoader sharedClassLoader = createSharedClassLoader( installDirectory ); | |||||
| final URLClassLoader classLoader = | |||||
| createContainerClassLoader( installDirectory, sharedClassLoader ); | |||||
| // Build the container classloader | |||||
| final URL[] containerClassPath = getContainerClassPath( installDirectory ); | |||||
| properties.put( "myrmidon.container.classpath", containerClassPath ); | |||||
| final URLClassLoader containerClassLoader = new URLClassLoader( containerClassPath, sharedClassLoader ); | |||||
| properties.put( "myrmidon.container.classloader", containerClassLoader ); | |||||
| execMainClass( classLoader, args ); | |||||
| execMainClass( containerClassLoader, properties, args ); | |||||
| } | } | ||||
| catch( final InvocationTargetException ite ) | catch( final InvocationTargetException ite ) | ||||
| { | { | ||||
| @@ -57,38 +69,42 @@ public final class Main | |||||
| } | } | ||||
| } | } | ||||
| private static void execMainClass( final URLClassLoader classLoader, final String[] args ) | |||||
| /** | |||||
| * Executes the main class. | |||||
| */ | |||||
| private static void execMainClass( final ClassLoader classLoader, | |||||
| final Map properties, | |||||
| final String[] args ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| //load class and retrieve appropriate main method. | //load class and retrieve appropriate main method. | ||||
| final Class clazz = classLoader.loadClass( "org.apache.myrmidon.frontends.CLIMain" ); | final Class clazz = classLoader.loadClass( "org.apache.myrmidon.frontends.CLIMain" ); | ||||
| final Method method = clazz.getMethod( "main", new Class[]{args.getClass()} ); | |||||
| Thread.currentThread().setContextClassLoader( classLoader ); | |||||
| final Method method = clazz.getMethod( "main", new Class[]{Map.class, args.getClass()} ); | |||||
| //kick the tires and light the fires.... | //kick the tires and light the fires.... | ||||
| method.invoke( null, new Object[]{args} ); | |||||
| method.invoke( null, new Object[]{properties, args} ); | |||||
| } | } | ||||
| private static URLClassLoader createContainerClassLoader( final File installDirectory, | |||||
| final URLClassLoader sharedClassLoader ) | |||||
| /** | |||||
| * Builds the classpath for the container classloader. | |||||
| */ | |||||
| private static URL[] getContainerClassPath( final File installDirectory ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| // Include everything from the bin/lib/ directory | |||||
| final File containerLibDir = new File( installDirectory, "bin" + File.separator + "lib" ); | final File containerLibDir = new File( installDirectory, "bin" + File.separator + "lib" ); | ||||
| final URL[] containerLibUrls = buildURLList( containerLibDir ); | |||||
| final URLClassLoader classLoader = | |||||
| new URLClassLoader( containerLibUrls, sharedClassLoader ); | |||||
| return classLoader; | |||||
| return buildURLList( containerLibDir ); | |||||
| } | } | ||||
| private static URLClassLoader createSharedClassLoader( final File installDirectory ) | |||||
| /** | |||||
| * Builds the classpath for the shared classloader. | |||||
| */ | |||||
| private static URL[] getSharedClassPath( final File installDirectory ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| //setup classloader appropriately for myrmidon jar | |||||
| // Include everything from the lib/ directory | |||||
| final File libDir = new File( installDirectory, "lib" ); | final File libDir = new File( installDirectory, "lib" ); | ||||
| final URL[] libUrls = buildURLList( libDir ); | |||||
| final URLClassLoader libClassLoader = new URLClassLoader( libUrls ); | |||||
| return libClassLoader; | |||||
| return buildURLList( libDir ); | |||||
| } | } | ||||
| private static final URL[] buildURLList( final File dir ) | private static final URL[] buildURLList( final File dir ) | ||||
| @@ -137,25 +153,23 @@ public final class Main | |||||
| final String classpath = System.getProperty( "java.class.path" ); | final String classpath = System.getProperty( "java.class.path" ); | ||||
| final String pathSeparator = System.getProperty( "path.separator" ); | final String pathSeparator = System.getProperty( "path.separator" ); | ||||
| final StringTokenizer tokenizer = new StringTokenizer( classpath, pathSeparator ); | final StringTokenizer tokenizer = new StringTokenizer( classpath, pathSeparator ); | ||||
| final String jarName = "myrmidon-launcher.jar"; | |||||
| while( tokenizer.hasMoreTokens() ) | while( tokenizer.hasMoreTokens() ) | ||||
| { | { | ||||
| final String element = tokenizer.nextToken(); | final String element = tokenizer.nextToken(); | ||||
| if( element.endsWith( "myrmidon-launcher.jar" ) ) | |||||
| File file = ( new File( element ) ).getAbsoluteFile(); | |||||
| if( file.isFile() && file.getName().equals( jarName ) ) | |||||
| { | { | ||||
| File file = ( new File( element ) ).getAbsoluteFile(); | |||||
| file = file.getParentFile(); | file = file.getParentFile(); | ||||
| if( null != file ) | if( null != file ) | ||||
| { | { | ||||
| file = file.getParentFile(); | file = file.getParentFile(); | ||||
| } | } | ||||
| return file; | return file; | ||||
| } | } | ||||
| } | } | ||||
| throw new Exception( "Unable to locate ant.jar in classpath" ); | |||||
| throw new Exception( "Unable to locate " + jarName + " in classpath." ); | |||||
| } | } | ||||
| } | } | ||||