From ab5d2d667652fc27a6965c50a9d0bc5d06035497 Mon Sep 17 00:00:00 2001 From: Peter Donald Date: Wed, 6 Dec 2000 00:23:43 +0000 Subject: [PATCH] Started adding some documentation and exporting the correct services via CM rather than all services. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268313 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/ant/AntContextResources.java | 5 + .../src/java/org/apache/ant/AntException.java | 20 ++ .../src/java/org/apache/ant/Main.java | 183 ++++++++++++++---- .../ant/configuration/Configuration.java | 5 +- .../configuration/ConfigurationBuilder.java | 5 +- .../configuration/DefaultConfiguration.java | 5 +- .../SAXConfigurationHandler.java | 5 +- .../apache/ant/convert/AbstractConverter.java | 21 ++ .../org/apache/ant/convert/Converter.java | 10 + .../apache/ant/convert/ConverterEntry.java | 6 + .../apache/ant/convert/ConverterFactory.java | 7 + .../apache/ant/convert/ConverterLoader.java | 7 + .../apache/ant/convert/ConverterRegistry.java | 13 +- .../ant/convert/DefaultConverterFactory.java | 27 +++ .../ant/convert/DefaultConverterLoader.java | 7 + .../ant/convert/DefaultConverterRegistry.java | 12 ++ .../org/apache/ant/launcher/AntLoader.java | 21 +- .../ant/project/DefaultProjectEngine.java | 51 ++--- .../apache/ant/tasklet/AbstractTasklet.java | 1 + .../ant/tasklet/DefaultTaskletContext.java | 3 +- .../org/apache/ant/tasklet/JavaVersion.java | 8 + .../java/org/apache/ant/tasklet/Tasklet.java | 7 + .../engine/DefaultTaskletConfigurer.java | 38 +++- .../tasklet/engine/DefaultTaskletEngine.java | 82 ++++---- .../tasklet/engine/DefaultTaskletLoader.java | 9 +- .../ant/tasklet/engine/TaskletConfigurer.java | 10 + .../ant/tasklet/engine/TaskletEngine.java | 36 +++- .../ant/tasklet/engine/TaskletLoader.java | 7 + .../ant/tasklet/engine/TaskletRegistry.java | 5 + .../ant/tasks/core/RegisterTasklet.java | 26 ++- 30 files changed, 527 insertions(+), 115 deletions(-) diff --git a/proposal/myrmidon/src/java/org/apache/ant/AntContextResources.java b/proposal/myrmidon/src/java/org/apache/ant/AntContextResources.java index fff46f0c9..c43186240 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/AntContextResources.java +++ b/proposal/myrmidon/src/java/org/apache/ant/AntContextResources.java @@ -7,6 +7,11 @@ */ package org.apache.ant; +/** + * Interface that holds constants used to access variables from context. + * + * @author Peter Donald + */ public interface AntContextResources { // the directory of ant diff --git a/proposal/myrmidon/src/java/org/apache/ant/AntException.java b/proposal/myrmidon/src/java/org/apache/ant/AntException.java index 846b52c35..c5651124b 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/AntException.java +++ b/proposal/myrmidon/src/java/org/apache/ant/AntException.java @@ -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 Peter Donald + */ 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 ); diff --git a/proposal/myrmidon/src/java/org/apache/ant/Main.java b/proposal/myrmidon/src/java/org/apache/ant/Main.java index 4f28ab4a6..59aa2a7f8 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/Main.java +++ b/proposal/myrmidon/src/java/org/apache/ant/Main.java @@ -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 ) { diff --git a/proposal/myrmidon/src/java/org/apache/ant/configuration/Configuration.java b/proposal/myrmidon/src/java/org/apache/ant/configuration/Configuration.java index c410857e3..f696f4847 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/configuration/Configuration.java +++ b/proposal/myrmidon/src/java/org/apache/ant/configuration/Configuration.java @@ -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 Peter Donald */ public interface Configuration extends org.apache.avalon.Configuration diff --git a/proposal/myrmidon/src/java/org/apache/ant/configuration/ConfigurationBuilder.java b/proposal/myrmidon/src/java/org/apache/ant/configuration/ConfigurationBuilder.java index a90c6c875..066b8a661 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/configuration/ConfigurationBuilder.java +++ b/proposal/myrmidon/src/java/org/apache/ant/configuration/ConfigurationBuilder.java @@ -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 Peter Donald */ public class ConfigurationBuilder extends org.apache.avalon.DefaultConfigurationBuilder diff --git a/proposal/myrmidon/src/java/org/apache/ant/configuration/DefaultConfiguration.java b/proposal/myrmidon/src/java/org/apache/ant/configuration/DefaultConfiguration.java index 916a5dc40..1bcd88f3a 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/configuration/DefaultConfiguration.java +++ b/proposal/myrmidon/src/java/org/apache/ant/configuration/DefaultConfiguration.java @@ -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 Peter Donald */ public class DefaultConfiguration extends org.apache.avalon.DefaultConfiguration diff --git a/proposal/myrmidon/src/java/org/apache/ant/configuration/SAXConfigurationHandler.java b/proposal/myrmidon/src/java/org/apache/ant/configuration/SAXConfigurationHandler.java index 0a3569bea..6802bdb0f 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/configuration/SAXConfigurationHandler.java +++ b/proposal/myrmidon/src/java/org/apache/ant/configuration/SAXConfigurationHandler.java @@ -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 Peter Donald */ public class SAXConfigurationHandler extends org.apache.avalon.SAXConfigurationHandler diff --git a/proposal/myrmidon/src/java/org/apache/ant/convert/AbstractConverter.java b/proposal/myrmidon/src/java/org/apache/ant/convert/AbstractConverter.java index bdadecdea..521cb9295 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/convert/AbstractConverter.java +++ b/proposal/myrmidon/src/java/org/apache/ant/convert/AbstractConverter.java @@ -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; } diff --git a/proposal/myrmidon/src/java/org/apache/ant/convert/Converter.java b/proposal/myrmidon/src/java/org/apache/ant/convert/Converter.java index a16b13a60..bcbdfcb33 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/convert/Converter.java +++ b/proposal/myrmidon/src/java/org/apache/ant/convert/Converter.java @@ -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; } diff --git a/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterEntry.java b/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterEntry.java index 18c7b1ee3..6b411e788 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterEntry.java +++ b/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterEntry.java @@ -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 Peter Donald + */ public class ConverterEntry extends AbstractEntry { diff --git a/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterFactory.java b/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterFactory.java index 504025622..fd5dd8266 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterFactory.java +++ b/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterFactory.java @@ -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; } diff --git a/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterLoader.java b/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterLoader.java index 13c975dae..8650cf22a 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterLoader.java +++ b/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterLoader.java @@ -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; } diff --git a/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterRegistry.java b/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterRegistry.java index 8feccecf5..0cd3e805f 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterRegistry.java +++ b/proposal/myrmidon/src/java/org/apache/ant/convert/ConverterRegistry.java @@ -8,9 +8,20 @@ package org.apache.ant.convert; import org.apache.avalon.camelot.Registry; - +/** + * Interface for registry for ConverterInfos. + * + * @author Peter Donald + */ 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 ); } diff --git a/proposal/myrmidon/src/java/org/apache/ant/convert/DefaultConverterFactory.java b/proposal/myrmidon/src/java/org/apache/ant/convert/DefaultConverterFactory.java index 256735905..d6766f740 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/convert/DefaultConverterFactory.java +++ b/proposal/myrmidon/src/java/org/apache/ant/convert/DefaultConverterFactory.java @@ -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 ); diff --git a/proposal/myrmidon/src/java/org/apache/ant/convert/DefaultConverterLoader.java b/proposal/myrmidon/src/java/org/apache/ant/convert/DefaultConverterLoader.java index 225fb8b19..f72176b85 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/convert/DefaultConverterLoader.java +++ b/proposal/myrmidon/src/java/org/apache/ant/convert/DefaultConverterLoader.java @@ -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 { diff --git a/proposal/myrmidon/src/java/org/apache/ant/convert/DefaultConverterRegistry.java b/proposal/myrmidon/src/java/org/apache/ant/convert/DefaultConverterRegistry.java index 54eaaecb3..a1522bcea 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/convert/DefaultConverterRegistry.java +++ b/proposal/myrmidon/src/java/org/apache/ant/convert/DefaultConverterRegistry.java @@ -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 Peter Donald + */ 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 ); diff --git a/proposal/myrmidon/src/java/org/apache/ant/launcher/AntLoader.java b/proposal/myrmidon/src/java/org/apache/ant/launcher/AntLoader.java index b61ac79bd..45c3a2e8e 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/launcher/AntLoader.java +++ b/proposal/myrmidon/src/java/org/apache/ant/launcher/AntLoader.java @@ -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 Peter Donald */ @@ -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 ); diff --git a/proposal/myrmidon/src/java/org/apache/ant/project/DefaultProjectEngine.java b/proposal/myrmidon/src/java/org/apache/ant/project/DefaultProjectEngine.java index a2780c6ec..8628a3844 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/project/DefaultProjectEngine.java +++ b/proposal/myrmidon/src/java/org/apache/ant/project/DefaultProjectEngine.java @@ -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(); diff --git a/proposal/myrmidon/src/java/org/apache/ant/tasklet/AbstractTasklet.java b/proposal/myrmidon/src/java/org/apache/ant/tasklet/AbstractTasklet.java index 82f415300..d381f811b 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/tasklet/AbstractTasklet.java +++ b/proposal/myrmidon/src/java/org/apache/ant/tasklet/AbstractTasklet.java @@ -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; diff --git a/proposal/myrmidon/src/java/org/apache/ant/tasklet/DefaultTaskletContext.java b/proposal/myrmidon/src/java/org/apache/ant/tasklet/DefaultTaskletContext.java index 34437ffcc..3f7e53675 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/tasklet/DefaultTaskletContext.java +++ b/proposal/myrmidon/src/java/org/apache/ant/tasklet/DefaultTaskletContext.java @@ -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 Peter Donald */ diff --git a/proposal/myrmidon/src/java/org/apache/ant/tasklet/JavaVersion.java b/proposal/myrmidon/src/java/org/apache/ant/tasklet/JavaVersion.java index e702b1bd1..e4ab6a706 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/tasklet/JavaVersion.java +++ b/proposal/myrmidon/src/java/org/apache/ant/tasklet/JavaVersion.java @@ -11,6 +11,8 @@ import org.apache.avalon.util.ValuedEnum; /** * Type safe wrapper class for Java Version enums. + * + * @author Peter Donald */ 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 ); diff --git a/proposal/myrmidon/src/java/org/apache/ant/tasklet/Tasklet.java b/proposal/myrmidon/src/java/org/apache/ant/tasklet/Tasklet.java index a19e92935..cb31a5df4 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/tasklet/Tasklet.java +++ b/proposal/myrmidon/src/java/org/apache/ant/tasklet/Tasklet.java @@ -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 Peter Donald */ diff --git a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/DefaultTaskletConfigurer.java b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/DefaultTaskletConfigurer.java index 1348abbbb..d69b38246 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/DefaultTaskletConfigurer.java +++ b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/DefaultTaskletConfigurer.java @@ -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] ); } diff --git a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/DefaultTaskletEngine.java b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/DefaultTaskletEngine.java index 2e095b6ed..6a540f125 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/DefaultTaskletEngine.java +++ b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/DefaultTaskletEngine.java @@ -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 ) diff --git a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/DefaultTaskletLoader.java b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/DefaultTaskletLoader.java index 87e9eac97..8ddc01bce 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/DefaultTaskletLoader.java +++ b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/DefaultTaskletLoader.java @@ -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 { diff --git a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletConfigurer.java b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletConfigurer.java index 3e23680a0..d9621e9b8 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletConfigurer.java +++ b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletConfigurer.java @@ -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; } diff --git a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletEngine.java b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletEngine.java index 139a88776..1210bd172 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletEngine.java +++ b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletEngine.java @@ -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 Peter Donald + */ 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; } diff --git a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletLoader.java b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletLoader.java index 913469aff..ea703959a 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletLoader.java +++ b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletLoader.java @@ -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; } diff --git a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletRegistry.java b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletRegistry.java index 59cf3a03c..501bdf75f 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletRegistry.java +++ b/proposal/myrmidon/src/java/org/apache/ant/tasklet/engine/TaskletRegistry.java @@ -9,6 +9,11 @@ package org.apache.ant.tasklet.engine; import org.apache.avalon.camelot.Registry; +/** + * The registry for tasklets + * + * @author Peter Donald + */ public interface TaskletRegistry extends Registry { diff --git a/proposal/myrmidon/src/java/org/apache/ant/tasks/core/RegisterTasklet.java b/proposal/myrmidon/src/java/org/apache/ant/tasks/core/RegisterTasklet.java index 99595e65e..dbee8c3ac 100644 --- a/proposal/myrmidon/src/java/org/apache/ant/tasks/core/RegisterTasklet.java +++ b/proposal/myrmidon/src/java/org/apache/ant/tasks/core/RegisterTasklet.java @@ -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 );