git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268313 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -7,6 +7,11 @@ | |||
| */ | |||
| package org.apache.ant; | |||
| /** | |||
| * Interface that holds constants used to access variables from context. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public interface AntContextResources | |||
| { | |||
| // the directory of ant | |||
| @@ -9,14 +9,34 @@ package org.apache.ant; | |||
| import org.apache.avalon.CascadingRuntimeException; | |||
| /** | |||
| * AntException thrown when a problem with tasks etc. | |||
| * It is cascading so that further embedded information can be contained. | |||
| * ie ANtException was caused by IOException etc. | |||
| * It is RuntimeException as it has to pass through a number of Java-defined | |||
| * interfaces - ala Runnable and also to aid in ease of indicating an error. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public class AntException | |||
| extends CascadingRuntimeException | |||
| { | |||
| /** | |||
| * Basic constructor with a message | |||
| * | |||
| * @param message the message | |||
| */ | |||
| public AntException( final String message ) | |||
| { | |||
| this( message, null ); | |||
| } | |||
| /** | |||
| * Constructor that builds cascade so that other exception information can be retained. | |||
| * | |||
| * @param message the message | |||
| * @param throwable the throwable | |||
| */ | |||
| public AntException( final String message, final Throwable throwable ) | |||
| { | |||
| super( message, throwable ); | |||
| @@ -18,6 +18,7 @@ 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 org.apache.ant.launcher.AntLoader; | |||
| @@ -33,6 +34,7 @@ import org.apache.avalon.Disposable; | |||
| import org.apache.avalon.Initializable; | |||
| import org.apache.avalon.camelot.Deployer; | |||
| import org.apache.avalon.camelot.DeploymentException; | |||
| import org.apache.avalon.util.ObjectUtil; | |||
| import org.apache.avalon.util.StringUtil; | |||
| import org.apache.avalon.util.cli.AbstractMain; | |||
| import org.apache.avalon.util.cli.CLOption; | |||
| @@ -54,16 +56,22 @@ import org.apache.log.Priority; | |||
| public class Main | |||
| extends AbstractMain | |||
| { | |||
| //Constants to indicate the build of Ant/Myrmidon | |||
| public final static String BUILD_DATE = "@@DATE@@"; | |||
| public final static String BUILD_VERSION = "@@VERSION@@"; | |||
| public final static String VERSION = | |||
| "Ant " + BUILD_VERSION + " compiled on " + BUILD_DATE; | |||
| //default log level | |||
| 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"; | |||
| @@ -73,6 +81,7 @@ public class Main | |||
| 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'; | |||
| private static final int VERBOSE_OPT = 'v'; | |||
| @@ -102,8 +111,8 @@ public class Main | |||
| QUIET_OPT, VERBOSE_OPT, LOG_LEVEL_OPT | |||
| }; | |||
| protected Logger m_logger; | |||
| protected Logger m_logger; | |||
| protected ProjectListener m_listener; | |||
| protected File m_binDir; | |||
| protected File m_homeDir; | |||
| @@ -112,6 +121,11 @@ public class Main | |||
| protected File m_buildFile; | |||
| protected File m_userDir; | |||
| /** | |||
| * Main entry point called to run standard Ant. | |||
| * | |||
| * @param args the args | |||
| */ | |||
| public static void main( final String[] args ) | |||
| { | |||
| final Main main = new Main(); | |||
| @@ -131,6 +145,7 @@ public class Main | |||
| /** | |||
| * Initialise the options for command line parser. | |||
| * This is called by super-class. | |||
| */ | |||
| protected CLOptionDescriptor[] createCLOptions() | |||
| { | |||
| @@ -278,6 +293,9 @@ public class Main | |||
| 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(); | |||
| @@ -304,6 +322,8 @@ public class Main | |||
| m_logger.debug( "Ant Lib Directory: " + m_libDir ); | |||
| m_logger.debug( "Ant Task Lib Directory: " + m_taskLibDir ); | |||
| //setup classloader so that it will correctly load | |||
| //the Project/ProjectBuilder/ProjectEngine and all dependencies | |||
| setupContextClassLoader( m_libDir ); | |||
| final Project project = getProject( builderName, m_buildFile ); | |||
| @@ -323,8 +343,10 @@ public class Main | |||
| BufferedReader reader = null; | |||
| //loop over build if we are in incremental mode.. | |||
| while( true ) | |||
| { | |||
| //actually do the build ... | |||
| doBuild( engine, project, targets ); | |||
| if( !incremental ) break; | |||
| @@ -341,13 +363,20 @@ public class Main | |||
| if( line.equalsIgnoreCase( "no" ) ) break; | |||
| } | |||
| //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 ) | |||
| @@ -375,6 +404,13 @@ public class Main | |||
| } | |||
| } | |||
| /** | |||
| * Actually do the build. | |||
| * | |||
| * @param engine the engine | |||
| * @param project the project | |||
| * @param targets the targets to build as passed by CLI | |||
| */ | |||
| protected void doBuild( final ProjectEngine engine, | |||
| final Project project, | |||
| final ArrayList targets ) | |||
| @@ -383,6 +419,7 @@ public class Main | |||
| { | |||
| final int targetCount = targets.size(); | |||
| //if we didn't specify a target on CLI then choose default | |||
| if( 0 == targetCount ) | |||
| { | |||
| engine.execute( project, project.getDefaultTargetName() ); | |||
| @@ -402,23 +439,68 @@ public class Main | |||
| } | |||
| } | |||
| /** | |||
| * 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. | |||
| * | |||
| * @param logLevel the log-level | |||
| * @return the logger | |||
| * @exception AntException if an error occurs | |||
| */ | |||
| protected Logger createLogger( final String logLevel ) | |||
| throws AntException | |||
| { | |||
| final String logLevelCapitalized = logLevel.toUpperCase(); | |||
| final Priority.Enum priority = LogKit.getPriorityForName( logLevelCapitalized ); | |||
| if( !priority.getName().equals( logLevelCapitalized ) ) | |||
| { | |||
| throw new AntException( "Unknown log level - " + logLevel ); | |||
| } | |||
| final Category category = LogKit.createCategory( "ant", priority ); | |||
| return LogKit.createLogger( category ); | |||
| } | |||
| /** | |||
| * Setup project listener. | |||
| * | |||
| * @param listenerName the name of project listener | |||
| */ | |||
| protected void setupListener( final String listenerName ) | |||
| { | |||
| m_listener = createListener( listenerName ); | |||
| m_logger.addLogTarget( new ProjectToListenerAdapter( m_listener ) ); | |||
| } | |||
| /** | |||
| * 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() ); | |||
| } | |||
| /** | |||
| * 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. | |||
| * | |||
| * @param libDir the directory of lib files to add | |||
| */ | |||
| protected void setupClassLoader( final File libDir ) | |||
| { | |||
| final ExtensionFileFilter filter = | |||
| @@ -430,6 +512,8 @@ public class Main | |||
| for( int i = 0; i < files.length; i++ ) | |||
| { | |||
| //except for a few *special* files add all the | |||
| //.zip/.jars to classloader | |||
| if( !files[ i ].getName().equals( "ant.jar" ) && | |||
| !files[ i ].getName().equals( "myrmidon.jar" ) && | |||
| !files[ i ].getName().equals( "avalonapi.jar" ) ) | |||
| @@ -440,6 +524,15 @@ public class Main | |||
| } | |||
| } | |||
| /** | |||
| * 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 | |||
| { | |||
| @@ -453,30 +546,59 @@ public class Main | |||
| return project; | |||
| } | |||
| /** | |||
| * Setup the projects context so all the "default" properties are defined. | |||
| * This also takes a hashmap that is added to context. Usually these are the | |||
| * ones defined on command line. | |||
| * | |||
| * @param project the project | |||
| * @param defines the defines | |||
| * @exception AntException if an error occurs | |||
| */ | |||
| protected void setupProjectContext( final Project project, final HashMap defines ) | |||
| throws AntException | |||
| { | |||
| //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.LOGGER, m_logger ); | |||
| defines.put( TaskletContext.JAVA_VERSION, getJavaVersion() ); | |||
| final TaskletContext context = project.getContext(); | |||
| final Iterator keys = defines.keySet().iterator(); | |||
| //make sure these come before following so they get overidden if user tries to | |||
| //confuse the system | |||
| addToContext( context, defines ); | |||
| //Add system properties second so that they overide user-defined properties | |||
| addToContext( context, System.getProperties() ); | |||
| } | |||
| /** | |||
| * Helper method to add values to a context | |||
| * | |||
| * @param context the context | |||
| * @param map the map of names->values | |||
| */ | |||
| protected void addToContext( final TaskletContext context, final Map map ) | |||
| { | |||
| final Iterator keys = map.keySet().iterator(); | |||
| while( keys.hasNext() ) | |||
| { | |||
| final String key = (String)keys.next(); | |||
| final String value = (String)defines.get( key ); | |||
| final Object value = map.get( key ); | |||
| context.setProperty( key, value ); | |||
| } | |||
| context.setProperty( AntContextResources.HOME_DIR, m_homeDir ); | |||
| context.setProperty( AntContextResources.BIN_DIR, m_binDir ); | |||
| context.setProperty( AntContextResources.LIB_DIR, m_libDir ); | |||
| context.setProperty( AntContextResources.TASKLIB_DIR, m_taskLibDir ); | |||
| //context.put( AntContextResources.USER_DIR, m_userDir ); | |||
| context.setProperty( TaskletContext.LOGGER, m_logger ); | |||
| context.setProperty( TaskletContext.JAVA_VERSION, getJavaVersion() ); | |||
| } | |||
| /** | |||
| * 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; | |||
| @@ -495,6 +617,11 @@ public class Main | |||
| return version; | |||
| } | |||
| /** | |||
| * Create and configure project engine | |||
| * | |||
| * @return the ProjectEngine | |||
| */ | |||
| protected ProjectEngine getProjectEngine() | |||
| { | |||
| final ProjectEngine engine = createProjectEngine(); | |||
| @@ -502,6 +629,12 @@ public class Main | |||
| 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" ); | |||
| @@ -510,7 +643,7 @@ public class Main | |||
| protected File getHomeDir( final String homeDir ) | |||
| throws AntException | |||
| { | |||
| final File file = new File( homeDir ); | |||
| final File file = (new File( homeDir )).getAbsoluteFile(); | |||
| checkDirectory( file, "ant-home" ); | |||
| return file; | |||
| } | |||
| @@ -568,21 +701,6 @@ public class Main | |||
| } | |||
| } | |||
| protected Logger createLogger( final String logLevel ) | |||
| throws AntException | |||
| { | |||
| final String logLevelCapitalized = logLevel.toUpperCase(); | |||
| final Priority.Enum priority = LogKit.getPriorityForName( logLevelCapitalized ); | |||
| if( !priority.getName().equals( logLevelCapitalized ) ) | |||
| { | |||
| throw new AntException( "Unknown log level - " + logLevel ); | |||
| } | |||
| final Category category = LogKit.createCategory( "ant", priority ); | |||
| return LogKit.createLogger( category ); | |||
| } | |||
| protected void setupDefaultAntDirs() | |||
| { | |||
| final String os = System.getProperty( "os.name" ); | |||
| @@ -767,8 +885,7 @@ public class Main | |||
| { | |||
| try | |||
| { | |||
| final Class clazz = Class.forName( objectName ); | |||
| return clazz.newInstance(); | |||
| return ObjectUtil.createObject( objectName ); | |||
| } | |||
| catch( final IllegalAccessException iae ) | |||
| { | |||
| @@ -10,7 +10,10 @@ package org.apache.ant.configuration; | |||
| import java.util.Iterator; | |||
| /** | |||
| * Hostile fork till Avalon gets equivelent functionality ;) | |||
| * Fork of Avalon code that will be folded back when they get equivelent facilties. | |||
| * Note that the code is different package so it should not cause any issues. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public interface Configuration | |||
| extends org.apache.avalon.Configuration | |||
| @@ -10,7 +10,10 @@ package org.apache.ant.configuration; | |||
| import org.xml.sax.SAXException; | |||
| /** | |||
| * Hostile fork till Avalon gets equivelent functionality ;) | |||
| * Fork of Avalon code that will be folded back when they get equivelent facilties. | |||
| * Note that the code is different package so it should not cause any issues. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public class ConfigurationBuilder | |||
| extends org.apache.avalon.DefaultConfigurationBuilder | |||
| @@ -10,7 +10,10 @@ package org.apache.ant.configuration; | |||
| import java.util.Iterator; | |||
| /** | |||
| * Hostile fork till Avalon gets equivelent functionality ;) | |||
| * Fork of Avalon code that will be folded back when they get equivelent facilties. | |||
| * Note that the code is different package so it should not cause any issues. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public class DefaultConfiguration | |||
| extends org.apache.avalon.DefaultConfiguration | |||
| @@ -8,7 +8,10 @@ | |||
| package org.apache.ant.configuration; | |||
| /** | |||
| * Hostile fork till Avalon gets equivelent functionality ;) | |||
| * Fork of Avalon code that will be folded back when they get equivelent facilties. | |||
| * Note that the code is different package so it should not cause any issues. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public class SAXConfigurationHandler | |||
| extends org.apache.avalon.SAXConfigurationHandler | |||
| @@ -18,12 +18,26 @@ public abstract class AbstractConverter | |||
| protected final Class m_source; | |||
| protected final Class m_destination; | |||
| /** | |||
| * Constructor for a converter between types source and destination | |||
| * | |||
| * @param source the source type | |||
| * @param destination the destination type | |||
| */ | |||
| public AbstractConverter( final Class source, final Class destination ) | |||
| { | |||
| m_source = source; | |||
| m_destination = destination; | |||
| } | |||
| /** | |||
| * Convert an object from original to destination types | |||
| * | |||
| * @param destination the destination type | |||
| * @param original the original Object | |||
| * @return the converted object | |||
| * @exception Exception if an error occurs | |||
| */ | |||
| public Object convert( final Class destination, final Object original ) | |||
| throws Exception | |||
| { | |||
| @@ -42,6 +56,13 @@ public abstract class AbstractConverter | |||
| return convert( original ); | |||
| } | |||
| /** | |||
| * Overide this in a particular converter to do the conversion. | |||
| * | |||
| * @param original the original Object | |||
| * @return the converted object | |||
| * @exception Exception if an error occurs | |||
| */ | |||
| protected abstract Object convert( Object original ) | |||
| throws Exception; | |||
| } | |||
| @@ -14,6 +14,16 @@ package org.apache.ant.convert; | |||
| */ | |||
| public interface Converter | |||
| { | |||
| /** | |||
| * Convert original to destination type. | |||
| * Destination is passed so that one converter can potentiall | |||
| * convert to multiple different types. | |||
| * | |||
| * @param destination the destinaiton type | |||
| * @param original the original type | |||
| * @return the converted object | |||
| * @exception Exception if an error occurs | |||
| */ | |||
| Object convert( Class destination, Object original ) | |||
| throws Exception; | |||
| } | |||
| @@ -10,6 +10,12 @@ package org.apache.ant.convert; | |||
| import org.apache.ant.convert.Converter; | |||
| import org.apache.avalon.camelot.AbstractEntry; | |||
| /** | |||
| * An entry representing an instance of Converter. | |||
| * See Cameloy documentation for more details. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public class ConverterEntry | |||
| extends AbstractEntry | |||
| { | |||
| @@ -18,6 +18,13 @@ import org.apache.avalon.camelot.FactoryException; | |||
| public interface ConverterFactory | |||
| extends Factory | |||
| { | |||
| /** | |||
| * Create entries (ie instances) from infos (ie types). | |||
| * | |||
| * @param info the info | |||
| * @return the entry | |||
| * @exception FactoryException if an error occurs | |||
| */ | |||
| ConverterEntry create( ConverterInfo info ) | |||
| throws FactoryException; | |||
| } | |||
| @@ -17,6 +17,13 @@ import org.apache.avalon.camelot.Loader; | |||
| public interface ConverterLoader | |||
| extends Loader | |||
| { | |||
| /** | |||
| * Load a particular converter. | |||
| * | |||
| * @param converter the converter name | |||
| * @return the loaded Converter | |||
| * @exception Exception if an error occurs | |||
| */ | |||
| Converter loadConverter( String converter ) | |||
| throws Exception; | |||
| } | |||
| @@ -8,9 +8,20 @@ | |||
| package org.apache.ant.convert; | |||
| import org.apache.avalon.camelot.Registry; | |||
| /** | |||
| * Interface for registry for ConverterInfos. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public interface ConverterRegistry | |||
| extends Registry | |||
| { | |||
| /** | |||
| * Retrieve ConverterInfo that describes converter that converts from source to destination. | |||
| * | |||
| * @param source the source classname | |||
| * @param destination the destination classname | |||
| * @return the converter-info or null if none available | |||
| */ | |||
| ConverterInfo getConverterInfo( String source, String destination ); | |||
| } | |||
| @@ -27,6 +27,13 @@ public class DefaultConverterFactory | |||
| { | |||
| protected final HashMap m_loaders = new HashMap(); | |||
| /** | |||
| * Method for generic Factory. | |||
| * | |||
| * @param info generic info | |||
| * @return the created entry | |||
| * @exception FactoryException if an error occurs | |||
| */ | |||
| public Entry create( final Info info ) | |||
| throws FactoryException | |||
| { | |||
| @@ -37,6 +44,13 @@ public class DefaultConverterFactory | |||
| return create( (ConverterInfo)info ); | |||
| } | |||
| /** | |||
| * Non-generic factory method. | |||
| * | |||
| * @param info the info to create instance from | |||
| * @return the created entry | |||
| * @exception FactoryException if an error occurs | |||
| */ | |||
| public ConverterEntry create( final ConverterInfo info ) | |||
| throws FactoryException | |||
| { | |||
| @@ -54,6 +68,12 @@ public class DefaultConverterFactory | |||
| return new ConverterEntry( info, (Converter)object ); | |||
| } | |||
| /** | |||
| * Get a loader for a particular location | |||
| * | |||
| * @param locationthe location | |||
| * @return the loader | |||
| */ | |||
| protected ConverterLoader getLoader( final URL location ) | |||
| { | |||
| ConverterLoader loader = (ConverterLoader)m_loaders.get( location ); | |||
| @@ -67,6 +87,13 @@ public class DefaultConverterFactory | |||
| return loader; | |||
| } | |||
| /** | |||
| * Create a new loader. | |||
| * Put in another method so that it can be overridden. | |||
| * | |||
| * @param location the location the Loader will load from | |||
| * @return the loader | |||
| */ | |||
| protected ConverterLoader createLoader( final URL location ) | |||
| { | |||
| if( null != location ) return new DefaultConverterLoader( location ); | |||
| @@ -32,6 +32,13 @@ public class DefaultConverterLoader | |||
| Thread.currentThread().getContextClassLoader() ) ); | |||
| } | |||
| /** | |||
| * Load a Converter object. | |||
| * | |||
| * @param converter the converter classname | |||
| * @return the converter instance | |||
| * @exception Exception if an error occurs | |||
| */ | |||
| public Converter loadConverter( final String converter ) | |||
| throws Exception | |||
| { | |||
| @@ -12,12 +12,24 @@ import org.apache.avalon.camelot.AbstractRegistry; | |||
| import org.apache.avalon.camelot.Info; | |||
| import org.apache.avalon.camelot.RegistryException; | |||
| /** | |||
| * Default implementation of ConverterInfo registry. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public class DefaultConverterRegistry | |||
| extends AbstractRegistry | |||
| implements ConverterRegistry | |||
| { | |||
| protected final HashMap m_mapping = new HashMap(); | |||
| /** | |||
| * Retrieve ConverterInfo that describes converter that converts from source to destination. | |||
| * | |||
| * @param source the source classname | |||
| * @param destination the destination classname | |||
| * @return the converter-info or null if none available | |||
| */ | |||
| public ConverterInfo getConverterInfo( final String source, final String destination ) | |||
| { | |||
| final HashMap map = (HashMap)m_mapping.get( source ); | |||
| @@ -12,7 +12,8 @@ import java.net.URL; | |||
| import java.net.URLClassLoader; | |||
| /** | |||
| * AvalonLoader is the class that bootstraps and installs the security manager. | |||
| * 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> | |||
| */ | |||
| @@ -31,7 +32,13 @@ public final class AntLoader | |||
| return c_classLoader; | |||
| } | |||
| public final static void main( final String args[] ) | |||
| /** | |||
| * Magic entry point. | |||
| * | |||
| * @param argsthe CLI arguments | |||
| * @exception Exception if an error occurs | |||
| */ | |||
| public final static void main( final String[] args ) | |||
| throws Exception | |||
| { | |||
| final URL archive = new URL( "file:lib/myrmidon.jar" ); | |||
| @@ -52,11 +59,21 @@ public final class AntLoader | |||
| } | |||
| } | |||
| /** | |||
| * Basic constructor. | |||
| * | |||
| * @param urls the Starting URLS | |||
| */ | |||
| public AntLoader( final URL[] urls ) | |||
| { | |||
| super( urls ); | |||
| } | |||
| /** | |||
| * Add a URL to classloader | |||
| * | |||
| * @param url the url | |||
| */ | |||
| public void addURL( final URL url ) | |||
| { | |||
| super.addURL( url ); | |||
| @@ -21,6 +21,7 @@ import org.apache.ant.tasklet.engine.DefaultTaskletRegistry; | |||
| import org.apache.ant.tasklet.engine.TaskletEngine; | |||
| import org.apache.ant.tasklet.engine.TaskletRegistry; | |||
| import org.apache.ant.tasklet.engine.TskDeployer; | |||
| import org.apache.avalon.Composer; | |||
| import org.apache.avalon.DefaultComponentManager; | |||
| import org.apache.avalon.Disposable; | |||
| import org.apache.avalon.Initializable; | |||
| @@ -60,29 +61,15 @@ public class DefaultProjectEngine | |||
| { | |||
| m_listenerSupport = new ProjectListenerSupport(); | |||
| m_taskletEngine = createTaskletEngine(); | |||
| m_taskletEngine.setLogger( m_logger ); | |||
| m_taskletRegistry = createTaskletRegistry(); | |||
| m_converterRegistry = createConverterRegistry(); | |||
| m_deployer = createDeployer(); | |||
| setupTaskletEngine(); | |||
| m_componentManager = new DefaultComponentManager(); | |||
| m_componentManager.put( "org.apache.ant.project.ProjectEngine", this ); | |||
| m_componentManager.put( "org.apache.ant.tasklet.engine.TaskletRegistry", | |||
| m_taskletRegistry ); | |||
| m_componentManager.put( "org.apache.ant.convert.ConverterRegistry", | |||
| m_converterRegistry ); | |||
| m_componentManager.put( "org.apache.avalon.camelot.Deployer", m_deployer ); | |||
| m_taskletEngine.compose( m_componentManager ); | |||
| if( m_taskletEngine instanceof Initializable ) | |||
| { | |||
| ((Initializable)m_taskletEngine).init(); | |||
| } | |||
| m_componentManager.put( "org.apache.ant.tasklet.engine.TaskletEngine", m_taskletEngine ); | |||
| } | |||
| public void dispose() | |||
| @@ -99,6 +86,29 @@ public class DefaultProjectEngine | |||
| return m_deployer; | |||
| } | |||
| protected void setupTaskletEngine() | |||
| throws Exception | |||
| { | |||
| m_taskletEngine = createTaskletEngine(); | |||
| m_taskletEngine.setLogger( m_logger ); | |||
| if( m_taskletEngine instanceof Composer ) | |||
| { | |||
| final DefaultComponentManager componentManager = new DefaultComponentManager(); | |||
| componentManager.put( "org.apache.ant.tasklet.engine.TaskletRegistry", | |||
| m_taskletRegistry ); | |||
| componentManager.put( "org.apache.ant.convert.ConverterRegistry", | |||
| m_converterRegistry ); | |||
| ((Composer)m_taskletEngine).compose( componentManager ); | |||
| } | |||
| if( m_taskletEngine instanceof Initializable ) | |||
| { | |||
| ((Initializable)m_taskletEngine).init(); | |||
| } | |||
| } | |||
| protected TaskletEngine createTaskletEngine() | |||
| { | |||
| return new DefaultTaskletEngine(); | |||
| @@ -219,19 +229,16 @@ public class DefaultProjectEngine | |||
| m_logger.debug( "Executing task " + name ); | |||
| //Set up context for task... | |||
| final TaskletContext taskletContext = context; | |||
| //is Only necessary if we are multi-threaded | |||
| //final TaskletContext targetContext = new DefaultTaskletContext( context ); | |||
| taskletContext.setProperty( TaskletContext.NAME, name ); | |||
| m_taskletEngine.contextualize( taskletContext ); | |||
| context.setProperty( TaskletContext.NAME, name ); | |||
| //notify listeners | |||
| m_listenerSupport.taskletStarted( name ); | |||
| //run task | |||
| m_taskletEngine.execute( configuration ); | |||
| m_taskletEngine.execute( configuration, context, m_componentManager ); | |||
| //notify listeners task has ended | |||
| m_listenerSupport.taskletFinished(); | |||
| @@ -20,6 +20,7 @@ import org.apache.log.Logger; | |||
| public abstract class AbstractTasklet | |||
| implements Tasklet, Initializable | |||
| { | |||
| //the user should set this in constructors of sub-classes | |||
| protected JavaVersion m_requiredJavaVersion; | |||
| private TaskletContext m_context; | |||
| @@ -16,7 +16,8 @@ import org.apache.avalon.util.io.FileUtil; | |||
| import org.apache.log.Logger; | |||
| /** | |||
| * This represents the *Context* in which a task can be executed. | |||
| * Default implementation of TaskletContext. | |||
| * It represents the *Context* in which a task can be executed. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| @@ -11,6 +11,8 @@ import org.apache.avalon.util.ValuedEnum; | |||
| /** | |||
| * Type safe wrapper class for Java Version enums. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public final class JavaVersion | |||
| extends ValuedEnum | |||
| @@ -21,6 +23,12 @@ public final class JavaVersion | |||
| public final static JavaVersion JAVA1_2 = new JavaVersion( "Java 1.2", 120 ); | |||
| public final static JavaVersion JAVA1_3 = new JavaVersion( "Java 1.3", 130 ); | |||
| /** | |||
| * Private constructor so no instance except here can be defined. | |||
| * | |||
| * @param name the java version name | |||
| * @param value the version * 100 | |||
| */ | |||
| private JavaVersion( final String name, final int value ) | |||
| { | |||
| super( name, value ); | |||
| @@ -12,6 +12,13 @@ import org.apache.avalon.Contextualizable; | |||
| /** | |||
| * This represents the individual tasks. | |||
| * Particular instances can also implement Initializable | |||
| * and/or Disposable, in which case init()/dispose() will | |||
| * be called at appropriate time. | |||
| * The task can also implement Composer in which case required | |||
| * facilities will be passed via a ComponentManager. The actual | |||
| * facilties is determined by particular task engine but will usually | |||
| * include ProjectEngine and TaskEngine. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| @@ -58,7 +58,20 @@ public class DefaultTaskletConfigurer | |||
| m_converterFactory = (ConverterFactory)componentManager. | |||
| lookup( "org.apache.ant.convert.ConverterFactory" ); | |||
| } | |||
| /** | |||
| * Configure a task based on a configuration in a particular context. | |||
| * This configuring can be done in different ways for different | |||
| * configurers. | |||
| * This one does it by first checking if object implements Configurable | |||
| * and if it does will pass the task the configuration - else it will use | |||
| * ants rules to map configuration to types | |||
| * | |||
| * @param tasklet the tasklet | |||
| * @param configuration the configuration | |||
| * @param context the Context | |||
| * @exception ConfigurationException if an error occurs | |||
| */ | |||
| public void configure( final Tasklet tasklet, | |||
| final Configuration configuration, | |||
| final Context context ) | |||
| @@ -67,6 +80,19 @@ public class DefaultTaskletConfigurer | |||
| configure( (Object)tasklet, configuration, context ); | |||
| } | |||
| /** | |||
| * Configure a task based on a configuration in a particular context. | |||
| * This configuring can be done in different ways for different | |||
| * configurers. | |||
| * This one does it by first checking if object implements Configurable | |||
| * and if it does will pass the task the configuration - else it will use | |||
| * ants rules to map configuration to types | |||
| * | |||
| * @param tasklet the tasklet | |||
| * @param configuration the configuration | |||
| * @param context the Context | |||
| * @exception ConfigurationException if an error occurs | |||
| */ | |||
| public void configure( final Object object, | |||
| final Configuration configuration, | |||
| final Context context ) | |||
| @@ -107,6 +133,14 @@ public class DefaultTaskletConfigurer | |||
| } | |||
| } | |||
| /** | |||
| * Try to configure content of an object. | |||
| * | |||
| * @param object the object | |||
| * @param content the content value to be set | |||
| * @param context the Context | |||
| * @exception ConfigurationException if an error occurs | |||
| */ | |||
| protected void configureContent( final Object object, | |||
| final String content, | |||
| final Context context ) | |||
| @@ -318,7 +352,7 @@ public class DefaultTaskletConfigurer | |||
| } | |||
| } | |||
| } | |||
| return (Method[])matches.toArray( new Method[0] ); | |||
| } | |||
| @@ -29,10 +29,8 @@ import org.apache.avalon.camelot.RegistryException; | |||
| import org.apache.log.Logger; | |||
| public class DefaultTaskletEngine | |||
| implements TaskletEngine, Initializable | |||
| implements TaskletEngine, Initializable, Composer | |||
| { | |||
| protected ComponentManager m_componentManager; | |||
| protected TaskletContext m_context; | |||
| protected TaskletFactory m_taskletFactory; | |||
| protected ConverterFactory m_converterFactory; | |||
| protected TaskletRegistry m_taskletRegistry; | |||
| @@ -45,21 +43,25 @@ public class DefaultTaskletEngine | |||
| m_logger = logger; | |||
| } | |||
| public void contextualize( final Context context ) | |||
| { | |||
| m_context = (TaskletContext)context; | |||
| } | |||
| public void compose( final ComponentManager componentManager ) | |||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||
| { | |||
| m_componentManager = componentManager; | |||
| m_taskletRegistry = (TaskletRegistry)componentManager. | |||
| lookup( "org.apache.ant.tasklet.engine.TaskletRegistry" ); | |||
| m_converterRegistry = (ConverterRegistry)componentManager. | |||
| lookup( "org.apache.ant.convert.ConverterRegistry" ); | |||
| } | |||
| public TaskletRegistry getTaskletRegistry() | |||
| { | |||
| return m_taskletRegistry; | |||
| } | |||
| public ConverterRegistry getConverterRegistry() | |||
| { | |||
| return m_converterRegistry; | |||
| } | |||
| public void init() | |||
| throws Exception | |||
| { | |||
| @@ -69,10 +71,11 @@ public class DefaultTaskletEngine | |||
| if( m_configurer instanceof Composer ) | |||
| { | |||
| final DefaultComponentManager componentManager = | |||
| new DefaultComponentManager( m_componentManager ); | |||
| final DefaultComponentManager componentManager = new DefaultComponentManager(); | |||
| componentManager.put( "org.apache.ant.convert.ConverterFactory", | |||
| m_converterFactory ); | |||
| componentManager.put( "org.apache.ant.convert.ConverterRegistry", | |||
| m_converterRegistry ); | |||
| ((Composer)m_configurer).compose( componentManager ); | |||
| } | |||
| @@ -98,37 +101,40 @@ public class DefaultTaskletEngine | |||
| return (ConverterFactory)m_taskletFactory; | |||
| } | |||
| public void execute( final Configuration task ) | |||
| public void execute( final Configuration task, | |||
| final TaskletContext context, | |||
| final ComponentManager componentManager ) | |||
| throws AntException | |||
| { | |||
| final Tasklet tasklet = createTasklet( task ); | |||
| final String name = task.getName(); | |||
| m_logger.debug( "Created task " + name ); | |||
| m_logger.debug( "Creating" ); | |||
| final Tasklet tasklet = createTasklet( task ); | |||
| doContextualize( tasklet, task ); | |||
| m_logger.debug( "Contextualized task " + name ); | |||
| m_logger.debug( "Contextualizing" ); | |||
| doContextualize( tasklet, task, context ); | |||
| doCompose( tasklet, task ); | |||
| m_logger.debug( "Composed task " + name ); | |||
| m_logger.debug( "Composing" ); | |||
| doCompose( tasklet, task, componentManager ); | |||
| doConfigure( tasklet, task ); | |||
| m_logger.debug( "Configured task " + name ); | |||
| m_logger.debug( "Configuring" ); | |||
| doConfigure( tasklet, task, context ); | |||
| m_logger.debug( "Initializing" ); | |||
| doInitialize( tasklet, task ); | |||
| m_logger.debug( "Initialize task " + name ); | |||
| m_logger.debug( "Running" ); | |||
| tasklet.run(); | |||
| m_logger.debug( "Ran task " + name ); | |||
| m_logger.debug( "Disposing" ); | |||
| doDispose( tasklet, task ); | |||
| m_logger.debug( "Dispose task " + name ); | |||
| } | |||
| protected void doConfigure( final Tasklet tasklet, final Configuration task ) | |||
| protected void doConfigure( final Tasklet tasklet, | |||
| final Configuration task, | |||
| final TaskletContext context ) | |||
| throws AntException | |||
| { | |||
| try { m_configurer.configure( tasklet, task, m_context ); } | |||
| try { m_configurer.configure( tasklet, task, context ); } | |||
| catch( final Throwable throwable ) | |||
| { | |||
| throw new AntException( "Error configuring task " + task.getName() + " at " + | |||
| @@ -136,24 +142,15 @@ public class DefaultTaskletEngine | |||
| throwable.getMessage() + ")", throwable ); | |||
| } | |||
| } | |||
| protected TaskletContext getContextFor( final String name ) | |||
| { | |||
| //If we are single threaded we really don't need to have a new object | |||
| //for context ... if we are not single threaded then we need to create new | |||
| //context. Alternatively we could remove getName from TaskletContext | |||
| //final DefaultTaskletContext context = new DefaultTaskletContext( m_context ); | |||
| m_context.setProperty( TaskletContext.NAME, name ); | |||
| return m_context; | |||
| } | |||
| protected void doCompose( final Tasklet tasklet, final Configuration task ) | |||
| protected void doCompose( final Tasklet tasklet, | |||
| final Configuration task, | |||
| final ComponentManager componentManager ) | |||
| throws AntException | |||
| { | |||
| if( tasklet instanceof Composer ) | |||
| { | |||
| try { ((Composer)tasklet).compose( m_componentManager ); } | |||
| try { ((Composer)tasklet).compose( componentManager ); } | |||
| catch( final Throwable throwable ) | |||
| { | |||
| throw new AntException( "Error composing task " + task.getName() + " at " + | |||
| @@ -163,10 +160,13 @@ public class DefaultTaskletEngine | |||
| } | |||
| } | |||
| protected void doContextualize( final Tasklet tasklet, final Configuration task ) | |||
| protected void doContextualize( final Tasklet tasklet, | |||
| final Configuration task, | |||
| final TaskletContext context ) | |||
| throws AntException | |||
| { | |||
| final TaskletContext context = getContextFor( task.getName() ); | |||
| // Already done in container ... | |||
| //context.setProperty( TaskletContext.NAME, name ); | |||
| try { tasklet.contextualize( context ); } | |||
| catch( final Throwable throwable ) | |||
| @@ -8,8 +8,8 @@ | |||
| package org.apache.ant.tasklet.engine; | |||
| import java.net.URL; | |||
| import org.apache.ant.tasklet.Tasklet; | |||
| import org.apache.ant.convert.DefaultConverterLoader; | |||
| import org.apache.ant.tasklet.Tasklet; | |||
| /** | |||
| * Class used to load tasks et al from a source. | |||
| @@ -29,6 +29,13 @@ public class DefaultTaskletLoader | |||
| super( location ); | |||
| } | |||
| /** | |||
| * Load a tasklet with a particular classname. | |||
| * | |||
| * @param tasklet the tasklet classname | |||
| * @return the tasklet | |||
| * @exception Exception if an error occurs | |||
| */ | |||
| public Tasklet loadTasklet( final String tasklet ) | |||
| throws Exception | |||
| { | |||
| @@ -19,6 +19,16 @@ import org.apache.avalon.Context; | |||
| */ | |||
| public interface TaskletConfigurer | |||
| { | |||
| /** | |||
| * Configure a task based on a configuration in a particular context. | |||
| * This configuring can be done in different ways for different | |||
| * configurers. | |||
| * | |||
| * @param tasklet the tasklet | |||
| * @param configuration the configuration | |||
| * @param context the Context | |||
| * @exception ConfigurationException if an error occurs | |||
| */ | |||
| void configure( Tasklet tasklet, Configuration configuration, Context context ) | |||
| throws ConfigurationException; | |||
| } | |||
| @@ -9,14 +9,46 @@ package org.apache.ant.tasklet.engine; | |||
| import org.apache.ant.AntException; | |||
| import org.apache.ant.configuration.Configuration; | |||
| import org.apache.ant.convert.ConverterRegistry; | |||
| import org.apache.ant.tasklet.TaskletContext; | |||
| import org.apache.avalon.Component; | |||
| import org.apache.avalon.ComponentManager; | |||
| import org.apache.avalon.Composer; | |||
| import org.apache.avalon.Contextualizable; | |||
| import org.apache.log.Logger; | |||
| /** | |||
| * Engine inteface that should be implemented by all tasklet engines. | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public interface TaskletEngine | |||
| extends Contextualizable, Composer | |||
| extends Component | |||
| { | |||
| void setLogger( Logger logger ); | |||
| void execute( final Configuration task ) | |||
| /** | |||
| * Retrieve tasklet registry associated with engine. | |||
| * | |||
| * @return the TaskletRegistry | |||
| */ | |||
| TaskletRegistry getTaskletRegistry(); | |||
| /** | |||
| * Retrieve converter registry associated with engine. | |||
| * | |||
| * @return the ConverterRegistry | |||
| */ | |||
| ConverterRegistry getConverterRegistry(); | |||
| /** | |||
| * execute a task. | |||
| * | |||
| * @param task the configruation data for task | |||
| * @exception AntException if an error occurs | |||
| */ | |||
| void execute( Configuration task, | |||
| TaskletContext context, | |||
| ComponentManager componentManager ) | |||
| throws AntException; | |||
| } | |||
| @@ -18,6 +18,13 @@ import org.apache.avalon.camelot.Loader; | |||
| public interface TaskletLoader | |||
| extends Loader | |||
| { | |||
| /** | |||
| * Load a tasklet with a particular classname. | |||
| * | |||
| * @param tasklet the tasklet classname | |||
| * @return the tasklet | |||
| * @exception Exception if an error occurs | |||
| */ | |||
| Tasklet loadTasklet( String tasklet ) | |||
| throws Exception; | |||
| } | |||
| @@ -9,6 +9,11 @@ package org.apache.ant.tasklet.engine; | |||
| import org.apache.avalon.camelot.Registry; | |||
| /** | |||
| * The registry for tasklets | |||
| * | |||
| * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> | |||
| */ | |||
| public interface TaskletRegistry | |||
| extends Registry | |||
| { | |||
| @@ -13,6 +13,7 @@ import java.net.URL; | |||
| import org.apache.ant.AntException; | |||
| import org.apache.ant.tasklet.AbstractTasklet; | |||
| import org.apache.ant.tasklet.engine.DefaultTaskletInfo; | |||
| import org.apache.ant.tasklet.engine.TaskletEngine; | |||
| import org.apache.ant.tasklet.engine.TaskletRegistry; | |||
| import org.apache.avalon.ComponentManager; | |||
| import org.apache.avalon.ComponentNotAccessibleException; | |||
| @@ -37,8 +38,9 @@ public class RegisterTasklet | |||
| public void compose( final ComponentManager componentManager ) | |||
| throws ComponentNotFoundException, ComponentNotAccessibleException | |||
| { | |||
| m_taskletRegistry = (TaskletRegistry)componentManager. | |||
| lookup( "org.apache.ant.tasklet.engine.TaskletRegistry" ); | |||
| final TaskletEngine engine = (TaskletEngine)componentManager. | |||
| lookup( "org.apache.ant.tasklet.engine.TaskletEngine" ); | |||
| m_taskletRegistry = engine.getTaskletRegistry(); | |||
| } | |||
| public void setTaskLib( final String tasklib ) | |||
| @@ -59,14 +61,21 @@ public class RegisterTasklet | |||
| public void run() | |||
| throws AntException | |||
| { | |||
| /* | |||
| if( null == m_tasklib ) | |||
| { | |||
| throw new AntException( "Must specify tasklib parameter" ); | |||
| } | |||
| */ | |||
| if( null == m_taskName ) | |||
| { | |||
| throw new AntException( "Must specify taskname parameter" ); | |||
| throw new AntException( "Must specify taskname parameter" ); | |||
| } | |||
| if( null == m_tasklib && null == m_classname ) | |||
| { | |||
| throw new AntException( "Must specify classname if don't specify " + | |||
| "tasklib parameter" ); | |||
| } | |||
| if( null == m_classname ) | |||
| @@ -76,8 +85,13 @@ public class RegisterTasklet | |||
| try | |||
| { | |||
| final File tasklib = new File( getContext().resolveFilename( m_tasklib ) ); | |||
| final URL url = tasklib.toURL(); | |||
| URL url = null; | |||
| if( null != m_tasklib ) | |||
| { | |||
| final File tasklib = new File( getContext().resolveFilename( m_tasklib ) ); | |||
| url = tasklib.toURL(); | |||
| } | |||
| final DefaultTaskletInfo info = new DefaultTaskletInfo( m_classname, url ); | |||