Major changes include * making convertion API context-sensitive * the simplification of all the interfaces. The simplification is achived by applying IOC. Now AntEngine is responsible for creating and instantiating shared components via a ComponentManager. * Moved most of startup code to AntEngine so that alternate front ends can be added in simply. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268409 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -4,11 +4,14 @@ echo. | |||||
| echo Ant Build System | echo Ant Build System | ||||
| echo ---------------- | echo ---------------- | ||||
| set ANT_HOME=. | |||||
| set ANT_HOME=tools | |||||
| set CLASSPATH= | |||||
| set LOCALCLASSPATH= | |||||
| for %%i in (lib\*.jar) do call tools\bin\lcp.bat %%i | |||||
| set CLASSPATH=%LOCALCLASSPATH% | |||||
| set LOCALCLASSPATH= | |||||
| %ANT_HOME%\bin\ant.bat -emacs %1 %2 %3 %4 %5 %6 %7 %8 | |||||
| %ANT_HOME%\bin\ant.bat -logger org.apache.tools.ant.NoBannerLogger -emacs %1 %2 %3 %4 %5 %6 %7 %8 | |||||
| goto cleanup | goto cleanup | ||||
| :cleanup | :cleanup | ||||
| @@ -154,7 +154,9 @@ Legal: | |||||
| destdir="${build.classes}" | destdir="${build.classes}" | ||||
| debug="${debug}" | debug="${debug}" | ||||
| optimize="${optimize}" | optimize="${optimize}" | ||||
| deprecation="${deprecation}" /> | |||||
| deprecation="${deprecation}"> | |||||
| <exclude name="org/apache/ant/gui/**"/> | |||||
| </javac> | |||||
| <!-- | <!-- | ||||
| <copy todir="${build.classes}"> | <copy todir="${build.classes}"> | ||||
| @@ -0,0 +1,48 @@ | |||||
| /* | |||||
| * 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 file. | |||||
| */ | |||||
| package org.apache.ant; | |||||
| import java.util.Properties; | |||||
| import org.apache.ant.project.ProjectBuilder; | |||||
| import org.apache.ant.project.ProjectEngine; | |||||
| import org.apache.avalon.Component; | |||||
| import org.apache.avalon.Disposable; | |||||
| import org.apache.avalon.Initializable; | |||||
| /** | |||||
| * Interface to the Ant runtime. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public interface AntEngine | |||||
| extends Component, Initializable, Disposable | |||||
| { | |||||
| /** | |||||
| * Setup basic properties of engine. | |||||
| * Called before init() and can be used to specify alternate components in system. | |||||
| * | |||||
| * @param properties the properties | |||||
| */ | |||||
| void setProperties( Properties properties ); | |||||
| /** | |||||
| * Retrieve builder for runtime. | |||||
| * Valid after init() call | |||||
| * | |||||
| * @return the ProjectBuilder | |||||
| */ | |||||
| ProjectBuilder getProjectBuilder(); | |||||
| /** | |||||
| * Retrieve project engine for runtime. | |||||
| * Valid after init() call | |||||
| * | |||||
| * @return the ProjectBuilder | |||||
| */ | |||||
| ProjectEngine getProjectEngine(); | |||||
| } | |||||
| @@ -0,0 +1,410 @@ | |||||
| /* | |||||
| * 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 file. | |||||
| */ | |||||
| package org.apache.ant; | |||||
| import java.io.File; | |||||
| import java.util.Properties; | |||||
| import org.apache.ant.configuration.Configurer; | |||||
| import org.apache.ant.convert.ConverterEngine; | |||||
| import org.apache.ant.datatypes.DataTypeEngine; | |||||
| import org.apache.ant.project.ProjectBuilder; | |||||
| import org.apache.ant.project.ProjectEngine; | |||||
| import org.apache.ant.tasklet.JavaVersion; | |||||
| import org.apache.ant.tasklet.engine.TaskletEngine; | |||||
| import org.apache.ant.tasklet.engine.TskDeployer; | |||||
| import org.apache.avalon.AbstractLoggable; | |||||
| import org.apache.avalon.Component; | |||||
| import org.apache.avalon.Composer; | |||||
| import org.apache.avalon.DefaultComponentManager; | |||||
| import org.apache.avalon.Initializable; | |||||
| import org.apache.avalon.camelot.CamelotUtil; | |||||
| import org.apache.avalon.camelot.DefaultFactory; | |||||
| import org.apache.avalon.camelot.Deployer; | |||||
| import org.apache.avalon.camelot.Factory; | |||||
| import org.apache.avalon.util.ObjectUtil; | |||||
| import org.apache.avalon.util.io.FileUtil; | |||||
| /** | |||||
| * Default implementation of Ant runtime. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public class DefaultAntEngine | |||||
| extends AbstractLoggable | |||||
| implements AntEngine, Initializable | |||||
| { | |||||
| protected ConverterEngine m_converterEngine; | |||||
| protected DataTypeEngine m_dataTypeEngine; | |||||
| protected TaskletEngine m_taskletEngine; | |||||
| protected ProjectEngine m_projectEngine; | |||||
| protected ProjectBuilder m_builder; | |||||
| protected TskDeployer m_deployer; | |||||
| protected Configurer m_configurer; | |||||
| protected Factory m_factory; | |||||
| protected DefaultComponentManager m_componentManager; | |||||
| protected Properties m_properties; | |||||
| protected Properties m_defaults; | |||||
| protected File m_homeDir; | |||||
| protected File m_binDir; | |||||
| protected File m_libDir; | |||||
| protected File m_taskLibDir; | |||||
| /** | |||||
| * Setup basic properties of engine. | |||||
| * Called before init() and can be used to specify alternate components in system. | |||||
| * | |||||
| * @param properties the properties | |||||
| */ | |||||
| public void setProperties( final Properties properties ) | |||||
| { | |||||
| m_properties = properties; | |||||
| } | |||||
| /** | |||||
| * Retrieve builder for runtime. | |||||
| * Valid after init() call | |||||
| * | |||||
| * @return the ProjectBuilder | |||||
| */ | |||||
| public ProjectBuilder getProjectBuilder() | |||||
| { | |||||
| return m_builder; | |||||
| } | |||||
| /** | |||||
| * Retrieve project engine for runtime. | |||||
| * Valid after init() call | |||||
| * | |||||
| * @return the ProjectBuilder | |||||
| */ | |||||
| public ProjectEngine getProjectEngine() | |||||
| { | |||||
| return m_projectEngine; | |||||
| } | |||||
| /** | |||||
| * Initialize the system. | |||||
| * | |||||
| * @exception Exception if an error occurs | |||||
| */ | |||||
| public void init() | |||||
| throws Exception | |||||
| { | |||||
| //setup default properties | |||||
| m_defaults = createDefaultProperties(); | |||||
| //create all the components | |||||
| m_factory = new DefaultFactory(); | |||||
| createComponents(); | |||||
| //setup the component manager | |||||
| m_componentManager = createComponentManager(); | |||||
| setupComponents(); | |||||
| setupFiles(); | |||||
| CamelotUtil.deployFromDirectory( m_deployer, m_taskLibDir, ".tsk" ); | |||||
| } | |||||
| /** | |||||
| * Dispose engine. | |||||
| * | |||||
| * @exception Exception if an error occurs | |||||
| */ | |||||
| public void dispose() | |||||
| throws Exception | |||||
| { | |||||
| m_converterEngine = null; | |||||
| m_dataTypeEngine = null; | |||||
| m_taskletEngine = null; | |||||
| m_projectEngine = null; | |||||
| m_builder = null; | |||||
| m_deployer = null; | |||||
| m_configurer = null; | |||||
| m_factory = null; | |||||
| m_componentManager = null; | |||||
| m_properties = null; | |||||
| m_defaults = null; | |||||
| m_homeDir = null; | |||||
| m_binDir = null; | |||||
| m_libDir = null; | |||||
| m_taskLibDir = null; | |||||
| } | |||||
| /** | |||||
| * Create default properties which includes default names of all components. | |||||
| * Overide this in sub-classes to change values. | |||||
| * | |||||
| * @return the Properties | |||||
| */ | |||||
| protected Properties createDefaultProperties() | |||||
| { | |||||
| final Properties defaults = new Properties(); | |||||
| //create all the default properties for files/directories | |||||
| defaults.setProperty( "ant.path.bin", "bin" ); | |||||
| defaults.setProperty( "ant.path.lib", "lib" ); | |||||
| defaults.setProperty( "ant.path.task-lib", "lib" ); | |||||
| //create all the default properties for components | |||||
| defaults.setProperty( "ant.comp.converter", | |||||
| "org.apache.ant.convert.DefaultConverterEngine" ); | |||||
| defaults.setProperty( "ant.comp.datatype", | |||||
| "org.apache.ant.datatypes.DefaultDataTypeEngine" ); | |||||
| defaults.setProperty( "ant.comp.tasklet", | |||||
| "org.apache.ant.tasklet.engine.DefaultTaskletEngine" ); | |||||
| defaults.setProperty( "ant.comp.project", | |||||
| "org.apache.ant.project.DefaultProjectEngine" ); | |||||
| defaults.setProperty( "ant.comp.builder", | |||||
| "org.apache.ant.project.DefaultProjectBuilder" ); | |||||
| defaults.setProperty( "ant.comp.deployer", | |||||
| "org.apache.ant.tasklet.engine.DefaultTskDeployer" ); | |||||
| defaults.setProperty( "ant.comp.configurer", | |||||
| "org.apache.ant.configuration.DefaultConfigurer" ); | |||||
| return defaults; | |||||
| } | |||||
| /** | |||||
| * Create a ComponentManager containing all components in engine. | |||||
| * | |||||
| * @return the ComponentManager | |||||
| */ | |||||
| protected DefaultComponentManager createComponentManager() | |||||
| { | |||||
| final DefaultComponentManager componentManager = new DefaultComponentManager(); | |||||
| componentManager.put( "org.apache.ant.tasklet.engine.TaskletEngine", m_taskletEngine ); | |||||
| componentManager.put( "org.apache.ant.project.ProjectEngine", m_projectEngine ); | |||||
| componentManager.put( "org.apache.ant.convert.ConverterEngine", m_converterEngine ); | |||||
| componentManager.put( "org.apache.ant.convert.Converter", m_converterEngine ); | |||||
| componentManager.put( "org.apache.ant.datatypes.DataTypeEngine", m_dataTypeEngine ); | |||||
| componentManager.put( "org.apache.ant.project.ProjectBuilder", m_builder ); | |||||
| componentManager.put( "org.apache.ant.tasklet.engine.TskDeployer", m_deployer ); | |||||
| componentManager.put( "org.apache.avalon.camelot.Factory", m_factory ); | |||||
| componentManager.put( "org.apache.ant.configuration.Configurer", m_configurer ); | |||||
| return componentManager; | |||||
| } | |||||
| /** | |||||
| * Create all required components. | |||||
| * | |||||
| * @exception Exception if an error occurs | |||||
| */ | |||||
| protected void createComponents() | |||||
| throws Exception | |||||
| { | |||||
| String component = null; | |||||
| component = getProperty( "ant.comp.converter" ); | |||||
| m_converterEngine = (ConverterEngine)createComponent( component, ConverterEngine.class ); | |||||
| component = getProperty( "ant.comp.datatype" ); | |||||
| m_dataTypeEngine = (DataTypeEngine)createComponent( component, DataTypeEngine.class ); | |||||
| component = getProperty( "ant.comp.tasklet" ); | |||||
| m_taskletEngine = (TaskletEngine)createComponent( component, TaskletEngine.class ); | |||||
| component = getProperty( "ant.comp.project" ); | |||||
| m_projectEngine = (ProjectEngine)createComponent( component, ProjectEngine.class ); | |||||
| component = getProperty( "ant.comp.builder" ); | |||||
| m_builder =(ProjectBuilder)createComponent( component, ProjectBuilder.class ); | |||||
| component = getProperty( "ant.comp.deployer" ); | |||||
| m_deployer = (TskDeployer)createComponent( component, TskDeployer.class ); | |||||
| component = getProperty( "ant.comp.configurer" ); | |||||
| m_configurer = (Configurer)createComponent( component, Configurer.class ); | |||||
| } | |||||
| /** | |||||
| * Setup all the components. (ir run all required lifecycle methods). | |||||
| * | |||||
| * @exception Exception if an error occurs | |||||
| */ | |||||
| protected void setupComponents() | |||||
| throws Exception | |||||
| { | |||||
| setupComponent( m_factory ); | |||||
| setupComponent( m_converterEngine ); | |||||
| setupComponent( m_dataTypeEngine ); | |||||
| setupComponent( m_taskletEngine ); | |||||
| setupComponent( m_projectEngine ); | |||||
| setupComponent( m_builder ); | |||||
| setupComponent( m_deployer ); | |||||
| setupComponent( m_configurer ); | |||||
| } | |||||
| /** | |||||
| * Setup an individual component. | |||||
| * | |||||
| * @param component the component | |||||
| * @exception Exception if an error occurs | |||||
| */ | |||||
| protected void setupComponent( final Component component ) | |||||
| throws Exception | |||||
| { | |||||
| setupLogger( component ); | |||||
| if( component instanceof Composer ) | |||||
| { | |||||
| ((Composer)component).compose( m_componentManager ); | |||||
| } | |||||
| if( component instanceof Initializable ) | |||||
| { | |||||
| ((Initializable)component).init(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Setup all the files attributes. | |||||
| */ | |||||
| protected void setupFiles() | |||||
| { | |||||
| String filepath = null; | |||||
| filepath = getProperty( "ant.home" ); | |||||
| m_homeDir = (new File( filepath )).getAbsoluteFile(); | |||||
| checkDirectory( m_homeDir, "ant-home" ); | |||||
| filepath = getProperty( "ant.path.bin" ); | |||||
| m_binDir = resolveDirectory( filepath, "bin-dir" ); | |||||
| filepath = getProperty( "ant.path.lib" ); | |||||
| m_libDir = resolveDirectory( filepath, "lib-dir" ); | |||||
| filepath = getProperty( "ant.path.task-lib" ); | |||||
| m_taskLibDir = resolveDirectory( filepath, "task-lib-dir" ); | |||||
| } | |||||
| /** | |||||
| * Retrieve value of named property. | |||||
| * First access passed in properties and then the default properties. | |||||
| * | |||||
| * @param name the name of property | |||||
| * @return the value of property or null | |||||
| */ | |||||
| protected String getProperty( final String name ) | |||||
| { | |||||
| String value = m_properties.getProperty( name ); | |||||
| if( null == value ) | |||||
| { | |||||
| value = m_defaults.getProperty( name ); | |||||
| } | |||||
| return value; | |||||
| } | |||||
| /** | |||||
| * Resolve a directory relative to another base directory. | |||||
| * | |||||
| * @param dir the base directory | |||||
| * @param name the relative directory | |||||
| * @return the created File | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| protected File resolveDirectory( final String dir, final String name ) | |||||
| throws AntException | |||||
| { | |||||
| final File file = FileUtil.resolveFile( m_homeDir, dir ); | |||||
| checkDirectory( file, name ); | |||||
| return file; | |||||
| } | |||||
| /** | |||||
| * Verify file is a directory else throw an exception. | |||||
| * | |||||
| * @param file the File | |||||
| * @param name the name of file type (used in error messages) | |||||
| */ | |||||
| protected void checkDirectory( final File file, final String name ) | |||||
| throws AntException | |||||
| { | |||||
| if( !file.exists() ) | |||||
| { | |||||
| throw new AntException( name + " (" + file + ") does not exist" ); | |||||
| } | |||||
| else if( !file.isDirectory() ) | |||||
| { | |||||
| throw new AntException( name + " (" + file + ") is not a directory" ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Helper method to retrieve current JVM version. | |||||
| * Basically stolen from original Ant sources. | |||||
| * | |||||
| * @return the current JVM version | |||||
| */ | |||||
| protected JavaVersion getJavaVersion() | |||||
| { | |||||
| JavaVersion version = JavaVersion.JAVA1_0; | |||||
| try | |||||
| { | |||||
| Class.forName( "java.lang.Void" ); | |||||
| version = JavaVersion.JAVA1_1; | |||||
| Class.forName( "java.lang.ThreadLocal" ); | |||||
| version = JavaVersion.JAVA1_2; | |||||
| Class.forName( "java.lang.StrictMath" ); | |||||
| version = JavaVersion.JAVA1_3; | |||||
| } | |||||
| catch( final ClassNotFoundException cnfe ) {} | |||||
| return version; | |||||
| } | |||||
| /** | |||||
| * Create a component that implements an interface. | |||||
| * | |||||
| * @param component the name of the component | |||||
| * @param clazz the name of interface/type | |||||
| * @return the created object | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| protected Object createComponent( final String component, final Class clazz ) | |||||
| throws AntException | |||||
| { | |||||
| try | |||||
| { | |||||
| final Object object = ObjectUtil.createObject( component ); | |||||
| if( !clazz.isInstance( object ) ) | |||||
| { | |||||
| throw new AntException( "Object " + component + " is not an instance of " + | |||||
| clazz ); | |||||
| } | |||||
| return object; | |||||
| } | |||||
| catch( final IllegalAccessException iae ) | |||||
| { | |||||
| throw new AntException( "Non-public constructor for " + clazz + " " + component, | |||||
| iae ); | |||||
| } | |||||
| catch( final InstantiationException ie ) | |||||
| { | |||||
| throw new AntException( "Error instantiating class for " + clazz + " " + component, | |||||
| ie ); | |||||
| } | |||||
| catch( final ClassNotFoundException cnfe ) | |||||
| { | |||||
| throw new AntException( "Could not find the class for " + clazz + | |||||
| " (" + component + ")", cnfe ); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,18 @@ | |||||
| /* | |||||
| * 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 file. | |||||
| */ | |||||
| package org.apache.ant; | |||||
| /** | |||||
| * Interface for front end. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| * @author James Duncan Davidson (duncan@apache.org) | |||||
| */ | |||||
| public interface FrontEnd | |||||
| { | |||||
| } | |||||
| @@ -15,25 +15,26 @@ import java.io.InputStream; | |||||
| import java.io.InputStreamReader; | import java.io.InputStreamReader; | ||||
| import java.net.MalformedURLException; | import java.net.MalformedURLException; | ||||
| import java.net.URL; | import java.net.URL; | ||||
| import java.net.URLClassLoader; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.HashMap; | import java.util.HashMap; | ||||
| import java.util.Map; | |||||
| import java.util.Iterator; | import java.util.Iterator; | ||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Map; | |||||
| import java.util.Properties; | |||||
| import org.apache.ant.launcher.AntClassLoader; | |||||
| import org.apache.ant.launcher.AntLoader; | import org.apache.ant.launcher.AntLoader; | ||||
| import org.apache.ant.project.DefaultProjectEngine; | |||||
| import org.apache.ant.project.LogTargetToListenerAdapter; | |||||
| import org.apache.ant.project.Project; | import org.apache.ant.project.Project; | ||||
| import org.apache.ant.project.ProjectBuilder; | import org.apache.ant.project.ProjectBuilder; | ||||
| import org.apache.ant.project.ProjectEngine; | import org.apache.ant.project.ProjectEngine; | ||||
| import org.apache.ant.project.ProjectListener; | import org.apache.ant.project.ProjectListener; | ||||
| import org.apache.ant.project.LogTargetToListenerAdapter; | |||||
| import org.apache.ant.tasklet.JavaVersion; | import org.apache.ant.tasklet.JavaVersion; | ||||
| import org.apache.ant.tasklet.TaskletContext; | import org.apache.ant.tasklet.TaskletContext; | ||||
| import org.apache.ant.tasklet.engine.TaskletEngine; | import org.apache.ant.tasklet.engine.TaskletEngine; | ||||
| import org.apache.ant.tasklet.engine.TskDeployer; | |||||
| import org.apache.avalon.Disposable; | import org.apache.avalon.Disposable; | ||||
| import org.apache.avalon.Initializable; | import org.apache.avalon.Initializable; | ||||
| import org.apache.avalon.camelot.CamelotUtil; | |||||
| import org.apache.avalon.camelot.Deployer; | |||||
| import org.apache.avalon.camelot.DeploymentException; | import org.apache.avalon.camelot.DeploymentException; | ||||
| import org.apache.avalon.util.ObjectUtil; | import org.apache.avalon.util.ObjectUtil; | ||||
| import org.apache.avalon.util.StringUtil; | import org.apache.avalon.util.StringUtil; | ||||
| @@ -41,7 +42,6 @@ import org.apache.avalon.util.cli.AbstractMain; | |||||
| import org.apache.avalon.util.cli.CLOption; | import org.apache.avalon.util.cli.CLOption; | ||||
| import org.apache.avalon.util.cli.CLOptionDescriptor; | import org.apache.avalon.util.cli.CLOptionDescriptor; | ||||
| import org.apache.avalon.util.io.ExtensionFileFilter; | import org.apache.avalon.util.io.ExtensionFileFilter; | ||||
| import org.apache.avalon.util.io.FileUtil; | |||||
| import org.apache.log.Category; | import org.apache.log.Category; | ||||
| import org.apache.log.LogKit; | import org.apache.log.LogKit; | ||||
| import org.apache.log.Logger; | import org.apache.log.Logger; | ||||
| @@ -67,21 +67,11 @@ public class Main | |||||
| protected final static String DEFAULT_LOGLEVEL = "WARN"; | protected final static String DEFAULT_LOGLEVEL = "WARN"; | ||||
| //Some defaults for file locations/names | //Some defaults for file locations/names | ||||
| protected final static String DEFAULT_LIB_DIRECTORY = "lib"; | |||||
| protected final static String DEFAULT_TASKLIB_DIRECTORY = DEFAULT_LIB_DIRECTORY; | |||||
| protected final static String DEFAULT_FILENAME = "build.xmk"; | protected final static String DEFAULT_FILENAME = "build.xmk"; | ||||
| //some constants that define the classes to be loaded to perform | |||||
| //particular services | |||||
| protected final static String DEFAULT_ENGINE = | |||||
| "org.apache.ant.project.DefaultProjectEngine"; | |||||
| protected final static String DEFAULT_LISTENER = | protected final static String DEFAULT_LISTENER = | ||||
| "org.apache.ant.project.DefaultProjectListener"; | "org.apache.ant.project.DefaultProjectListener"; | ||||
| protected final static String DEFAULT_BUILDER = | |||||
| "org.apache.ant.project.DefaultProjectBuilder"; | |||||
| //defines for the Command Line options | //defines for the Command Line options | ||||
| private static final int HELP_OPT = 'h'; | private static final int HELP_OPT = 'h'; | ||||
| private static final int QUIET_OPT = 'q'; | private static final int QUIET_OPT = 'q'; | ||||
| @@ -91,8 +81,6 @@ public class Main | |||||
| private static final int DEFINE_OPT = 'D'; | private static final int DEFINE_OPT = 'D'; | ||||
| private static final int VERSION_OPT = 1; | private static final int VERSION_OPT = 1; | ||||
| private static final int LISTENER_OPT = 2; | private static final int LISTENER_OPT = 2; | ||||
| private static final int BIN_DIR_OPT = 3; | |||||
| private static final int LIB_DIR_OPT = 4; | |||||
| private static final int TASKLIB_DIR_OPT = 5; | private static final int TASKLIB_DIR_OPT = 5; | ||||
| private static final int INCREMENTAL_OPT = 6; | private static final int INCREMENTAL_OPT = 6; | ||||
| private static final int HOME_DIR_OPT = 7; | private static final int HOME_DIR_OPT = 7; | ||||
| @@ -102,8 +90,7 @@ public class Main | |||||
| { | { | ||||
| HELP_OPT, QUIET_OPT, VERBOSE_OPT, FILE_OPT, | HELP_OPT, QUIET_OPT, VERBOSE_OPT, FILE_OPT, | ||||
| LOG_LEVEL_OPT, VERSION_OPT, LISTENER_OPT, | LOG_LEVEL_OPT, VERSION_OPT, LISTENER_OPT, | ||||
| DEFINE_OPT | |||||
| //BIN_DIR_OPT, LIB_DIR_OPT, TASKLIB_DIR_OPT, HOME_DIR_OPT | |||||
| DEFINE_OPT //TASKLIB_DIR_OPT, HOME_DIR_OPT | |||||
| }; | }; | ||||
| //incompatable options for other logging options | //incompatable options for other logging options | ||||
| @@ -112,15 +99,8 @@ public class Main | |||||
| QUIET_OPT, VERBOSE_OPT, LOG_LEVEL_OPT | QUIET_OPT, VERBOSE_OPT, LOG_LEVEL_OPT | ||||
| }; | }; | ||||
| protected Logger m_logger; | |||||
| protected ProjectListener m_listener; | protected ProjectListener m_listener; | ||||
| protected File m_binDir; | |||||
| protected File m_homeDir; | protected File m_homeDir; | ||||
| protected File m_libDir; | |||||
| protected File m_taskLibDir; | |||||
| protected File m_buildFile; | |||||
| protected File m_userDir; | |||||
| /** | /** | ||||
| * Main entry point called to run standard Ant. | * Main entry point called to run standard Ant. | ||||
| @@ -134,13 +114,13 @@ public class Main | |||||
| try { main.execute( args ); } | try { main.execute( args ); } | ||||
| catch( final AntException ae ) | catch( final AntException ae ) | ||||
| { | { | ||||
| main.m_logger.error( "Error: " + ae.getMessage() ); | |||||
| main.m_logger.debug( "Exception..." + StringUtil.printStackTrace( ae ) ); | |||||
| main.getLogger().error( "Error: " + ae.getMessage() ); | |||||
| main.getLogger().debug( "Exception..." + StringUtil.printStackTrace( ae ) ); | |||||
| } | } | ||||
| catch( final Throwable throwable ) | catch( final Throwable throwable ) | ||||
| { | { | ||||
| main.m_logger.error( "Error: " + throwable ); | |||||
| main.m_logger.debug( "Exception..." + StringUtil.printStackTrace( throwable ) ); | |||||
| main.getLogger().error( "Error: " + throwable ); | |||||
| main.getLogger().debug( "Exception..." + StringUtil.printStackTrace( throwable ) ); | |||||
| } | } | ||||
| } | } | ||||
| @@ -151,7 +131,7 @@ public class Main | |||||
| protected CLOptionDescriptor[] createCLOptions() | protected CLOptionDescriptor[] createCLOptions() | ||||
| { | { | ||||
| //TODO: localise | //TODO: localise | ||||
| final CLOptionDescriptor[] options = new CLOptionDescriptor[ 13 ]; | |||||
| final CLOptionDescriptor[] options = new CLOptionDescriptor[ 11 ]; | |||||
| options[0] = | options[0] = | ||||
| new CLOptionDescriptor( "help", | new CLOptionDescriptor( "help", | ||||
| @@ -202,33 +182,21 @@ public class Main | |||||
| INFO_OPT_INCOMPAT ); | INFO_OPT_INCOMPAT ); | ||||
| options[7] = | options[7] = | ||||
| new CLOptionDescriptor( "bin-dir", | |||||
| CLOptionDescriptor.ARGUMENT_REQUIRED, | |||||
| BIN_DIR_OPT, | |||||
| "the listener for log events." ); | |||||
| options[8] = | |||||
| new CLOptionDescriptor( "lib-dir", | |||||
| CLOptionDescriptor.ARGUMENT_REQUIRED, | |||||
| LIB_DIR_OPT, | |||||
| "the lib directory to scan for jars/zip files." ); | |||||
| options[9] = | |||||
| new CLOptionDescriptor( "task-lib-dir", | new CLOptionDescriptor( "task-lib-dir", | ||||
| CLOptionDescriptor.ARGUMENT_REQUIRED, | CLOptionDescriptor.ARGUMENT_REQUIRED, | ||||
| TASKLIB_DIR_OPT, | TASKLIB_DIR_OPT, | ||||
| "the task lib directory to scan for .tsk files." ); | "the task lib directory to scan for .tsk files." ); | ||||
| options[10] = | |||||
| options[8] = | |||||
| new CLOptionDescriptor( "incremental", | new CLOptionDescriptor( "incremental", | ||||
| CLOptionDescriptor.ARGUMENT_DISALLOWED, | CLOptionDescriptor.ARGUMENT_DISALLOWED, | ||||
| INCREMENTAL_OPT, | INCREMENTAL_OPT, | ||||
| "Run in incremental mode" ); | "Run in incremental mode" ); | ||||
| options[11] = | |||||
| options[9] = | |||||
| new CLOptionDescriptor( "ant-home", | new CLOptionDescriptor( "ant-home", | ||||
| CLOptionDescriptor.ARGUMENT_REQUIRED, | CLOptionDescriptor.ARGUMENT_REQUIRED, | ||||
| HOME_DIR_OPT, | HOME_DIR_OPT, | ||||
| "Specify ant home directory" ); | "Specify ant home directory" ); | ||||
| options[12] = | |||||
| options[10] = | |||||
| new CLOptionDescriptor( "define", | new CLOptionDescriptor( "define", | ||||
| CLOptionDescriptor.ARGUMENTS_REQUIRED_2, | CLOptionDescriptor.ARGUMENTS_REQUIRED_2, | ||||
| DEFINE_OPT, | DEFINE_OPT, | ||||
| @@ -249,11 +217,8 @@ public class Main | |||||
| final ArrayList targets = new ArrayList(); | final ArrayList targets = new ArrayList(); | ||||
| String filename = null; | String filename = null; | ||||
| String listenerName = null; | String listenerName = null; | ||||
| String builderName = null; | |||||
| String logLevel = null; | String logLevel = null; | ||||
| String binDir = null; | |||||
| String homeDir = null; | String homeDir = null; | ||||
| String libDir = null; | |||||
| String taskLibDir = null; | String taskLibDir = null; | ||||
| boolean incremental = false; | boolean incremental = false; | ||||
| HashMap defines = new HashMap(); | HashMap defines = new HashMap(); | ||||
| @@ -268,8 +233,6 @@ public class Main | |||||
| case HELP_OPT: usage(); return; | case HELP_OPT: usage(); return; | ||||
| case VERSION_OPT: System.out.println( VERSION ); return; | case VERSION_OPT: System.out.println( VERSION ); return; | ||||
| case FILE_OPT: filename = option.getArgument(); break; | case FILE_OPT: filename = option.getArgument(); break; | ||||
| case BIN_DIR_OPT: binDir = option.getArgument(); break; | |||||
| case LIB_DIR_OPT: libDir = option.getArgument(); break; | |||||
| case HOME_DIR_OPT: homeDir = option.getArgument(); break; | case HOME_DIR_OPT: homeDir = option.getArgument(); break; | ||||
| case TASKLIB_DIR_OPT: taskLibDir = option.getArgument(); break; | case TASKLIB_DIR_OPT: taskLibDir = option.getArgument(); break; | ||||
| case VERBOSE_OPT: logLevel = "INFO"; break; | case VERBOSE_OPT: logLevel = "INFO"; break; | ||||
| @@ -284,64 +247,63 @@ public class Main | |||||
| } | } | ||||
| } | } | ||||
| if( null == logLevel ) logLevel = getDefaultLogLevel(); | |||||
| if( null == listenerName ) listenerName = getDefaultListener(); | |||||
| if( null == filename ) filename = getDefaultFilename(); | |||||
| if( null == libDir ) libDir = getDefaultLibDir(); | |||||
| if( null == taskLibDir ) taskLibDir = getDefaultTaskLibDir(); | |||||
| if( null == builderName ) builderName = getBuilderNameFor( filename ); | |||||
| setupLogger( logLevel ); //handle logging... | |||||
| setupListener( listenerName ); //handle listener.. | |||||
| setupDefaultAntDirs(); | |||||
| //try to auto-discover the location of ant so that | |||||
| //can populate classpath with libs/tasks and gain access | |||||
| //to antRun | |||||
| if( null == binDir && null == homeDir ) | |||||
| { | |||||
| m_homeDir = getDefaultHomeDir(); | |||||
| m_binDir = m_homeDir.getParentFile(); | |||||
| } | |||||
| else if( null == binDir ) // && null != homeDir | |||||
| { | |||||
| m_homeDir = getHomeDir( homeDir ); | |||||
| m_binDir = new File( m_homeDir, "bin" ); | |||||
| } | |||||
| else | |||||
| if( null == logLevel ) logLevel = DEFAULT_LOGLEVEL; | |||||
| if( null == listenerName ) listenerName = DEFAULT_LISTENER; | |||||
| if( null == filename ) filename = DEFAULT_FILENAME; | |||||
| //handle logging... | |||||
| setLogger( createLogger( logLevel ) ); | |||||
| //if ant home not set then use system property ant.home | |||||
| //that was set up by launcher. | |||||
| if( null == homeDir ) homeDir = System.getProperty( "ant.home" ); | |||||
| final Properties properties = new Properties(); | |||||
| properties.setProperty( "ant.home", homeDir ); | |||||
| if( null != taskLibDir ) properties.setProperty( "ant.path.task-lib", taskLibDir ); | |||||
| m_homeDir = (new File( homeDir )).getAbsoluteFile(); | |||||
| if( !m_homeDir.isDirectory() ) | |||||
| { | { | ||||
| m_binDir = getBinDir( binDir ); | |||||
| m_homeDir = m_binDir.getParentFile(); | |||||
| throw new AntException( "ant-home (" + m_homeDir + ") is not a directory" ); | |||||
| } | } | ||||
| m_libDir = getLibDir( m_homeDir, libDir ); | |||||
| m_taskLibDir = getTaskLibDir( m_homeDir, taskLibDir ); | |||||
| m_buildFile = getFile( filename ); | |||||
| m_logger.warn( "Ant Build File: " + m_buildFile ); | |||||
| m_logger.info( "Ant Home Directory: " + m_homeDir ); | |||||
| m_logger.info( "Ant Bin Directory: " + m_binDir ); | |||||
| m_logger.debug( "Ant Lib Directory: " + m_libDir ); | |||||
| m_logger.debug( "Ant Task Lib Directory: " + m_taskLibDir ); | |||||
| final File libDir = new File( m_homeDir, "lib" ); | |||||
| final File buildFile = (new File( filename )).getCanonicalFile(); | |||||
| if( !buildFile.isFile() ) | |||||
| { | |||||
| throw new AntException( "File " + buildFile + " is not a file or doesn't exist" ); | |||||
| } | |||||
| //setup classloader so that it will correctly load | //setup classloader so that it will correctly load | ||||
| //the Project/ProjectBuilder/ProjectEngine and all dependencies | //the Project/ProjectBuilder/ProjectEngine and all dependencies | ||||
| setupContextClassLoader( m_libDir ); | |||||
| final ClassLoader classLoader = createClassLoader( libDir ); | |||||
| Thread.currentThread().setContextClassLoader( classLoader ); | |||||
| final Project project = getProject( builderName, m_buildFile ); | |||||
| setupProjectContext( project, defines ); | |||||
| //handle listener.. | |||||
| final ProjectListener listener = createListener( listenerName ); | |||||
| final ProjectEngine engine = getProjectEngine(); | |||||
| getLogger().warn( "Ant Build File: " + buildFile ); | |||||
| getLogger().info( "Ant Home Directory: " + m_homeDir ); | |||||
| //getLogger().info( "Ant Bin Directory: " + m_binDir ); | |||||
| //getLogger().debug( "Ant Lib Directory: " + m_libDir ); | |||||
| //getLogger().debug( "Ant Task Lib Directory: " + m_taskLibDir ); | |||||
| //make sure Engine is sweet... | |||||
| if( engine instanceof Initializable ) | |||||
| { | |||||
| ((Initializable)engine).init(); | |||||
| } | |||||
| final AntEngine antEngine = new DefaultAntEngine(); | |||||
| setupLogger( antEngine ); | |||||
| antEngine.setProperties( properties ); | |||||
| antEngine.init(); | |||||
| engine.addProjectListener( m_listener ); | |||||
| final ProjectBuilder builder = antEngine.getProjectBuilder(); | |||||
| //create the project | |||||
| final Project project = builder.build( buildFile ); | |||||
| setupProjectContext( project, defines ); | |||||
| deployDefaultTaskLibs( engine, m_taskLibDir ); | |||||
| final ProjectEngine engine = antEngine.getProjectEngine(); | |||||
| engine.addProjectListener( listener ); | |||||
| BufferedReader reader = null; | BufferedReader reader = null; | ||||
| @@ -366,44 +328,7 @@ public class Main | |||||
| } | } | ||||
| //shutdown engine gracefully if needed | |||||
| if( engine instanceof Disposable ) | |||||
| { | |||||
| ((Disposable)engine).dispose(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Deploy all tasklibs in tasklib directory into ProjectEngine. | |||||
| * | |||||
| * @param engine the ProjectEngine | |||||
| * @param taskLibDirectory the directory to look for .tsk files | |||||
| */ | |||||
| protected void deployDefaultTaskLibs( final ProjectEngine engine, | |||||
| final File taskLibDirectory ) | |||||
| { | |||||
| final ExtensionFileFilter filter = new ExtensionFileFilter( ".tsk" ); | |||||
| final File[] files = taskLibDirectory.listFiles( filter ); | |||||
| final TskDeployer deployer = engine.getTaskletEngine().getTskDeployer(); | |||||
| for( int i = 0; i < files.length; i++ ) | |||||
| { | |||||
| final String name = files[ i ].getName(); | |||||
| try | |||||
| { | |||||
| deployer.deploy( name.substring( 0, name.length() - 4 ), | |||||
| files[ i ].toURL() ); | |||||
| } | |||||
| catch( final MalformedURLException mue ) {} | |||||
| catch( final DeploymentException de ) | |||||
| { | |||||
| throw new AntException( "Failed to deploy task library " + files[ i ], | |||||
| de ); | |||||
| } | |||||
| } | |||||
| antEngine.dispose(); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -436,22 +361,11 @@ public class Main | |||||
| } | } | ||||
| catch( final AntException ae ) | catch( final AntException ae ) | ||||
| { | { | ||||
| m_logger.error( "BUILD FAILED" ); | |||||
| m_logger.error( "Reason:\n" + StringUtil.printStackTrace( ae, 5, true ) ); | |||||
| getLogger().error( "BUILD FAILED" ); | |||||
| getLogger().error( "Reason:\n" + StringUtil.printStackTrace( ae, 5, true ) ); | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Setup Logger for a particular log-level. | |||||
| * This is in seperate method so it can be overidden if sub-classed. | |||||
| * | |||||
| * @param logLevel the log-level | |||||
| */ | |||||
| protected void setupLogger( final String logLevel ) | |||||
| { | |||||
| m_logger = createLogger( logLevel ); | |||||
| } | |||||
| /** | /** | ||||
| * Create Logger of appropriate log-level. | * Create Logger of appropriate log-level. | ||||
| * | * | ||||
| @@ -479,39 +393,47 @@ public class Main | |||||
| * | * | ||||
| * @param listenerName the name of project listener | * @param listenerName the name of project listener | ||||
| */ | */ | ||||
| protected void setupListener( final String listenerName ) | |||||
| protected ProjectListener createListener( final String listenerName ) | |||||
| throws AntException | |||||
| { | { | ||||
| m_listener = createListener( listenerName ); | |||||
| m_logger.addLogTarget( new LogTargetToListenerAdapter( m_listener ) ); | |||||
| } | |||||
| ProjectListener result = null; | |||||
| /** | |||||
| * Make sure classloader is setup correctly so can do Class.forName safely | |||||
| * | |||||
| * @param libDir the directory to grab all the lib files from | |||||
| */ | |||||
| protected void setupContextClassLoader( final File libDir ) | |||||
| { | |||||
| setupClassLoader( libDir ); | |||||
| Thread.currentThread().setContextClassLoader( AntLoader.getLoader() ); | |||||
| try { result = (ProjectListener)ObjectUtil.createObject( listenerName ); } | |||||
| catch( final Throwable t ) | |||||
| { | |||||
| throw new AntException( "Error creating the listener " + listenerName + | |||||
| " due to " + StringUtil.printStackTrace( t, 5, true ), | |||||
| t ); | |||||
| } | |||||
| getLogger().addLogTarget( new LogTargetToListenerAdapter( result ) ); | |||||
| return result; | |||||
| } | } | ||||
| /** | /** | ||||
| * Setup classloader so that the *current* classloader has access to parsers etc. | |||||
| * This is a bit of a hack as it assumes that AntLoader was used to load this file | |||||
| * but it is the only way to add to current classloader safely. | |||||
| * Try to load all extra zipz/jars from lib directory into CURRENT classloader. | |||||
| * | * | ||||
| * @param libDir the directory of lib files to add | * @param libDir the directory of lib files to add | ||||
| */ | */ | ||||
| protected void setupClassLoader( final File libDir ) | |||||
| protected ClassLoader createClassLoader( final File libDir ) | |||||
| { | { | ||||
| final ClassLoader candidate = getClass().getClassLoader(); | |||||
| if( !(candidate instanceof AntClassLoader) ) | |||||
| { | |||||
| getLogger().warn( "Warning: Unable to add entries from " + | |||||
| "lib-path to classloader" ); | |||||
| return candidate; | |||||
| } | |||||
| final AntClassLoader classLoader = (AntClassLoader)candidate; | |||||
| final ExtensionFileFilter filter = | final ExtensionFileFilter filter = | ||||
| new ExtensionFileFilter( new String[] { ".jar", ".zip" } ); | new ExtensionFileFilter( new String[] { ".jar", ".zip" } ); | ||||
| final File[] files = libDir.listFiles( filter ); | final File[] files = libDir.listFiles( filter ); | ||||
| final AntLoader classLoader = AntLoader.getLoader(); | |||||
| for( int i = 0; i < files.length; i++ ) | for( int i = 0; i < files.length; i++ ) | ||||
| { | { | ||||
| //except for a few *special* files add all the | //except for a few *special* files add all the | ||||
| @@ -524,28 +446,8 @@ public class Main | |||||
| catch( final MalformedURLException mue ) {} | catch( final MalformedURLException mue ) {} | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| /** | |||||
| * Using a specified builder create a project from a particular file. | |||||
| * | |||||
| * @param builderName the name of the builder class | |||||
| * @param file the file | |||||
| * @return the newly created Project | |||||
| * @exception AntException if an error occurs | |||||
| * @exception IOException if an error occurs | |||||
| */ | |||||
| protected Project getProject( final String builderName, final File file ) | |||||
| throws AntException, IOException | |||||
| { | |||||
| m_logger.debug( "Ant Project Builder: " + builderName ); | |||||
| final ProjectBuilder builder = createBuilder( builderName ); | |||||
| builder.setLogger( m_logger ); | |||||
| //create the project | |||||
| final Project project = builder.build( file ); | |||||
| return project; | |||||
| return classLoader; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -562,12 +464,11 @@ public class Main | |||||
| { | { | ||||
| //put these values into defines so that they overide | //put these values into defines so that they overide | ||||
| //user-defined proeprties | //user-defined proeprties | ||||
| defines.put( AntContextResources.HOME_DIR, m_homeDir ); | |||||
| defines.put( AntContextResources.BIN_DIR, m_binDir ); | |||||
| defines.put( AntContextResources.LIB_DIR, m_libDir ); | |||||
| defines.put( AntContextResources.TASKLIB_DIR, m_taskLibDir ); | |||||
| //defines.put( AntContextResources.USER_DIR, m_userDir ); | |||||
| defines.put( TaskletContext.JAVA_VERSION, getJavaVersion() ); | |||||
| //defines.put( AntContextResources.HOME_DIR, m_homeDir ); | |||||
| //defines.put( AntContextResources.BIN_DIR, m_binDir ); | |||||
| //defines.put( AntContextResources.LIB_DIR, m_libDir ); | |||||
| //defines.put( AntContextResources.TASKLIB_DIR, m_taskLibDir ); | |||||
| //defines.put( TaskletContext.JAVA_VERSION, getJavaVersion() ); | |||||
| final TaskletContext context = project.getContext(); | final TaskletContext context = project.getContext(); | ||||
| addToContext( context, defines ); | addToContext( context, defines ); | ||||
| @@ -593,330 +494,5 @@ public class Main | |||||
| context.setProperty( key, value ); | context.setProperty( key, value ); | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Helper method to retrieve current JVM version. | |||||
| * Basically stolen from original Ant sources. | |||||
| * | |||||
| * @return the current JVM version | |||||
| */ | |||||
| protected JavaVersion getJavaVersion() | |||||
| { | |||||
| JavaVersion version = JavaVersion.JAVA1_0; | |||||
| try | |||||
| { | |||||
| Class.forName( "java.lang.Void" ); | |||||
| version = JavaVersion.JAVA1_1; | |||||
| Class.forName( "java.lang.ThreadLocal" ); | |||||
| version = JavaVersion.JAVA1_2; | |||||
| Class.forName( "java.lang.StrictMath" ); | |||||
| version = JavaVersion.JAVA1_3; | |||||
| } | |||||
| catch( final ClassNotFoundException cnfe ) {} | |||||
| return version; | |||||
| } | |||||
| /** | |||||
| * Create and configure project engine | |||||
| * | |||||
| * @return the ProjectEngine | |||||
| */ | |||||
| protected ProjectEngine getProjectEngine() | |||||
| { | |||||
| final ProjectEngine engine = createProjectEngine(); | |||||
| engine.setLogger( m_logger ); | |||||
| return engine; | |||||
| } | |||||
| /** | |||||
| * Create the project engine. | |||||
| * This is seperate method so that it can be overidden in a sub-class. | |||||
| * | |||||
| * @return the new ProjectEngine | |||||
| */ | |||||
| protected ProjectEngine createProjectEngine() | |||||
| { | |||||
| return (ProjectEngine)createObject( DEFAULT_ENGINE, "project-engine" ); | |||||
| } | |||||
| protected File getHomeDir( final String homeDir ) | |||||
| throws AntException | |||||
| { | |||||
| final File file = (new File( homeDir )).getAbsoluteFile(); | |||||
| checkDirectory( file, "ant-home" ); | |||||
| return file; | |||||
| } | |||||
| protected File getBinDir( final String binDir ) | |||||
| throws AntException | |||||
| { | |||||
| File file = (new File( binDir )).getAbsoluteFile(); | |||||
| if( !file.isDirectory() ) file = file.getParentFile(); | |||||
| checkDirectory( file, "bin-dir" ); | |||||
| return file; | |||||
| } | |||||
| protected File getLibDir( final File antHome, String libDir ) | |||||
| throws AntException | |||||
| { | |||||
| return resolveDirectory( antHome, libDir, "lib-dir" ); | |||||
| } | |||||
| protected File getTaskLibDir( final File antHome, final String taskLibDir ) | |||||
| throws AntException | |||||
| { | |||||
| return resolveDirectory( antHome, taskLibDir, "task-lib-dir" ); | |||||
| } | |||||
| protected File resolveDirectory( final File antHome, final String dir, final String name ) | |||||
| throws AntException | |||||
| { | |||||
| final File file = FileUtil.resolveFile( antHome, dir ); | |||||
| checkDirectory( file, name ); | |||||
| return file; | |||||
| } | |||||
| protected void checkDirectory( final File file, final String name ) | |||||
| { | |||||
| if( !file.exists() ) | |||||
| { | |||||
| throw new AntException( name + " (" + file + ") does not exist" ); | |||||
| } | |||||
| else if( !file.isDirectory() ) | |||||
| { | |||||
| throw new AntException( name + " (" + file + ") is not a directory" ); | |||||
| } | |||||
| } | |||||
| protected ProjectListener createListener( final String listenerName ) | |||||
| throws AntException | |||||
| { | |||||
| try { return (ProjectListener)createObject( listenerName, "listener" ); } | |||||
| catch( final ClassCastException cce ) | |||||
| { | |||||
| throw new AntException( "Aparently the listener named " + listenerName + | |||||
| " does not implement the ProjectListener interface", | |||||
| cce ); | |||||
| } | |||||
| } | |||||
| protected void setupDefaultAntDirs() | |||||
| { | |||||
| final String os = System.getProperty( "os.name" ); | |||||
| final String userDir = System.getProperty( "user.home" ); | |||||
| m_userDir = | |||||
| (new File( getUserLocationFor( os, userDir ) )).getAbsoluteFile(); | |||||
| } | |||||
| /** | |||||
| * Retrieve default bin-dir value if possible (Otherwise throw an exception). | |||||
| * | |||||
| * Lookup OS specific places for ant to be. | |||||
| * /opt/ant on *BSD ? | |||||
| * /usr/local/ant on linux ? | |||||
| * /Program Files/Ant on Win32 ? | |||||
| * | |||||
| * @return bin directory | |||||
| */ | |||||
| protected File getDefaultHomeDir() | |||||
| throws AntException | |||||
| { | |||||
| if( null != m_userDir ) | |||||
| { | |||||
| try | |||||
| { | |||||
| checkDirectory( m_userDir, null ); | |||||
| return m_userDir; | |||||
| } | |||||
| catch( final AntException ae ) {} | |||||
| } | |||||
| final String os = System.getProperty( "os.name" ); | |||||
| final File candidate = | |||||
| (new File( getSystemLocationFor( os ) )).getAbsoluteFile(); | |||||
| checkDirectory( candidate, "ant-home" ); | |||||
| return candidate; | |||||
| } | |||||
| /** | |||||
| * This determins a mapping from an OS specific place to ants home directory. | |||||
| * In later versions the mapping should be read from configuration file. | |||||
| * | |||||
| * @param os the name of OS | |||||
| * @return the location of directory | |||||
| */ | |||||
| protected String getUserLocationFor( final String os, final String userDir ) | |||||
| { | |||||
| if( os.startsWith( "Windows" ) ) | |||||
| { | |||||
| return userDir + "\\Ant"; | |||||
| } | |||||
| else if( '/' == File.separatorChar ) | |||||
| { | |||||
| if( os.startsWith( "Linux" ) ) return userDir + "/ant"; | |||||
| else return userDir + "/opt/ant"; | |||||
| } | |||||
| else | |||||
| { | |||||
| return userDir + File.separator + "ant"; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * This determins a mapping from an OS specific place to ants home directory. | |||||
| * In later versions the mapping should be read from configuration file. | |||||
| * | |||||
| * @param os the name of OS | |||||
| * @return the location of directory | |||||
| */ | |||||
| protected String getSystemLocationFor( final String os ) | |||||
| { | |||||
| if( os.startsWith( "Windows" ) ) | |||||
| { | |||||
| return "\\Program Files\\Ant"; | |||||
| } | |||||
| else if( '/' == File.separatorChar ) | |||||
| { | |||||
| if( os.startsWith( "Linux" ) ) return "/usr/local/ant"; | |||||
| else return "/opt/ant"; | |||||
| } | |||||
| else | |||||
| { | |||||
| return File.separator + "ant"; | |||||
| } | |||||
| } | |||||
| protected String getDefaultLibDir() | |||||
| { | |||||
| return DEFAULT_LIB_DIRECTORY; | |||||
| } | |||||
| protected String getDefaultTaskLibDir() | |||||
| { | |||||
| return DEFAULT_TASKLIB_DIRECTORY; | |||||
| } | |||||
| /** | |||||
| * Retrieve default filename. Overide this in base classes to change default. | |||||
| * | |||||
| * @return the default filename | |||||
| */ | |||||
| protected String getDefaultFilename() | |||||
| { | |||||
| return DEFAULT_FILENAME; | |||||
| } | |||||
| /** | |||||
| * Retrieve default logelevel. Overide this in base classes to change default. | |||||
| * | |||||
| * @return the default loglevel | |||||
| */ | |||||
| protected String getDefaultLogLevel() | |||||
| { | |||||
| return DEFAULT_LOGLEVEL; | |||||
| } | |||||
| /** | |||||
| * Retrieve default listener. Overide this in base classes to change default. | |||||
| * | |||||
| * @return the default listener | |||||
| */ | |||||
| protected String getDefaultListener() | |||||
| { | |||||
| return DEFAULT_LISTENER; | |||||
| } | |||||
| /** | |||||
| * Get File object for filename. | |||||
| * Check that file exists and is not a directory. | |||||
| * | |||||
| * @param filename the filename | |||||
| * @return the file object | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| protected File getFile( final String filename ) | |||||
| throws AntException, IOException | |||||
| { | |||||
| final File file = (new File( filename )).getCanonicalFile(); | |||||
| if( !file.exists() ) | |||||
| { | |||||
| throw new AntException( "File " + file + " does not exist." ); | |||||
| } | |||||
| if( file.isDirectory() ) | |||||
| { | |||||
| throw new AntException( "File " + file + " is a directory." ); | |||||
| } | |||||
| return file; | |||||
| } | |||||
| /** | |||||
| * Create instance of Builder based on classname. | |||||
| * | |||||
| * @param builderName builder class name | |||||
| * @return the ProjectBuilder | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| protected ProjectBuilder createBuilder( final String builderName ) | |||||
| throws AntException | |||||
| { | |||||
| try { return (ProjectBuilder)createObject( builderName, "builder" ); } | |||||
| catch( final ClassCastException cce ) | |||||
| { | |||||
| throw new AntException( "Aparently the builder named " + builderName + | |||||
| " does not implement the ProjectBuilder interface", | |||||
| cce ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Helper method to create object and throw an apporpriate AntException if creation failed. | |||||
| * | |||||
| * @param objectName the classname of object | |||||
| * @param type the type of object being created (ie builder|listener) | |||||
| * @return the created object | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| protected Object createObject( final String objectName, final String type ) | |||||
| throws AntException | |||||
| { | |||||
| try | |||||
| { | |||||
| return ObjectUtil.createObject( objectName ); | |||||
| } | |||||
| catch( final IllegalAccessException iae ) | |||||
| { | |||||
| throw new AntException( "Non-public constructor for " + type + " " + objectName, | |||||
| iae ); | |||||
| } | |||||
| catch( final InstantiationException ie ) | |||||
| { | |||||
| throw new AntException( "Error instantiating class for " + type + " " + objectName, | |||||
| ie ); | |||||
| } | |||||
| catch( final ClassNotFoundException cnfe ) | |||||
| { | |||||
| throw new AntException( "Could not find the class for " + type + " " + objectName, | |||||
| cnfe ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Retrieve class name of builder for file. | |||||
| * Eventually this will look in a registry of file extentions to BuilderNames. | |||||
| * | |||||
| * @param filename the filename | |||||
| * @return the name of Class for Builder | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| protected String getBuilderNameFor( final String filename ) | |||||
| throws AntException | |||||
| { | |||||
| return DEFAULT_BUILDER; | |||||
| } | |||||
| } | } | ||||
| @@ -18,12 +18,6 @@ import org.xml.sax.SAXException; | |||||
| public class ConfigurationBuilder | public class ConfigurationBuilder | ||||
| extends org.apache.avalon.DefaultConfigurationBuilder | extends org.apache.avalon.DefaultConfigurationBuilder | ||||
| { | { | ||||
| public ConfigurationBuilder() | |||||
| throws SAXException | |||||
| { | |||||
| super(); | |||||
| } | |||||
| protected org.apache.avalon.SAXConfigurationHandler getHandler() | protected org.apache.avalon.SAXConfigurationHandler getHandler() | ||||
| { | { | ||||
| return new SAXConfigurationHandler(); | return new SAXConfigurationHandler(); | ||||
| @@ -13,9 +13,9 @@ import java.util.ArrayList; | |||||
| import java.util.Iterator; | import java.util.Iterator; | ||||
| import org.apache.ant.convert.Converter; | import org.apache.ant.convert.Converter; | ||||
| import org.apache.ant.convert.ConverterException; | import org.apache.ant.convert.ConverterException; | ||||
| import org.apache.avalon.AbstractLoggable; | |||||
| import org.apache.avalon.ComponentManager; | import org.apache.avalon.ComponentManager; | ||||
| import org.apache.avalon.ComponentNotAccessibleException; | |||||
| import org.apache.avalon.ComponentNotFoundException; | |||||
| import org.apache.avalon.ComponentManagerException; | |||||
| import org.apache.avalon.Composer; | import org.apache.avalon.Composer; | ||||
| import org.apache.avalon.ConfigurationException; | import org.apache.avalon.ConfigurationException; | ||||
| import org.apache.avalon.Context; | import org.apache.avalon.Context; | ||||
| @@ -30,6 +30,7 @@ import org.apache.log.Logger; | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | ||||
| */ | */ | ||||
| public class DefaultConfigurer | public class DefaultConfigurer | ||||
| extends AbstractLoggable | |||||
| implements Configurer, Composer, Loggable | implements Configurer, Composer, Loggable | ||||
| { | { | ||||
| protected final static String RESERVED_ATTRIBUTES[] = | protected final static String RESERVED_ATTRIBUTES[] = | ||||
| @@ -44,15 +45,9 @@ public class DefaultConfigurer | |||||
| protected final static boolean DEBUG = false; | protected final static boolean DEBUG = false; | ||||
| protected Converter m_converter; | protected Converter m_converter; | ||||
| protected Logger m_logger; | |||||
| public void setLogger( final Logger logger ) | |||||
| { | |||||
| m_logger = logger; | |||||
| } | |||||
| public void compose( final ComponentManager componentManager ) | public void compose( final ComponentManager componentManager ) | ||||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||||
| throws ComponentManagerException | |||||
| { | { | ||||
| m_converter = (Converter)componentManager.lookup( "org.apache.ant.convert.Converter" ); | m_converter = (Converter)componentManager.lookup( "org.apache.ant.convert.Converter" ); | ||||
| } | } | ||||
| @@ -206,7 +201,7 @@ public class DefaultConfigurer | |||||
| final Object objectValue = | final Object objectValue = | ||||
| PropertyUtil.resolveProperty( value, context, false ); | PropertyUtil.resolveProperty( value, context, false ); | ||||
| setValue( object, objectValue, methods ); | |||||
| setValue( object, objectValue, methods, context ); | |||||
| } | } | ||||
| catch( final PropertyException pe ) | catch( final PropertyException pe ) | ||||
| { | { | ||||
| @@ -215,7 +210,10 @@ public class DefaultConfigurer | |||||
| } | } | ||||
| } | } | ||||
| protected void setValue( final Object object, Object value, final Method methods[] ) | |||||
| protected void setValue( final Object object, | |||||
| Object value, | |||||
| final Method methods[], | |||||
| final Context context ) | |||||
| throws ConfigurationException | throws ConfigurationException | ||||
| { | { | ||||
| final Class sourceClass = value.getClass(); | final Class sourceClass = value.getClass(); | ||||
| @@ -223,7 +221,7 @@ public class DefaultConfigurer | |||||
| for( int i = 0; i < methods.length; i++ ) | for( int i = 0; i < methods.length; i++ ) | ||||
| { | { | ||||
| if( setValue( object, value, methods[ i ], sourceClass, source ) ) | |||||
| if( setValue( object, value, methods[ i ], sourceClass, source, context ) ) | |||||
| { | { | ||||
| return; | return; | ||||
| } | } | ||||
| @@ -238,7 +236,8 @@ public class DefaultConfigurer | |||||
| Object value, | Object value, | ||||
| final Method method, | final Method method, | ||||
| final Class sourceClass, | final Class sourceClass, | ||||
| final String source ) | |||||
| final String source, | |||||
| final Context context ) | |||||
| throws ConfigurationException | throws ConfigurationException | ||||
| { | { | ||||
| Class parameterType = method.getParameterTypes()[ 0 ]; | Class parameterType = method.getParameterTypes()[ 0 ]; | ||||
| @@ -249,7 +248,7 @@ public class DefaultConfigurer | |||||
| try | try | ||||
| { | { | ||||
| value = m_converter.convert( parameterType, value ); | |||||
| value = m_converter.convert( parameterType, value, context ); | |||||
| } | } | ||||
| catch( final ConverterException ce ) | catch( final ConverterException ce ) | ||||
| { | { | ||||
| @@ -359,7 +358,7 @@ public class DefaultConfigurer | |||||
| protected String getMethodNameFor( final String attribute ) | protected String getMethodNameFor( final String attribute ) | ||||
| { | { | ||||
| return "set" + getJavaNameFor( attribute ); | |||||
| return "set" + getJavaNameFor( attribute.toLowerCase() ); | |||||
| } | } | ||||
| protected String getJavaNameFor( final String name ) | protected String getJavaNameFor( final String name ) | ||||
| @@ -7,6 +7,8 @@ | |||||
| */ | */ | ||||
| package org.apache.ant.convert; | package org.apache.ant.convert; | ||||
| import org.apache.avalon.Context; | |||||
| /** | /** | ||||
| * Instances of this interface are used to convert between different types. | * Instances of this interface are used to convert between different types. | ||||
| * | * | ||||
| @@ -35,10 +37,11 @@ public abstract class AbstractConverter | |||||
| * | * | ||||
| * @param destination the destination type | * @param destination the destination type | ||||
| * @param original the original Object | * @param original the original Object | ||||
| * @param context the context in which to convert | |||||
| * @return the converted object | * @return the converted object | ||||
| * @exception Exception if an error occurs | * @exception Exception if an error occurs | ||||
| */ | */ | ||||
| public Object convert( final Class destination, final Object original ) | |||||
| public Object convert( final Class destination, final Object original, Context context ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| if( m_destination != destination ) | if( m_destination != destination ) | ||||
| @@ -53,17 +56,18 @@ public abstract class AbstractConverter | |||||
| "instance of " + m_source.getName() ); | "instance of " + m_source.getName() ); | ||||
| } | } | ||||
| return convert( original ); | |||||
| return convert( original, context ); | |||||
| } | } | ||||
| /** | /** | ||||
| * Overide this in a particular converter to do the conversion. | * Overide this in a particular converter to do the conversion. | ||||
| * | * | ||||
| * @param original the original Object | * @param original the original Object | ||||
| * @param context the context in which to convert | |||||
| * @return the converted object | * @return the converted object | ||||
| * @exception Exception if an error occurs | * @exception Exception if an error occurs | ||||
| */ | */ | ||||
| protected abstract Object convert( Object original ) | |||||
| protected abstract Object convert( Object original, Context context ) | |||||
| throws Exception; | throws Exception; | ||||
| } | } | ||||
| @@ -7,6 +7,8 @@ | |||||
| */ | */ | ||||
| package org.apache.ant.convert; | package org.apache.ant.convert; | ||||
| import org.apache.avalon.Context; | |||||
| /** | /** | ||||
| * Instances of this interface are used to convert between different types. | * Instances of this interface are used to convert between different types. | ||||
| * | * | ||||
| @@ -21,9 +23,10 @@ public interface Converter | |||||
| * | * | ||||
| * @param destination the destinaiton type | * @param destination the destinaiton type | ||||
| * @param original the original type | * @param original the original type | ||||
| * @param context the context in which to convert | |||||
| * @return the converted object | * @return the converted object | ||||
| * @exception Exception if an error occurs | * @exception Exception if an error occurs | ||||
| */ | */ | ||||
| Object convert( Class destination, Object original ) | |||||
| Object convert( Class destination, Object original, Context context ) | |||||
| throws ConverterException, Exception; | throws ConverterException, Exception; | ||||
| } | } | ||||
| @@ -8,13 +8,27 @@ | |||||
| package org.apache.ant.convert; | package org.apache.ant.convert; | ||||
| import org.apache.avalon.Component; | import org.apache.avalon.Component; | ||||
| import org.apache.avalon.Loggable; | |||||
| import org.apache.avalon.camelot.LocatorRegistry; | import org.apache.avalon.camelot.LocatorRegistry; | ||||
| import org.apache.log.Logger; | |||||
| /** | |||||
| * Converter engine to handle converting between types. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public interface ConverterEngine | public interface ConverterEngine | ||||
| extends Component, Converter, Loggable | |||||
| extends Component, Converter | |||||
| { | { | ||||
| /** | |||||
| * Get registry used to locate converters. | |||||
| * | |||||
| * @return the LocatorRegistry | |||||
| */ | |||||
| LocatorRegistry getRegistry(); | LocatorRegistry getRegistry(); | ||||
| /** | |||||
| * Get registry for converterInfo objects. | |||||
| * | |||||
| * @return the ConverterRegistry | |||||
| */ | |||||
| ConverterRegistry getInfoRegistry(); | ConverterRegistry getInfoRegistry(); | ||||
| } | } | ||||
| @@ -8,62 +8,74 @@ | |||||
| package org.apache.ant.convert; | package org.apache.ant.convert; | ||||
| import org.apache.ant.AntException; | import org.apache.ant.AntException; | ||||
| import org.apache.avalon.Component; | |||||
| import org.apache.avalon.Initializable; | |||||
| import org.apache.avalon.AbstractLoggable; | |||||
| import org.apache.avalon.ComponentManager; | |||||
| import org.apache.avalon.ComponentManagerException; | |||||
| import org.apache.avalon.Composer; | |||||
| import org.apache.avalon.Context; | |||||
| import org.apache.avalon.camelot.DefaultFactory; | import org.apache.avalon.camelot.DefaultFactory; | ||||
| import org.apache.avalon.camelot.DefaultLocatorRegistry; | import org.apache.avalon.camelot.DefaultLocatorRegistry; | ||||
| import org.apache.avalon.camelot.Factory; | |||||
| import org.apache.avalon.camelot.Locator; | import org.apache.avalon.camelot.Locator; | ||||
| import org.apache.avalon.camelot.LocatorRegistry; | import org.apache.avalon.camelot.LocatorRegistry; | ||||
| import org.apache.log.Logger; | |||||
| /** | |||||
| * Converter engine to handle converting between types. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public class DefaultConverterEngine | public class DefaultConverterEngine | ||||
| implements ConverterEngine, Initializable | |||||
| extends AbstractLoggable | |||||
| implements ConverterEngine, Composer | |||||
| { | { | ||||
| protected final static boolean DEBUG = false; | protected final static boolean DEBUG = false; | ||||
| protected DefaultFactory m_factory; | |||||
| protected LocatorRegistry m_registry; | |||||
| protected ConverterRegistry m_infoRegistry; | |||||
| protected Logger m_logger; | |||||
| public void setLogger( final Logger logger ) | |||||
| { | |||||
| m_logger = logger; | |||||
| } | |||||
| protected Factory m_factory; | |||||
| protected LocatorRegistry m_registry = new DefaultLocatorRegistry(); | |||||
| protected ConverterRegistry m_infoRegistry = new DefaultConverterRegistry(); | |||||
| /** | |||||
| * Get registry used to locate converters. | |||||
| * | |||||
| * @return the LocatorRegistry | |||||
| */ | |||||
| public LocatorRegistry getRegistry() | public LocatorRegistry getRegistry() | ||||
| { | { | ||||
| return m_registry; | return m_registry; | ||||
| } | } | ||||
| /** | |||||
| * Get registry for converterInfo objects. | |||||
| * | |||||
| * @return the ConverterRegistry | |||||
| */ | |||||
| public ConverterRegistry getInfoRegistry() | public ConverterRegistry getInfoRegistry() | ||||
| { | { | ||||
| return m_infoRegistry; | return m_infoRegistry; | ||||
| } | } | ||||
| public void init() | |||||
| throws Exception | |||||
| { | |||||
| m_infoRegistry = createInfoRegistry(); | |||||
| m_registry = createRegistry(); | |||||
| m_factory = createFactory(); | |||||
| } | |||||
| protected ConverterRegistry createInfoRegistry() | |||||
| { | |||||
| return new DefaultConverterRegistry(); | |||||
| } | |||||
| protected LocatorRegistry createRegistry() | |||||
| { | |||||
| return new DefaultLocatorRegistry(); | |||||
| } | |||||
| protected DefaultFactory createFactory() | |||||
| /** | |||||
| * Retrieve relevent services needed to deploy. | |||||
| * | |||||
| * @param componentManager the ComponentManager | |||||
| * @exception ComponentManagerException if an error occurs | |||||
| */ | |||||
| public void compose( final ComponentManager componentManager ) | |||||
| throws ComponentManagerException | |||||
| { | { | ||||
| return new DefaultFactory(); | |||||
| m_factory = (Factory)componentManager.lookup( "org.apache.avalon.camelot.Factory" ); | |||||
| } | } | ||||
| public Object convert( Class destination, final Object original ) | |||||
| /** | |||||
| * Convert object to destination type. | |||||
| * | |||||
| * @param destination the destination type | |||||
| * @param original the original object | |||||
| * @param context the context in which to convert | |||||
| * @return the converted object | |||||
| * @exception Exception if an error occurs | |||||
| */ | |||||
| public Object convert( Class destination, final Object original, final Context context ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| final Class originalClass = original.getClass(); | final Class originalClass = original.getClass(); | ||||
| @@ -79,6 +91,7 @@ public class DefaultConverterEngine | |||||
| " to " + destination.getName() ); | " to " + destination.getName() ); | ||||
| } | } | ||||
| //TODO: Start searching inheritance hierarchy for converter | |||||
| final String name = | final String name = | ||||
| m_infoRegistry.getConverterInfoName( originalClass.getName(), | m_infoRegistry.getConverterInfoName( originalClass.getName(), | ||||
| destination.getName() ); | destination.getName() ); | ||||
| @@ -90,8 +103,9 @@ public class DefaultConverterEngine | |||||
| destination.getName() + " conversion" ); | destination.getName() + " conversion" ); | ||||
| } | } | ||||
| //TODO: Start caching converters instead of repeatedly instantiating em. | |||||
| final Locator locator = m_registry.getLocator( name ); | final Locator locator = m_registry.getLocator( name ); | ||||
| final Converter converter = (Converter)m_factory.create( locator, Converter.class ); | final Converter converter = (Converter)m_factory.create( locator, Converter.class ); | ||||
| return converter.convert( destination, original ); | |||||
| return converter.convert( destination, original, context ); | |||||
| } | } | ||||
| } | } | ||||
| @@ -8,7 +8,7 @@ | |||||
| package org.apache.ant.convert; | package org.apache.ant.convert; | ||||
| import java.util.HashMap; | import java.util.HashMap; | ||||
| import org.apache.avalon.camelot.AbstractRegistry; | |||||
| import org.apache.avalon.camelot.DefaultRegistry; | |||||
| import org.apache.avalon.camelot.Info; | import org.apache.avalon.camelot.Info; | ||||
| import org.apache.avalon.camelot.RegistryException; | import org.apache.avalon.camelot.RegistryException; | ||||
| @@ -18,11 +18,16 @@ import org.apache.avalon.camelot.RegistryException; | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | ||||
| */ | */ | ||||
| public class DefaultConverterRegistry | public class DefaultConverterRegistry | ||||
| extends AbstractRegistry | |||||
| extends DefaultRegistry | |||||
| implements ConverterRegistry | implements ConverterRegistry | ||||
| { | { | ||||
| protected final HashMap m_mapping = new HashMap(); | protected final HashMap m_mapping = new HashMap(); | ||||
| public DefaultConverterRegistry() | |||||
| { | |||||
| super( ConverterInfo.class ); | |||||
| } | |||||
| /** | /** | ||||
| * Retrieve ConverterInfo that describes converter that converts from source to destination. | * Retrieve ConverterInfo that describes converter that converts from source to destination. | ||||
| * | * | ||||
| @@ -37,6 +42,13 @@ public class DefaultConverterRegistry | |||||
| return (String)map.get( destination ); | return (String)map.get( destination ); | ||||
| } | } | ||||
| /** | |||||
| * Overidden method so can add info into mapping. | |||||
| * | |||||
| * @param name the name of info | |||||
| * @param info the Info | |||||
| * @exception RegistryException if an error occurs | |||||
| */ | |||||
| protected void checkInfo( final String name, final Info info ) | protected void checkInfo( final String name, final Info info ) | ||||
| throws RegistryException | throws RegistryException | ||||
| { | { | ||||
| @@ -55,9 +67,4 @@ public class DefaultConverterRegistry | |||||
| map.put( destination, name ); | map.put( destination, name ); | ||||
| } | } | ||||
| protected Class getInfoClass() | |||||
| { | |||||
| return ConverterInfo.class; | |||||
| } | |||||
| } | } | ||||
| @@ -8,6 +8,7 @@ | |||||
| package org.apache.ant.convert.core; | package org.apache.ant.convert.core; | ||||
| import org.apache.ant.convert.AbstractConverter; | import org.apache.ant.convert.AbstractConverter; | ||||
| import org.apache.avalon.Context; | |||||
| /** | /** | ||||
| * String to byte converter | * String to byte converter | ||||
| @@ -22,7 +23,7 @@ public class StringToByteConverter | |||||
| super( String.class, Byte.class ); | super( String.class, Byte.class ); | ||||
| } | } | ||||
| public Object convert( final Object original ) | |||||
| public Object convert( final Object original, final Context context ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| return new Byte( (String)original ); | return new Byte( (String)original ); | ||||
| @@ -8,6 +8,7 @@ | |||||
| package org.apache.ant.convert.core; | package org.apache.ant.convert.core; | ||||
| import org.apache.ant.convert.AbstractConverter; | import org.apache.ant.convert.AbstractConverter; | ||||
| import org.apache.avalon.Context; | |||||
| /** | /** | ||||
| * String to class converter | * String to class converter | ||||
| @@ -22,7 +23,7 @@ public class StringToClassConverter | |||||
| super( String.class, Class.class ); | super( String.class, Class.class ); | ||||
| } | } | ||||
| public Object convert( final Object original ) | |||||
| public Object convert( final Object original, final Context context ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| return Class.forName( (String)original ); | return Class.forName( (String)original ); | ||||
| @@ -8,6 +8,7 @@ | |||||
| package org.apache.ant.convert.core; | package org.apache.ant.convert.core; | ||||
| import org.apache.ant.convert.AbstractConverter; | import org.apache.ant.convert.AbstractConverter; | ||||
| import org.apache.avalon.Context; | |||||
| /** | /** | ||||
| * String to double converter | * String to double converter | ||||
| @@ -22,7 +23,7 @@ public class StringToDoubleConverter | |||||
| super( String.class, Double.class ); | super( String.class, Double.class ); | ||||
| } | } | ||||
| public Object convert( final Object original ) | |||||
| public Object convert( final Object original, final Context context ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| return new Double( (String)original ); | return new Double( (String)original ); | ||||
| @@ -0,0 +1,35 @@ | |||||
| /* | |||||
| * 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 file. | |||||
| */ | |||||
| package org.apache.ant.convert.core; | |||||
| import java.io.File; | |||||
| import org.apache.ant.convert.AbstractConverter; | |||||
| import org.apache.ant.tasklet.TaskletContext; | |||||
| import org.apache.avalon.Context; | |||||
| /** | |||||
| * String to file converter | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public class StringToFileConverter | |||||
| extends AbstractConverter | |||||
| { | |||||
| public StringToFileConverter() | |||||
| { | |||||
| super( String.class, File.class ); | |||||
| } | |||||
| public Object convert( final Object original, final Context context ) | |||||
| throws Exception | |||||
| { | |||||
| final TaskletContext taskletContext = (TaskletContext)context; | |||||
| return taskletContext.resolveFile( (String)original ); | |||||
| } | |||||
| } | |||||
| @@ -8,6 +8,7 @@ | |||||
| package org.apache.ant.convert.core; | package org.apache.ant.convert.core; | ||||
| import org.apache.ant.convert.AbstractConverter; | import org.apache.ant.convert.AbstractConverter; | ||||
| import org.apache.avalon.Context; | |||||
| /** | /** | ||||
| * String to float converter | * String to float converter | ||||
| @@ -22,7 +23,7 @@ public class StringToFloatConverter | |||||
| super( String.class, Float.class ); | super( String.class, Float.class ); | ||||
| } | } | ||||
| public Object convert( final Object original ) | |||||
| public Object convert( final Object original, final Context context ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| return new Float( (String)original ); | return new Float( (String)original ); | ||||
| @@ -8,6 +8,7 @@ | |||||
| package org.apache.ant.convert.core; | package org.apache.ant.convert.core; | ||||
| import org.apache.ant.convert.AbstractConverter; | import org.apache.ant.convert.AbstractConverter; | ||||
| import org.apache.avalon.Context; | |||||
| /** | /** | ||||
| * String to integer converter. | * String to integer converter. | ||||
| @@ -22,7 +23,7 @@ public class StringToIntegerConverter | |||||
| super( String.class, Integer.class ); | super( String.class, Integer.class ); | ||||
| } | } | ||||
| public Object convert( final Object original ) | |||||
| public Object convert( final Object original, final Context context ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| return new Integer( (String)original ); | return new Integer( (String)original ); | ||||
| @@ -8,6 +8,7 @@ | |||||
| package org.apache.ant.convert.core; | package org.apache.ant.convert.core; | ||||
| import org.apache.ant.convert.AbstractConverter; | import org.apache.ant.convert.AbstractConverter; | ||||
| import org.apache.avalon.Context; | |||||
| /** | /** | ||||
| * String to long converter | * String to long converter | ||||
| @@ -22,7 +23,7 @@ public class StringToLongConverter | |||||
| super( String.class, Long.class ); | super( String.class, Long.class ); | ||||
| } | } | ||||
| public Object convert( final Object original ) | |||||
| public Object convert( final Object original, final Context context ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| return new Long( (String)original ); | return new Long( (String)original ); | ||||
| @@ -8,6 +8,7 @@ | |||||
| package org.apache.ant.convert.core; | package org.apache.ant.convert.core; | ||||
| import org.apache.ant.convert.AbstractConverter; | import org.apache.ant.convert.AbstractConverter; | ||||
| import org.apache.avalon.Context; | |||||
| /** | /** | ||||
| * String to short converter | * String to short converter | ||||
| @@ -22,7 +23,7 @@ public class StringToShortConverter | |||||
| super( String.class, Short.class ); | super( String.class, Short.class ); | ||||
| } | } | ||||
| public Object convert( final Object original ) | |||||
| public Object convert( final Object original, final Context context ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| return new Short( (String)original ); | return new Short( (String)original ); | ||||
| @@ -9,6 +9,7 @@ package org.apache.ant.convert.core; | |||||
| import java.net.URL; | import java.net.URL; | ||||
| import org.apache.ant.convert.AbstractConverter; | import org.apache.ant.convert.AbstractConverter; | ||||
| import org.apache.avalon.Context; | |||||
| /** | /** | ||||
| * String to url converter | * String to url converter | ||||
| @@ -23,7 +24,7 @@ public class StringToURLConverter | |||||
| super( String.class, URL.class ); | super( String.class, URL.class ); | ||||
| } | } | ||||
| public Object convert( final Object original ) | |||||
| public Object convert( final Object original, final Context context ) | |||||
| throws Exception | throws Exception | ||||
| { | { | ||||
| return new URL( (String)original ); | return new URL( (String)original ); | ||||
| @@ -13,11 +13,31 @@ import org.apache.avalon.camelot.FactoryException; | |||||
| import org.apache.avalon.camelot.LocatorRegistry; | import org.apache.avalon.camelot.LocatorRegistry; | ||||
| import org.apache.avalon.camelot.RegistryException; | import org.apache.avalon.camelot.RegistryException; | ||||
| /** | |||||
| * This is basically a engine that can be used to access data-types. | |||||
| * The engine acts as a repository and factory for these types. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public interface DataTypeEngine | public interface DataTypeEngine | ||||
| extends Component, Loggable | |||||
| extends Component | |||||
| { | { | ||||
| /** | |||||
| * Retrieve registry of data-types. | |||||
| * This is used by deployer to add types into engine. | |||||
| * | |||||
| * @return the registry | |||||
| */ | |||||
| LocatorRegistry getRegistry(); | LocatorRegistry getRegistry(); | ||||
| /** | |||||
| * Create a data-type of type registered under name. | |||||
| * | |||||
| * @param name the name of data type | |||||
| * @return the DataType | |||||
| * @exception RegistryException if an error occurs | |||||
| * @exception FactoryException if an error occurs | |||||
| */ | |||||
| DataType createDataType( String name ) | DataType createDataType( String name ) | ||||
| throws RegistryException, FactoryException; | throws RegistryException, FactoryException; | ||||
| } | } | ||||
| @@ -7,65 +7,62 @@ | |||||
| */ | */ | ||||
| package org.apache.ant.datatypes; | package org.apache.ant.datatypes; | ||||
| import org.apache.ant.AntException; | |||||
| import org.apache.avalon.Initializable; | |||||
| import org.apache.avalon.Loggable; | |||||
| import org.apache.avalon.camelot.DefaultFactory; | |||||
| import org.apache.avalon.Composer; | |||||
| import org.apache.avalon.ComponentManager; | |||||
| import org.apache.avalon.ComponentManagerException; | |||||
| import org.apache.avalon.Composer; | |||||
| import org.apache.avalon.camelot.DefaultLocatorRegistry; | import org.apache.avalon.camelot.DefaultLocatorRegistry; | ||||
| import org.apache.avalon.camelot.Factory; | |||||
| import org.apache.avalon.camelot.FactoryException; | |||||
| import org.apache.avalon.camelot.Locator; | import org.apache.avalon.camelot.Locator; | ||||
| import org.apache.avalon.camelot.LocatorRegistry; | import org.apache.avalon.camelot.LocatorRegistry; | ||||
| import org.apache.avalon.camelot.RegistryException; | import org.apache.avalon.camelot.RegistryException; | ||||
| import org.apache.avalon.camelot.FactoryException; | |||||
| import org.apache.log.Logger; | |||||
| /** | |||||
| * This is basically a engine that can be used to access data-types. | |||||
| * The engine acts as a repository and factory for these types. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public class DefaultDataTypeEngine | public class DefaultDataTypeEngine | ||||
| implements DataTypeEngine, Initializable | |||||
| implements DataTypeEngine, Composer | |||||
| { | { | ||||
| protected DefaultFactory m_factory; | |||||
| protected LocatorRegistry m_registry; | |||||
| protected Logger m_logger; | |||||
| public void setLogger( final Logger logger ) | |||||
| { | |||||
| m_logger = logger; | |||||
| } | |||||
| protected Factory m_factory; | |||||
| protected LocatorRegistry m_registry = new DefaultLocatorRegistry(); | |||||
| /** | |||||
| * Retrieve registry of data-types. | |||||
| * This is used by deployer to add types into engine. | |||||
| * | |||||
| * @return the registry | |||||
| */ | |||||
| public LocatorRegistry getRegistry() | public LocatorRegistry getRegistry() | ||||
| { | { | ||||
| return m_registry; | return m_registry; | ||||
| } | } | ||||
| public void init() | |||||
| throws Exception | |||||
| { | |||||
| m_registry = createRegistry(); | |||||
| setupComponent( m_registry ); | |||||
| m_factory = createFactory(); | |||||
| setupComponent( m_factory ); | |||||
| } | |||||
| protected void setupComponent( final Object object ) | |||||
| throws Exception | |||||
| { | |||||
| if( object instanceof Loggable ) | |||||
| { | |||||
| ((Loggable)object).setLogger( m_logger ); | |||||
| } | |||||
| } | |||||
| protected LocatorRegistry createRegistry() | |||||
| { | |||||
| return new DefaultLocatorRegistry(); | |||||
| } | |||||
| protected DefaultFactory createFactory() | |||||
| /** | |||||
| * Retrieve relevent services needed to deploy. | |||||
| * | |||||
| * @param componentManager the ComponentManager | |||||
| * @exception ComponentManagerException if an error occurs | |||||
| */ | |||||
| public void compose( final ComponentManager componentManager ) | |||||
| throws ComponentManagerException | |||||
| { | { | ||||
| return new DefaultFactory(); | |||||
| m_factory = (Factory)componentManager.lookup( "org.apache.avalon.camelot.Factory" ); | |||||
| } | } | ||||
| /** | |||||
| * Create a data-type of type registered under name. | |||||
| * | |||||
| * @param name the name of data type | |||||
| * @return the DataType | |||||
| * @exception RegistryException if an error occurs | |||||
| * @exception FactoryException if an error occurs | |||||
| */ | |||||
| public DataType createDataType( final String name ) | public DataType createDataType( final String name ) | ||||
| throws RegistryException, FactoryException | |||||
| throws RegistryException, FactoryException | |||||
| { | { | ||||
| final Locator locator = m_registry.getLocator( name ); | final Locator locator = m_registry.getLocator( name ); | ||||
| return (DataType)m_factory.create( locator, DataType.class ); | return (DataType)m_factory.create( locator, DataType.class ); | ||||
| @@ -8,6 +8,7 @@ | |||||
| package org.apache.ant.datatypes; | package org.apache.ant.datatypes; | ||||
| import org.apache.ant.AntException; | import org.apache.ant.AntException; | ||||
| import org.apache.ant.util.Condition; | |||||
| /** | /** | ||||
| * Basic data type for holding patterns. | * Basic data type for holding patterns. | ||||
| @@ -20,21 +21,43 @@ public class Pattern | |||||
| protected String m_name; | protected String m_name; | ||||
| protected Condition m_condition; | protected Condition m_condition; | ||||
| /** | |||||
| * Retrieve name (aka value) of pattern. | |||||
| * | |||||
| * @return the name/value of pattern | |||||
| */ | |||||
| public String getName() | public String getName() | ||||
| { | { | ||||
| return m_name; | return m_name; | ||||
| } | } | ||||
| /** | |||||
| * Get condition associated with pattern if any. | |||||
| * | |||||
| * @return the Condition | |||||
| */ | |||||
| public Condition getCondition() | public Condition getCondition() | ||||
| { | { | ||||
| return m_condition; | return m_condition; | ||||
| } | } | ||||
| /** | |||||
| * Setter method for name/value of pattern. | |||||
| * Conforms to ant setter patterns | |||||
| * | |||||
| * @param name the value | |||||
| */ | |||||
| public void setName( final String name ) | public void setName( final String name ) | ||||
| { | { | ||||
| m_name = name; | m_name = name; | ||||
| } | } | ||||
| /** | |||||
| * Set if clause on pattern. | |||||
| * | |||||
| * @param condition the condition | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| public void setIf( final String condition ) | public void setIf( final String condition ) | ||||
| throws AntException | throws AntException | ||||
| { | { | ||||
| @@ -42,6 +65,12 @@ public class Pattern | |||||
| m_condition = new Condition( true, condition ); | m_condition = new Condition( true, condition ); | ||||
| } | } | ||||
| /** | |||||
| * Set unless clause of pattern. | |||||
| * | |||||
| * @param condition the unless clause | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| public void setUnless( final String condition ) | public void setUnless( final String condition ) | ||||
| throws AntException | throws AntException | ||||
| { | { | ||||
| @@ -49,6 +78,12 @@ public class Pattern | |||||
| m_condition = new Condition( false, condition ); | m_condition = new Condition( false, condition ); | ||||
| } | } | ||||
| /** | |||||
| * Utility method to make sure condition unset. | |||||
| * Made so that it is not possible for both if and unless to be set. | |||||
| * | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| protected void verifyConditionNull() | protected void verifyConditionNull() | ||||
| throws AntException | throws AntException | ||||
| { | { | ||||
| @@ -0,0 +1,56 @@ | |||||
| /* | |||||
| * 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 file. | |||||
| */ | |||||
| package org.apache.ant.launcher; | |||||
| import java.io.File; | |||||
| import java.lang.reflect.Method; | |||||
| import java.net.URL; | |||||
| import java.net.URLClassLoader; | |||||
| import java.util.StringTokenizer; | |||||
| /** | |||||
| * Basic classloader that allows modification at runtime. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public final class AntClassLoader | |||||
| extends URLClassLoader | |||||
| { | |||||
| /** | |||||
| * Basic constructor. | |||||
| * | |||||
| * @param urls the Starting URLS | |||||
| */ | |||||
| public AntClassLoader( final URL[] urls ) | |||||
| { | |||||
| super( urls ); | |||||
| } | |||||
| /** | |||||
| * Add a URL to classloader | |||||
| * | |||||
| * @param url the url | |||||
| */ | |||||
| public void addURL( final URL url ) | |||||
| { | |||||
| super.addURL( url ); | |||||
| } | |||||
| /** | |||||
| * Add an array of URLs to classloader | |||||
| * | |||||
| * @param url the url | |||||
| */ | |||||
| public void addURLs( final URL[] urls ) | |||||
| { | |||||
| for( int i = 0; i < urls.length; i++ ) | |||||
| { | |||||
| addURL( urls[ i ] ); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -7,31 +7,22 @@ | |||||
| */ | */ | ||||
| package org.apache.ant.launcher; | package org.apache.ant.launcher; | ||||
| import java.io.File; | |||||
| import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||
| import java.lang.reflect.InvocationTargetException; | |||||
| import java.net.URL; | import java.net.URL; | ||||
| import java.net.URLClassLoader; | import java.net.URLClassLoader; | ||||
| import java.util.StringTokenizer; | |||||
| /** | /** | ||||
| * 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. | ||||
| * Other classes can call AntLoader.getLoader() and add to their own classloader. | * Other classes can call AntLoader.getLoader() and add to their own classloader. | ||||
| * | * | ||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | ||||
| * @author <a href="mailto:mpfoemme@thoughtworks.com">Matthew Foemmel</a> | |||||
| */ | */ | ||||
| public final class AntLoader | public final class AntLoader | ||||
| extends URLClassLoader | |||||
| { | { | ||||
| protected static AntLoader c_classLoader; | |||||
| public static AntLoader getLoader() | |||||
| { | |||||
| if( null == c_classLoader ) | |||||
| { | |||||
| c_classLoader = new AntLoader( new URL[ 0 ] ); | |||||
| } | |||||
| return c_classLoader; | |||||
| } | |||||
| /** | /** | ||||
| * Magic entry point. | * Magic entry point. | ||||
| * | * | ||||
| @@ -40,42 +31,67 @@ public final class AntLoader | |||||
| */ | */ | ||||
| public final static void main( final String[] args ) | public final static void main( final String[] args ) | ||||
| throws Exception | throws Exception | ||||
| { | |||||
| final URL archive = new URL( "file:lib/myrmidon.jar" ); | |||||
| c_classLoader = new AntLoader( new URL[] { archive } ); | |||||
| { | |||||
| try | try | ||||
| { | { | ||||
| //actually try to discover the install directory based on where | |||||
| // the ant.jar is | |||||
| final File installDirectory = findInstallDir(); | |||||
| System.setProperty( "ant.home", installDirectory.toString() ); | |||||
| //setup classloader appropriately for myrmidon jar | |||||
| final File archive = | |||||
| new File( installDirectory, "lib" + File.separator + "myrmidon.jar" ); | |||||
| final AntClassLoader classLoader = | |||||
| new AntClassLoader( new URL[] { archive.toURL() } ); | |||||
| //load class and retrieve appropriate main method. | //load class and retrieve appropriate main method. | ||||
| final Class clazz = c_classLoader.loadClass( "org.apache.ant.Main" ); | |||||
| final Class clazz = classLoader.loadClass( "org.apache.ant.Main" ); | |||||
| final Method method = clazz.getMethod( "main", new Class[] { args.getClass() } ); | final Method method = clazz.getMethod( "main", new 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[] { args } ); | ||||
| } | } | ||||
| catch( final InvocationTargetException ite ) | |||||
| { | |||||
| System.err.println( "Error: " + ite.getTargetException().getMessage() ); | |||||
| ite.getTargetException().printStackTrace(); | |||||
| } | |||||
| catch( final Throwable throwable ) | catch( final Throwable throwable ) | ||||
| { | { | ||||
| System.err.println( "Error: " + throwable.getMessage() ); | |||||
| throwable.printStackTrace(); | throwable.printStackTrace(); | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Basic constructor. | |||||
| * | |||||
| * @param urls the Starting URLS | |||||
| * Finds the ant.jar file in the classpath. | |||||
| */ | */ | ||||
| public AntLoader( final URL[] urls ) | |||||
| protected final static File findInstallDir() | |||||
| throws Exception | |||||
| { | { | ||||
| super( urls ); | |||||
| } | |||||
| final String classpath = System.getProperty( "java.class.path" ); | |||||
| final String pathSeparator = System.getProperty( "path.separator" ); | |||||
| final StringTokenizer tokenizer = new StringTokenizer( classpath, pathSeparator ); | |||||
| while( tokenizer.hasMoreTokens() ) | |||||
| { | |||||
| final String element = tokenizer.nextToken(); | |||||
| /** | |||||
| * Add a URL to classloader | |||||
| * | |||||
| * @param url the url | |||||
| */ | |||||
| public void addURL( final URL url ) | |||||
| { | |||||
| super.addURL( url ); | |||||
| if( element.endsWith( "ant.jar" ) ) | |||||
| { | |||||
| 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" ); | |||||
| } | } | ||||
| } | } | ||||
| @@ -16,6 +16,11 @@ import org.apache.ant.AntException; | |||||
| import org.apache.ant.tasklet.DefaultTaskletContext; | import org.apache.ant.tasklet.DefaultTaskletContext; | ||||
| import org.apache.ant.tasklet.TaskletContext; | import org.apache.ant.tasklet.TaskletContext; | ||||
| /** | |||||
| * Default project implementation. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public class DefaultProject | public class DefaultProject | ||||
| implements Project | implements Project | ||||
| { | { | ||||
| @@ -23,42 +28,87 @@ public class DefaultProject | |||||
| protected final HashMap m_targets = new HashMap(); | protected final HashMap m_targets = new HashMap(); | ||||
| protected Target m_implicitTarget; | protected Target m_implicitTarget; | ||||
| protected String m_defaultTarget; | protected String m_defaultTarget; | ||||
| /** | |||||
| * Retrieve implicit target. | |||||
| * The implicit target is top level tasks. | |||||
| * Currently restricted to property tasks. | |||||
| * | |||||
| * @return the Target | |||||
| */ | |||||
| public Target getImplicitTarget() | public Target getImplicitTarget() | ||||
| { | { | ||||
| return m_implicitTarget; | return m_implicitTarget; | ||||
| } | } | ||||
| /** | |||||
| * Set ImplicitTarget. | |||||
| * | |||||
| * @param target the implicit target | |||||
| */ | |||||
| public void setImplicitTarget( final Target target ) | public void setImplicitTarget( final Target target ) | ||||
| { | { | ||||
| m_implicitTarget = target; | m_implicitTarget = target; | ||||
| } | } | ||||
| /** | |||||
| * Retrieve a target by name. | |||||
| * | |||||
| * @param name the name of target | |||||
| * @return the Target or null if no target exists with name | |||||
| */ | |||||
| public Target getTarget( final String targetName ) | public Target getTarget( final String targetName ) | ||||
| { | { | ||||
| return (Target)m_targets.get( targetName ); | return (Target)m_targets.get( targetName ); | ||||
| } | } | ||||
| /** | |||||
| * Get name of default target. | |||||
| * | |||||
| * @return the default target name | |||||
| */ | |||||
| public String getDefaultTargetName() | public String getDefaultTargetName() | ||||
| { | { | ||||
| return m_defaultTarget; | return m_defaultTarget; | ||||
| } | } | ||||
| /** | |||||
| * Retrieve names of all targets in project. | |||||
| * | |||||
| * @return the iterator of project names | |||||
| */ | |||||
| public Iterator getTargetNames() | public Iterator getTargetNames() | ||||
| { | { | ||||
| return m_targets.keySet().iterator(); | return m_targets.keySet().iterator(); | ||||
| } | } | ||||
| /** | |||||
| * Get project (top-level) context. | |||||
| * | |||||
| * @return the context | |||||
| */ | |||||
| public TaskletContext getContext() | public TaskletContext getContext() | ||||
| { | { | ||||
| return m_baseContext; | return m_baseContext; | ||||
| } | } | ||||
| /** | |||||
| * Set DefaultTargetName. | |||||
| * | |||||
| * @param defaultTarget the default target name | |||||
| */ | |||||
| public void setDefaultTargetName( final String defaultTarget ) | public void setDefaultTargetName( final String defaultTarget ) | ||||
| { | { | ||||
| m_defaultTarget = defaultTarget; | m_defaultTarget = defaultTarget; | ||||
| } | } | ||||
| /** | |||||
| * Add a target to project. | |||||
| * | |||||
| * @param name the name of target | |||||
| * @param target the Target | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| public void addTarget( final String name, final Target target ) | public void addTarget( final String name, final Target target ) | ||||
| throws AntException | throws AntException | ||||
| { | { | ||||
| @@ -13,54 +13,87 @@ import java.util.Iterator; | |||||
| import org.apache.ant.AntException; | import org.apache.ant.AntException; | ||||
| import org.apache.ant.configuration.Configuration; | import org.apache.ant.configuration.Configuration; | ||||
| import org.apache.ant.configuration.ConfigurationBuilder; | import org.apache.ant.configuration.ConfigurationBuilder; | ||||
| import org.apache.ant.datatypes.Condition; | |||||
| import org.apache.ant.util.Condition; | |||||
| import org.apache.ant.tasklet.TaskletContext; | import org.apache.ant.tasklet.TaskletContext; | ||||
| import org.apache.avalon.AbstractLoggable; | |||||
| import org.apache.avalon.ConfigurationException; | import org.apache.avalon.ConfigurationException; | ||||
| import org.apache.avalon.util.StringUtil; | |||||
| import org.apache.log.Logger; | import org.apache.log.Logger; | ||||
| import org.xml.sax.InputSource; | import org.xml.sax.InputSource; | ||||
| import org.xml.sax.SAXException; | import org.xml.sax.SAXException; | ||||
| /** | |||||
| * Default implementation to construct project from a build file. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public class DefaultProjectBuilder | public class DefaultProjectBuilder | ||||
| extends AbstractLoggable | |||||
| implements ProjectBuilder | implements ProjectBuilder | ||||
| { | { | ||||
| protected final ConfigurationBuilder m_configurationBuilder; | |||||
| protected Logger m_logger; | |||||
| protected ConfigurationBuilder m_builder; | |||||
| public DefaultProjectBuilder() | public DefaultProjectBuilder() | ||||
| { | { | ||||
| ConfigurationBuilder builder = null; | |||||
| try { builder = new ConfigurationBuilder(); } | |||||
| catch( final SAXException se ) {} | |||||
| m_configurationBuilder = builder; | |||||
| } | |||||
| public void setLogger( final Logger logger ) | |||||
| { | |||||
| m_logger = logger; | |||||
| m_builder = new ConfigurationBuilder(); | |||||
| } | } | ||||
| /** | |||||
| * build a project from file. | |||||
| * | |||||
| * @param source the source | |||||
| * @return the constructed Project | |||||
| * @exception IOException if an error occurs | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| public Project build( final File projectFile ) | public Project build( final File projectFile ) | ||||
| throws IOException, AntException | throws IOException, AntException | ||||
| { | { | ||||
| try | try | ||||
| { | { | ||||
| final String location = projectFile.getCanonicalFile().toURL().toString(); | |||||
| final InputSource inputSource = new InputSource( location ); | |||||
| final Configuration configuration = | |||||
| (Configuration)m_configurationBuilder.build( inputSource ); | |||||
| final String location = projectFile.getCanonicalFile().toString(); | |||||
| final Configuration configuration = buildConfiguration( location ); | |||||
| return build( projectFile, configuration ); | return build( projectFile, configuration ); | ||||
| } | } | ||||
| catch( final SAXException se ) | |||||
| { | |||||
| throw new AntException( "SAXEception: " + se.getMessage(), se ); | |||||
| } | |||||
| catch( final ConfigurationException ce ) | catch( final ConfigurationException ce ) | ||||
| { | { | ||||
| throw new AntException( "ConfigurationException: " + ce.getMessage(), ce ); | throw new AntException( "ConfigurationException: " + ce.getMessage(), ce ); | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Utility method to build a Configuration tree from a source. | |||||
| * Overide this in sub-classes if you want to provide extra | |||||
| * functionality (ie xslt/css). | |||||
| * | |||||
| * @param location the location | |||||
| * @return the created Configuration | |||||
| * @exception AntException if an error occurs | |||||
| * @exception IOException if an error occurs | |||||
| */ | |||||
| protected Configuration buildConfiguration( final String location ) | |||||
| throws AntException, IOException, ConfigurationException | |||||
| { | |||||
| try | |||||
| { | |||||
| return (Configuration)m_builder.build( location ); | |||||
| } | |||||
| catch( final SAXException se ) | |||||
| { | |||||
| throw new AntException( "SAXEception: " + se.getMessage(), se ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * build project from configuration. | |||||
| * | |||||
| * @param file the file from which configuration was loaded | |||||
| * @param configuration the configuration loaded | |||||
| * @return the created Project | |||||
| * @exception IOException if an error occurs | |||||
| * @exception AntException if an error occurs | |||||
| * @exception ConfigurationException if an error occurs | |||||
| */ | |||||
| protected Project build( final File file, final Configuration configuration ) | protected Project build( final File file, final Configuration configuration ) | ||||
| throws IOException, AntException, ConfigurationException | throws IOException, AntException, ConfigurationException | ||||
| { | { | ||||
| @@ -68,29 +101,41 @@ public class DefaultProjectBuilder | |||||
| { | { | ||||
| throw new AntException( "Project file must be enclosed in project element" ); | throw new AntException( "Project file must be enclosed in project element" ); | ||||
| } | } | ||||
| //get project-level attributes | |||||
| final String baseDirectoryName = configuration.getAttribute( "basedir" ); | final String baseDirectoryName = configuration.getAttribute( "basedir" ); | ||||
| final String defaultTarget = configuration.getAttribute( "default" ); | final String defaultTarget = configuration.getAttribute( "default" ); | ||||
| final String projectName = configuration.getAttribute( "name" ); | final String projectName = configuration.getAttribute( "name" ); | ||||
| final DefaultProject project = new DefaultProject(); | |||||
| project.setDefaultTargetName( defaultTarget ); | |||||
| //determine base directory for project | |||||
| final File baseDirectory = | final File baseDirectory = | ||||
| (new File( file.getParentFile(), baseDirectoryName )).getAbsoluteFile(); | (new File( file.getParentFile(), baseDirectoryName )).getAbsoluteFile(); | ||||
| m_logger.debug( "Project " + projectName + " base directory: " + baseDirectory ); | |||||
| getLogger().debug( "Project " + projectName + " base directory: " + baseDirectory ); | |||||
| //create project and ... | |||||
| final DefaultProject project = new DefaultProject(); | |||||
| project.setDefaultTargetName( defaultTarget ); | |||||
| //setup basic context of project | |||||
| final TaskletContext context = project.getContext(); | final TaskletContext context = project.getContext(); | ||||
| context.setProperty( TaskletContext.BASE_DIRECTORY, baseDirectory ); | context.setProperty( TaskletContext.BASE_DIRECTORY, baseDirectory ); | ||||
| context.setProperty( Project.PROJECT_FILE, file ); | context.setProperty( Project.PROJECT_FILE, file ); | ||||
| context.setProperty( Project.PROJECT, projectName ); | context.setProperty( Project.PROJECT, projectName ); | ||||
| //build using all top-level attributes | |||||
| buildTopLevelProject( project, configuration ); | buildTopLevelProject( project, configuration ); | ||||
| return project; | return project; | ||||
| } | } | ||||
| /** | |||||
| * Handle all top level elements in configuration. | |||||
| * | |||||
| * @param project the project | |||||
| * @param configuration the Configuration | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| protected void buildTopLevelProject( final DefaultProject project, | protected void buildTopLevelProject( final DefaultProject project, | ||||
| final Configuration configuration ) | final Configuration configuration ) | ||||
| throws AntException | throws AntException | ||||
| @@ -102,8 +147,9 @@ public class DefaultProjectBuilder | |||||
| final Configuration element = (Configuration)elements.next(); | final Configuration element = (Configuration)elements.next(); | ||||
| final String name = element.getName(); | final String name = element.getName(); | ||||
| //handle individual elements | |||||
| if( name.equals( "target" ) ) buildTarget( project, element ); | if( name.equals( "target" ) ) buildTarget( project, element ); | ||||
| else if( name.equals( "property" ) ) buildProperty( project, element ); | |||||
| else if( name.equals( "property" ) ) buildImplicitTask( project, element ); | |||||
| else | else | ||||
| { | { | ||||
| throw new AntException( "Unknown top-level element " + name + | throw new AntException( "Unknown top-level element " + name + | ||||
| @@ -112,95 +158,88 @@ public class DefaultProjectBuilder | |||||
| } | } | ||||
| } | } | ||||
| protected void buildTarget( final DefaultProject project, | |||||
| final Configuration configuration ) | |||||
| /** | |||||
| * Build a target from configuration. | |||||
| * | |||||
| * @param project the project | |||||
| * @param task the Configuration | |||||
| */ | |||||
| protected void buildTarget( final DefaultProject project, final Configuration target ) | |||||
| { | { | ||||
| final String name = configuration.getAttribute( "name", null ); | |||||
| final String depends = configuration.getAttribute( "depends", null ); | |||||
| final String ifCondition = configuration.getAttribute( "if", null ); | |||||
| final String unlessCondition = configuration.getAttribute( "unless", null ); | |||||
| final String name = target.getAttribute( "name", null ); | |||||
| final String depends = target.getAttribute( "depends", null ); | |||||
| final String ifCondition = target.getAttribute( "if", null ); | |||||
| final String unlessCondition = target.getAttribute( "unless", null ); | |||||
| if( null == name ) | if( null == name ) | ||||
| { | { | ||||
| throw new AntException( "Discovered un-named target at " + | throw new AntException( "Discovered un-named target at " + | ||||
| configuration.getLocation() ); | |||||
| target.getLocation() ); | |||||
| } | } | ||||
| m_logger.debug( "Parsing target: " + name ); | |||||
| getLogger().debug( "Parsing target: " + name ); | |||||
| if( null != ifCondition && null != unlessCondition ) | if( null != ifCondition && null != unlessCondition ) | ||||
| { | { | ||||
| throw new AntException( "Discovered invalid target that has both a if and " + | throw new AntException( "Discovered invalid target that has both a if and " + | ||||
| "unless condition at " + configuration.getLocation() ); | |||||
| "unless condition at " + target.getLocation() ); | |||||
| } | } | ||||
| Condition condition = null; | Condition condition = null; | ||||
| if( null != ifCondition ) | if( null != ifCondition ) | ||||
| { | { | ||||
| m_logger.debug( "Target if condition: " + ifCondition ); | |||||
| getLogger().debug( "Target if condition: " + ifCondition ); | |||||
| condition = new Condition( true, ifCondition ); | condition = new Condition( true, ifCondition ); | ||||
| } | } | ||||
| else if( null != unlessCondition ) | else if( null != unlessCondition ) | ||||
| { | { | ||||
| m_logger.debug( "Target unless condition: " + unlessCondition ); | |||||
| getLogger().debug( "Target unless condition: " + unlessCondition ); | |||||
| condition = new Condition( false, unlessCondition ); | condition = new Condition( false, unlessCondition ); | ||||
| } | } | ||||
| final DefaultTarget target = new DefaultTarget( condition ); | |||||
| final DefaultTarget defaultTarget = new DefaultTarget( condition ); | |||||
| //apply depends attribute | |||||
| if( null != depends ) | if( null != depends ) | ||||
| { | { | ||||
| int start = 0; | |||||
| int end = depends.indexOf( ',' ); | |||||
| final String[] elements = StringUtil.splitString( depends, "," ); | |||||
| while( -1 != end ) | |||||
| for( int i = 0; i < elements.length; i++ ) | |||||
| { | { | ||||
| final String dependency = | |||||
| parseDependency( configuration, depends.substring( start, end ) ); | |||||
| target.addDependency( dependency ); | |||||
| start = end++; | |||||
| end = depends.indexOf( ',', start ); | |||||
| } | |||||
| final String dependency = elements[ i ].trim(); | |||||
| final String dependency = | |||||
| parseDependency( configuration, depends.substring( start ) ); | |||||
| if( 0 == dependency.length() ) | |||||
| { | |||||
| throw new AntException( "Discovered empty dependency in target " + | |||||
| target.getName() + " at " + target.getLocation() ); | |||||
| } | |||||
| target.addDependency( dependency ); | |||||
| getLogger().debug( "Target dependency: " + dependency ); | |||||
| defaultTarget.addDependency( dependency ); | |||||
| } | |||||
| } | } | ||||
| final Iterator tasks = configuration.getChildren(); | |||||
| //add all the targets from element | |||||
| final Iterator tasks = target.getChildren(); | |||||
| while( tasks.hasNext() ) | while( tasks.hasNext() ) | ||||
| { | { | ||||
| final Configuration task = (Configuration)tasks.next(); | final Configuration task = (Configuration)tasks.next(); | ||||
| m_logger.debug( "Parsed task: " + task.getName() ); | |||||
| target.addTask( task ); | |||||
| } | |||||
| project.addTarget( name, target ); | |||||
| } | |||||
| protected String parseDependency( final Configuration configuration, | |||||
| String dependency ) | |||||
| throws AntException | |||||
| { | |||||
| dependency = dependency.trim(); | |||||
| if( 0 == dependency.length() ) | |||||
| { | |||||
| throw new AntException( "Discovered empty dependency in target " + | |||||
| configuration.getName() + " at " + | |||||
| configuration.getLocation() ); | |||||
| getLogger().debug( "Parsed task: " + task.getName() ); | |||||
| defaultTarget.addTask( task ); | |||||
| } | } | ||||
| m_logger.debug( "Target dependency: " + dependency ); | |||||
| return dependency; | |||||
| //add target to project | |||||
| project.addTarget( name, defaultTarget ); | |||||
| } | } | ||||
| protected void buildProperty( final DefaultProject project, | |||||
| final Configuration configuration ) | |||||
| /** | |||||
| * Create an implict task from configuration | |||||
| * | |||||
| * @param project the project | |||||
| * @param task the configuration | |||||
| */ | |||||
| protected void buildImplicitTask( final DefaultProject project, final Configuration task ) | |||||
| { | { | ||||
| DefaultTarget target = (DefaultTarget)project.getImplicitTarget(); | DefaultTarget target = (DefaultTarget)project.getImplicitTarget(); | ||||
| @@ -210,7 +249,7 @@ public class DefaultProjectBuilder | |||||
| project.setImplicitTarget( target ); | project.setImplicitTarget( target ); | ||||
| } | } | ||||
| m_logger.debug( "Parsed implicit task: " + configuration.getName() ); | |||||
| target.addTask( configuration ); | |||||
| getLogger().debug( "Parsed implicit task: " + task.getName() ); | |||||
| target.addTask( task ); | |||||
| } | } | ||||
| } | } | ||||
| @@ -11,88 +11,80 @@ import java.util.ArrayList; | |||||
| import java.util.Iterator; | import java.util.Iterator; | ||||
| import org.apache.ant.AntException; | import org.apache.ant.AntException; | ||||
| import org.apache.ant.configuration.Configuration; | import org.apache.ant.configuration.Configuration; | ||||
| import org.apache.ant.datatypes.Condition; | |||||
| import org.apache.ant.tasklet.DefaultTaskletContext; | import org.apache.ant.tasklet.DefaultTaskletContext; | ||||
| import org.apache.ant.tasklet.TaskletContext; | import org.apache.ant.tasklet.TaskletContext; | ||||
| import org.apache.ant.tasklet.engine.DefaultTaskletEngine; | import org.apache.ant.tasklet.engine.DefaultTaskletEngine; | ||||
| import org.apache.ant.tasklet.engine.TaskletEngine; | import org.apache.ant.tasklet.engine.TaskletEngine; | ||||
| import org.apache.ant.util.Condition; | |||||
| import org.apache.avalon.AbstractLoggable; | |||||
| import org.apache.avalon.Composer; | import org.apache.avalon.Composer; | ||||
| import org.apache.avalon.ComponentManager; | |||||
| import org.apache.avalon.DefaultComponentManager; | |||||
| import org.apache.avalon.ComponentManagerException; | |||||
| import org.apache.avalon.DefaultComponentManager; | import org.apache.avalon.DefaultComponentManager; | ||||
| import org.apache.avalon.Disposable; | import org.apache.avalon.Disposable; | ||||
| import org.apache.avalon.Initializable; | import org.apache.avalon.Initializable; | ||||
| import org.apache.log.Logger; | import org.apache.log.Logger; | ||||
| /** | |||||
| * This is the default implementation of ProjectEngine. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public class DefaultProjectEngine | public class DefaultProjectEngine | ||||
| implements ProjectEngine, Initializable, Disposable | |||||
| extends AbstractLoggable | |||||
| implements ProjectEngine, Composer | |||||
| { | { | ||||
| protected TaskletEngine m_taskletEngine; | protected TaskletEngine m_taskletEngine; | ||||
| protected Logger m_logger; | |||||
| protected ProjectListenerSupport m_listenerSupport; | |||||
| protected ProjectListenerSupport m_listenerSupport = new ProjectListenerSupport(); | |||||
| protected DefaultComponentManager m_componentManager; | protected DefaultComponentManager m_componentManager; | ||||
| public void setLogger( final Logger logger ) | |||||
| { | |||||
| m_logger = logger; | |||||
| } | |||||
| /** | |||||
| * Add a listener to project events. | |||||
| * | |||||
| * @param listener the listener | |||||
| */ | |||||
| public void addProjectListener( final ProjectListener listener ) | public void addProjectListener( final ProjectListener listener ) | ||||
| { | { | ||||
| m_listenerSupport.addProjectListener( listener ); | m_listenerSupport.addProjectListener( listener ); | ||||
| } | } | ||||
| /** | |||||
| * Remove a listener from project events. | |||||
| * | |||||
| * @param listener the listener | |||||
| */ | |||||
| public void removeProjectListener( final ProjectListener listener ) | public void removeProjectListener( final ProjectListener listener ) | ||||
| { | { | ||||
| m_listenerSupport.removeProjectListener( listener ); | m_listenerSupport.removeProjectListener( listener ); | ||||
| } | } | ||||
| public void init() | |||||
| throws Exception | |||||
| { | |||||
| m_listenerSupport = new ProjectListenerSupport(); | |||||
| setupTaskletEngine(); | |||||
| m_componentManager = new DefaultComponentManager(); | |||||
| m_componentManager.put( "org.apache.ant.project.ProjectEngine", this ); | |||||
| m_componentManager.put( "org.apache.ant.tasklet.engine.TaskletEngine", m_taskletEngine ); | |||||
| m_componentManager.put( "org.apache.ant.convert.ConverterEngine", | |||||
| m_taskletEngine.getConverterEngine() ); | |||||
| } | |||||
| public void dispose() | |||||
| throws Exception | |||||
| { | |||||
| if( m_taskletEngine instanceof Disposable ) | |||||
| { | |||||
| ((Disposable)m_taskletEngine).dispose(); | |||||
| } | |||||
| } | |||||
| public TaskletEngine getTaskletEngine() | |||||
| /** | |||||
| * Retrieve relevent services needed for engine. | |||||
| * | |||||
| * @param componentManager the ComponentManager | |||||
| * @exception ComponentManagerException if an error occurs | |||||
| */ | |||||
| public void compose( final ComponentManager componentManager ) | |||||
| throws ComponentManagerException | |||||
| { | { | ||||
| return m_taskletEngine; | |||||
| m_componentManager = (DefaultComponentManager)componentManager; | |||||
| m_taskletEngine = (TaskletEngine)componentManager. | |||||
| lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | |||||
| } | } | ||||
| protected void setupTaskletEngine() | |||||
| throws Exception | |||||
| { | |||||
| m_taskletEngine = createTaskletEngine(); | |||||
| m_taskletEngine.setLogger( m_logger ); | |||||
| if( m_taskletEngine instanceof Initializable ) | |||||
| { | |||||
| ((Initializable)m_taskletEngine).init(); | |||||
| } | |||||
| } | |||||
| protected TaskletEngine createTaskletEngine() | |||||
| { | |||||
| return new DefaultTaskletEngine(); | |||||
| } | |||||
| /** | |||||
| * Execute a target in a particular project. | |||||
| * Execute in the project context. | |||||
| * | |||||
| * @param project the Project | |||||
| * @param target the name of the target | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| public void execute( final Project project, final String target ) | public void execute( final Project project, final String target ) | ||||
| throws AntException | throws AntException | ||||
| { | { | ||||
| //HACK: should do this a better way !!!!!! | |||||
| m_componentManager.put( "org.apache.ant.project.Project", project ); | m_componentManager.put( "org.apache.ant.project.Project", project ); | ||||
| final TaskletContext context = project.getContext(); | final TaskletContext context = project.getContext(); | ||||
| @@ -110,12 +102,29 @@ public class DefaultProjectEngine | |||||
| m_listenerSupport.projectFinished(); | m_listenerSupport.projectFinished(); | ||||
| } | } | ||||
| /** | |||||
| * Execute a target in a particular project, in a particular context. | |||||
| * | |||||
| * @param project the Project | |||||
| * @param target the name of the target | |||||
| * @param context the context | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| public void execute( Project project, String target, TaskletContext context ) | public void execute( Project project, String target, TaskletContext context ) | ||||
| throws AntException | throws AntException | ||||
| { | { | ||||
| execute( project, target, context, new ArrayList() ); | execute( project, target, context, new ArrayList() ); | ||||
| } | } | ||||
| /** | |||||
| * Helper method to execute a target. | |||||
| * | |||||
| * @param project the Project | |||||
| * @param target the name of the target | |||||
| * @param context the context | |||||
| * @param done the list of targets already executed in current run | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| protected void execute( final Project project, | protected void execute( final Project project, | ||||
| final String targetName, | final String targetName, | ||||
| final TaskletContext context, | final TaskletContext context, | ||||
| @@ -128,9 +137,11 @@ public class DefaultProjectEngine | |||||
| { | { | ||||
| throw new AntException( "Unable to find target " + targetName ); | throw new AntException( "Unable to find target " + targetName ); | ||||
| } | } | ||||
| //add target to list of targets executed | |||||
| done.add( targetName ); | done.add( targetName ); | ||||
| //execute all dependencies | |||||
| final Iterator dependencies = target.getDependencies(); | final Iterator dependencies = target.getDependencies(); | ||||
| while( dependencies.hasNext() ) | while( dependencies.hasNext() ) | ||||
| { | { | ||||
| @@ -144,41 +155,65 @@ public class DefaultProjectEngine | |||||
| executeTarget( targetName, target, context ); | executeTarget( targetName, target, context ); | ||||
| } | } | ||||
| /** | |||||
| * Method to execute a particular target instance. | |||||
| * | |||||
| * @param targetName the name of target | |||||
| * @param target the target | |||||
| * @param context the context in which to execute | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| protected void executeTarget( final String targetName, | protected void executeTarget( final String targetName, | ||||
| final Target target, | final Target target, | ||||
| final TaskletContext context ) | final TaskletContext context ) | ||||
| throws AntException | throws AntException | ||||
| { | { | ||||
| m_componentManager.put( "org.apache.ant.project.Target", target ); | |||||
| //is this necessary ? I think not but .... | |||||
| // NO it isn't because you set target name and project has already been provided | |||||
| //m_componentManager.put( "org.apache.ant.project.Target", target ); | |||||
| //create project context and set target name | |||||
| final TaskletContext targetContext = new DefaultTaskletContext( context ); | final TaskletContext targetContext = new DefaultTaskletContext( context ); | ||||
| targetContext.setProperty( Project.TARGET, targetName ); | targetContext.setProperty( Project.TARGET, targetName ); | ||||
| //notify listeners | |||||
| m_listenerSupport.targetStarted( targetName ); | m_listenerSupport.targetStarted( targetName ); | ||||
| //actually do the execution work | |||||
| executeTargetWork( targetName, target, targetContext ); | executeTargetWork( targetName, target, targetContext ); | ||||
| //notify listeners | |||||
| m_listenerSupport.targetFinished(); | m_listenerSupport.targetFinished(); | ||||
| } | } | ||||
| /** | |||||
| * Do the work associated with target. | |||||
| * ie execute all tasks | |||||
| * | |||||
| * @param name the name of target | |||||
| * @param target the target | |||||
| * @param context the context | |||||
| */ | |||||
| protected void executeTargetWork( final String name, | protected void executeTargetWork( final String name, | ||||
| final Target target, | final Target target, | ||||
| final TaskletContext context ) | final TaskletContext context ) | ||||
| { | { | ||||
| //check the condition associated with target. | |||||
| //if it is not satisfied then skip target | |||||
| final Condition condition = target.getCondition(); | final Condition condition = target.getCondition(); | ||||
| if( null != condition ) | if( null != condition ) | ||||
| { | { | ||||
| if( false == condition.evaluate( context ) ) | if( false == condition.evaluate( context ) ) | ||||
| { | { | ||||
| m_logger.debug( "Skipping target " + name + | |||||
| " as it does not satisfy condition" ); | |||||
| getLogger().debug( "Skipping target " + name + | |||||
| " as it does not satisfy condition" ); | |||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| m_logger.debug( "Executing target " + name ); | |||||
| getLogger().debug( "Executing target " + name ); | |||||
| //execute all tasks assciated with target | |||||
| final Iterator tasks = target.getTasks(); | final Iterator tasks = target.getTasks(); | ||||
| while( tasks.hasNext() ) | while( tasks.hasNext() ) | ||||
| { | { | ||||
| @@ -187,24 +222,32 @@ public class DefaultProjectEngine | |||||
| } | } | ||||
| } | } | ||||
| protected void executeTask( final Configuration configuration, | |||||
| final TaskletContext context ) | |||||
| /** | |||||
| * Execute a task. | |||||
| * | |||||
| * @param task the task definition | |||||
| * @param context the context | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| protected void executeTask( final Configuration task, final TaskletContext context ) | |||||
| throws AntException | throws AntException | ||||
| { | { | ||||
| final String name = configuration.getName(); | |||||
| m_logger.debug( "Executing task " + name ); | |||||
| final String name = task.getName(); | |||||
| getLogger().debug( "Executing task " + name ); | |||||
| //Set up context for task... | //Set up context for task... | ||||
| //is Only necessary if we are multi-threaded | //is Only necessary if we are multi-threaded | ||||
| //final TaskletContext targetContext = new DefaultTaskletContext( context ); | //final TaskletContext targetContext = new DefaultTaskletContext( context ); | ||||
| //is setting name even necessary ??? | |||||
| context.setProperty( TaskletContext.NAME, name ); | context.setProperty( TaskletContext.NAME, name ); | ||||
| //notify listeners | //notify listeners | ||||
| m_listenerSupport.taskletStarted( name ); | m_listenerSupport.taskletStarted( name ); | ||||
| //run task | //run task | ||||
| m_taskletEngine.execute( configuration, context, m_componentManager ); | |||||
| m_taskletEngine.execute( task, context ); | |||||
| //notify listeners task has ended | //notify listeners task has ended | ||||
| m_listenerSupport.taskletFinished(); | m_listenerSupport.taskletFinished(); | ||||
| @@ -9,49 +9,95 @@ package org.apache.ant.project; | |||||
| import org.apache.avalon.util.StringUtil; | import org.apache.avalon.util.StringUtil; | ||||
| /** | |||||
| * Default listener that emulates the old ant listener notifications. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public class DefaultProjectListener | public class DefaultProjectListener | ||||
| implements ProjectListener | implements ProjectListener | ||||
| { | { | ||||
| protected String m_prefix; | protected String m_prefix; | ||||
| /** | |||||
| * Notify listener of projectStarted event. | |||||
| * | |||||
| * @param projectName the projectName | |||||
| */ | |||||
| public void projectStarted( final String projectName ) | public void projectStarted( final String projectName ) | ||||
| { | { | ||||
| output( "Starting project " + projectName + "\n" ); | output( "Starting project " + projectName + "\n" ); | ||||
| } | } | ||||
| /** | |||||
| * Notify listener of projectFinished event. | |||||
| */ | |||||
| public void projectFinished() | public void projectFinished() | ||||
| { | { | ||||
| } | } | ||||
| /** | |||||
| * Notify listener of targetStarted event. | |||||
| * | |||||
| * @param targetName the name of target | |||||
| */ | |||||
| public void targetStarted( final String targetName ) | public void targetStarted( final String targetName ) | ||||
| { | { | ||||
| output( targetName + ":\n" ); | output( targetName + ":\n" ); | ||||
| } | } | ||||
| /** | |||||
| * Notify listener of targetFinished event. | |||||
| */ | |||||
| public void targetFinished() | public void targetFinished() | ||||
| { | { | ||||
| } | } | ||||
| /** | |||||
| * Notify listener of taskletStarted event. | |||||
| * | |||||
| * @param taskletName the name of tasklet | |||||
| */ | |||||
| public void taskletStarted( final String taskletName ) | public void taskletStarted( final String taskletName ) | ||||
| { | { | ||||
| m_prefix = taskletName; | m_prefix = taskletName; | ||||
| } | } | ||||
| /** | |||||
| * Notify listener of taskletFinished event. | |||||
| */ | |||||
| public void taskletFinished() | public void taskletFinished() | ||||
| { | { | ||||
| m_prefix = null; | m_prefix = null; | ||||
| } | } | ||||
| /** | |||||
| * Notify listener of log message event. | |||||
| * | |||||
| * @param message the message | |||||
| */ | |||||
| public void log( String message ) | public void log( String message ) | ||||
| { | { | ||||
| output( message ); | output( message ); | ||||
| } | } | ||||
| /** | |||||
| * Notify listener of log message event. | |||||
| * | |||||
| * @param message the message | |||||
| * @param throwable the throwable | |||||
| */ | |||||
| public void log( String message, Throwable throwable ) | public void log( String message, Throwable throwable ) | ||||
| { | { | ||||
| output( message + "\n" + StringUtil.printStackTrace( throwable, 5, true ) ); | output( message + "\n" + StringUtil.printStackTrace( throwable, 5, true ) ); | ||||
| } | } | ||||
| /** | |||||
| * Utility class to output data. | |||||
| * Overide in sub-classes to direct to a different destination. | |||||
| * | |||||
| * @param data the data | |||||
| */ | |||||
| protected void output( final String data ) | protected void output( final String data ) | ||||
| { | { | ||||
| if( null != m_prefix ) System.out.println( "\t[" + m_prefix + "] " + data ); | if( null != m_prefix ) System.out.println( "\t[" + m_prefix + "] " + data ); | ||||
| @@ -10,8 +10,13 @@ package org.apache.ant.project; | |||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.Iterator; | import java.util.Iterator; | ||||
| import org.apache.ant.configuration.Configuration; | import org.apache.ant.configuration.Configuration; | ||||
| import org.apache.ant.datatypes.Condition; | |||||
| import org.apache.ant.util.Condition; | |||||
| /** | |||||
| * Default implementation of target. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public class DefaultTarget | public class DefaultTarget | ||||
| implements Target | implements Target | ||||
| { | { | ||||
| @@ -19,36 +24,68 @@ public class DefaultTarget | |||||
| protected final ArrayList m_tasks = new ArrayList(); | protected final ArrayList m_tasks = new ArrayList(); | ||||
| protected final Condition m_condition; | protected final Condition m_condition; | ||||
| /** | |||||
| * Constructor taking condition for target. | |||||
| * | |||||
| * @param condition the condition | |||||
| */ | |||||
| public DefaultTarget( final Condition condition ) | public DefaultTarget( final Condition condition ) | ||||
| { | { | ||||
| m_condition = condition; | m_condition = condition; | ||||
| } | } | ||||
| /** | |||||
| * Constructor for target with no condition. | |||||
| */ | |||||
| public DefaultTarget() | public DefaultTarget() | ||||
| { | { | ||||
| this( null ); | this( null ); | ||||
| } | } | ||||
| /** | |||||
| * Get condition under which target is executed. | |||||
| * | |||||
| * @return the condition for target or null | |||||
| */ | |||||
| public Condition getCondition() | public Condition getCondition() | ||||
| { | { | ||||
| return m_condition; | return m_condition; | ||||
| } | } | ||||
| /** | |||||
| * Get dependencies of target | |||||
| * | |||||
| * @return the dependency list | |||||
| */ | |||||
| public Iterator getDependencies() | public Iterator getDependencies() | ||||
| { | { | ||||
| return m_dependencies.iterator(); | return m_dependencies.iterator(); | ||||
| } | } | ||||
| /** | |||||
| * Get tasks in target | |||||
| * | |||||
| * @return the target list | |||||
| */ | |||||
| public Iterator getTasks() | public Iterator getTasks() | ||||
| { | { | ||||
| return m_tasks.iterator(); | return m_tasks.iterator(); | ||||
| } | } | ||||
| /** | |||||
| * Add a dependency to target. | |||||
| * | |||||
| * @param dependency the dependency | |||||
| */ | |||||
| public void addDependency( final String dependency ) | public void addDependency( final String dependency ) | ||||
| { | { | ||||
| m_dependencies.add( dependency ); | m_dependencies.add( dependency ); | ||||
| } | } | ||||
| /** | |||||
| * Add task to target. | |||||
| * | |||||
| * @param taskConfiguration the task representation | |||||
| */ | |||||
| public void addTask( final Configuration taskConfiguration ) | public void addTask( final Configuration taskConfiguration ) | ||||
| { | { | ||||
| m_tasks.add( taskConfiguration ); | m_tasks.add( taskConfiguration ); | ||||
| @@ -10,12 +10,21 @@ package org.apache.ant.project; | |||||
| import org.apache.log.LogEntry; | import org.apache.log.LogEntry; | ||||
| import org.apache.log.LogTarget; | import org.apache.log.LogTarget; | ||||
| /** | |||||
| * Adapter between Avalon LogKit and Project listener interfaces. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public class LogTargetToListenerAdapter | public class LogTargetToListenerAdapter | ||||
| implements LogTarget | implements LogTarget | ||||
| { | { | ||||
| protected final ProjectListener m_listener; | protected final ProjectListener m_listener; | ||||
| /** | |||||
| * Constructor taking listener to convert to. | |||||
| * | |||||
| * @param listener the ProjectListener | |||||
| */ | |||||
| public LogTargetToListenerAdapter( final ProjectListener listener ) | public LogTargetToListenerAdapter( final ProjectListener listener ) | ||||
| { | { | ||||
| m_listener = listener; | m_listener = listener; | ||||
| @@ -12,6 +12,11 @@ import org.apache.ant.AntException; | |||||
| import org.apache.ant.tasklet.TaskletContext; | import org.apache.ant.tasklet.TaskletContext; | ||||
| import org.apache.avalon.Component; | import org.apache.avalon.Component; | ||||
| /** | |||||
| * Interface through which to interact with projects. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public interface Project | public interface Project | ||||
| extends Component | extends Component | ||||
| { | { | ||||
| @@ -24,9 +29,41 @@ public interface Project | |||||
| // the name of currently executing target | // the name of currently executing target | ||||
| String TARGET = "ant.target.name"; | String TARGET = "ant.target.name"; | ||||
| /** | |||||
| * Get name of default target. | |||||
| * | |||||
| * @return the default target name | |||||
| */ | |||||
| String getDefaultTargetName(); | String getDefaultTargetName(); | ||||
| /** | |||||
| * Retrieve implicit target. | |||||
| * The implicit target is top level tasks. | |||||
| * Currently restricted to property tasks. | |||||
| * | |||||
| * @return the Target | |||||
| */ | |||||
| Target getImplicitTarget(); | Target getImplicitTarget(); | ||||
| /** | |||||
| * Retrieve a target by name. | |||||
| * | |||||
| * @param name the name of target | |||||
| * @return the Target or null if no target exists with name | |||||
| */ | |||||
| Target getTarget( String name ); | Target getTarget( String name ); | ||||
| /** | |||||
| * Retrieve names of all targets in project. | |||||
| * | |||||
| * @return the iterator of project names | |||||
| */ | |||||
| Iterator getTargetNames(); | Iterator getTargetNames(); | ||||
| /** | |||||
| * Get project (top-level) context. | |||||
| * | |||||
| * @return the context | |||||
| */ | |||||
| TaskletContext getContext(); | TaskletContext getContext(); | ||||
| } | } | ||||
| @@ -10,13 +10,25 @@ package org.apache.ant.project; | |||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import org.apache.ant.AntException; | import org.apache.ant.AntException; | ||||
| import org.apache.log.Logger; | |||||
| import org.apache.avalon.Component; | |||||
| /** | |||||
| * Interface implemented by components that build projects from sources. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public interface ProjectBuilder | public interface ProjectBuilder | ||||
| extends Component | |||||
| { | { | ||||
| void setLogger( Logger logger ); | |||||
| Project build( File projectFile ) | |||||
| /** | |||||
| * build a project from source. | |||||
| * | |||||
| * @param source the source | |||||
| * @return the constructed Project | |||||
| * @exception IOException if an error occurs | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| Project build( File source ) | |||||
| throws IOException, AntException; | throws IOException, AntException; | ||||
| } | } | ||||
| @@ -11,21 +11,50 @@ import org.apache.ant.AntException; | |||||
| import org.apache.ant.tasklet.TaskletContext; | import org.apache.ant.tasklet.TaskletContext; | ||||
| import org.apache.ant.tasklet.engine.TaskletEngine; | import org.apache.ant.tasklet.engine.TaskletEngine; | ||||
| import org.apache.avalon.Component; | import org.apache.avalon.Component; | ||||
| import org.apache.log.Logger; | |||||
| /** | |||||
| * This is the interface between ProjectEngine and rest of the system. | |||||
| * This is the interface that tasks/frontends must use to interact with | |||||
| * project execution. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public interface ProjectEngine | public interface ProjectEngine | ||||
| extends Component | extends Component | ||||
| { | { | ||||
| void setLogger( Logger logger ); | |||||
| TaskletEngine getTaskletEngine(); | |||||
| /** | |||||
| * Add a listener to project events. | |||||
| * | |||||
| * @param listener the listener | |||||
| */ | |||||
| void addProjectListener( ProjectListener listener ); | void addProjectListener( ProjectListener listener ); | ||||
| /** | |||||
| * Remove a listener from project events. | |||||
| * | |||||
| * @param listener the listener | |||||
| */ | |||||
| void removeProjectListener( ProjectListener listener ); | void removeProjectListener( ProjectListener listener ); | ||||
| /** | |||||
| * Execute a target in a particular project. | |||||
| * Execute in the project context. | |||||
| * | |||||
| * @param project the Project | |||||
| * @param target the name of the target | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| void execute( Project project, String target ) | void execute( Project project, String target ) | ||||
| throws AntException; | throws AntException; | ||||
| /** | |||||
| * Execute a target in a particular project, in a particular context. | |||||
| * | |||||
| * @param project the Project | |||||
| * @param target the name of the target | |||||
| * @param context the context | |||||
| * @exception AntException if an error occurs | |||||
| */ | |||||
| void execute( Project project, String target, TaskletContext context ) | void execute( Project project, String target, TaskletContext context ) | ||||
| throws AntException; | throws AntException; | ||||
| } | } | ||||
| @@ -7,17 +7,62 @@ | |||||
| */ | */ | ||||
| package org.apache.ant.project; | package org.apache.ant.project; | ||||
| /** | |||||
| * The interface to implement if you want to receive | |||||
| * notification of project status. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public interface ProjectListener | public interface ProjectListener | ||||
| { | { | ||||
| /** | |||||
| * Notify listener of projectStarted event. | |||||
| * | |||||
| * @param projectName the projectName | |||||
| */ | |||||
| void projectStarted( String projectName ); | void projectStarted( String projectName ); | ||||
| /** | |||||
| * Notify listener of projectFinished event. | |||||
| */ | |||||
| void projectFinished(); | void projectFinished(); | ||||
| /** | |||||
| * Notify listener of targetStarted event. | |||||
| * | |||||
| * @param targetName the name of target | |||||
| */ | |||||
| void targetStarted( String targetName ); | void targetStarted( String targetName ); | ||||
| /** | |||||
| * Notify listener of targetFinished event. | |||||
| */ | |||||
| void targetFinished(); | void targetFinished(); | ||||
| /** | |||||
| * Notify listener of taskletStarted event. | |||||
| * | |||||
| * @param taskletName the name of tasklet | |||||
| */ | |||||
| void taskletStarted( String taskletName ); | void taskletStarted( String taskletName ); | ||||
| /** | |||||
| * Notify listener of taskletFinished event. | |||||
| */ | |||||
| void taskletFinished(); | void taskletFinished(); | ||||
| /** | |||||
| * Notify listener of log message event. | |||||
| * | |||||
| * @param message the message | |||||
| */ | |||||
| void log( String message ); | void log( String message ); | ||||
| /** | |||||
| * Notify listener of log message event. | |||||
| * | |||||
| * @param message the message | |||||
| * @param throwable the throwable | |||||
| */ | |||||
| void log( String message, Throwable throwable ); | void log( String message, Throwable throwable ); | ||||
| } | } | ||||
| @@ -7,11 +7,21 @@ | |||||
| */ | */ | ||||
| package org.apache.ant.project; | package org.apache.ant.project; | ||||
| /** | |||||
| * Support for the project listener event dispatching. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public class ProjectListenerSupport | public class ProjectListenerSupport | ||||
| implements ProjectListener | implements ProjectListener | ||||
| { | { | ||||
| protected ProjectListener[] m_listeners = new ProjectListener[ 0 ]; | protected ProjectListener[] m_listeners = new ProjectListener[ 0 ]; | ||||
| /** | |||||
| * Add an extra project listener that wants to receive notification of listener events. | |||||
| * | |||||
| * @param listener the listener | |||||
| */ | |||||
| public void addProjectListener( final ProjectListener listener ) | public void addProjectListener( final ProjectListener listener ) | ||||
| { | { | ||||
| final ProjectListener[] listeners = new ProjectListener[ m_listeners.length + 1 ]; | final ProjectListener[] listeners = new ProjectListener[ m_listeners.length + 1 ]; | ||||
| @@ -20,6 +30,11 @@ public class ProjectListenerSupport | |||||
| m_listeners = listeners; | m_listeners = listeners; | ||||
| } | } | ||||
| /** | |||||
| * Remove a project listener that wants to receive notification of listener events. | |||||
| * | |||||
| * @param listener the listener | |||||
| */ | |||||
| public void removeProjectListener( final ProjectListener listener ) | public void removeProjectListener( final ProjectListener listener ) | ||||
| { | { | ||||
| int found = -1; | int found = -1; | ||||
| @@ -44,6 +59,11 @@ public class ProjectListenerSupport | |||||
| m_listeners = listeners; | m_listeners = listeners; | ||||
| } | } | ||||
| /** | |||||
| * Fire a projectStarted event. | |||||
| * | |||||
| * @param projectName the projectName | |||||
| */ | |||||
| public void projectStarted( final String projectName ) | public void projectStarted( final String projectName ) | ||||
| { | { | ||||
| for( int i = 0; i < m_listeners.length; i++ ) | for( int i = 0; i < m_listeners.length; i++ ) | ||||
| @@ -52,6 +72,9 @@ public class ProjectListenerSupport | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Fire a projectFinished event. | |||||
| */ | |||||
| public void projectFinished() | public void projectFinished() | ||||
| { | { | ||||
| for( int i = 0; i < m_listeners.length; i++ ) | for( int i = 0; i < m_listeners.length; i++ ) | ||||
| @@ -60,6 +83,11 @@ public class ProjectListenerSupport | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Fire a targetStarted event. | |||||
| * | |||||
| * @param targetName the name of target | |||||
| */ | |||||
| public void targetStarted( String targetName ) | public void targetStarted( String targetName ) | ||||
| { | { | ||||
| for( int i = 0; i < m_listeners.length; i++ ) | for( int i = 0; i < m_listeners.length; i++ ) | ||||
| @@ -68,6 +96,9 @@ public class ProjectListenerSupport | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Fire a targetFinished event. | |||||
| */ | |||||
| public void targetFinished() | public void targetFinished() | ||||
| { | { | ||||
| for( int i = 0; i < m_listeners.length; i++ ) | for( int i = 0; i < m_listeners.length; i++ ) | ||||
| @@ -76,6 +107,11 @@ public class ProjectListenerSupport | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Fire a targetStarted event. | |||||
| * | |||||
| * @param targetName the name of target | |||||
| */ | |||||
| public void taskletStarted( String taskletName ) | public void taskletStarted( String taskletName ) | ||||
| { | { | ||||
| for( int i = 0; i < m_listeners.length; i++ ) | for( int i = 0; i < m_listeners.length; i++ ) | ||||
| @@ -84,6 +120,9 @@ public class ProjectListenerSupport | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Fire a taskletFinished event. | |||||
| */ | |||||
| public void taskletFinished() | public void taskletFinished() | ||||
| { | { | ||||
| for( int i = 0; i < m_listeners.length; i++ ) | for( int i = 0; i < m_listeners.length; i++ ) | ||||
| @@ -92,6 +131,11 @@ public class ProjectListenerSupport | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Fire a log event. | |||||
| * | |||||
| * @param message the log message | |||||
| */ | |||||
| public void log( String message ) | public void log( String message ) | ||||
| { | { | ||||
| for( int i = 0; i < m_listeners.length; i++ ) | for( int i = 0; i < m_listeners.length; i++ ) | ||||
| @@ -100,6 +144,12 @@ public class ProjectListenerSupport | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Fire a log event. | |||||
| * | |||||
| * @param message the log message | |||||
| * @param throwable the throwable to be logged | |||||
| */ | |||||
| public void log( String message, Throwable throwable ) | public void log( String message, Throwable throwable ) | ||||
| { | { | ||||
| for( int i = 0; i < m_listeners.length; i++ ) | for( int i = 0; i < m_listeners.length; i++ ) | ||||
| @@ -8,14 +8,36 @@ | |||||
| package org.apache.ant.project; | package org.apache.ant.project; | ||||
| import java.util.Iterator; | import java.util.Iterator; | ||||
| import org.apache.ant.util.Condition; | |||||
| import org.apache.avalon.Component; | import org.apache.avalon.Component; | ||||
| import org.apache.ant.datatypes.Condition; | |||||
| /** | |||||
| * Interface to represent targets in build file. | |||||
| * | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||||
| */ | |||||
| public interface Target | public interface Target | ||||
| extends Component | extends Component | ||||
| { | { | ||||
| /** | |||||
| * Get dependencies of target | |||||
| * | |||||
| * @return the dependency list | |||||
| */ | |||||
| Iterator getDependencies(); | Iterator getDependencies(); | ||||
| /** | |||||
| * Get tasks in target | |||||
| * | |||||
| * @return the target list | |||||
| */ | |||||
| Iterator getTasks(); | Iterator getTasks(); | ||||
| /** | |||||
| * Get condition under which target is executed. | |||||
| * | |||||
| * @return the condition for target or null | |||||
| */ | |||||
| Condition getCondition(); | Condition getCondition(); | ||||
| } | } | ||||
| @@ -8,9 +8,9 @@ | |||||
| package org.apache.ant.tasklet; | package org.apache.ant.tasklet; | ||||
| import org.apache.ant.AntException; | import org.apache.ant.AntException; | ||||
| import org.apache.avalon.AbstractLoggable; | |||||
| import org.apache.avalon.Context; | import org.apache.avalon.Context; | ||||
| import org.apache.avalon.Initializable; | import org.apache.avalon.Initializable; | ||||
| import org.apache.log.Logger; | |||||
| /** | /** | ||||
| * This is abstract base class for tasklets. | * This is abstract base class for tasklets. | ||||
| @@ -18,23 +18,13 @@ import org.apache.log.Logger; | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | ||||
| */ | */ | ||||
| public abstract class AbstractTasklet | public abstract class AbstractTasklet | ||||
| extends AbstractLoggable | |||||
| implements Tasklet, Initializable | implements Tasklet, Initializable | ||||
| { | { | ||||
| //the user should set this in constructors of sub-classes | //the user should set this in constructors of sub-classes | ||||
| protected JavaVersion m_requiredJavaVersion; | protected JavaVersion m_requiredJavaVersion; | ||||
| private TaskletContext m_context; | private TaskletContext m_context; | ||||
| private Logger m_logger; | |||||
| /** | |||||
| * Receive logger from container. | |||||
| * | |||||
| * @param logger the logger | |||||
| */ | |||||
| public void setLogger( final Logger logger ) | |||||
| { | |||||
| m_logger = logger; | |||||
| } | |||||
| /** | /** | ||||
| * Retrieve context from container. | * Retrieve context from container. | ||||
| @@ -79,14 +69,4 @@ public abstract class AbstractTasklet | |||||
| { | { | ||||
| return m_context; | return m_context; | ||||
| } | } | ||||
| /** | |||||
| * Convenience method for subclass to get logger. | |||||
| * | |||||
| * @return the Logger | |||||
| */ | |||||
| protected Logger getLogger() | |||||
| { | |||||
| return m_logger; | |||||
| } | |||||
| } | } | ||||
| @@ -87,10 +87,10 @@ public class DefaultTaskletContext | |||||
| * @param filename the filename to resolve | * @param filename the filename to resolve | ||||
| * @return the resolved filename | * @return the resolved filename | ||||
| */ | */ | ||||
| public String resolveFilename( final String filename ) | |||||
| public File resolveFile( final String filename ) | |||||
| { | { | ||||
| final File result = FileUtil.resolveFile( m_baseDirectory, filename ); | final File result = FileUtil.resolveFile( m_baseDirectory, filename ); | ||||
| if( null != result ) return result.toString(); | |||||
| if( null != result ) return result; | |||||
| else return null; | else return null; | ||||
| } | } | ||||
| @@ -106,7 +106,7 @@ public class DefaultTaskletContext | |||||
| try { return PropertyUtil.resolveProperty( property, this, false ); } | try { return PropertyUtil.resolveProperty( property, this, false ); } | ||||
| catch( final PropertyException pe ) | catch( final PropertyException pe ) | ||||
| { | { | ||||
| throw new AntException( "Error resolving " + property + " due to " +pe.getMessage(), | |||||
| throw new AntException( "Error resolving " + property + " due to " + pe.getMessage(), | |||||
| pe ); | pe ); | ||||
| } | } | ||||
| } | } | ||||
| @@ -173,6 +173,14 @@ public class DefaultTaskletContext | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * put a value in context. | |||||
| * This put method is overidden so new baseDirectory can be saved | |||||
| * in member variable. | |||||
| * | |||||
| * @param key the key | |||||
| * @param value the value | |||||
| */ | |||||
| public void put( final Object key, final Object value ) | public void put( final Object key, final Object value ) | ||||
| { | { | ||||
| if( key.equals( BASE_DIRECTORY ) ) | if( key.equals( BASE_DIRECTORY ) ) | ||||
| @@ -24,6 +24,6 @@ import org.apache.avalon.Loggable; | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | ||||
| */ | */ | ||||
| public interface Tasklet | public interface Tasklet | ||||
| extends Component, Contextualizable, Runnable, Loggable | |||||
| extends Component, Loggable, Contextualizable, Runnable | |||||
| { | { | ||||
| } | } | ||||
| @@ -60,9 +60,9 @@ public interface TaskletContext | |||||
| * different volumes, file conventions etc) | * different volumes, file conventions etc) | ||||
| * | * | ||||
| * @param filename the filename to resolve | * @param filename the filename to resolve | ||||
| * @return the resolved filename | |||||
| * @return the resolved file | |||||
| */ | */ | ||||
| String resolveFilename( String filename ); | |||||
| File resolveFile( String filename ); | |||||
| /** | /** | ||||
| * Resolve property. | * Resolve property. | ||||
| @@ -17,8 +17,11 @@ import org.apache.ant.convert.ConverterEngine; | |||||
| import org.apache.ant.datatypes.DataTypeEngine; | import org.apache.ant.datatypes.DataTypeEngine; | ||||
| import org.apache.ant.tasklet.Tasklet; | import org.apache.ant.tasklet.Tasklet; | ||||
| import org.apache.ant.tasklet.TaskletContext; | import org.apache.ant.tasklet.TaskletContext; | ||||
| import org.apache.avalon.AbstractLoggable; | |||||
| import org.apache.avalon.Component; | import org.apache.avalon.Component; | ||||
| import org.apache.avalon.ComponentManager; | import org.apache.avalon.ComponentManager; | ||||
| import org.apache.avalon.DefaultComponentManager; | |||||
| import org.apache.avalon.ComponentManagerException; | |||||
| import org.apache.avalon.Composer; | import org.apache.avalon.Composer; | ||||
| import org.apache.avalon.Context; | import org.apache.avalon.Context; | ||||
| import org.apache.avalon.Contextualizable; | import org.apache.avalon.Contextualizable; | ||||
| @@ -28,6 +31,7 @@ import org.apache.avalon.Initializable; | |||||
| import org.apache.avalon.Loggable; | import org.apache.avalon.Loggable; | ||||
| import org.apache.avalon.camelot.DefaultFactory; | import org.apache.avalon.camelot.DefaultFactory; | ||||
| import org.apache.avalon.camelot.DefaultLocatorRegistry; | import org.apache.avalon.camelot.DefaultLocatorRegistry; | ||||
| import org.apache.avalon.camelot.Factory; | |||||
| import org.apache.avalon.camelot.FactoryException; | import org.apache.avalon.camelot.FactoryException; | ||||
| import org.apache.avalon.camelot.Locator; | import org.apache.avalon.camelot.Locator; | ||||
| import org.apache.avalon.camelot.LocatorRegistry; | import org.apache.avalon.camelot.LocatorRegistry; | ||||
| @@ -35,20 +39,17 @@ import org.apache.avalon.camelot.RegistryException; | |||||
| import org.apache.log.Logger; | import org.apache.log.Logger; | ||||
| public class DefaultTaskletEngine | public class DefaultTaskletEngine | ||||
| implements TaskletEngine, Initializable | |||||
| extends AbstractLoggable | |||||
| implements TaskletEngine, Composer | |||||
| { | { | ||||
| protected TskDeployer m_tskDeployer; | protected TskDeployer m_tskDeployer; | ||||
| protected DefaultFactory m_factory; | |||||
| protected LocatorRegistry m_locatorRegistry; | |||||
| protected Factory m_factory; | |||||
| protected LocatorRegistry m_locatorRegistry = new DefaultLocatorRegistry(); | |||||
| protected Configurer m_configurer; | protected Configurer m_configurer; | ||||
| protected Logger m_logger; | |||||
| protected DataTypeEngine m_dataTypeEngine; | protected DataTypeEngine m_dataTypeEngine; | ||||
| protected ConverterEngine m_converterEngine; | protected ConverterEngine m_converterEngine; | ||||
| public void setLogger( final Logger logger ) | |||||
| { | |||||
| m_logger = logger; | |||||
| } | |||||
| protected ComponentManager m_componentManager; | |||||
| public TskDeployer getTskDeployer() | public TskDeployer getTskDeployer() | ||||
| { | { | ||||
| @@ -74,120 +75,74 @@ public class DefaultTaskletEngine | |||||
| { | { | ||||
| return m_dataTypeEngine; | return m_dataTypeEngine; | ||||
| } | } | ||||
| public void init() | |||||
| throws Exception | |||||
| { | |||||
| //converter must be created before configurerer | |||||
| //so that it gets placed in configurers componentManager | |||||
| m_converterEngine = createConverterEngine(); | |||||
| setupSubComponent( m_converterEngine ); | |||||
| m_configurer = createConfigurer(); | |||||
| setupSubComponent( m_configurer ); | |||||
| m_locatorRegistry = createLocatorRegistry(); | |||||
| m_factory = createFactory(); | |||||
| setupSubComponent( m_factory ); | |||||
| m_dataTypeEngine = createDataTypeEngine(); | |||||
| setupSubComponent( m_dataTypeEngine ); | |||||
| m_tskDeployer = createTskDeployer(); | |||||
| setupSubComponent( m_tskDeployer ); | |||||
| } | |||||
| protected void setupSubComponent( final Component component ) | |||||
| throws Exception | |||||
| { | |||||
| if( component instanceof Loggable ) | |||||
| { | |||||
| ((Loggable)component).setLogger( m_logger ); | |||||
| } | |||||
| if( component instanceof Composer ) | |||||
| { | |||||
| final DefaultComponentManager componentManager = new DefaultComponentManager(); | |||||
| componentManager.put( "org.apache.ant.convert.Converter", | |||||
| getConverterEngine() ); | |||||
| componentManager.put( "org.apache.ant.configuration.Configurer", | |||||
| m_configurer ); | |||||
| componentManager.put( "org.apache.ant.tasklet.engine.TaskletEngine", | |||||
| this ); | |||||
| ((Composer)component).compose( componentManager ); | |||||
| } | |||||
| if( component instanceof Initializable ) | |||||
| { | |||||
| ((Initializable)component).init(); | |||||
| } | |||||
| } | |||||
| protected DataTypeEngine createDataTypeEngine() | |||||
| { | |||||
| final TaskletDataTypeEngine engine = new TaskletDataTypeEngine(); | |||||
| engine.setFactory( m_factory ); | |||||
| return engine; | |||||
| } | |||||
| protected TskDeployer createTskDeployer() | |||||
| /** | |||||
| * Retrieve relevent services needed to deploy. | |||||
| * | |||||
| * @param componentManager the ComponentManager | |||||
| * @exception ComponentManagerException if an error occurs | |||||
| */ | |||||
| public void compose( final ComponentManager componentManager ) | |||||
| throws ComponentManagerException | |||||
| { | { | ||||
| return new DefaultTskDeployer(); | |||||
| } | |||||
| //cache CM so it can be used while executing tasks | |||||
| m_componentManager = componentManager; | |||||
| protected Configurer createConfigurer() | |||||
| { | |||||
| return new DefaultConfigurer(); | |||||
| } | |||||
| protected LocatorRegistry createLocatorRegistry() | |||||
| { | |||||
| return new DefaultLocatorRegistry(); | |||||
| } | |||||
| protected DefaultFactory createFactory() | |||||
| { | |||||
| return new DefaultFactory(); | |||||
| } | |||||
| protected ConverterEngine createConverterEngine() | |||||
| { | |||||
| //this is done so that the loaders are shared | |||||
| //which results in much less overhead | |||||
| final TaskletConverterEngine engine = new TaskletConverterEngine(); | |||||
| engine.setFactory( m_factory ); | |||||
| return engine; | |||||
| m_factory = (Factory)componentManager.lookup( "org.apache.avalon.camelot.Factory" ); | |||||
| m_tskDeployer = | |||||
| (TskDeployer)componentManager.lookup( "org.apache.ant.tasklet.engine.TskDeployer" ); | |||||
| m_configurer = | |||||
| (Configurer)componentManager.lookup( "org.apache.ant.configuration.Configurer" ); | |||||
| m_dataTypeEngine = | |||||
| (DataTypeEngine)componentManager.lookup( "org.apache.ant.datatypes.DataTypeEngine" ); | |||||
| m_converterEngine = | |||||
| (ConverterEngine)componentManager.lookup( "org.apache.ant.convert.ConverterEngine" ); | |||||
| } | } | ||||
| public void execute( final Configuration task, | public void execute( final Configuration task, | ||||
| final TaskletContext context, | |||||
| final ComponentManager componentManager ) | |||||
| final TaskletContext context ) | |||||
| throws AntException | throws AntException | ||||
| { | { | ||||
| m_logger.debug( "Creating" ); | |||||
| getLogger().debug( "Creating" ); | |||||
| final Tasklet tasklet = createTasklet( task.getName() ); | final Tasklet tasklet = createTasklet( task.getName() ); | ||||
| tasklet.setLogger( m_logger ); | |||||
| setupLogger( tasklet ); | |||||
| m_logger.debug( "Contextualizing" ); | |||||
| getLogger().debug( "Contextualizing" ); | |||||
| doContextualize( tasklet, task, context ); | doContextualize( tasklet, task, context ); | ||||
| m_logger.debug( "Composing" ); | |||||
| doCompose( tasklet, task, componentManager ); | |||||
| getLogger().debug( "Composing" ); | |||||
| doCompose( tasklet, task ); | |||||
| m_logger.debug( "Configuring" ); | |||||
| getLogger().debug( "Configuring" ); | |||||
| doConfigure( tasklet, task, context ); | doConfigure( tasklet, task, context ); | ||||
| m_logger.debug( "Initializing" ); | |||||
| getLogger().debug( "Initializing" ); | |||||
| doInitialize( tasklet, task ); | doInitialize( tasklet, task ); | ||||
| m_logger.debug( "Running" ); | |||||
| getLogger().debug( "Running" ); | |||||
| tasklet.run(); | tasklet.run(); | ||||
| m_logger.debug( "Disposing" ); | |||||
| getLogger().debug( "Disposing" ); | |||||
| doDispose( tasklet, task ); | doDispose( tasklet, task ); | ||||
| } | } | ||||
| protected Tasklet createTasklet( final String name ) | |||||
| throws AntException | |||||
| { | |||||
| try | |||||
| { | |||||
| final Locator locator = m_locatorRegistry.getLocator( name ); | |||||
| return (Tasklet)m_factory.create( locator, Tasklet.class ); | |||||
| } | |||||
| catch( final RegistryException re ) | |||||
| { | |||||
| throw new AntException( "Unable to locate task " + name, re ); | |||||
| } | |||||
| catch( final FactoryException fe ) | |||||
| { | |||||
| throw new AntException( "Unable to create task " + name, fe ); | |||||
| } | |||||
| } | |||||
| protected void doConfigure( final Tasklet tasklet, | protected void doConfigure( final Tasklet tasklet, | ||||
| final Configuration task, | final Configuration task, | ||||
| @@ -203,20 +158,12 @@ public class DefaultTaskletEngine | |||||
| } | } | ||||
| } | } | ||||
| protected void doCompose( final Tasklet tasklet, | |||||
| final Configuration task, | |||||
| final ComponentManager componentManager ) | |||||
| protected void doCompose( final Tasklet tasklet, final Configuration task ) | |||||
| throws AntException | throws AntException | ||||
| { | { | ||||
| final DefaultComponentManager subComponentManager = | |||||
| new DefaultComponentManager( componentManager ); | |||||
| subComponentManager.put( "org.apache.ant.configuration.Configurer", m_configurer ); | |||||
| if( tasklet instanceof Composer ) | if( tasklet instanceof Composer ) | ||||
| { | { | ||||
| try { ((Composer)tasklet).compose( subComponentManager ); } | |||||
| try { ((Composer)tasklet).compose( m_componentManager ); } | |||||
| catch( final Throwable throwable ) | catch( final Throwable throwable ) | ||||
| { | { | ||||
| throw new AntException( "Error composing task " + task.getName() + " at " + | throw new AntException( "Error composing task " + task.getName() + " at " + | ||||
| @@ -231,9 +178,6 @@ public class DefaultTaskletEngine | |||||
| final TaskletContext context ) | final TaskletContext context ) | ||||
| throws AntException | throws AntException | ||||
| { | { | ||||
| // Already done in container ... | |||||
| //context.setProperty( TaskletContext.NAME, name ); | |||||
| try { tasklet.contextualize( context ); } | try { tasklet.contextualize( context ); } | ||||
| catch( final Throwable throwable ) | catch( final Throwable throwable ) | ||||
| { | { | ||||
| @@ -272,22 +216,4 @@ public class DefaultTaskletEngine | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| protected Tasklet createTasklet( final String name ) | |||||
| throws AntException | |||||
| { | |||||
| try | |||||
| { | |||||
| final Locator locator = m_locatorRegistry.getLocator( name ); | |||||
| return (Tasklet)m_factory.create( locator, Tasklet.class ); | |||||
| } | |||||
| catch( final RegistryException re ) | |||||
| { | |||||
| throw new AntException( "Unable to locate task " + name, re ); | |||||
| } | |||||
| catch( final FactoryException fe ) | |||||
| { | |||||
| throw new AntException( "Unable to create task " + name, fe ); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -15,13 +15,13 @@ import java.util.Iterator; | |||||
| import java.util.zip.ZipEntry; | import java.util.zip.ZipEntry; | ||||
| import java.util.zip.ZipException; | import java.util.zip.ZipException; | ||||
| import java.util.zip.ZipFile; | import java.util.zip.ZipFile; | ||||
| import org.apache.ant.datatypes.DataTypeEngine; | |||||
| import org.apache.ant.convert.ConverterEngine; | import org.apache.ant.convert.ConverterEngine; | ||||
| import org.apache.ant.convert.ConverterRegistry; | import org.apache.ant.convert.ConverterRegistry; | ||||
| import org.apache.ant.convert.DefaultConverterInfo; | import org.apache.ant.convert.DefaultConverterInfo; | ||||
| import org.apache.avalon.Component; | import org.apache.avalon.Component; | ||||
| import org.apache.avalon.ComponentManager; | import org.apache.avalon.ComponentManager; | ||||
| import org.apache.avalon.ComponentNotAccessibleException; | |||||
| import org.apache.avalon.ComponentNotFoundException; | |||||
| import org.apache.avalon.ComponentManagerException; | |||||
| import org.apache.avalon.Composer; | import org.apache.avalon.Composer; | ||||
| import org.apache.avalon.Configuration; | import org.apache.avalon.Configuration; | ||||
| import org.apache.avalon.ConfigurationException; | import org.apache.avalon.ConfigurationException; | ||||
| @@ -29,6 +29,7 @@ import org.apache.avalon.camelot.AbstractZipDeployer; | |||||
| import org.apache.avalon.camelot.DefaultLocator; | import org.apache.avalon.camelot.DefaultLocator; | ||||
| import org.apache.avalon.camelot.DefaultLocatorRegistry; | import org.apache.avalon.camelot.DefaultLocatorRegistry; | ||||
| import org.apache.avalon.camelot.DeploymentException; | import org.apache.avalon.camelot.DeploymentException; | ||||
| import org.apache.avalon.camelot.DeployerUtil; | |||||
| import org.apache.avalon.camelot.Loader; | import org.apache.avalon.camelot.Loader; | ||||
| import org.apache.avalon.camelot.LocatorRegistry; | import org.apache.avalon.camelot.LocatorRegistry; | ||||
| import org.apache.avalon.camelot.RegistryException; | import org.apache.avalon.camelot.RegistryException; | ||||
| @@ -55,7 +56,7 @@ public class DefaultTskDeployer | |||||
| */ | */ | ||||
| public DefaultTskDeployer() | public DefaultTskDeployer() | ||||
| { | { | ||||
| super( false ); | |||||
| super(); | |||||
| m_autoUndeploy = true; | m_autoUndeploy = true; | ||||
| m_type = "Tasklet"; | m_type = "Tasklet"; | ||||
| } | } | ||||
| @@ -64,34 +65,32 @@ public class DefaultTskDeployer | |||||
| * Retrieve relevent services needed to deploy. | * Retrieve relevent services needed to deploy. | ||||
| * | * | ||||
| * @param componentManager the ComponentManager | * @param componentManager the ComponentManager | ||||
| * @exception ComponentNotFoundException if an error occurs | |||||
| * @exception ComponentNotAccessibleException if an error occurs | |||||
| * @exception ComponentManagerException if an error occurs | |||||
| */ | */ | ||||
| public void compose( final ComponentManager componentManager ) | public void compose( final ComponentManager componentManager ) | ||||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||||
| throws ComponentManagerException | |||||
| { | { | ||||
| final TaskletEngine taskletEngine = (TaskletEngine)componentManager. | final TaskletEngine taskletEngine = (TaskletEngine)componentManager. | ||||
| lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | ||||
| final ConverterEngine converterEngine = taskletEngine.getConverterEngine(); | |||||
| m_taskletRegistry = taskletEngine.getRegistry(); | |||||
| final ConverterEngine converterEngine = (ConverterEngine)componentManager. | |||||
| lookup( "org.apache.ant.convert.ConverterEngine" ); | |||||
| m_converterInfoRegistry = converterEngine.getInfoRegistry(); | m_converterInfoRegistry = converterEngine.getInfoRegistry(); | ||||
| m_converterRegistry = converterEngine.getRegistry(); | m_converterRegistry = converterEngine.getRegistry(); | ||||
| m_taskletRegistry = taskletEngine.getRegistry(); | |||||
| final DataTypeEngine dataTypeEngine = (DataTypeEngine)componentManager. | |||||
| lookup( "org.apache.ant.datatypes.DataTypeEngine" ); | |||||
| m_dataTypeRegistry = taskletEngine.getDataTypeEngine().getRegistry(); | |||||
| } | |||||
| public void setLogger( final Logger logger ) | |||||
| { | |||||
| m_logger = logger; | |||||
| m_dataTypeRegistry = dataTypeEngine.getRegistry(); | |||||
| } | } | ||||
| protected void loadResources( final ZipFile zipFile, final String location, final URL url ) | protected void loadResources( final ZipFile zipFile, final String location, final URL url ) | ||||
| throws DeploymentException | throws DeploymentException | ||||
| { | { | ||||
| final Configuration taskdefs = loadConfiguration( zipFile, TSKDEF_FILE ); | |||||
| final Configuration taskdefs = DeployerUtil.loadConfiguration( zipFile, TSKDEF_FILE ); | |||||
| try | try | ||||
| { | { | ||||
| @@ -126,8 +125,8 @@ public class DefaultTskDeployer | |||||
| throws DeploymentException | throws DeploymentException | ||||
| { | { | ||||
| checkDeployment( location, url ); | checkDeployment( location, url ); | ||||
| final ZipFile zipFile = getZipFileFor( url ); | |||||
| final Configuration taskdefs = loadConfiguration( zipFile, TSKDEF_FILE ); | |||||
| final ZipFile zipFile = DeployerUtil.getZipFileFor( getFileFor( url ) ); | |||||
| final Configuration taskdefs = DeployerUtil.loadConfiguration( zipFile, TSKDEF_FILE ); | |||||
| try | try | ||||
| { | { | ||||
| @@ -152,8 +151,9 @@ public class DefaultTskDeployer | |||||
| throws DeploymentException | throws DeploymentException | ||||
| { | { | ||||
| checkDeployment( location, url ); | checkDeployment( location, url ); | ||||
| final ZipFile zipFile = getZipFileFor( url ); | |||||
| final Configuration datatypedefs = loadConfiguration( zipFile, TSKDEF_FILE ); | |||||
| final ZipFile zipFile = DeployerUtil.getZipFileFor( getFileFor( url ) ); | |||||
| final Configuration datatypedefs = | |||||
| DeployerUtil.loadConfiguration( zipFile, TSKDEF_FILE ); | |||||
| try | try | ||||
| { | { | ||||
| @@ -178,8 +178,8 @@ public class DefaultTskDeployer | |||||
| throws DeploymentException | throws DeploymentException | ||||
| { | { | ||||
| checkDeployment( location, url ); | checkDeployment( location, url ); | ||||
| final ZipFile zipFile = getZipFileFor( url ); | |||||
| final Configuration taskdefs = loadConfiguration( zipFile, TSKDEF_FILE ); | |||||
| final ZipFile zipFile = DeployerUtil.getZipFileFor( getFileFor( url ) ); | |||||
| final Configuration taskdefs = DeployerUtil.loadConfiguration( zipFile, TSKDEF_FILE ); | |||||
| try | try | ||||
| { | { | ||||
| @@ -1,29 +0,0 @@ | |||||
| /* | |||||
| * 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 file. | |||||
| */ | |||||
| package org.apache.ant.tasklet.engine; | |||||
| import org.apache.ant.convert.DefaultConverterEngine; | |||||
| import org.apache.avalon.camelot.DefaultFactory; | |||||
| public class TaskletConverterEngine | |||||
| extends DefaultConverterEngine | |||||
| { | |||||
| /** | |||||
| * Set the ConverterFactory. | |||||
| * Package access intended. | |||||
| */ | |||||
| void setFactory( final DefaultFactory factory ) | |||||
| { | |||||
| m_factory = factory; | |||||
| } | |||||
| protected DefaultFactory createFactory() | |||||
| { | |||||
| return m_factory; | |||||
| } | |||||
| } | |||||
| @@ -1,29 +0,0 @@ | |||||
| /* | |||||
| * 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 file. | |||||
| */ | |||||
| package org.apache.ant.tasklet.engine; | |||||
| import org.apache.ant.datatypes.DefaultDataTypeEngine; | |||||
| import org.apache.avalon.camelot.DefaultFactory; | |||||
| public class TaskletDataTypeEngine | |||||
| extends DefaultDataTypeEngine | |||||
| { | |||||
| /** | |||||
| * Set the DataTypeFactory. | |||||
| * Package access intended. | |||||
| */ | |||||
| void setFactory( final DefaultFactory factory ) | |||||
| { | |||||
| m_factory = factory; | |||||
| } | |||||
| protected DefaultFactory createFactory() | |||||
| { | |||||
| return m_factory; | |||||
| } | |||||
| } | |||||
| @@ -24,7 +24,7 @@ import org.apache.log.Logger; | |||||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | ||||
| */ | */ | ||||
| public interface TaskletEngine | public interface TaskletEngine | ||||
| extends Component, Loggable | |||||
| extends Component | |||||
| { | { | ||||
| /** | /** | ||||
| * Retrieve deployer for engine. | * Retrieve deployer for engine. | ||||
| @@ -60,8 +60,6 @@ public interface TaskletEngine | |||||
| * @param task the configruation data for task | * @param task the configruation data for task | ||||
| * @exception AntException if an error occurs | * @exception AntException if an error occurs | ||||
| */ | */ | ||||
| void execute( Configuration task, | |||||
| TaskletContext context, | |||||
| ComponentManager componentManager ) | |||||
| void execute( Configuration task, TaskletContext context ) | |||||
| throws AntException; | throws AntException; | ||||
| } | } | ||||
| @@ -14,8 +14,7 @@ import org.apache.ant.AntException; | |||||
| import org.apache.ant.tasklet.AbstractTasklet; | import org.apache.ant.tasklet.AbstractTasklet; | ||||
| import org.apache.ant.tasklet.engine.TaskletEngine; | import org.apache.ant.tasklet.engine.TaskletEngine; | ||||
| import org.apache.avalon.ComponentManager; | import org.apache.avalon.ComponentManager; | ||||
| import org.apache.avalon.ComponentNotAccessibleException; | |||||
| import org.apache.avalon.ComponentNotFoundException; | |||||
| import org.apache.avalon.ComponentManagerException; | |||||
| import org.apache.avalon.Composer; | import org.apache.avalon.Composer; | ||||
| import org.apache.avalon.camelot.RegistryException; | import org.apache.avalon.camelot.RegistryException; | ||||
| @@ -34,7 +33,7 @@ public abstract class AbstractResourceRegisterer | |||||
| protected TaskletEngine m_engine; | protected TaskletEngine m_engine; | ||||
| public void compose( final ComponentManager componentManager ) | public void compose( final ComponentManager componentManager ) | ||||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||||
| throws ComponentManagerException | |||||
| { | { | ||||
| m_engine = (TaskletEngine)componentManager. | m_engine = (TaskletEngine)componentManager. | ||||
| lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | ||||
| @@ -84,7 +83,7 @@ public abstract class AbstractResourceRegisterer | |||||
| { | { | ||||
| if( null != libName ) | if( null != libName ) | ||||
| { | { | ||||
| final File lib = new File( getContext().resolveFilename( libName ) ); | |||||
| final File lib = getContext().resolveFile( libName ); | |||||
| try { return lib.toURL(); } | try { return lib.toURL(); } | ||||
| catch( final MalformedURLException mue ) | catch( final MalformedURLException mue ) | ||||
| { | { | ||||
| @@ -16,8 +16,7 @@ import org.apache.ant.tasklet.DefaultTaskletContext; | |||||
| import org.apache.ant.tasklet.TaskletContext; | import org.apache.ant.tasklet.TaskletContext; | ||||
| import org.apache.avalon.ComponentManager; | import org.apache.avalon.ComponentManager; | ||||
| import org.apache.avalon.Context; | import org.apache.avalon.Context; | ||||
| import org.apache.avalon.ComponentNotAccessibleException; | |||||
| import org.apache.avalon.ComponentNotFoundException; | |||||
| import org.apache.avalon.ComponentManagerException; | |||||
| import org.apache.avalon.Composer; | import org.apache.avalon.Composer; | ||||
| /** | /** | ||||
| @@ -43,7 +42,7 @@ public class AntCall | |||||
| } | } | ||||
| public void compose( final ComponentManager componentManager ) | public void compose( final ComponentManager componentManager ) | ||||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||||
| throws ComponentManagerException | |||||
| { | { | ||||
| m_componentManager = componentManager; | m_componentManager = componentManager; | ||||
| m_projectEngine = (ProjectEngine)componentManager. | m_projectEngine = (ProjectEngine)componentManager. | ||||
| @@ -19,8 +19,7 @@ import org.apache.ant.tasklet.AbstractTasklet; | |||||
| import org.apache.ant.tasklet.TaskletContext; | import org.apache.ant.tasklet.TaskletContext; | ||||
| import org.apache.ant.tasklet.engine.TaskletEngine; | import org.apache.ant.tasklet.engine.TaskletEngine; | ||||
| import org.apache.avalon.ComponentManager; | import org.apache.avalon.ComponentManager; | ||||
| import org.apache.avalon.ComponentNotAccessibleException; | |||||
| import org.apache.avalon.ComponentNotFoundException; | |||||
| import org.apache.avalon.ComponentManagerException; | |||||
| import org.apache.avalon.Composer; | import org.apache.avalon.Composer; | ||||
| import org.apache.avalon.ConfigurationException; | import org.apache.avalon.ConfigurationException; | ||||
| import org.apache.avalon.Resolvable; | import org.apache.avalon.Resolvable; | ||||
| @@ -40,16 +39,15 @@ public class Property | |||||
| protected Configurer m_configurer; | protected Configurer m_configurer; | ||||
| public void compose( final ComponentManager componentManager ) | public void compose( final ComponentManager componentManager ) | ||||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||||
| throws ComponentManagerException | |||||
| { | { | ||||
| m_configurer = (Configurer)componentManager. | m_configurer = (Configurer)componentManager. | ||||
| lookup( "org.apache.ant.configuration.Configurer" ); | lookup( "org.apache.ant.configuration.Configurer" ); | ||||
| final TaskletEngine taskletEngine = (TaskletEngine)componentManager. | |||||
| lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | |||||
| m_engine = taskletEngine.getDataTypeEngine(); | |||||
| m_converter = taskletEngine.getConverterEngine(); | |||||
| m_engine = (DataTypeEngine)componentManager. | |||||
| lookup( "org.apache.ant.datatypes.DataTypeEngine" ); | |||||
| m_converter = (Converter)componentManager.lookup( "org.apache.ant.convert.Converter" ); | |||||
| } | } | ||||
| public void configure( final Configuration configuration ) | public void configure( final Configuration configuration ) | ||||
| @@ -71,7 +69,12 @@ public class Property | |||||
| if( name.equals( "name" ) ) | if( name.equals( "name" ) ) | ||||
| { | { | ||||
| try { setName( (String)m_converter.convert( String.class, object ) ); } | |||||
| try | |||||
| { | |||||
| final String convertedValue = | |||||
| (String)m_converter.convert( String.class, object, getContext() ); | |||||
| setName( convertedValue ); | |||||
| } | |||||
| catch( final Exception e ) | catch( final Exception e ) | ||||
| { | { | ||||
| throw new ConfigurationException( "Error converting value", e ); | throw new ConfigurationException( "Error converting value", e ); | ||||
| @@ -86,7 +89,7 @@ public class Property | |||||
| try | try | ||||
| { | { | ||||
| final Boolean localScope = | final Boolean localScope = | ||||
| (Boolean)m_converter.convert( Boolean.class, object ); | |||||
| (Boolean)m_converter.convert( Boolean.class, object, getContext() ); | |||||
| setLocalScope( Boolean.TRUE == localScope ); | setLocalScope( Boolean.TRUE == localScope ); | ||||
| } | } | ||||
| catch( final Exception e ) | catch( final Exception e ) | ||||
| @@ -17,8 +17,7 @@ import org.apache.ant.convert.DefaultConverterInfo; | |||||
| import org.apache.ant.tasklet.AbstractTasklet; | import org.apache.ant.tasklet.AbstractTasklet; | ||||
| import org.apache.ant.tasklet.engine.TaskletEngine; | import org.apache.ant.tasklet.engine.TaskletEngine; | ||||
| import org.apache.avalon.ComponentManager; | import org.apache.avalon.ComponentManager; | ||||
| import org.apache.avalon.ComponentNotAccessibleException; | |||||
| import org.apache.avalon.ComponentNotFoundException; | |||||
| import org.apache.avalon.ComponentManagerException; | |||||
| import org.apache.avalon.Composer; | import org.apache.avalon.Composer; | ||||
| import org.apache.avalon.camelot.DeploymentException; | import org.apache.avalon.camelot.DeploymentException; | ||||
| import org.apache.avalon.camelot.RegistryException; | import org.apache.avalon.camelot.RegistryException; | ||||
| @@ -39,7 +38,7 @@ public class RegisterConverter | |||||
| protected TaskletEngine m_engine; | protected TaskletEngine m_engine; | ||||
| public void compose( final ComponentManager componentManager ) | public void compose( final ComponentManager componentManager ) | ||||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||||
| throws ComponentManagerException | |||||
| { | { | ||||
| m_engine = (TaskletEngine)componentManager. | m_engine = (TaskletEngine)componentManager. | ||||
| lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | ||||
| @@ -90,7 +89,7 @@ public class RegisterConverter | |||||
| if( !isFullyDefined && null == url ) | if( !isFullyDefined && null == url ) | ||||
| { | { | ||||
| throw new AntException( "Must supply parameter if not fully specifying converter" ); | throw new AntException( "Must supply parameter if not fully specifying converter" ); | ||||
| } | |||||
| } | |||||
| if( !isFullyDefined ) | if( !isFullyDefined ) | ||||
| { | { | ||||
| @@ -126,7 +125,7 @@ public class RegisterConverter | |||||
| { | { | ||||
| if( null != libName ) | if( null != libName ) | ||||
| { | { | ||||
| final File lib = new File( getContext().resolveFilename( libName ) ); | |||||
| final File lib = getContext().resolveFile( libName ); | |||||
| try { return lib.toURL(); } | try { return lib.toURL(); } | ||||
| catch( final MalformedURLException mue ) | catch( final MalformedURLException mue ) | ||||
| { | { | ||||
| @@ -14,8 +14,7 @@ import org.apache.ant.AntException; | |||||
| import org.apache.ant.tasklet.AbstractTasklet; | import org.apache.ant.tasklet.AbstractTasklet; | ||||
| import org.apache.ant.tasklet.engine.TaskletEngine; | import org.apache.ant.tasklet.engine.TaskletEngine; | ||||
| import org.apache.avalon.ComponentManager; | import org.apache.avalon.ComponentManager; | ||||
| import org.apache.avalon.ComponentNotAccessibleException; | |||||
| import org.apache.avalon.ComponentNotFoundException; | |||||
| import org.apache.avalon.ComponentManagerException; | |||||
| import org.apache.avalon.Composer; | import org.apache.avalon.Composer; | ||||
| import org.apache.avalon.camelot.DeploymentException; | import org.apache.avalon.camelot.DeploymentException; | ||||
| @@ -32,7 +31,7 @@ public class RegisterTasklib | |||||
| protected TaskletEngine m_engine; | protected TaskletEngine m_engine; | ||||
| public void compose( final ComponentManager componentManager ) | public void compose( final ComponentManager componentManager ) | ||||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||||
| throws ComponentManagerException | |||||
| { | { | ||||
| m_engine = (TaskletEngine)componentManager. | m_engine = (TaskletEngine)componentManager. | ||||
| lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | ||||
| @@ -53,7 +52,7 @@ public class RegisterTasklib | |||||
| URL url = null; | URL url = null; | ||||
| final File lib = new File( getContext().resolveFilename( m_lib ) ); | |||||
| final File lib = getContext().resolveFile( m_lib ); | |||||
| try { url = lib.toURL(); } | try { url = lib.toURL(); } | ||||
| catch( final MalformedURLException mue ) | catch( final MalformedURLException mue ) | ||||
| { | { | ||||
| @@ -5,7 +5,7 @@ | |||||
| * version 1.1, a copy of which has been included with this distribution in | * version 1.1, a copy of which has been included with this distribution in | ||||
| * the LICENSE file. | * the LICENSE file. | ||||
| */ | */ | ||||
| package org.apache.ant.datatypes; | |||||
| package org.apache.ant.util; | |||||
| import org.apache.ant.AntException; | import org.apache.ant.AntException; | ||||
| import org.apache.avalon.Component; | import org.apache.avalon.Component; | ||||
| @@ -25,7 +25,7 @@ while [ -h "$PRG" ] ; do | |||||
| fi | fi | ||||
| done | done | ||||
| MYRMIDON_HOME=`dirname "$PRG"`/.. | |||||
| ANT_HOME=`dirname "$PRG"`/.. | |||||
| if [ "$JAVA_HOME" == "" ] ; then | if [ "$JAVA_HOME" == "" ] ; then | ||||
| @@ -42,4 +42,4 @@ else | |||||
| fi | fi | ||||
| fi | fi | ||||
| $JAVACMD $ANT_OPTS -jar ant.jar --ant-home=${MYRMIDON_HOME} $@ | |||||
| $JAVACMD $ANT_OPTS -jar $ANT_HOME/lib/ant.jar $@ | |||||
| @@ -2,6 +2,30 @@ | |||||
| if exist "%HOME%\antrc_pre.bat" call "%HOME%\antrc_pre.bat" | if exist "%HOME%\antrc_pre.bat" call "%HOME%\antrc_pre.bat" | ||||
| if not "%OS%"=="Windows_NT" goto start | |||||
| rem %~dp0 is name of current script under NT | |||||
| set DEFAULT_ANT_HOME=%~dp0 | |||||
| rem : operator works similar to make : operator | |||||
| set DEFAULT_ANT_HOME=%DEFAULT_ANT_HOME:\bin\=% | |||||
| if "%ANT_HOME%"=="" set ANT_HOME=%DEFAULT_ANT_HOME% | |||||
| set DEFAULT_ANT_HOME= | |||||
| :start | |||||
| if not "%ANT_HOME%" == "" goto ant_home_found | |||||
| echo. | |||||
| echo Warning: ANT_HOME environment variable is not set. | |||||
| echo This needs to be set for Win9x as it's command prompt | |||||
| echo scripting bites | |||||
| echo. | |||||
| goto end | |||||
| :ant_home_found | |||||
| if not "%JAVA_HOME%" == "" goto javaCmdSetup | if not "%JAVA_HOME%" == "" goto javaCmdSetup | ||||
| echo. | echo. | ||||
| @@ -10,7 +34,6 @@ echo If build fails because sun.* classes could not be found | |||||
| echo you will need to set the JAVA_HOME environment variable | echo you will need to set the JAVA_HOME environment variable | ||||
| echo to the installation directory of java. | echo to the installation directory of java. | ||||
| echo. | echo. | ||||
| goto end | |||||
| rem hope that there is java command in path | rem hope that there is java command in path | ||||
| if "%JAVACMD%" == "" set JAVACMD=java | if "%JAVACMD%" == "" set JAVACMD=java | ||||
| @@ -22,7 +45,6 @@ if "%JAVACMD%" == "" set JAVACMD=%JAVA_HOME%\bin\java | |||||
| :argSetup | :argSetup | ||||
| set THIS_FILE=%0 | |||||
| set ANT_CMD_LINE_ARGS= | set ANT_CMD_LINE_ARGS= | ||||
| rem Slurp all args... | rem Slurp all args... | ||||
| @@ -35,9 +57,8 @@ goto setupArgs | |||||
| :doneArgs | :doneArgs | ||||
| rem Mmmmmm tasty - finished slurping args | rem Mmmmmm tasty - finished slurping args | ||||
| %JAVACMD% %ANT_OPTS% -jar lib\ant.jar "--bin-dir=%THIS_FILE%" %ANT_CMD_LINE_ARGS% | |||||
| %JAVACMD% %ANT_OPTS% -jar %ANT_HOME%\lib\ant.jar %ANT_CMD_LINE_ARGS% | |||||
| :end | :end | ||||
| if exist "%HOME%\antrc_post.bat" call "%HOME%\antrc_post.bat" | if exist "%HOME%\antrc_post.bat" call "%HOME%\antrc_post.bat" | ||||
| set THIS_FILE= | |||||
| set ANT_CMD_LINE_ARGS= | set ANT_CMD_LINE_ARGS= | ||||
| @@ -0,0 +1,224 @@ | |||||
| <html> | |||||
| <head> | |||||
| <title>Myrmidon: The Ant2.0 Proposal</title> | |||||
| </head> | |||||
| <body BGCOLOR="#ffffff"> | |||||
| <center> | |||||
| <h1>Myrmidon: The Ant2.0 Proposal</h1> | |||||
| <i>by Peter Donald <a href="mailto:donaldp@apache.org"><donaldp@apache.org></a></i> | |||||
| </center> | |||||
| <br /> | |||||
| <div align="center"> | |||||
| <table border="0" width="60%"> | |||||
| <tr> | |||||
| <td width="100%"> | |||||
| <i>Myrmidon is a proposal for <a href="http://jakarta.apache.org/ant">Ant</a> 2.0, a | |||||
| java based build tool. Unlike other proposals it was specifically designed as | |||||
| both a tool a an API library that can be reused in other domains.</i> | |||||
| </td> | |||||
| </tr> | |||||
| </table> | |||||
| </div> | |||||
| <br /> | |||||
| <h3>To do and what not to do</h3> | |||||
| <blockquote> | |||||
| <p> | |||||
| There is a number of issues that this proposal addresses and a number of issues that | |||||
| have been deliberately elided. The focus is currently at the lower levels - namely | |||||
| the task execution engine, the notion of contexts/scopes, loading of tasklets, | |||||
| datatypes and converters etc. While it does implement a Project engine API is still | |||||
| being discussed on ant-dev and this proposal just adopts Ant1.x's model until a better | |||||
| understanding is gained of what is required. | |||||
| </p> | |||||
| <p> | |||||
| Neither this document nor the proposal is intended to be a vision statement. Rather it | |||||
| is a description of how it could be implemented based on commonly accepted needs | |||||
| requested on ant lists and discussed by ant-dev. The vision statement is more | |||||
| strongly associated with the Project API and extentions (CJAN, import project trees, | |||||
| preprocessing via xslt/css/whatever, templating etc). And thus is not addressed here. | |||||
| </p> | |||||
| </blockquote> | |||||
| <h3>The Prime Directive: Execute tasks</h3> | |||||
| <blockquote> | |||||
| <p> | |||||
| One of the primary concerns of ant is providing a task execution environment (TEE). | |||||
| The TEE provides a number of services to tasks. The TEE manages the lifecycle of | |||||
| the tasks. This includes providing the tasks with a logger instance, context | |||||
| information and access to peer components. The lifecycle also involves executing | |||||
| init(), run() and dispose() methods at appropriate times. | |||||
| </p> | |||||
| <p> | |||||
| Instead of reinventing the wheel this proposal instead reuses the Avalon framework | |||||
| that already provides facilities for many of the concepts required. It already has | |||||
| interfaces/classes to model concepts of context, logger, containers etc. | |||||
| </p> | |||||
| <p> | |||||
| One of the requirements identified was the need for dynamic interpretation and | |||||
| instantiation of tasks. To implement this there needs to be an abstraction layer | |||||
| between task object instances and the objects that are manipulated by projects | |||||
| and tools outside tasklet API. This abstraction has the same requirements as | |||||
| Configuration objects in Avalon and thus the task proxies are represented by | |||||
| Avalons Configuration object. | |||||
| </p> | |||||
| </blockquote> | |||||
| <h3>SOC, IOC and the alphabet soup</h3> | |||||
| <blockquote> | |||||
| <p> | |||||
| The design of Myrmidon follows many of the design patterns found in Avalon. The strongest | |||||
| influence cna be seen from the meta-patterns; Separation of Concerns (SOC) and Inversion of | |||||
| Control (IOC). | |||||
| </p> | |||||
| <p> | |||||
| SOC essentially is a design pattern used to separate the system accroding to relevent | |||||
| dimensions. (SOC is often called multi-dimensional SOC). The definition of "relevent" | |||||
| is domain specific and in our case there is a number of dimensions. For instance you | |||||
| will notice that there is a separation between project, tasklet, conversion and datatype | |||||
| functionality. Where in Ant1.x these were only partially separated or tightly coupled | |||||
| there is now decoupling. This separation allows easy reuse of parts in other projects. ie | |||||
| It is now extremely easy to reuse the tasklet api in other tools (such as Installshield | |||||
| type apps or Cron-like deamons etc). | |||||
| </p> | |||||
| <p> | |||||
| Another dimension in which myrmidon is separated is by users. For instance there is | |||||
| a separation between engine code and client code. The client code is the code used by | |||||
| those who implement the components. For instance tasklet developers only have to | |||||
| look at client code for tasklets and never look at implementation of engine. | |||||
| </p> | |||||
| <p> | |||||
| Inversion of Control (IOC) aka the Holywood Principle (Don't call us - we'll call you) is | |||||
| another pattern applied within Myrmidon. In this pattern it is the container that provides | |||||
| facilities and executes lifecycle by calling methods of child components. So instead of the | |||||
| component calling methods to lookup or create peer components or method managing it's | |||||
| own lifecycle the container is responsible for these functions. | |||||
| </p> | |||||
| <p> | |||||
| These approach should be familiar to a servlet or EJB developer as they are also based on | |||||
| SOC and IOC except they do it at a lower resolution. For more detailed explanation of | |||||
| these design approaches have a look at <a | |||||
| href="http://java.apache.org/framework/developer/index.html"> | |||||
| http://java.apache.org/framework/developer/index.html</a>. | |||||
| </p> | |||||
| <p> | |||||
| The result of these design choices is a more flexable and reusable components. | |||||
| </p> | |||||
| </blockquote> | |||||
| <h3>Enough theory - give me Nuts and Bolts</h3> | |||||
| <blockquote> | |||||
| <p> | |||||
| The code is separated into 5 different sections. These are the project, tastlet, | |||||
| converter, datatype and frontend APIs. The project API is concerned with building | |||||
| and representing a project. The tasklet API is concerned with executing tasks in a | |||||
| particular environment. The converter API is concerned with converting instances of one | |||||
| type into another type. The datatype API is used to register, load and instantiate | |||||
| instances of named datatypes. The frontend API involves instantiating and managing | |||||
| all the other components and making it easy to build different frontends (CLI, GUI, | |||||
| Servlet). | |||||
| </p> | |||||
| <p> | |||||
| When Myrmidon is started it interacts with FrontEnd API. It aquires a ProjectBuilder | |||||
| instance from FrontEnd API and uses it to build a project. It then aquires a | |||||
| ProjectEngine instance from FrontEnd again and uses it to execute the created project. | |||||
| This project will first execute the implicit target (which includes all of properties | |||||
| outside target element). And then execute the default or specified target. Each target | |||||
| executes it's dependencies first and then checks it's condition to see if it should | |||||
| execute itself. Each target contains a list of tasks (in the form of Configuraiton | |||||
| objects). These are passed to the tasklet API that instantiates and executes the tasks. | |||||
| The tasklet API instantiates the relevent task and then applies rules to use the | |||||
| Configuration object to configure the task. In some cases this involves resolving | |||||
| properties and converting values to the correct type required by task. The convertion | |||||
| is done by Converter API. Properties are associations between a name and a value, the | |||||
| types of the value aremanaged by the DataType API and accessed via the Property task. | |||||
| </p> | |||||
| <p> | |||||
| Now if you wanted to change a certain component of the system - lets say the ProjectBuilder | |||||
| component. You instead want to use a component that you wrote yourself that builds a project | |||||
| with the result of a xslt + xml -> xml process so that you can use static templating. The | |||||
| way to do this would be to set the property "ant.comp.builder" to | |||||
| "com.biz.ant.MyXSLTProjectBuilder" before handing the properties to the FrontEnd API. The | |||||
| FrontEnd API would then wire together the components appropriately and the same process as | |||||
| documented above would be used. Other components can be replaced in a similar manner. For | |||||
| a full list of properties that can be set see the default FrontEnd implementation. | |||||
| </p> | |||||
| <p> | |||||
| Now instead of replacing a component in the system say you wanted to add an extra task. In | |||||
| this case you would create a task "com.biz.ant.tasks.ProcessFile" that extends | |||||
| "org.apache.ant.tasklet.AbstractTasklet". You would then implement run() method to do the | |||||
| work and and setter methods to accept parameters. The run method can throw AntException if | |||||
| the task fails for any reason. The setter methods are in format of Ant1.x setters with one | |||||
| extention. The extention allows '-' characters to appear in xml names and these will be | |||||
| transferred into capitalisation of next character in java names. ie file-permission | |||||
| attribute --> setFilePermission() method. After implementing this task you would have | |||||
| to define it in taskdef.xml of it's archive or else define it with a taskdef construct. | |||||
| </p> | |||||
| <p> | |||||
| In a similar method new converters and datatypes can be added to the system. For example | |||||
| if you needed to add a TestSet datatype that held a list of test names then this would | |||||
| be possible. You could also add a converter that converted a list of comma separated | |||||
| strings into a TestSet. | |||||
| </p> | |||||
| <p> | |||||
| The one thing that this proposal does not address is validation concerns. You will notice | |||||
| that the above is mainly aimed to reduce the complexity for task developers. Where in 1.x | |||||
| you had to manage convertion manually (depending on version of Ant) and also had to explcitly | |||||
| incorporate support for datatypes manually. The one other concern that was coded into every | |||||
| task was validation. ie Were the correct parameters set ? It would be desirable to be able to | |||||
| associate meta-information with the task that indicated the required parameters. This would | |||||
| reduce the workload on task developers even more and encourage better task structure. This | |||||
| is a future TODO. | |||||
| </p> | |||||
| </blockquote> | |||||
| <h3>A Rose by any other name ...</h3> | |||||
| <blockquote> | |||||
| <p> | |||||
| The name Myrmidon is a derivation of a mythological name for some anst that were turned | |||||
| into soldiers by the god Zeus. It came to mean "a subordinate who executes orders | |||||
| unquestioningly" which seemed suitable for a task execution/build tool. A more complete | |||||
| description stolen from <a href="http://bondi-blue.parlez.com/previous_words/myrmidon.txt"> | |||||
| http://bondi-blue.parlez.com/previous_words/myrmidon.txt</a>. | |||||
| </p> | |||||
| <quote> | |||||
| <i>The appellation Myrmidon was derived from the Greek word "myrmex", | |||||
| meaning ant. According to Greek mythology, the Myrmidons were | |||||
| transformed into humans by the god Zeus as an act of kindness to his | |||||
| son Aeacus. King Aeacus, captivated by a colony of ants, prayed | |||||
| that he should receive an increase in population equal to the | |||||
| number of ants before him. When he awoke the next day, the ants | |||||
| were his human subjects. Thereafter, they were known as the | |||||
| Myrmidons. See "The Iliad" for Homers' account of the Myrmidons | |||||
| during the Trojan War.</i> | |||||
| </quote> | |||||
| </blockquote> | |||||
| </body> | |||||
| </html> | |||||
| @@ -40,7 +40,7 @@ fi | |||||
| LOCALCLASSPATH=`echo $ANT_HOME/lib/*.jar | tr ' ' ':'` | LOCALCLASSPATH=`echo $ANT_HOME/lib/*.jar | tr ' ' ':'` | ||||
| if [ "$CLASSPATH" != "" ] ; then | if [ "$CLASSPATH" != "" ] ; then | ||||
| LOCALCLASSPATH=$CLASSPATH:$LOCALCLASSPATH | |||||
| LOCALCLASSPATH=$LOCALCLASSPATH:$CLASSPATH | |||||
| fi | fi | ||||
| if [ "$JAVA_HOME" != "" ] ; then | if [ "$JAVA_HOME" != "" ] ; then | ||||
| @@ -1,4 +1,4 @@ | |||||
| rem @echo off | |||||
| @echo off | |||||
| rem find ANT_HOME | rem find ANT_HOME | ||||
| if not "%ANT_HOME%"=="" goto checkJava | if not "%ANT_HOME%"=="" goto checkJava | ||||
| @@ -2,7 +2,7 @@ | |||||
| cd %1 | cd %1 | ||||
| set ANT_RUN_CMD=%2 | set ANT_RUN_CMD=%2 | ||||
| shift | |||||
| shift | |||||
| shift | shift | ||||
| %ANT_RUN_CMD% %1 %2 %3 %4 %5 %6 %7 %8 %9 | %ANT_RUN_CMD% %1 %2 %3 %4 %5 %6 %7 %8 %9 | ||||
| @@ -1 +1,2 @@ | |||||
| set LOCALCLASSPATH=%LOCALCLASSPATH%;%1 | set LOCALCLASSPATH=%LOCALCLASSPATH%;%1 | ||||