blob: cd41fe2d7380d5a98c36fe60ab8c4fb6f500384f [file] [log] [blame]
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.ant;
import java.io.File;
import java.util.Properties;
import org.apache.ant.configuration.Configurer;
import org.apache.ant.convert.engine.ConverterEngine;
import org.apache.ant.tasklet.engine.DataTypeEngine;
import org.apache.ant.project.ProjectBuilder;
import org.apache.ant.project.ProjectEngine;
import org.apache.ant.tasklet.JavaVersion;
import org.apache.ant.tasklet.engine.TaskletEngine;
import org.apache.ant.tasklet.engine.TskDeployer;
import org.apache.avalon.AbstractLoggable;
import org.apache.avalon.Component;
import org.apache.avalon.Composer;
import org.apache.avalon.DefaultComponentManager;
import org.apache.avalon.Initializable;
import org.apache.avalon.camelot.CamelotUtil;
import org.apache.avalon.camelot.DefaultFactory;
import org.apache.avalon.camelot.Deployer;
import org.apache.avalon.camelot.Factory;
import org.apache.avalon.util.ObjectUtil;
import org.apache.avalon.util.io.FileUtil;
/**
* Default implementation of Ant runtime.
*
* @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
*/
public class DefaultAntEngine
extends AbstractLoggable
implements AntEngine, Initializable
{
protected ConverterEngine m_converterEngine;
protected DataTypeEngine m_dataTypeEngine;
protected TaskletEngine m_taskletEngine;
protected ProjectEngine m_projectEngine;
protected ProjectBuilder m_builder;
protected TskDeployer m_deployer;
protected Configurer m_configurer;
protected Factory m_factory;
protected DefaultComponentManager m_componentManager;
protected Properties m_properties;
protected Properties m_defaults;
protected File m_homeDir;
protected File m_binDir;
protected File m_libDir;
protected File m_taskLibDir;
/**
* Setup basic properties of engine.
* Called before init() and can be used to specify alternate components in system.
*
* @param properties the properties
*/
public void setProperties( final Properties properties )
{
m_properties = properties;
}
/**
* Retrieve builder for runtime.
* Valid after init() call
*
* @return the ProjectBuilder
*/
public ProjectBuilder getProjectBuilder()
{
return m_builder;
}
/**
* Retrieve project engine for runtime.
* Valid after init() call
*
* @return the ProjectBuilder
*/
public ProjectEngine getProjectEngine()
{
return m_projectEngine;
}
/**
* Initialize the system.
*
* @exception Exception if an error occurs
*/
public void init()
throws Exception
{
//setup default properties
m_defaults = createDefaultProperties();
//create all the components
m_factory = new DefaultFactory();
createComponents();
//setup the component manager
m_componentManager = createComponentManager();
setupComponents();
setupFiles();
CamelotUtil.deployFromDirectory( m_deployer, m_taskLibDir, ".tsk" );
}
/**
* Dispose engine.
*
* @exception Exception if an error occurs
*/
public void dispose()
throws Exception
{
m_converterEngine = null;
m_dataTypeEngine = null;
m_taskletEngine = null;
m_projectEngine = null;
m_builder = null;
m_deployer = null;
m_configurer = null;
m_factory = null;
m_componentManager = null;
m_properties = null;
m_defaults = null;
m_homeDir = null;
m_binDir = null;
m_libDir = null;
m_taskLibDir = null;
}
/**
* Create default properties which includes default names of all components.
* Overide this in sub-classes to change values.
*
* @return the Properties
*/
protected Properties createDefaultProperties()
{
final Properties defaults = new Properties();
//create all the default properties for files/directories
defaults.setProperty( "ant.path.bin", "bin" );
defaults.setProperty( "ant.path.lib", "lib" );
defaults.setProperty( "ant.path.task-lib", "lib" );
//create all the default properties for components
defaults.setProperty( "ant.comp.converter",
"org.apache.ant.convert.engine.DefaultConverterEngine" );
defaults.setProperty( "ant.comp.datatype",
"org.apache.ant.tasklet.engine.DefaultDataTypeEngine" );
defaults.setProperty( "ant.comp.tasklet",
"org.apache.ant.tasklet.engine.DefaultTaskletEngine" );
defaults.setProperty( "ant.comp.project",
"org.apache.ant.project.DefaultProjectEngine" );
defaults.setProperty( "ant.comp.builder",
"org.apache.ant.project.DefaultProjectBuilder" );
defaults.setProperty( "ant.comp.deployer",
"org.apache.ant.tasklet.engine.DefaultTskDeployer" );
defaults.setProperty( "ant.comp.configurer",
"org.apache.ant.configuration.DefaultConfigurer" );
return defaults;
}
/**
* Create a ComponentManager containing all components in engine.
*
* @return the ComponentManager
*/
protected DefaultComponentManager createComponentManager()
{
final DefaultComponentManager componentManager = new DefaultComponentManager();
componentManager.put( "org.apache.ant.tasklet.engine.TaskletEngine", m_taskletEngine );
componentManager.put( "org.apache.ant.project.ProjectEngine", m_projectEngine );
componentManager.put( "org.apache.ant.convert.engine.ConverterEngine",
m_converterEngine );
componentManager.put( "org.apache.ant.convert.Converter", m_converterEngine );
componentManager.put( "org.apache.ant.tasklet.engine.DataTypeEngine", m_dataTypeEngine );
componentManager.put( "org.apache.ant.project.ProjectBuilder", m_builder );
componentManager.put( "org.apache.ant.tasklet.engine.TskDeployer", m_deployer );
componentManager.put( "org.apache.avalon.camelot.Factory", m_factory );
componentManager.put( "org.apache.ant.configuration.Configurer", m_configurer );
return componentManager;
}
/**
* Create all required components.
*
* @exception Exception if an error occurs
*/
protected void createComponents()
throws Exception
{
String component = null;
component = getProperty( "ant.comp.converter" );
m_converterEngine = (ConverterEngine)createComponent( component, ConverterEngine.class );
component = getProperty( "ant.comp.datatype" );
m_dataTypeEngine = (DataTypeEngine)createComponent( component, DataTypeEngine.class );
component = getProperty( "ant.comp.tasklet" );
m_taskletEngine = (TaskletEngine)createComponent( component, TaskletEngine.class );
component = getProperty( "ant.comp.project" );
m_projectEngine = (ProjectEngine)createComponent( component, ProjectEngine.class );
component = getProperty( "ant.comp.builder" );
m_builder =(ProjectBuilder)createComponent( component, ProjectBuilder.class );
component = getProperty( "ant.comp.deployer" );
m_deployer = (TskDeployer)createComponent( component, TskDeployer.class );
component = getProperty( "ant.comp.configurer" );
m_configurer = (Configurer)createComponent( component, Configurer.class );
}
/**
* Setup all the components. (ir run all required lifecycle methods).
*
* @exception Exception if an error occurs
*/
protected void setupComponents()
throws Exception
{
setupComponent( m_factory );
setupComponent( m_converterEngine );
setupComponent( m_dataTypeEngine );
setupComponent( m_taskletEngine );
setupComponent( m_projectEngine );
setupComponent( m_builder );
setupComponent( m_deployer );
setupComponent( m_configurer );
}
/**
* Setup an individual component.
*
* @param component the component
* @exception Exception if an error occurs
*/
protected void setupComponent( final Component component )
throws Exception
{
setupLogger( component );
if( component instanceof Composer )
{
((Composer)component).compose( m_componentManager );
}
if( component instanceof Initializable )
{
((Initializable)component).init();
}
}
/**
* Setup all the files attributes.
*/
protected void setupFiles()
{
String filepath = null;
filepath = getProperty( "ant.home" );
m_homeDir = (new File( filepath )).getAbsoluteFile();
checkDirectory( m_homeDir, "ant-home" );
filepath = getProperty( "ant.path.bin" );
m_binDir = resolveDirectory( filepath, "bin-dir" );
filepath = getProperty( "ant.path.lib" );
m_libDir = resolveDirectory( filepath, "lib-dir" );
filepath = getProperty( "ant.path.task-lib" );
m_taskLibDir = resolveDirectory( filepath, "task-lib-dir" );
}
/**
* Retrieve value of named property.
* First access passed in properties and then the default properties.
*
* @param name the name of property
* @return the value of property or null
*/
protected String getProperty( final String name )
{
String value = m_properties.getProperty( name );
if( null == value )
{
value = m_defaults.getProperty( name );
}
return value;
}
/**
* Resolve a directory relative to another base directory.
*
* @param dir the base directory
* @param name the relative directory
* @return the created File
* @exception AntException if an error occurs
*/
protected File resolveDirectory( final String dir, final String name )
throws AntException
{
final File file = FileUtil.resolveFile( m_homeDir, dir );
checkDirectory( file, name );
return file;
}
/**
* Verify file is a directory else throw an exception.
*
* @param file the File
* @param name the name of file type (used in error messages)
*/
protected void checkDirectory( final File file, final String name )
throws AntException
{
if( !file.exists() )
{
throw new AntException( name + " (" + file + ") does not exist" );
}
else if( !file.isDirectory() )
{
throw new AntException( name + " (" + file + ") is not a directory" );
}
}
/**
* Helper method to retrieve current JVM version.
* Basically stolen from original Ant sources.
*
* @return the current JVM version
*/
protected JavaVersion getJavaVersion()
{
JavaVersion version = JavaVersion.JAVA1_0;
try
{
Class.forName( "java.lang.Void" );
version = JavaVersion.JAVA1_1;
Class.forName( "java.lang.ThreadLocal" );
version = JavaVersion.JAVA1_2;
Class.forName( "java.lang.StrictMath" );
version = JavaVersion.JAVA1_3;
}
catch( final ClassNotFoundException cnfe ) {}
return version;
}
/**
* Create a component that implements an interface.
*
* @param component the name of the component
* @param clazz the name of interface/type
* @return the created object
* @exception AntException if an error occurs
*/
protected Object createComponent( final String component, final Class clazz )
throws AntException
{
try
{
final Object object = ObjectUtil.createObject( component );
if( !clazz.isInstance( object ) )
{
throw new AntException( "Object " + component + " is not an instance of " +
clazz );
}
return object;
}
catch( final IllegalAccessException iae )
{
throw new AntException( "Non-public constructor for " + clazz + " " + component,
iae );
}
catch( final InstantiationException ie )
{
throw new AntException( "Error instantiating class for " + clazz + " " + component,
ie );
}
catch( final ClassNotFoundException cnfe )
{
throw new AntException( "Could not find the class for " + clazz +
" (" + component + ")", cnfe );
}
}
}