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." ); | |||||
} | } | ||||
} | } |