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_taskLibDir; | |||
| private static final String MYRMIDON_HOME = "myrmidon.home"; | |||
| /** | |||
| * Setup basic properties of engine. | |||
| @@ -133,6 +134,9 @@ public class DefaultEmbeddor | |||
| { | |||
| final Workspace workspace = | |||
| (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 ); | |||
| return workspace; | |||
| } | |||
| @@ -186,7 +190,7 @@ public class DefaultEmbeddor | |||
| throws Exception | |||
| { | |||
| // 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 ); | |||
| typeDeployer.deployAll(); | |||
| @@ -297,7 +301,7 @@ public class DefaultEmbeddor | |||
| { | |||
| String filepath = null; | |||
| filepath = getParameter( "myrmidon.home" ); | |||
| filepath = getParameter( MYRMIDON_HOME ); | |||
| m_homeDir = ( new File( filepath ) ).getAbsoluteFile(); | |||
| checkDirectory( m_homeDir, "home-dir.name" ); | |||
| @@ -147,7 +147,7 @@ public class DefaultWorkspace | |||
| } | |||
| private File findTypeLib( final String libraryName ) | |||
| throws TaskException | |||
| throws Exception | |||
| { | |||
| //TODO: In future this will be expanded to allow | |||
| //users to specify search path or automagically | |||
| @@ -155,7 +155,7 @@ public class DefaultWorkspace | |||
| //workspace specific) | |||
| 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 library = new File( homeDir, name ); | |||
| @@ -178,7 +178,7 @@ public class DefaultWorkspace | |||
| } | |||
| private void deployTypeLib( final Deployer deployer, final Project project ) | |||
| throws TaskException | |||
| throws Exception | |||
| { | |||
| final TypeLib[] typeLibs = project.getTypeLibs(); | |||
| @@ -213,7 +213,7 @@ public class DefaultWorkspace | |||
| * Creates an execution frame for a project. | |||
| */ | |||
| private ExecutionFrame createExecutionFrame( final Project project ) | |||
| throws TaskException, ServiceException | |||
| throws Exception | |||
| { | |||
| //Create per frame ComponentManager | |||
| final DefaultServiceManager serviceManager = | |||
| @@ -12,6 +12,9 @@ import org.apache.aut.nativelib.ExecException; | |||
| import org.apache.aut.nativelib.impl.DefaultExecManager; | |||
| import org.apache.avalon.excalibur.i18n.ResourceManager; | |||
| 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.ServiceFactory; | |||
| @@ -22,23 +25,31 @@ import org.apache.myrmidon.interfaces.service.ServiceFactory; | |||
| * @version $Revision$ $Date$ | |||
| */ | |||
| public class ExecManagerFactory | |||
| implements ServiceFactory | |||
| implements ServiceFactory, Parameterizable | |||
| { | |||
| private final static Resources REZ = | |||
| ResourceManager.getPackageResources( ExecManagerFactory.class ); | |||
| private Parameters m_parameters; | |||
| public void parameterize( final Parameters parameters ) | |||
| throws ParameterException | |||
| { | |||
| m_parameters = parameters; | |||
| } | |||
| /** | |||
| * Create the ExecManager Service. | |||
| */ | |||
| public Object createService() | |||
| throws AntServiceException | |||
| { | |||
| final File home = getHomeDirectory(); | |||
| try | |||
| { | |||
| final File home = getHomeDirectory(); | |||
| return new DefaultExecManager( home ); | |||
| } | |||
| catch( final ExecException ee ) | |||
| catch( final Exception ee ) | |||
| { | |||
| throw new AntServiceException( ee.getMessage(), ee ); | |||
| } | |||
| @@ -47,10 +58,10 @@ public class ExecManagerFactory | |||
| /** | |||
| * 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 ) | |||
| { | |||
| final String message = REZ.getString( "missing-home-dir.error" ); | |||
| @@ -8,10 +8,12 @@ | |||
| package org.apache.myrmidon.frontends; | |||
| import java.io.BufferedReader; | |||
| import java.io.File; | |||
| import java.io.InputStreamReader; | |||
| import java.io.File; | |||
| import java.util.ArrayList; | |||
| 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.CLOption; | |||
| 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.framework.CascadingException; | |||
| 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.api.TaskException; | |||
| import org.apache.myrmidon.interfaces.embeddor.Embeddor; | |||
| 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. | |||
| @@ -39,14 +35,10 @@ import org.apache.myrmidon.listeners.ProjectListener; | |||
| * @version $Revision$ $Date$ | |||
| */ | |||
| public class CLIMain | |||
| extends AbstractLogEnabled | |||
| { | |||
| private final static Resources REZ = | |||
| ResourceManager.getPackageResources( CLIMain.class ); | |||
| private static final String DEFAULT_EMBEDDOR_CLASS = | |||
| "org.apache.myrmidon.components.embeddor.DefaultEmbeddor"; | |||
| //defines for the Command Line options | |||
| private final static int HELP_OPT = 'h'; | |||
| private final static int QUIET_OPT = 'q'; | |||
| @@ -84,23 +76,19 @@ public class CLIMain | |||
| 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 | |||
| 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 | |||
| private boolean m_dryRun = false; | |||
| ///Enables incremental mode | |||
| private boolean m_incremental; | |||
| ///The launcher | |||
| private EmbeddedAnt m_embedded = new EmbeddedAnt(); | |||
| ///Log level to use | |||
| //private static Priority m_priority = Priority.WARN; | |||
| private static int m_priority = BasicLogger.LEVEL_WARN; | |||
| /** | |||
| @@ -109,12 +97,24 @@ public class CLIMain | |||
| * @param args the 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; | |||
| final CLIMain main = new CLIMain(); | |||
| try | |||
| { | |||
| main.execute( args ); | |||
| main.execute( properties, args ); | |||
| } | |||
| catch( final Throwable throwable ) | |||
| { | |||
| @@ -243,10 +243,10 @@ public class CLIMain | |||
| return false; | |||
| case HOME_DIR_OPT: | |||
| m_parameters.setParameter( "myrmidon.home", option.getArgument() ); | |||
| m_embedded.setEmbeddorProperty( "myrmidon.home", option.getArgument() ); | |||
| break; | |||
| case TASKLIB_DIR_OPT: | |||
| m_parameters.setParameter( "myrmidon.lib.path", option.getArgument() ); | |||
| m_embedded.setEmbeddorProperty( "myrmidon.lib.path", option.getArgument() ); | |||
| break; | |||
| case LOG_LEVEL_OPT: | |||
| @@ -260,26 +260,26 @@ public class CLIMain | |||
| break; | |||
| case INCREMENTAL_OPT: | |||
| m_parameters.setParameter( "incremental", "true" ); | |||
| m_incremental = true; | |||
| break; | |||
| case FILE_OPT: | |||
| m_parameters.setParameter( "filename", option.getArgument() ); | |||
| m_embedded.setProjectFile( option.getArgument() ); | |||
| break; | |||
| case LISTENER_OPT: | |||
| m_parameters.setParameter( "listener", option.getArgument() ); | |||
| m_embedded.setListener( option.getArgument() ); | |||
| break; | |||
| case NO_PREFIX_OPT: | |||
| m_parameters.setParameter( "listener", "noprefix" ); | |||
| m_embedded.setListener( "noprefix" ); | |||
| break; | |||
| case DEFINE_OPT: | |||
| m_defines.setParameter( option.getArgument( 0 ), option.getArgument( 1 ) ); | |||
| m_embedded.setWorkspaceProperty( option.getArgument( 0 ), option.getArgument( 1 ) ); | |||
| break; | |||
| case BUILDER_PARAM_OPT: | |||
| m_builderParameters.setParameter( option.getArgument( 0 ), option.getArgument( 1 ) ); | |||
| m_embedded.setBuilderProperty( option.getArgument( 0 ), option.getArgument( 1 ) ); | |||
| break; | |||
| case DRY_RUN_OPT: | |||
| @@ -295,61 +295,42 @@ public class CLIMain | |||
| 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 | |||
| { | |||
| 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.. | |||
| final boolean incremental = m_parameters.getParameterAsBoolean( "incremental", false ); | |||
| if( !incremental ) | |||
| if( !m_incremental ) | |||
| { | |||
| executeBuild( embeddor, project, listener ); | |||
| executeBuild(); | |||
| } | |||
| else | |||
| { | |||
| executeIncrementalBuild( embeddor, project, listener ); | |||
| executeIncrementalBuild(); | |||
| } | |||
| } | |||
| catch( final Exception e ) | |||
| @@ -359,13 +340,11 @@ public class CLIMain | |||
| } | |||
| finally | |||
| { | |||
| shutdownEmbeddor( embeddor ); | |||
| m_embedded.stop(); | |||
| } | |||
| } | |||
| private void executeIncrementalBuild( final Embeddor embeddor, | |||
| final Project project, | |||
| final ProjectListener listener ) | |||
| private void executeIncrementalBuild() | |||
| throws Exception | |||
| { | |||
| BufferedReader reader = null; | |||
| @@ -374,7 +353,7 @@ public class CLIMain | |||
| { | |||
| try | |||
| { | |||
| executeBuild( embeddor, project, listener ); | |||
| executeBuild(); | |||
| } | |||
| 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 | |||
| */ | |||
| @@ -426,131 +412,7 @@ public class CLIMain | |||
| } | |||
| // 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.util.ArrayList; | |||
| 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. | |||
| @@ -34,16 +36,26 @@ public final class Main | |||
| { | |||
| 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(); | |||
| 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 ) | |||
| { | |||
| @@ -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 | |||
| { | |||
| //load class and retrieve appropriate main method. | |||
| 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.... | |||
| 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 | |||
| { | |||
| // Include everything from the bin/lib/ directory | |||
| 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 | |||
| { | |||
| //setup classloader appropriately for myrmidon jar | |||
| // Include everything from the lib/ directory | |||
| 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 ) | |||
| @@ -137,25 +153,23 @@ public final class Main | |||
| final String classpath = System.getProperty( "java.class.path" ); | |||
| final String pathSeparator = System.getProperty( "path.separator" ); | |||
| final StringTokenizer tokenizer = new StringTokenizer( classpath, pathSeparator ); | |||
| final String jarName = "myrmidon-launcher.jar"; | |||
| while( tokenizer.hasMoreTokens() ) | |||
| { | |||
| 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(); | |||
| if( null != file ) | |||
| { | |||
| file = file.getParentFile(); | |||
| } | |||
| return file; | |||
| } | |||
| } | |||
| throw new Exception( "Unable to locate ant.jar in classpath" ); | |||
| throw new Exception( "Unable to locate " + jarName + " in classpath." ); | |||
| } | |||
| } | |||