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 ); | |||