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 ---------------- | |||
| 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 | |||
| :cleanup | |||
| @@ -154,7 +154,9 @@ Legal: | |||
| destdir="${build.classes}" | |||
| debug="${debug}" | |||
| optimize="${optimize}" | |||
| deprecation="${deprecation}" /> | |||
| deprecation="${deprecation}"> | |||
| <exclude name="org/apache/ant/gui/**"/> | |||
| </javac> | |||
| <!-- | |||
| <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.net.MalformedURLException; | |||
| import java.net.URL; | |||
| import java.net.URLClassLoader; | |||
| import java.util.ArrayList; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| import java.util.Iterator; | |||
| 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.project.DefaultProjectEngine; | |||
| import org.apache.ant.project.LogTargetToListenerAdapter; | |||
| import org.apache.ant.project.Project; | |||
| import org.apache.ant.project.ProjectBuilder; | |||
| import org.apache.ant.project.ProjectEngine; | |||
| import org.apache.ant.project.ProjectListener; | |||
| import org.apache.ant.project.LogTargetToListenerAdapter; | |||
| import org.apache.ant.tasklet.JavaVersion; | |||
| import org.apache.ant.tasklet.TaskletContext; | |||
| import org.apache.ant.tasklet.engine.TaskletEngine; | |||
| import org.apache.ant.tasklet.engine.TskDeployer; | |||
| import org.apache.avalon.Disposable; | |||
| 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.util.ObjectUtil; | |||
| 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.CLOptionDescriptor; | |||
| import org.apache.avalon.util.io.ExtensionFileFilter; | |||
| import org.apache.avalon.util.io.FileUtil; | |||
| import org.apache.log.Category; | |||
| import org.apache.log.LogKit; | |||
| import org.apache.log.Logger; | |||
| @@ -67,21 +67,11 @@ public class Main | |||
| protected final static String DEFAULT_LOGLEVEL = "WARN"; | |||
| //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"; | |||
| //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 = | |||
| "org.apache.ant.project.DefaultProjectListener"; | |||
| protected final static String DEFAULT_BUILDER = | |||
| "org.apache.ant.project.DefaultProjectBuilder"; | |||
| //defines for the Command Line options | |||
| private static final int HELP_OPT = 'h'; | |||
| 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 VERSION_OPT = 1; | |||
| 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 INCREMENTAL_OPT = 6; | |||
| private static final int HOME_DIR_OPT = 7; | |||
| @@ -102,8 +90,7 @@ public class Main | |||
| { | |||
| HELP_OPT, QUIET_OPT, VERBOSE_OPT, FILE_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 | |||
| @@ -112,15 +99,8 @@ public class Main | |||
| QUIET_OPT, VERBOSE_OPT, LOG_LEVEL_OPT | |||
| }; | |||
| protected Logger m_logger; | |||
| protected ProjectListener m_listener; | |||
| protected File m_binDir; | |||
| 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. | |||
| @@ -134,13 +114,13 @@ public class Main | |||
| try { main.execute( args ); } | |||
| 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 ) | |||
| { | |||
| 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() | |||
| { | |||
| //TODO: localise | |||
| final CLOptionDescriptor[] options = new CLOptionDescriptor[ 13 ]; | |||
| final CLOptionDescriptor[] options = new CLOptionDescriptor[ 11 ]; | |||
| options[0] = | |||
| new CLOptionDescriptor( "help", | |||
| @@ -202,33 +182,21 @@ public class Main | |||
| INFO_OPT_INCOMPAT ); | |||
| 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", | |||
| CLOptionDescriptor.ARGUMENT_REQUIRED, | |||
| TASKLIB_DIR_OPT, | |||
| "the task lib directory to scan for .tsk files." ); | |||
| options[10] = | |||
| options[8] = | |||
| new CLOptionDescriptor( "incremental", | |||
| CLOptionDescriptor.ARGUMENT_DISALLOWED, | |||
| INCREMENTAL_OPT, | |||
| "Run in incremental mode" ); | |||
| options[11] = | |||
| options[9] = | |||
| new CLOptionDescriptor( "ant-home", | |||
| CLOptionDescriptor.ARGUMENT_REQUIRED, | |||
| HOME_DIR_OPT, | |||
| "Specify ant home directory" ); | |||
| options[12] = | |||
| options[10] = | |||
| new CLOptionDescriptor( "define", | |||
| CLOptionDescriptor.ARGUMENTS_REQUIRED_2, | |||
| DEFINE_OPT, | |||
| @@ -249,11 +217,8 @@ public class Main | |||
| final ArrayList targets = new ArrayList(); | |||
| String filename = null; | |||
| String listenerName = null; | |||
| String builderName = null; | |||
| String logLevel = null; | |||
| String binDir = null; | |||
| String homeDir = null; | |||
| String libDir = null; | |||
| String taskLibDir = null; | |||
| boolean incremental = false; | |||
| HashMap defines = new HashMap(); | |||
| @@ -268,8 +233,6 @@ public class Main | |||
| case HELP_OPT: usage(); return; | |||
| case VERSION_OPT: System.out.println( VERSION ); return; | |||
| 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 TASKLIB_DIR_OPT: taskLibDir = option.getArgument(); 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 | |||
| //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; | |||
| @@ -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 ) | |||
| { | |||
| 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. | |||
| * | |||
| @@ -479,39 +393,47 @@ public class Main | |||
| * | |||
| * @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 | |||
| */ | |||
| 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 = | |||
| new ExtensionFileFilter( new String[] { ".jar", ".zip" } ); | |||
| final File[] files = libDir.listFiles( filter ); | |||
| final AntLoader classLoader = AntLoader.getLoader(); | |||
| for( int i = 0; i < files.length; i++ ) | |||
| { | |||
| //except for a few *special* files add all the | |||
| @@ -524,28 +446,8 @@ public class Main | |||
| 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 | |||
| //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(); | |||
| addToContext( context, defines ); | |||
| @@ -593,330 +494,5 @@ public class Main | |||
| 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 | |||
| extends org.apache.avalon.DefaultConfigurationBuilder | |||
| { | |||
| public ConfigurationBuilder() | |||
| throws SAXException | |||
| { | |||
| super(); | |||
| } | |||
| protected org.apache.avalon.SAXConfigurationHandler getHandler() | |||
| { | |||
| return new SAXConfigurationHandler(); | |||
| @@ -13,9 +13,9 @@ import java.util.ArrayList; | |||
| import java.util.Iterator; | |||
| import org.apache.ant.convert.Converter; | |||
| import org.apache.ant.convert.ConverterException; | |||
| import org.apache.avalon.AbstractLoggable; | |||
| 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.ConfigurationException; | |||
| import org.apache.avalon.Context; | |||
| @@ -30,6 +30,7 @@ import org.apache.log.Logger; | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public class DefaultConfigurer | |||
| extends AbstractLoggable | |||
| implements Configurer, Composer, Loggable | |||
| { | |||
| protected final static String RESERVED_ATTRIBUTES[] = | |||
| @@ -44,15 +45,9 @@ public class DefaultConfigurer | |||
| protected final static boolean DEBUG = false; | |||
| protected Converter m_converter; | |||
| protected Logger m_logger; | |||
| public void setLogger( final Logger logger ) | |||
| { | |||
| m_logger = logger; | |||
| } | |||
| public void compose( final ComponentManager componentManager ) | |||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||
| throws ComponentManagerException | |||
| { | |||
| m_converter = (Converter)componentManager.lookup( "org.apache.ant.convert.Converter" ); | |||
| } | |||
| @@ -206,7 +201,7 @@ public class DefaultConfigurer | |||
| final Object objectValue = | |||
| PropertyUtil.resolveProperty( value, context, false ); | |||
| setValue( object, objectValue, methods ); | |||
| setValue( object, objectValue, methods, context ); | |||
| } | |||
| 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 | |||
| { | |||
| final Class sourceClass = value.getClass(); | |||
| @@ -223,7 +221,7 @@ public class DefaultConfigurer | |||
| 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; | |||
| } | |||
| @@ -238,7 +236,8 @@ public class DefaultConfigurer | |||
| Object value, | |||
| final Method method, | |||
| final Class sourceClass, | |||
| final String source ) | |||
| final String source, | |||
| final Context context ) | |||
| throws ConfigurationException | |||
| { | |||
| Class parameterType = method.getParameterTypes()[ 0 ]; | |||
| @@ -249,7 +248,7 @@ public class DefaultConfigurer | |||
| try | |||
| { | |||
| value = m_converter.convert( parameterType, value ); | |||
| value = m_converter.convert( parameterType, value, context ); | |||
| } | |||
| catch( final ConverterException ce ) | |||
| { | |||
| @@ -359,7 +358,7 @@ public class DefaultConfigurer | |||
| protected String getMethodNameFor( final String attribute ) | |||
| { | |||
| return "set" + getJavaNameFor( attribute ); | |||
| return "set" + getJavaNameFor( attribute.toLowerCase() ); | |||
| } | |||
| protected String getJavaNameFor( final String name ) | |||
| @@ -7,6 +7,8 @@ | |||
| */ | |||
| package org.apache.ant.convert; | |||
| import org.apache.avalon.Context; | |||
| /** | |||
| * 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 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( final Class destination, final Object original ) | |||
| public Object convert( final Class destination, final Object original, Context context ) | |||
| throws Exception | |||
| { | |||
| if( m_destination != destination ) | |||
| @@ -53,17 +56,18 @@ public abstract class AbstractConverter | |||
| "instance of " + m_source.getName() ); | |||
| } | |||
| return convert( original ); | |||
| return convert( original, context ); | |||
| } | |||
| /** | |||
| * Overide this in a particular converter to do the conversion. | |||
| * | |||
| * @param original the original Object | |||
| * @param context the context in which to convert | |||
| * @return the converted object | |||
| * @exception Exception if an error occurs | |||
| */ | |||
| protected abstract Object convert( Object original ) | |||
| protected abstract Object convert( Object original, Context context ) | |||
| throws Exception; | |||
| } | |||
| @@ -7,6 +7,8 @@ | |||
| */ | |||
| package org.apache.ant.convert; | |||
| import org.apache.avalon.Context; | |||
| /** | |||
| * Instances of this interface are used to convert between different types. | |||
| * | |||
| @@ -21,9 +23,10 @@ public interface Converter | |||
| * | |||
| * @param destination the destinaiton type | |||
| * @param original the original type | |||
| * @param context the context in which to convert | |||
| * @return the converted object | |||
| * @exception Exception if an error occurs | |||
| */ | |||
| Object convert( Class destination, Object original ) | |||
| Object convert( Class destination, Object original, Context context ) | |||
| throws ConverterException, Exception; | |||
| } | |||
| @@ -8,13 +8,27 @@ | |||
| package org.apache.ant.convert; | |||
| import org.apache.avalon.Component; | |||
| import org.apache.avalon.Loggable; | |||
| 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 | |||
| extends Component, Converter, Loggable | |||
| extends Component, Converter | |||
| { | |||
| /** | |||
| * Get registry used to locate converters. | |||
| * | |||
| * @return the LocatorRegistry | |||
| */ | |||
| LocatorRegistry getRegistry(); | |||
| /** | |||
| * Get registry for converterInfo objects. | |||
| * | |||
| * @return the ConverterRegistry | |||
| */ | |||
| ConverterRegistry getInfoRegistry(); | |||
| } | |||
| @@ -8,62 +8,74 @@ | |||
| package org.apache.ant.convert; | |||
| 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.DefaultLocatorRegistry; | |||
| import org.apache.avalon.camelot.Factory; | |||
| import org.apache.avalon.camelot.Locator; | |||
| 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 | |||
| implements ConverterEngine, Initializable | |||
| extends AbstractLoggable | |||
| implements ConverterEngine, Composer | |||
| { | |||
| 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() | |||
| { | |||
| return m_registry; | |||
| } | |||
| /** | |||
| * Get registry for converterInfo objects. | |||
| * | |||
| * @return the ConverterRegistry | |||
| */ | |||
| public ConverterRegistry getInfoRegistry() | |||
| { | |||
| 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 | |||
| { | |||
| final Class originalClass = original.getClass(); | |||
| @@ -79,6 +91,7 @@ public class DefaultConverterEngine | |||
| " to " + destination.getName() ); | |||
| } | |||
| //TODO: Start searching inheritance hierarchy for converter | |||
| final String name = | |||
| m_infoRegistry.getConverterInfoName( originalClass.getName(), | |||
| destination.getName() ); | |||
| @@ -90,8 +103,9 @@ public class DefaultConverterEngine | |||
| destination.getName() + " conversion" ); | |||
| } | |||
| //TODO: Start caching converters instead of repeatedly instantiating em. | |||
| final Locator locator = m_registry.getLocator( name ); | |||
| 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; | |||
| 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.RegistryException; | |||
| @@ -18,11 +18,16 @@ import org.apache.avalon.camelot.RegistryException; | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public class DefaultConverterRegistry | |||
| extends AbstractRegistry | |||
| extends DefaultRegistry | |||
| implements ConverterRegistry | |||
| { | |||
| protected final HashMap m_mapping = new HashMap(); | |||
| public DefaultConverterRegistry() | |||
| { | |||
| super( ConverterInfo.class ); | |||
| } | |||
| /** | |||
| * Retrieve ConverterInfo that describes converter that converts from source to destination. | |||
| * | |||
| @@ -37,6 +42,13 @@ public class DefaultConverterRegistry | |||
| 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 ) | |||
| throws RegistryException | |||
| { | |||
| @@ -55,9 +67,4 @@ public class DefaultConverterRegistry | |||
| map.put( destination, name ); | |||
| } | |||
| protected Class getInfoClass() | |||
| { | |||
| return ConverterInfo.class; | |||
| } | |||
| } | |||
| @@ -8,6 +8,7 @@ | |||
| package org.apache.ant.convert.core; | |||
| import org.apache.ant.convert.AbstractConverter; | |||
| import org.apache.avalon.Context; | |||
| /** | |||
| * String to byte converter | |||
| @@ -22,7 +23,7 @@ public class StringToByteConverter | |||
| super( String.class, Byte.class ); | |||
| } | |||
| public Object convert( final Object original ) | |||
| public Object convert( final Object original, final Context context ) | |||
| throws Exception | |||
| { | |||
| return new Byte( (String)original ); | |||
| @@ -8,6 +8,7 @@ | |||
| package org.apache.ant.convert.core; | |||
| import org.apache.ant.convert.AbstractConverter; | |||
| import org.apache.avalon.Context; | |||
| /** | |||
| * String to class converter | |||
| @@ -22,7 +23,7 @@ public class StringToClassConverter | |||
| super( String.class, Class.class ); | |||
| } | |||
| public Object convert( final Object original ) | |||
| public Object convert( final Object original, final Context context ) | |||
| throws Exception | |||
| { | |||
| return Class.forName( (String)original ); | |||
| @@ -8,6 +8,7 @@ | |||
| package org.apache.ant.convert.core; | |||
| import org.apache.ant.convert.AbstractConverter; | |||
| import org.apache.avalon.Context; | |||
| /** | |||
| * String to double converter | |||
| @@ -22,7 +23,7 @@ public class StringToDoubleConverter | |||
| super( String.class, Double.class ); | |||
| } | |||
| public Object convert( final Object original ) | |||
| public Object convert( final Object original, final Context context ) | |||
| throws Exception | |||
| { | |||
| 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; | |||
| import org.apache.ant.convert.AbstractConverter; | |||
| import org.apache.avalon.Context; | |||
| /** | |||
| * String to float converter | |||
| @@ -22,7 +23,7 @@ public class StringToFloatConverter | |||
| super( String.class, Float.class ); | |||
| } | |||
| public Object convert( final Object original ) | |||
| public Object convert( final Object original, final Context context ) | |||
| throws Exception | |||
| { | |||
| return new Float( (String)original ); | |||
| @@ -8,6 +8,7 @@ | |||
| package org.apache.ant.convert.core; | |||
| import org.apache.ant.convert.AbstractConverter; | |||
| import org.apache.avalon.Context; | |||
| /** | |||
| * String to integer converter. | |||
| @@ -22,7 +23,7 @@ public class StringToIntegerConverter | |||
| super( String.class, Integer.class ); | |||
| } | |||
| public Object convert( final Object original ) | |||
| public Object convert( final Object original, final Context context ) | |||
| throws Exception | |||
| { | |||
| return new Integer( (String)original ); | |||
| @@ -8,6 +8,7 @@ | |||
| package org.apache.ant.convert.core; | |||
| import org.apache.ant.convert.AbstractConverter; | |||
| import org.apache.avalon.Context; | |||
| /** | |||
| * String to long converter | |||
| @@ -22,7 +23,7 @@ public class StringToLongConverter | |||
| super( String.class, Long.class ); | |||
| } | |||
| public Object convert( final Object original ) | |||
| public Object convert( final Object original, final Context context ) | |||
| throws Exception | |||
| { | |||
| return new Long( (String)original ); | |||
| @@ -8,6 +8,7 @@ | |||
| package org.apache.ant.convert.core; | |||
| import org.apache.ant.convert.AbstractConverter; | |||
| import org.apache.avalon.Context; | |||
| /** | |||
| * String to short converter | |||
| @@ -22,7 +23,7 @@ public class StringToShortConverter | |||
| super( String.class, Short.class ); | |||
| } | |||
| public Object convert( final Object original ) | |||
| public Object convert( final Object original, final Context context ) | |||
| throws Exception | |||
| { | |||
| return new Short( (String)original ); | |||
| @@ -9,6 +9,7 @@ package org.apache.ant.convert.core; | |||
| import java.net.URL; | |||
| import org.apache.ant.convert.AbstractConverter; | |||
| import org.apache.avalon.Context; | |||
| /** | |||
| * String to url converter | |||
| @@ -23,7 +24,7 @@ public class StringToURLConverter | |||
| super( String.class, URL.class ); | |||
| } | |||
| public Object convert( final Object original ) | |||
| public Object convert( final Object original, final Context context ) | |||
| throws Exception | |||
| { | |||
| 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.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 | |||
| 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(); | |||
| /** | |||
| * 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 ) | |||
| throws RegistryException, FactoryException; | |||
| } | |||
| @@ -7,65 +7,62 @@ | |||
| */ | |||
| 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.Factory; | |||
| import org.apache.avalon.camelot.FactoryException; | |||
| import org.apache.avalon.camelot.Locator; | |||
| import org.apache.avalon.camelot.LocatorRegistry; | |||
| 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 | |||
| 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() | |||
| { | |||
| 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 ) | |||
| throws RegistryException, FactoryException | |||
| throws RegistryException, FactoryException | |||
| { | |||
| final Locator locator = m_registry.getLocator( name ); | |||
| return (DataType)m_factory.create( locator, DataType.class ); | |||
| @@ -8,6 +8,7 @@ | |||
| package org.apache.ant.datatypes; | |||
| import org.apache.ant.AntException; | |||
| import org.apache.ant.util.Condition; | |||
| /** | |||
| * Basic data type for holding patterns. | |||
| @@ -20,21 +21,43 @@ public class Pattern | |||
| protected String m_name; | |||
| protected Condition m_condition; | |||
| /** | |||
| * Retrieve name (aka value) of pattern. | |||
| * | |||
| * @return the name/value of pattern | |||
| */ | |||
| public String getName() | |||
| { | |||
| return m_name; | |||
| } | |||
| /** | |||
| * Get condition associated with pattern if any. | |||
| * | |||
| * @return the Condition | |||
| */ | |||
| public Condition getCondition() | |||
| { | |||
| 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 ) | |||
| { | |||
| m_name = name; | |||
| } | |||
| /** | |||
| * Set if clause on pattern. | |||
| * | |||
| * @param condition the condition | |||
| * @exception AntException if an error occurs | |||
| */ | |||
| public void setIf( final String condition ) | |||
| throws AntException | |||
| { | |||
| @@ -42,6 +65,12 @@ public class Pattern | |||
| 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 ) | |||
| throws AntException | |||
| { | |||
| @@ -49,6 +78,12 @@ public class Pattern | |||
| 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() | |||
| 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; | |||
| import java.io.File; | |||
| import java.lang.reflect.Method; | |||
| import java.lang.reflect.InvocationTargetException; | |||
| import java.net.URL; | |||
| import java.net.URLClassLoader; | |||
| import java.util.StringTokenizer; | |||
| /** | |||
| * 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. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| * @author <a href="mailto:mpfoemme@thoughtworks.com">Matthew Foemmel</a> | |||
| */ | |||
| 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. | |||
| * | |||
| @@ -40,42 +31,67 @@ public final class AntLoader | |||
| */ | |||
| public final static void main( final String[] args ) | |||
| throws Exception | |||
| { | |||
| final URL archive = new URL( "file:lib/myrmidon.jar" ); | |||
| c_classLoader = new AntLoader( new URL[] { archive } ); | |||
| { | |||
| 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. | |||
| 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() } ); | |||
| //kick the tires and light the fires.... | |||
| method.invoke( null, new Object[] { args } ); | |||
| } | |||
| catch( final InvocationTargetException ite ) | |||
| { | |||
| System.err.println( "Error: " + ite.getTargetException().getMessage() ); | |||
| ite.getTargetException().printStackTrace(); | |||
| } | |||
| catch( final Throwable throwable ) | |||
| { | |||
| System.err.println( "Error: " + throwable.getMessage() ); | |||
| 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.TaskletContext; | |||
| /** | |||
| * Default project implementation. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public class DefaultProject | |||
| implements Project | |||
| { | |||
| @@ -23,42 +28,87 @@ public class DefaultProject | |||
| protected final HashMap m_targets = new HashMap(); | |||
| protected Target m_implicitTarget; | |||
| 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() | |||
| { | |||
| return m_implicitTarget; | |||
| } | |||
| /** | |||
| * Set ImplicitTarget. | |||
| * | |||
| * @param target the implicit target | |||
| */ | |||
| public void setImplicitTarget( final Target 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 ) | |||
| { | |||
| return (Target)m_targets.get( targetName ); | |||
| } | |||
| /** | |||
| * Get name of default target. | |||
| * | |||
| * @return the default target name | |||
| */ | |||
| public String getDefaultTargetName() | |||
| { | |||
| return m_defaultTarget; | |||
| } | |||
| /** | |||
| * Retrieve names of all targets in project. | |||
| * | |||
| * @return the iterator of project names | |||
| */ | |||
| public Iterator getTargetNames() | |||
| { | |||
| return m_targets.keySet().iterator(); | |||
| } | |||
| /** | |||
| * Get project (top-level) context. | |||
| * | |||
| * @return the context | |||
| */ | |||
| public TaskletContext getContext() | |||
| { | |||
| return m_baseContext; | |||
| } | |||
| /** | |||
| * Set DefaultTargetName. | |||
| * | |||
| * @param defaultTarget the default target name | |||
| */ | |||
| public void setDefaultTargetName( final String 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 ) | |||
| throws AntException | |||
| { | |||
| @@ -13,54 +13,87 @@ import java.util.Iterator; | |||
| import org.apache.ant.AntException; | |||
| import org.apache.ant.configuration.Configuration; | |||
| 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.avalon.AbstractLoggable; | |||
| import org.apache.avalon.ConfigurationException; | |||
| import org.apache.avalon.util.StringUtil; | |||
| import org.apache.log.Logger; | |||
| import org.xml.sax.InputSource; | |||
| 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 | |||
| extends AbstractLoggable | |||
| implements ProjectBuilder | |||
| { | |||
| protected final ConfigurationBuilder m_configurationBuilder; | |||
| protected Logger m_logger; | |||
| protected ConfigurationBuilder m_builder; | |||
| 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 ) | |||
| throws IOException, AntException | |||
| { | |||
| 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 ); | |||
| } | |||
| catch( final SAXException se ) | |||
| { | |||
| throw new AntException( "SAXEception: " + se.getMessage(), se ); | |||
| } | |||
| catch( final ConfigurationException 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 ) | |||
| throws IOException, AntException, ConfigurationException | |||
| { | |||
| @@ -68,29 +101,41 @@ public class DefaultProjectBuilder | |||
| { | |||
| throw new AntException( "Project file must be enclosed in project element" ); | |||
| } | |||
| //get project-level attributes | |||
| final String baseDirectoryName = configuration.getAttribute( "basedir" ); | |||
| final String defaultTarget = configuration.getAttribute( "default" ); | |||
| final String projectName = configuration.getAttribute( "name" ); | |||
| final DefaultProject project = new DefaultProject(); | |||
| project.setDefaultTargetName( defaultTarget ); | |||
| //determine base directory for project | |||
| final File baseDirectory = | |||
| (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(); | |||
| context.setProperty( TaskletContext.BASE_DIRECTORY, baseDirectory ); | |||
| context.setProperty( Project.PROJECT_FILE, file ); | |||
| context.setProperty( Project.PROJECT, projectName ); | |||
| //build using all top-level attributes | |||
| buildTopLevelProject( project, configuration ); | |||
| 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, | |||
| final Configuration configuration ) | |||
| throws AntException | |||
| @@ -102,8 +147,9 @@ public class DefaultProjectBuilder | |||
| final Configuration element = (Configuration)elements.next(); | |||
| final String name = element.getName(); | |||
| //handle individual elements | |||
| if( name.equals( "target" ) ) buildTarget( project, element ); | |||
| else if( name.equals( "property" ) ) buildProperty( project, element ); | |||
| else if( name.equals( "property" ) ) buildImplicitTask( project, element ); | |||
| else | |||
| { | |||
| 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 ) | |||
| { | |||
| 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 ) | |||
| { | |||
| 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; | |||
| if( null != ifCondition ) | |||
| { | |||
| m_logger.debug( "Target if condition: " + ifCondition ); | |||
| getLogger().debug( "Target if condition: " + ifCondition ); | |||
| condition = new Condition( true, ifCondition ); | |||
| } | |||
| else if( null != unlessCondition ) | |||
| { | |||
| m_logger.debug( "Target unless condition: " + unlessCondition ); | |||
| getLogger().debug( "Target unless condition: " + unlessCondition ); | |||
| condition = new Condition( false, unlessCondition ); | |||
| } | |||
| final DefaultTarget target = new DefaultTarget( condition ); | |||
| final DefaultTarget defaultTarget = new DefaultTarget( condition ); | |||
| //apply depends attribute | |||
| 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() ) | |||
| { | |||
| 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(); | |||
| @@ -210,7 +249,7 @@ public class DefaultProjectBuilder | |||
| 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 org.apache.ant.AntException; | |||
| import org.apache.ant.configuration.Configuration; | |||
| import org.apache.ant.datatypes.Condition; | |||
| import org.apache.ant.tasklet.DefaultTaskletContext; | |||
| import org.apache.ant.tasklet.TaskletContext; | |||
| import org.apache.ant.tasklet.engine.DefaultTaskletEngine; | |||
| 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.ComponentManager; | |||
| import org.apache.avalon.DefaultComponentManager; | |||
| import org.apache.avalon.ComponentManagerException; | |||
| import org.apache.avalon.DefaultComponentManager; | |||
| import org.apache.avalon.Disposable; | |||
| import org.apache.avalon.Initializable; | |||
| 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 | |||
| implements ProjectEngine, Initializable, Disposable | |||
| extends AbstractLoggable | |||
| implements ProjectEngine, Composer | |||
| { | |||
| protected TaskletEngine m_taskletEngine; | |||
| protected Logger m_logger; | |||
| protected ProjectListenerSupport m_listenerSupport; | |||
| protected ProjectListenerSupport m_listenerSupport = new ProjectListenerSupport(); | |||
| 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 ) | |||
| { | |||
| m_listenerSupport.addProjectListener( listener ); | |||
| } | |||
| /** | |||
| * Remove a listener from project events. | |||
| * | |||
| * @param listener the listener | |||
| */ | |||
| public void removeProjectListener( final ProjectListener 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 ) | |||
| throws AntException | |||
| { | |||
| //HACK: should do this a better way !!!!!! | |||
| m_componentManager.put( "org.apache.ant.project.Project", project ); | |||
| final TaskletContext context = project.getContext(); | |||
| @@ -110,12 +102,29 @@ public class DefaultProjectEngine | |||
| 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 ) | |||
| throws AntException | |||
| { | |||
| 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, | |||
| final String targetName, | |||
| final TaskletContext context, | |||
| @@ -128,9 +137,11 @@ public class DefaultProjectEngine | |||
| { | |||
| throw new AntException( "Unable to find target " + targetName ); | |||
| } | |||
| //add target to list of targets executed | |||
| done.add( targetName ); | |||
| //execute all dependencies | |||
| final Iterator dependencies = target.getDependencies(); | |||
| while( dependencies.hasNext() ) | |||
| { | |||
| @@ -144,41 +155,65 @@ public class DefaultProjectEngine | |||
| 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, | |||
| final Target target, | |||
| final TaskletContext context ) | |||
| 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 ); | |||
| targetContext.setProperty( Project.TARGET, targetName ); | |||
| //notify listeners | |||
| m_listenerSupport.targetStarted( targetName ); | |||
| //actually do the execution work | |||
| executeTargetWork( targetName, target, targetContext ); | |||
| //notify listeners | |||
| 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, | |||
| final Target target, | |||
| final TaskletContext context ) | |||
| { | |||
| //check the condition associated with target. | |||
| //if it is not satisfied then skip target | |||
| final Condition condition = target.getCondition(); | |||
| if( null != condition ) | |||
| { | |||
| 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; | |||
| } | |||
| } | |||
| m_logger.debug( "Executing target " + name ); | |||
| getLogger().debug( "Executing target " + name ); | |||
| //execute all tasks assciated with target | |||
| final Iterator tasks = target.getTasks(); | |||
| 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 | |||
| { | |||
| 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... | |||
| //is Only necessary if we are multi-threaded | |||
| //final TaskletContext targetContext = new DefaultTaskletContext( context ); | |||
| //is setting name even necessary ??? | |||
| context.setProperty( TaskletContext.NAME, name ); | |||
| //notify listeners | |||
| m_listenerSupport.taskletStarted( name ); | |||
| //run task | |||
| m_taskletEngine.execute( configuration, context, m_componentManager ); | |||
| m_taskletEngine.execute( task, context ); | |||
| //notify listeners task has ended | |||
| m_listenerSupport.taskletFinished(); | |||
| @@ -9,49 +9,95 @@ package org.apache.ant.project; | |||
| 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 | |||
| implements ProjectListener | |||
| { | |||
| protected String m_prefix; | |||
| /** | |||
| * Notify listener of projectStarted event. | |||
| * | |||
| * @param projectName the projectName | |||
| */ | |||
| public void projectStarted( final String projectName ) | |||
| { | |||
| output( "Starting project " + projectName + "\n" ); | |||
| } | |||
| /** | |||
| * Notify listener of projectFinished event. | |||
| */ | |||
| public void projectFinished() | |||
| { | |||
| } | |||
| /** | |||
| * Notify listener of targetStarted event. | |||
| * | |||
| * @param targetName the name of target | |||
| */ | |||
| public void targetStarted( final String targetName ) | |||
| { | |||
| output( targetName + ":\n" ); | |||
| } | |||
| /** | |||
| * Notify listener of targetFinished event. | |||
| */ | |||
| public void targetFinished() | |||
| { | |||
| } | |||
| /** | |||
| * Notify listener of taskletStarted event. | |||
| * | |||
| * @param taskletName the name of tasklet | |||
| */ | |||
| public void taskletStarted( final String taskletName ) | |||
| { | |||
| m_prefix = taskletName; | |||
| } | |||
| /** | |||
| * Notify listener of taskletFinished event. | |||
| */ | |||
| public void taskletFinished() | |||
| { | |||
| m_prefix = null; | |||
| } | |||
| /** | |||
| * Notify listener of log message event. | |||
| * | |||
| * @param message the message | |||
| */ | |||
| public void log( String message ) | |||
| { | |||
| output( message ); | |||
| } | |||
| /** | |||
| * Notify listener of log message event. | |||
| * | |||
| * @param message the message | |||
| * @param throwable the throwable | |||
| */ | |||
| public void log( String message, Throwable throwable ) | |||
| { | |||
| 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 ) | |||
| { | |||
| 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.Iterator; | |||
| 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 | |||
| implements Target | |||
| { | |||
| @@ -19,36 +24,68 @@ public class DefaultTarget | |||
| protected final ArrayList m_tasks = new ArrayList(); | |||
| protected final Condition m_condition; | |||
| /** | |||
| * Constructor taking condition for target. | |||
| * | |||
| * @param condition the condition | |||
| */ | |||
| public DefaultTarget( final Condition condition ) | |||
| { | |||
| m_condition = condition; | |||
| } | |||
| /** | |||
| * Constructor for target with no condition. | |||
| */ | |||
| public DefaultTarget() | |||
| { | |||
| this( null ); | |||
| } | |||
| /** | |||
| * Get condition under which target is executed. | |||
| * | |||
| * @return the condition for target or null | |||
| */ | |||
| public Condition getCondition() | |||
| { | |||
| return m_condition; | |||
| } | |||
| /** | |||
| * Get dependencies of target | |||
| * | |||
| * @return the dependency list | |||
| */ | |||
| public Iterator getDependencies() | |||
| { | |||
| return m_dependencies.iterator(); | |||
| } | |||
| /** | |||
| * Get tasks in target | |||
| * | |||
| * @return the target list | |||
| */ | |||
| public Iterator getTasks() | |||
| { | |||
| return m_tasks.iterator(); | |||
| } | |||
| /** | |||
| * Add a dependency to target. | |||
| * | |||
| * @param dependency the dependency | |||
| */ | |||
| public void addDependency( final String dependency ) | |||
| { | |||
| m_dependencies.add( dependency ); | |||
| } | |||
| /** | |||
| * Add task to target. | |||
| * | |||
| * @param taskConfiguration the task representation | |||
| */ | |||
| public void addTask( final Configuration taskConfiguration ) | |||
| { | |||
| m_tasks.add( taskConfiguration ); | |||
| @@ -10,12 +10,21 @@ package org.apache.ant.project; | |||
| import org.apache.log.LogEntry; | |||
| 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 | |||
| implements LogTarget | |||
| { | |||
| protected final ProjectListener m_listener; | |||
| /** | |||
| * Constructor taking listener to convert to. | |||
| * | |||
| * @param listener the ProjectListener | |||
| */ | |||
| public LogTargetToListenerAdapter( final ProjectListener listener ) | |||
| { | |||
| m_listener = listener; | |||
| @@ -12,6 +12,11 @@ import org.apache.ant.AntException; | |||
| import org.apache.ant.tasklet.TaskletContext; | |||
| 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 | |||
| extends Component | |||
| { | |||
| @@ -24,9 +29,41 @@ public interface Project | |||
| // the name of currently executing target | |||
| String TARGET = "ant.target.name"; | |||
| /** | |||
| * Get name of default target. | |||
| * | |||
| * @return the default target name | |||
| */ | |||
| String getDefaultTargetName(); | |||
| /** | |||
| * Retrieve implicit target. | |||
| * The implicit target is top level tasks. | |||
| * Currently restricted to property tasks. | |||
| * | |||
| * @return the Target | |||
| */ | |||
| 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 ); | |||
| /** | |||
| * Retrieve names of all targets in project. | |||
| * | |||
| * @return the iterator of project names | |||
| */ | |||
| Iterator getTargetNames(); | |||
| /** | |||
| * Get project (top-level) context. | |||
| * | |||
| * @return the context | |||
| */ | |||
| TaskletContext getContext(); | |||
| } | |||
| @@ -10,13 +10,25 @@ package org.apache.ant.project; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| 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 | |||
| 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; | |||
| } | |||
| @@ -11,21 +11,50 @@ import org.apache.ant.AntException; | |||
| import org.apache.ant.tasklet.TaskletContext; | |||
| import org.apache.ant.tasklet.engine.TaskletEngine; | |||
| 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 | |||
| extends Component | |||
| { | |||
| void setLogger( Logger logger ); | |||
| TaskletEngine getTaskletEngine(); | |||
| /** | |||
| * Add a listener to project events. | |||
| * | |||
| * @param listener the listener | |||
| */ | |||
| void addProjectListener( ProjectListener listener ); | |||
| /** | |||
| * Remove a listener from project events. | |||
| * | |||
| * @param listener the 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 ) | |||
| 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 ) | |||
| throws AntException; | |||
| } | |||
| @@ -7,17 +7,62 @@ | |||
| */ | |||
| 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 | |||
| { | |||
| /** | |||
| * Notify listener of projectStarted event. | |||
| * | |||
| * @param projectName the projectName | |||
| */ | |||
| void projectStarted( String projectName ); | |||
| /** | |||
| * Notify listener of projectFinished event. | |||
| */ | |||
| void projectFinished(); | |||
| /** | |||
| * Notify listener of targetStarted event. | |||
| * | |||
| * @param targetName the name of target | |||
| */ | |||
| void targetStarted( String targetName ); | |||
| /** | |||
| * Notify listener of targetFinished event. | |||
| */ | |||
| void targetFinished(); | |||
| /** | |||
| * Notify listener of taskletStarted event. | |||
| * | |||
| * @param taskletName the name of tasklet | |||
| */ | |||
| void taskletStarted( String taskletName ); | |||
| /** | |||
| * Notify listener of taskletFinished event. | |||
| */ | |||
| void taskletFinished(); | |||
| /** | |||
| * Notify listener of log message event. | |||
| * | |||
| * @param message the 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 ); | |||
| } | |||
| @@ -7,11 +7,21 @@ | |||
| */ | |||
| 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 | |||
| implements ProjectListener | |||
| { | |||
| 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 ) | |||
| { | |||
| final ProjectListener[] listeners = new ProjectListener[ m_listeners.length + 1 ]; | |||
| @@ -20,6 +30,11 @@ public class ProjectListenerSupport | |||
| 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 ) | |||
| { | |||
| int found = -1; | |||
| @@ -44,6 +59,11 @@ public class ProjectListenerSupport | |||
| m_listeners = listeners; | |||
| } | |||
| /** | |||
| * Fire a projectStarted event. | |||
| * | |||
| * @param projectName the projectName | |||
| */ | |||
| public void projectStarted( final String projectName ) | |||
| { | |||
| for( int i = 0; i < m_listeners.length; i++ ) | |||
| @@ -52,6 +72,9 @@ public class ProjectListenerSupport | |||
| } | |||
| } | |||
| /** | |||
| * Fire a projectFinished event. | |||
| */ | |||
| public void projectFinished() | |||
| { | |||
| 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 ) | |||
| { | |||
| for( int i = 0; i < m_listeners.length; i++ ) | |||
| @@ -68,6 +96,9 @@ public class ProjectListenerSupport | |||
| } | |||
| } | |||
| /** | |||
| * Fire a targetFinished event. | |||
| */ | |||
| public void targetFinished() | |||
| { | |||
| 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 ) | |||
| { | |||
| for( int i = 0; i < m_listeners.length; i++ ) | |||
| @@ -84,6 +120,9 @@ public class ProjectListenerSupport | |||
| } | |||
| } | |||
| /** | |||
| * Fire a taskletFinished event. | |||
| */ | |||
| public void taskletFinished() | |||
| { | |||
| 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 ) | |||
| { | |||
| 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 ) | |||
| { | |||
| for( int i = 0; i < m_listeners.length; i++ ) | |||
| @@ -8,14 +8,36 @@ | |||
| package org.apache.ant.project; | |||
| import java.util.Iterator; | |||
| import org.apache.ant.util.Condition; | |||
| 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 | |||
| extends Component | |||
| { | |||
| /** | |||
| * Get dependencies of target | |||
| * | |||
| * @return the dependency list | |||
| */ | |||
| Iterator getDependencies(); | |||
| /** | |||
| * Get tasks in target | |||
| * | |||
| * @return the target list | |||
| */ | |||
| Iterator getTasks(); | |||
| /** | |||
| * Get condition under which target is executed. | |||
| * | |||
| * @return the condition for target or null | |||
| */ | |||
| Condition getCondition(); | |||
| } | |||
| @@ -8,9 +8,9 @@ | |||
| package org.apache.ant.tasklet; | |||
| import org.apache.ant.AntException; | |||
| import org.apache.avalon.AbstractLoggable; | |||
| import org.apache.avalon.Context; | |||
| import org.apache.avalon.Initializable; | |||
| import org.apache.log.Logger; | |||
| /** | |||
| * 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> | |||
| */ | |||
| public abstract class AbstractTasklet | |||
| extends AbstractLoggable | |||
| implements Tasklet, Initializable | |||
| { | |||
| //the user should set this in constructors of sub-classes | |||
| protected JavaVersion m_requiredJavaVersion; | |||
| 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. | |||
| @@ -79,14 +69,4 @@ public abstract class AbstractTasklet | |||
| { | |||
| 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 | |||
| * @return the resolved filename | |||
| */ | |||
| public String resolveFilename( final String filename ) | |||
| public File resolveFile( final String filename ) | |||
| { | |||
| final File result = FileUtil.resolveFile( m_baseDirectory, filename ); | |||
| if( null != result ) return result.toString(); | |||
| if( null != result ) return result; | |||
| else return null; | |||
| } | |||
| @@ -106,7 +106,7 @@ public class DefaultTaskletContext | |||
| try { return PropertyUtil.resolveProperty( property, this, false ); } | |||
| 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 ); | |||
| } | |||
| } | |||
| @@ -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 ) | |||
| { | |||
| if( key.equals( BASE_DIRECTORY ) ) | |||
| @@ -24,6 +24,6 @@ import org.apache.avalon.Loggable; | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| 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) | |||
| * | |||
| * @param filename the filename to resolve | |||
| * @return the resolved filename | |||
| * @return the resolved file | |||
| */ | |||
| String resolveFilename( String filename ); | |||
| File resolveFile( String filename ); | |||
| /** | |||
| * Resolve property. | |||
| @@ -17,8 +17,11 @@ import org.apache.ant.convert.ConverterEngine; | |||
| import org.apache.ant.datatypes.DataTypeEngine; | |||
| import org.apache.ant.tasklet.Tasklet; | |||
| import org.apache.ant.tasklet.TaskletContext; | |||
| import org.apache.avalon.AbstractLoggable; | |||
| import org.apache.avalon.Component; | |||
| import org.apache.avalon.ComponentManager; | |||
| import org.apache.avalon.DefaultComponentManager; | |||
| import org.apache.avalon.ComponentManagerException; | |||
| import org.apache.avalon.Composer; | |||
| import org.apache.avalon.Context; | |||
| import org.apache.avalon.Contextualizable; | |||
| @@ -28,6 +31,7 @@ import org.apache.avalon.Initializable; | |||
| import org.apache.avalon.Loggable; | |||
| import org.apache.avalon.camelot.DefaultFactory; | |||
| 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.LocatorRegistry; | |||
| @@ -35,20 +39,17 @@ import org.apache.avalon.camelot.RegistryException; | |||
| import org.apache.log.Logger; | |||
| public class DefaultTaskletEngine | |||
| implements TaskletEngine, Initializable | |||
| extends AbstractLoggable | |||
| implements TaskletEngine, Composer | |||
| { | |||
| 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 Logger m_logger; | |||
| protected DataTypeEngine m_dataTypeEngine; | |||
| protected ConverterEngine m_converterEngine; | |||
| public void setLogger( final Logger logger ) | |||
| { | |||
| m_logger = logger; | |||
| } | |||
| protected ComponentManager m_componentManager; | |||
| public TskDeployer getTskDeployer() | |||
| { | |||
| @@ -74,120 +75,74 @@ public class DefaultTaskletEngine | |||
| { | |||
| 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, | |||
| final TaskletContext context, | |||
| final ComponentManager componentManager ) | |||
| final TaskletContext context ) | |||
| throws AntException | |||
| { | |||
| m_logger.debug( "Creating" ); | |||
| getLogger().debug( "Creating" ); | |||
| final Tasklet tasklet = createTasklet( task.getName() ); | |||
| tasklet.setLogger( m_logger ); | |||
| setupLogger( tasklet ); | |||
| m_logger.debug( "Contextualizing" ); | |||
| getLogger().debug( "Contextualizing" ); | |||
| 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 ); | |||
| m_logger.debug( "Initializing" ); | |||
| getLogger().debug( "Initializing" ); | |||
| doInitialize( tasklet, task ); | |||
| m_logger.debug( "Running" ); | |||
| getLogger().debug( "Running" ); | |||
| tasklet.run(); | |||
| m_logger.debug( "Disposing" ); | |||
| getLogger().debug( "Disposing" ); | |||
| 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, | |||
| 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 | |||
| { | |||
| final DefaultComponentManager subComponentManager = | |||
| new DefaultComponentManager( componentManager ); | |||
| subComponentManager.put( "org.apache.ant.configuration.Configurer", m_configurer ); | |||
| if( tasklet instanceof Composer ) | |||
| { | |||
| try { ((Composer)tasklet).compose( subComponentManager ); } | |||
| try { ((Composer)tasklet).compose( m_componentManager ); } | |||
| catch( final Throwable throwable ) | |||
| { | |||
| throw new AntException( "Error composing task " + task.getName() + " at " + | |||
| @@ -231,9 +178,6 @@ public class DefaultTaskletEngine | |||
| final TaskletContext context ) | |||
| throws AntException | |||
| { | |||
| // Already done in container ... | |||
| //context.setProperty( TaskletContext.NAME, name ); | |||
| try { tasklet.contextualize( context ); } | |||
| 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.ZipException; | |||
| import java.util.zip.ZipFile; | |||
| import org.apache.ant.datatypes.DataTypeEngine; | |||
| import org.apache.ant.convert.ConverterEngine; | |||
| import org.apache.ant.convert.ConverterRegistry; | |||
| import org.apache.ant.convert.DefaultConverterInfo; | |||
| import org.apache.avalon.Component; | |||
| 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.Configuration; | |||
| 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.DefaultLocatorRegistry; | |||
| import org.apache.avalon.camelot.DeploymentException; | |||
| import org.apache.avalon.camelot.DeployerUtil; | |||
| import org.apache.avalon.camelot.Loader; | |||
| import org.apache.avalon.camelot.LocatorRegistry; | |||
| import org.apache.avalon.camelot.RegistryException; | |||
| @@ -55,7 +56,7 @@ public class DefaultTskDeployer | |||
| */ | |||
| public DefaultTskDeployer() | |||
| { | |||
| super( false ); | |||
| super(); | |||
| m_autoUndeploy = true; | |||
| m_type = "Tasklet"; | |||
| } | |||
| @@ -64,34 +65,32 @@ public class DefaultTskDeployer | |||
| * Retrieve relevent services needed to deploy. | |||
| * | |||
| * @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 ) | |||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||
| throws ComponentManagerException | |||
| { | |||
| final TaskletEngine taskletEngine = (TaskletEngine)componentManager. | |||
| 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_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 ) | |||
| throws DeploymentException | |||
| { | |||
| final Configuration taskdefs = loadConfiguration( zipFile, TSKDEF_FILE ); | |||
| final Configuration taskdefs = DeployerUtil.loadConfiguration( zipFile, TSKDEF_FILE ); | |||
| try | |||
| { | |||
| @@ -126,8 +125,8 @@ public class DefaultTskDeployer | |||
| throws DeploymentException | |||
| { | |||
| 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 | |||
| { | |||
| @@ -152,8 +151,9 @@ public class DefaultTskDeployer | |||
| throws DeploymentException | |||
| { | |||
| 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 | |||
| { | |||
| @@ -178,8 +178,8 @@ public class DefaultTskDeployer | |||
| throws DeploymentException | |||
| { | |||
| 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 | |||
| { | |||
| @@ -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> | |||
| */ | |||
| public interface TaskletEngine | |||
| extends Component, Loggable | |||
| extends Component | |||
| { | |||
| /** | |||
| * Retrieve deployer for engine. | |||
| @@ -60,8 +60,6 @@ public interface TaskletEngine | |||
| * @param task the configruation data for task | |||
| * @exception AntException if an error occurs | |||
| */ | |||
| void execute( Configuration task, | |||
| TaskletContext context, | |||
| ComponentManager componentManager ) | |||
| void execute( Configuration task, TaskletContext context ) | |||
| throws AntException; | |||
| } | |||
| @@ -14,8 +14,7 @@ import org.apache.ant.AntException; | |||
| import org.apache.ant.tasklet.AbstractTasklet; | |||
| import org.apache.ant.tasklet.engine.TaskletEngine; | |||
| 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.camelot.RegistryException; | |||
| @@ -34,7 +33,7 @@ public abstract class AbstractResourceRegisterer | |||
| protected TaskletEngine m_engine; | |||
| public void compose( final ComponentManager componentManager ) | |||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||
| throws ComponentManagerException | |||
| { | |||
| m_engine = (TaskletEngine)componentManager. | |||
| lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | |||
| @@ -84,7 +83,7 @@ public abstract class AbstractResourceRegisterer | |||
| { | |||
| if( null != libName ) | |||
| { | |||
| final File lib = new File( getContext().resolveFilename( libName ) ); | |||
| final File lib = getContext().resolveFile( libName ); | |||
| try { return lib.toURL(); } | |||
| catch( final MalformedURLException mue ) | |||
| { | |||
| @@ -16,8 +16,7 @@ import org.apache.ant.tasklet.DefaultTaskletContext; | |||
| import org.apache.ant.tasklet.TaskletContext; | |||
| import org.apache.avalon.ComponentManager; | |||
| 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; | |||
| /** | |||
| @@ -43,7 +42,7 @@ public class AntCall | |||
| } | |||
| public void compose( final ComponentManager componentManager ) | |||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||
| throws ComponentManagerException | |||
| { | |||
| m_componentManager = 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.engine.TaskletEngine; | |||
| 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.ConfigurationException; | |||
| import org.apache.avalon.Resolvable; | |||
| @@ -40,16 +39,15 @@ public class Property | |||
| protected Configurer m_configurer; | |||
| public void compose( final ComponentManager componentManager ) | |||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||
| throws ComponentManagerException | |||
| { | |||
| m_configurer = (Configurer)componentManager. | |||
| 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 ) | |||
| @@ -71,7 +69,12 @@ public class Property | |||
| 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 ) | |||
| { | |||
| throw new ConfigurationException( "Error converting value", e ); | |||
| @@ -86,7 +89,7 @@ public class Property | |||
| try | |||
| { | |||
| final Boolean localScope = | |||
| (Boolean)m_converter.convert( Boolean.class, object ); | |||
| (Boolean)m_converter.convert( Boolean.class, object, getContext() ); | |||
| setLocalScope( Boolean.TRUE == localScope ); | |||
| } | |||
| 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.engine.TaskletEngine; | |||
| 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.camelot.DeploymentException; | |||
| import org.apache.avalon.camelot.RegistryException; | |||
| @@ -39,7 +38,7 @@ public class RegisterConverter | |||
| protected TaskletEngine m_engine; | |||
| public void compose( final ComponentManager componentManager ) | |||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||
| throws ComponentManagerException | |||
| { | |||
| m_engine = (TaskletEngine)componentManager. | |||
| lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | |||
| @@ -90,7 +89,7 @@ public class RegisterConverter | |||
| if( !isFullyDefined && null == url ) | |||
| { | |||
| throw new AntException( "Must supply parameter if not fully specifying converter" ); | |||
| } | |||
| } | |||
| if( !isFullyDefined ) | |||
| { | |||
| @@ -126,7 +125,7 @@ public class RegisterConverter | |||
| { | |||
| if( null != libName ) | |||
| { | |||
| final File lib = new File( getContext().resolveFilename( libName ) ); | |||
| final File lib = getContext().resolveFile( libName ); | |||
| try { return lib.toURL(); } | |||
| catch( final MalformedURLException mue ) | |||
| { | |||
| @@ -14,8 +14,7 @@ import org.apache.ant.AntException; | |||
| import org.apache.ant.tasklet.AbstractTasklet; | |||
| import org.apache.ant.tasklet.engine.TaskletEngine; | |||
| 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.camelot.DeploymentException; | |||
| @@ -32,7 +31,7 @@ public class RegisterTasklib | |||
| protected TaskletEngine m_engine; | |||
| public void compose( final ComponentManager componentManager ) | |||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||
| throws ComponentManagerException | |||
| { | |||
| m_engine = (TaskletEngine)componentManager. | |||
| lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | |||
| @@ -53,7 +52,7 @@ public class RegisterTasklib | |||
| URL url = null; | |||
| final File lib = new File( getContext().resolveFilename( m_lib ) ); | |||
| final File lib = getContext().resolveFile( m_lib ); | |||
| try { url = lib.toURL(); } | |||
| catch( final MalformedURLException mue ) | |||
| { | |||
| @@ -5,7 +5,7 @@ | |||
| * version 1.1, a copy of which has been included with this distribution in | |||
| * the LICENSE file. | |||
| */ | |||
| package org.apache.ant.datatypes; | |||
| package org.apache.ant.util; | |||
| import org.apache.ant.AntException; | |||
| import org.apache.avalon.Component; | |||
| @@ -25,7 +25,7 @@ while [ -h "$PRG" ] ; do | |||
| fi | |||
| done | |||
| MYRMIDON_HOME=`dirname "$PRG"`/.. | |||
| ANT_HOME=`dirname "$PRG"`/.. | |||
| if [ "$JAVA_HOME" == "" ] ; then | |||
| @@ -42,4 +42,4 @@ else | |||
| 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 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 | |||
| 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 to the installation directory of java. | |||
| echo. | |||
| goto end | |||
| rem hope that there is java command in path | |||
| if "%JAVACMD%" == "" set JAVACMD=java | |||
| @@ -22,7 +45,6 @@ if "%JAVACMD%" == "" set JAVACMD=%JAVA_HOME%\bin\java | |||
| :argSetup | |||
| set THIS_FILE=%0 | |||
| set ANT_CMD_LINE_ARGS= | |||
| rem Slurp all args... | |||
| @@ -35,9 +57,8 @@ goto setupArgs | |||
| :doneArgs | |||
| 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 | |||
| if exist "%HOME%\antrc_post.bat" call "%HOME%\antrc_post.bat" | |||
| set THIS_FILE= | |||
| 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 ' ' ':'` | |||
| if [ "$CLASSPATH" != "" ] ; then | |||
| LOCALCLASSPATH=$CLASSPATH:$LOCALCLASSPATH | |||
| LOCALCLASSPATH=$LOCALCLASSPATH:$CLASSPATH | |||
| fi | |||
| if [ "$JAVA_HOME" != "" ] ; then | |||
| @@ -1,4 +1,4 @@ | |||
| rem @echo off | |||
| @echo off | |||
| rem find ANT_HOME | |||
| if not "%ANT_HOME%"=="" goto checkJava | |||
| @@ -2,7 +2,7 @@ | |||
| cd %1 | |||
| set ANT_RUN_CMD=%2 | |||
| shift | |||
| shift | |||
| shift | |||
| %ANT_RUN_CMD% %1 %2 %3 %4 %5 %6 %7 %8 %9 | |||
| @@ -1 +1,2 @@ | |||
| set LOCALCLASSPATH=%LOCALCLASSPATH%;%1 | |||