blob: a44aa96c2f7f5e2c9b84925d9006b9957f7371c7 [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.project;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.ant.AntException;
import org.apache.ant.configuration.Configuration;
import org.apache.ant.tasklet.DefaultTaskletContext;
import org.apache.ant.tasklet.TaskletContext;
import org.apache.ant.tasklet.engine.DefaultTaskletEngine;
import org.apache.ant.tasklet.engine.TaskletEngine;
import org.apache.ant.util.Condition;
import org.apache.avalon.AbstractLoggable;
import org.apache.avalon.Composer;
import org.apache.avalon.ComponentManager;
import org.apache.avalon.DefaultComponentManager;
import org.apache.avalon.ComponentManagerException;
import org.apache.avalon.DefaultComponentManager;
import org.apache.avalon.Disposable;
import org.apache.avalon.Initializable;
import org.apache.log.Logger;
/**
* This is the default implementation of ProjectEngine.
*
* @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
*/
public class DefaultProjectEngine
extends AbstractLoggable
implements ProjectEngine, Composer
{
protected TaskletEngine m_taskletEngine;
protected ProjectListenerSupport m_listenerSupport = new ProjectListenerSupport();
protected DefaultComponentManager m_componentManager;
/**
* Add a listener to project events.
*
* @param listener the listener
*/
public void addProjectListener( final ProjectListener listener )
{
m_listenerSupport.addProjectListener( listener );
}
/**
* Remove a listener from project events.
*
* @param listener the listener
*/
public void removeProjectListener( final ProjectListener listener )
{
m_listenerSupport.removeProjectListener( listener );
}
/**
* Retrieve relevent services needed for engine.
*
* @param componentManager the ComponentManager
* @exception ComponentManagerException if an error occurs
*/
public void compose( final ComponentManager componentManager )
throws ComponentManagerException
{
m_componentManager = (DefaultComponentManager)componentManager;
m_taskletEngine = (TaskletEngine)componentManager.
lookup( "org.apache.ant.tasklet.engine.TaskletEngine" );
}
/**
* Execute a target in a particular project.
* Execute in the project context.
*
* @param project the Project
* @param target the name of the target
* @exception AntException if an error occurs
*/
public void execute( final Project project, final String target )
throws AntException
{
//HACK: should do this a better way !!!!!!
m_componentManager.put( "org.apache.ant.project.Project", project );
final TaskletContext context = project.getContext();
final String projectName = (String)context.getProperty( Project.PROJECT );
m_listenerSupport.projectStarted( projectName );
//context = new DefaultTaskletContext( context );
executeTargetWork( "<init>", project.getImplicitTarget(), context );
execute( project, target, context );
m_listenerSupport.projectFinished();
}
/**
* Execute a target in a particular project, in a particular context.
*
* @param project the Project
* @param target the name of the target
* @param context the context
* @exception AntException if an error occurs
*/
public void execute( Project project, String target, TaskletContext context )
throws AntException
{
execute( project, target, context, new ArrayList() );
}
/**
* Helper method to execute a target.
*
* @param project the Project
* @param target the name of the target
* @param context the context
* @param done the list of targets already executed in current run
* @exception AntException if an error occurs
*/
protected void execute( final Project project,
final String targetName,
final TaskletContext context,
final ArrayList done )
throws AntException
{
final Target target = project.getTarget( targetName );
if( null == target )
{
throw new AntException( "Unable to find target " + targetName );
}
//add target to list of targets executed
done.add( targetName );
//execute all dependencies
final Iterator dependencies = target.getDependencies();
while( dependencies.hasNext() )
{
final String dependency = (String)dependencies.next();
if( !done.contains( dependency ) )
{
execute( project, dependency, context, done );
}
}
executeTarget( targetName, target, context );
}
/**
* Method to execute a particular target instance.
*
* @param targetName the name of target
* @param target the target
* @param context the context in which to execute
* @exception AntException if an error occurs
*/
protected void executeTarget( final String targetName,
final Target target,
final TaskletContext context )
throws AntException
{
//is this necessary ? I think not but ....
// NO it isn't because you set target name and project has already been provided
//m_componentManager.put( "org.apache.ant.project.Target", target );
//create project context and set target name
final TaskletContext targetContext = new DefaultTaskletContext( context );
targetContext.setProperty( Project.TARGET, targetName );
//notify listeners
m_listenerSupport.targetStarted( targetName );
//actually do the execution work
executeTargetWork( targetName, target, targetContext );
//notify listeners
m_listenerSupport.targetFinished();
}
/**
* Do the work associated with target.
* ie execute all tasks
*
* @param name the name of target
* @param target the target
* @param context the context
*/
protected void executeTargetWork( final String name,
final Target target,
final TaskletContext context )
{
//check the condition associated with target.
//if it is not satisfied then skip target
final Condition condition = target.getCondition();
if( null != condition )
{
if( false == condition.evaluate( context ) )
{
getLogger().debug( "Skipping target " + name +
" as it does not satisfy condition" );
return;
}
}
getLogger().debug( "Executing target " + name );
//execute all tasks assciated with target
final Iterator tasks = target.getTasks();
while( tasks.hasNext() )
{
final Configuration task = (Configuration)tasks.next();
executeTask( task, context );
}
}
/**
* Execute a task.
*
* @param task the task definition
* @param context the context
* @exception AntException if an error occurs
*/
protected void executeTask( final Configuration task, final TaskletContext context )
throws AntException
{
final String name = task.getName();
getLogger().debug( "Executing task " + name );
//Set up context for task...
//is Only necessary if we are multi-threaded
//final TaskletContext targetContext = new DefaultTaskletContext( context );
//is setting name even necessary ???
context.setProperty( TaskletContext.NAME, name );
//notify listeners
m_listenerSupport.taskletStarted( name );
//run task
m_taskletEngine.execute( task, context );
//notify listeners task has ended
m_listenerSupport.taskletFinished();
}
}