git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271453 13f79535-47bb-0310-9956-ffa450edef68master
@@ -25,4 +25,4 @@ java -classpath bin/init:bin/bootstrap org.apache.ant.bootstrap.Bootstrap | |||
java -classpath bootstrap/lib/start.jar:bootstrap/lib/init.jar org.apache.ant.start.Main $* | |||
# Use the full build as the build used by the build script | |||
cp -r dist/* bootstrap | |||
cp -r dist/lib bootstrap |
@@ -1,6 +1,6 @@ | |||
#!/bin/sh | |||
#!/bin/sh -x | |||
# Copyright (c) 2000-2001 The Apache Software Foundation. All rights | |||
# reserved. | |||
java -classpath bootstrap/lib/start.jar:bootstrap/lib/init.jar org.apache.ant.start.Main $* | |||
java -classpath bootstrap/lib/start.jar:bootstrap/lib/init.jar org.apache.ant.start.Main $@ |
@@ -28,8 +28,8 @@ | |||
<exclude name="org/apache/tools/ant/taskdefs/RecorderEntry.java"/> | |||
<exclude name="org/apache/tools/ant/taskdefs/optional/Native2Ascii.java"/> | |||
<exclude name="org/apache/tools/ant/taskdefs/optional/Javah.java"/> | |||
<exclude name="org/apache/tools/ant/taskdefs/Parallel.java"/> | |||
<exclude name="org/apache/tools/ant/taskdefs/Sequential.java"/> | |||
<!-- <exclude name="org/apache/tools/ant/taskdefs/Parallel.java"/> --> | |||
<!-- <exclude name="org/apache/tools/ant/taskdefs/Sequential.java"/> --> | |||
<exclude name="org/apache/tools/ant/taskdefs/optional/jdepend/*.java"/> | |||
</patternset> | |||
@@ -1,49 +0,0 @@ | |||
<project name="build-site" default="docs" basedir="."> | |||
<!-- Initialization properties --> | |||
<property name="project.name" value="mutant"/> | |||
<property name="docs.src" location="xdocs"/> | |||
<property name="docs.dest" location="docs"/> | |||
<property name="project.file" value="stylesheets/project.xml" /> | |||
<property name="site.dir" location="../../../jakarta-site2" /> | |||
<property name="templ.path" location="xdocs/stylesheets" /> | |||
<property name="velocity.props" location="${docs.src}/velocity.properties" /> | |||
<path id="anakia.classpath"> | |||
<fileset dir="${site.dir}/lib"> | |||
<include name="*.jar"/> | |||
</fileset> | |||
</path> | |||
<target name="prepare"> | |||
<available classname="org.apache.velocity.anakia.AnakiaTask" | |||
property="AnakiaTask.present"> | |||
<classpath refid="anakia.classpath"/> | |||
</available> | |||
</target> | |||
<target depends="prepare" name="prepare-error" unless="AnakiaTask.present"> | |||
<echo> | |||
AnakiaTask is not present! Please check to make sure that | |||
velocity.jar is in your classpath. | |||
</echo> | |||
</target> | |||
<target name="docs" depends="prepare-error" if="AnakiaTask.present"> | |||
<taskdef name="anakia" classname="org.apache.velocity.anakia.AnakiaTask"> | |||
<classpath refid="anakia.classpath"/> | |||
</taskdef> | |||
<anakia basedir="${docs.src}" destdir="${docs.dest}/" | |||
extension=".html" style="./site.vsl" | |||
projectFile="${project.file}" | |||
excludes="**/stylesheets/** faq.xml" | |||
includes="**/*.xml" | |||
lastModifiedCheck="true" | |||
templatePath="${templ.path}" | |||
velocityPropertiesFile="${velocity.props}"> | |||
</anakia> | |||
</target> | |||
<target name="all" depends="docs"/> | |||
</project> |
@@ -59,6 +59,7 @@ import java.util.List; | |||
import org.apache.ant.common.model.ModelElement; | |||
import org.apache.ant.common.event.BuildListener; | |||
import org.apache.ant.common.event.BuildEvent; | |||
import org.apache.ant.common.antlib.Task; | |||
/** | |||
* BuildEventSupport is used by classes which which to send build events to | |||
@@ -162,10 +163,10 @@ public class BuildEventSupport { | |||
/** | |||
* fire a task started event | |||
* | |||
* @param element the build element with which the event is associated | |||
* @param task the task with which the event is associated | |||
*/ | |||
public void fireTaskStarted(ModelElement element) { | |||
BuildEvent event = new BuildEvent(element, BuildEvent.TASK_STARTED); | |||
public void fireTaskStarted(Task task) { | |||
BuildEvent event = new BuildEvent(task, BuildEvent.TASK_STARTED); | |||
for (Iterator i = listeners.iterator(); i.hasNext(); ) { | |||
BuildListener listener = (BuildListener)i.next(); | |||
listener.taskStarted(event); | |||
@@ -175,12 +176,12 @@ public class BuildEventSupport { | |||
/** | |||
* fire a task finished event | |||
* | |||
* @param element the build element with which the event is associated | |||
* @param task the task with which the event is associated | |||
* @param cause an exception if there was a failure in the task | |||
*/ | |||
public void fireTaskFinished(ModelElement element, | |||
public void fireTaskFinished(Task task, | |||
Throwable cause) { | |||
BuildEvent event = new BuildEvent(element, BuildEvent.TASK_FINISHED, | |||
BuildEvent event = new BuildEvent(task, BuildEvent.TASK_FINISHED, | |||
cause); | |||
for (Iterator i = listeners.iterator(); i.hasNext(); ) { | |||
BuildListener listener = (BuildListener)i.next(); | |||
@@ -68,10 +68,17 @@ import org.apache.ant.antcore.antlib.ComponentLibrary; | |||
import org.apache.ant.antcore.antlib.DynamicLibrary; | |||
import org.apache.ant.common.antlib.AntLibFactory; | |||
import org.apache.ant.common.antlib.Converter; | |||
import org.apache.ant.common.antlib.DeferredTask; | |||
import org.apache.ant.common.antlib.ExecutionComponent; | |||
import org.apache.ant.common.antlib.StandardLibFactory; | |||
import org.apache.ant.common.antlib.Task; | |||
import org.apache.ant.common.antlib.TaskContainer; | |||
import org.apache.ant.common.event.MessageLevel; | |||
import org.apache.ant.common.model.BuildElement; | |||
import org.apache.ant.common.service.ComponentService; | |||
import org.apache.ant.common.util.ExecutionException; | |||
import org.apache.ant.common.util.Location; | |||
import org.apache.ant.init.LoaderUtils; | |||
/** | |||
* The instance of the ComponentServices made available by the core to the | |||
@@ -81,9 +88,6 @@ import org.apache.ant.common.util.ExecutionException; | |||
* @created 27 January 2002 | |||
*/ | |||
public class ComponentManager implements ComponentService { | |||
/** The prefix for library ids that are automatically imported */ | |||
public static final String ANT_LIB_PREFIX = "ant."; | |||
/** | |||
* Type converters for this frame. Converters are used when configuring | |||
* Tasks to handle special type conversions. | |||
@@ -120,6 +124,10 @@ public class ComponentManager implements ComponentService { | |||
*/ | |||
private Map libPathsMap; | |||
/** Reflector objects used to configure Tasks from the Task models. */ | |||
private Map setters = new HashMap(); | |||
/** | |||
* Constructor | |||
* | |||
@@ -279,26 +287,41 @@ public class ComponentManager implements ComponentService { | |||
*/ | |||
public void importFrameComponent(String relativeName, String alias) | |||
throws ExecutionException { | |||
ImportInfo definition | |||
= frame.getReferencedDefinition(relativeName); | |||
ImportInfo definition | |||
= frame.getReferencedDefinition(relativeName); | |||
if (definition == null) { | |||
throw new ExecutionException("The reference \"relativeName\" does" | |||
+ " not refer to a defined component"); | |||
throw new ExecutionException("The reference \"relativeName\" does" | |||
+ " not refer to a defined component"); | |||
} | |||
String label = alias; | |||
if (label == null) { | |||
label = frame.getNameInFrame(relativeName); | |||
} | |||
frame.log("Adding referenced component <" + definition.getLocalName() | |||
+ "> as <" + label + "> from library \"" | |||
frame.log("Adding referenced component <" + definition.getLocalName() | |||
+ "> as <" + label + "> from library \"" | |||
+ definition.getComponentLibrary().getLibraryId() + "\", class: " | |||
+ definition.getClassName(), MessageLevel.MSG_DEBUG); | |||
definitions.put(label, definition); | |||
} | |||
/** | |||
* Create a component. The component will have a context but will not be | |||
* configured. It should be configured using the appropriate set methods | |||
* and then validated before being used. | |||
* | |||
* @param componentName the name of the component | |||
* @return the created component. The return type of this method depends | |||
* on the component type. | |||
* @exception ExecutionException if the component cannot be created | |||
*/ | |||
public Object createComponent(String componentName) | |||
throws ExecutionException { | |||
return createComponent(componentName, null); | |||
} | |||
/** | |||
* Set the standard libraries (i.e. those which are independent of the | |||
* build files) to be used in this component manager | |||
@@ -316,7 +339,7 @@ public class ComponentManager implements ComponentService { | |||
// go through the libraries and import all standard ant libraries | |||
for (Iterator i = antLibraries.keySet().iterator(); i.hasNext(); ) { | |||
String libraryId = (String)i.next(); | |||
if (libraryId.startsWith(ANT_LIB_PREFIX)) { | |||
if (libraryId.startsWith(Constants.ANT_LIB_PREFIX)) { | |||
// standard library - import whole library | |||
importLibrary(libraryId); | |||
} | |||
@@ -348,8 +371,9 @@ public class ComponentManager implements ComponentService { | |||
if (libFactories.containsKey(libraryId)) { | |||
return (AntLibFactory)libFactories.get(libraryId); | |||
} | |||
AntLibFactory libFactory | |||
= componentLibrary.getFactory(new ExecutionContext(frame)); | |||
ExecutionContext context | |||
= new ExecutionContext(frame, null, Location.UNKNOWN_LOCATION); | |||
AntLibFactory libFactory = componentLibrary.getFactory(context); | |||
if (libFactory == null) { | |||
libFactory = new StandardLibFactory(); | |||
} | |||
@@ -368,6 +392,109 @@ public class ComponentManager implements ComponentService { | |||
return (ImportInfo)definitions.get(name); | |||
} | |||
/** | |||
* Create a component from a build model | |||
* | |||
* @param model the build model representing the component and its | |||
* configuration | |||
* @return the configured component | |||
* @exception ExecutionException if there is a problem creating or | |||
* configuring the component | |||
*/ | |||
protected Object createComponent(BuildElement model) | |||
throws ExecutionException { | |||
String componentName = model.getType(); | |||
return createComponent(componentName, model); | |||
} | |||
/** | |||
* Create a component. | |||
* | |||
* @param componentName the name of the component which is used to | |||
* select the object type to be created | |||
* @param model the build model of the component. If this is null, the | |||
* component is created but not configured. | |||
* @return the configured component | |||
* @exception ExecutionException if there is a problem creating or | |||
* configuring the component | |||
*/ | |||
protected Object createComponent(String componentName, BuildElement model) | |||
throws ExecutionException { | |||
ImportInfo definition = getDefinition(componentName); | |||
String className = definition.getClassName(); | |||
ComponentLibrary componentLibrary | |||
= definition.getComponentLibrary(); | |||
String localName = definition.getLocalName(); | |||
try { | |||
ClassLoader componentLoader = componentLibrary.getClassLoader(); | |||
Class componentClass | |||
= Class.forName(className, true, componentLoader); | |||
AntLibFactory libFactory = getLibFactory(componentLibrary); | |||
Location location = Location.UNKNOWN_LOCATION; | |||
if (model != null) { | |||
location = model.getLocation(); | |||
} | |||
Object component | |||
= libFactory.createComponent(componentClass, localName); | |||
ExecutionComponent execComponent = null; | |||
if (definition.getDefinitionType() == AntLibrary.TASKDEF) { | |||
if (component instanceof Task) { | |||
execComponent = (Task)component; | |||
} else { | |||
execComponent = new TaskAdapter(componentName, component); | |||
} | |||
} else if (component instanceof ExecutionComponent) { | |||
execComponent = (ExecutionComponent)component; | |||
} | |||
ExecutionContext context | |||
= new ExecutionContext(frame, execComponent, location); | |||
context.setClassLoader(componentLoader); | |||
ClassLoader currentLoader | |||
= LoaderUtils.setContextLoader(componentLoader); | |||
if (execComponent != null) { | |||
execComponent.init(context, componentName); | |||
} | |||
if (model != null) { | |||
configureElement(libFactory, component, model); | |||
if (execComponent != null) { | |||
execComponent.validateComponent(); | |||
} | |||
} | |||
LoaderUtils.setContextLoader(currentLoader); | |||
if (execComponent != null) { | |||
return execComponent; | |||
} | |||
return component; | |||
} catch (ClassNotFoundException e) { | |||
throw new ExecutionException("Class " + className | |||
+ " for component <" + componentName + "> was not found", e, | |||
model.getLocation()); | |||
} catch (NoClassDefFoundError e) { | |||
throw new ExecutionException("Could not load a dependent class (" | |||
+ e.getMessage() + ") for component " + componentName, | |||
e, model.getLocation()); | |||
} catch (InstantiationException e) { | |||
throw new ExecutionException("Unable to instantiate component " | |||
+ "class " + className + " for component <" + componentName | |||
+ ">", e, model.getLocation()); | |||
} catch (IllegalAccessException e) { | |||
throw new ExecutionException("Unable to access task class " | |||
+ className + " for component <" + componentName + ">", | |||
e, model.getLocation()); | |||
} catch (ExecutionException e) { | |||
e.setLocation(model.getLocation(), false); | |||
throw e; | |||
} catch (RuntimeException e) { | |||
throw new ExecutionException(e.getClass().getName() + ": " | |||
+ e.getMessage(), e, model.getLocation()); | |||
} | |||
} | |||
/** | |||
* Import a single component from the given library | |||
* | |||
@@ -390,6 +517,268 @@ public class ComponentManager implements ComponentService { | |||
definitions.put(label, new ImportInfo(library, libDef)); | |||
} | |||
/** | |||
* Gets the setter for the given class | |||
* | |||
* @param c the class for which the reflector is desired | |||
* @return the reflector | |||
*/ | |||
private Setter getSetter(Class c) { | |||
if (setters.containsKey(c)) { | |||
return (Setter)setters.get(c); | |||
} | |||
Setter setter = null; | |||
if (DeferredTask.class.isAssignableFrom(c)) { | |||
setter = new DeferredSetter(); | |||
} else { | |||
ClassIntrospector introspector | |||
= new ClassIntrospector(c, getConverters()); | |||
setter = introspector.getReflector(); | |||
} | |||
setters.put(c, setter); | |||
return setter; | |||
} | |||
/** | |||
* Create an instance of a type given its required class | |||
* | |||
* @param typeClass the class from which the instance should be created | |||
* @param model the model describing the required configuration of the | |||
* instance | |||
* @param libFactory the factory object of the typeClass's Ant library | |||
* @param localName the name of the type within its Ant library | |||
* @return an instance of the given class appropriately configured | |||
* @exception ExecutionException if there is a problem creating the type | |||
* instance | |||
*/ | |||
private Object createTypeInstance(Class typeClass, AntLibFactory libFactory, | |||
BuildElement model, String localName) | |||
throws ExecutionException { | |||
try { | |||
Object typeInstance | |||
= libFactory.createComponent(typeClass, localName); | |||
if (typeInstance instanceof ExecutionComponent) { | |||
ExecutionComponent component = (ExecutionComponent)typeInstance; | |||
ExecutionContext context = new ExecutionContext(frame, | |||
component, model.getLocation()); | |||
component.init(context, localName); | |||
configureElement(libFactory, typeInstance, model); | |||
component.validateComponent(); | |||
} else { | |||
configureElement(libFactory, typeInstance, model); | |||
} | |||
return typeInstance; | |||
} catch (InstantiationException e) { | |||
throw new ExecutionException("Unable to instantiate type class " | |||
+ typeClass.getName() + " for type <" + model.getType() + ">", | |||
e, model.getLocation()); | |||
} catch (IllegalAccessException e) { | |||
throw new ExecutionException("Unable to access type class " | |||
+ typeClass.getName() + " for type <" + model.getType() + ">", | |||
e, model.getLocation()); | |||
} catch (ExecutionException e) { | |||
e.setLocation(model.getLocation(), false); | |||
throw e; | |||
} catch (RuntimeException e) { | |||
throw new ExecutionException(e.getClass().getName() + ": " | |||
+ e.getMessage(), e, model.getLocation()); | |||
} | |||
} | |||
/** | |||
* Create and add a nested element | |||
* | |||
* @param setter The Setter instance for the container element | |||
* @param element the container element in which the nested element will | |||
* be created | |||
* @param model the model of the nested element | |||
* @param factory Ant Library factory associated with the element to | |||
* which the attribute is to be added. | |||
* @exception ExecutionException if the nested element cannot be created | |||
*/ | |||
private void addNestedElement(AntLibFactory factory, Setter setter, | |||
Object element, BuildElement model) | |||
throws ExecutionException { | |||
String nestedElementName = model.getType(); | |||
Class nestedType = setter.getType(nestedElementName); | |||
// is there a polymorph indicator - look in Ant aspects | |||
String typeName = model.getAspectValue(Constants.ANT_ASPECT, "type"); | |||
String refId = model.getAspectValue(Constants.ANT_ASPECT, "refid"); | |||
if (refId != null && typeName != null) { | |||
throw new ExecutionException("Only one of " + Constants.ANT_ASPECT | |||
+ ":type and " + Constants.ANT_ASPECT | |||
+ ":refid may be specified at a time", model.getLocation()); | |||
} | |||
Object typeInstance = null; | |||
if (typeName != null) { | |||
// the build file has specified the actual type of the element. | |||
// we need to look up that type and use it | |||
typeInstance = createComponent(typeName, model); | |||
} else if (refId != null) { | |||
// We have a reference to an existing instance. Need to check if | |||
// it is compatible with the type expected by the nested element's | |||
// adder method | |||
typeInstance = frame.getDataValue(refId); | |||
if (model.getAttributeNames().hasNext() || | |||
model.getNestedElements().hasNext() || | |||
model.getText().length() != 0) { | |||
throw new ExecutionException("Element <" + nestedElementName | |||
+ "> is defined by reference and hence may not specify " | |||
+ "any attributes, nested elements or content", | |||
model.getLocation()); | |||
} | |||
if (typeInstance == null) { | |||
throw new ExecutionException("The given ant:refid value '" | |||
+ refId + "' is not defined", model.getLocation()); | |||
} | |||
} else if (nestedType != null) { | |||
// We need to create an instance of the class expected by the nested | |||
// element's adder method if that is possible | |||
if (nestedType.isInterface()) { | |||
throw new ExecutionException("No element can be created for " | |||
+ "nested element <" + nestedElementName + ">. Please " | |||
+ "provide a value by reference or specify the value type", | |||
model.getLocation()); | |||
} | |||
typeInstance = createTypeInstance(nestedType, factory, model, null); | |||
} else { | |||
throw new ExecutionException("The type of the <" | |||
+ nestedElementName + "> nested element is not known. " | |||
+ "Please specify by the type using the \"ant:type\" " | |||
+ "attribute or provide a reference to an instance with " | |||
+ "the \"ant:id\" attribute"); | |||
} | |||
// is the typeInstance compatible with the type expected | |||
// by the element's add method | |||
if (!nestedType.isInstance(typeInstance)) { | |||
if (refId != null) { | |||
throw new ExecutionException("The value specified by refId " | |||
+ refId + " is not compatible with the <" | |||
+ nestedElementName + "> nested element", | |||
model.getLocation()); | |||
} else if (typeName != null) { | |||
throw new ExecutionException("The type " | |||
+ typeName + " is not compatible with the <" | |||
+ nestedElementName + "> nested element", | |||
model.getLocation()); | |||
} | |||
} | |||
setter.addElement(element, nestedElementName, typeInstance); | |||
} | |||
/** | |||
* Create a nested element for the given object according to the model. | |||
* | |||
* @param setter the Setter instance of the container object | |||
* @param element the container object for which a nested element is | |||
* required. | |||
* @param model the build model for the nestd element | |||
* @param factory Ant Library factory associated with the element | |||
* creating the nested element | |||
* @exception ExecutionException if the nested element cannot be | |||
* created. | |||
*/ | |||
private void createNestedElement(AntLibFactory factory, Setter setter, | |||
Object element, BuildElement model) | |||
throws ExecutionException { | |||
String nestedElementName = model.getType(); | |||
try { | |||
Object nestedElement | |||
= setter.createElement(element, nestedElementName); | |||
factory.registerCreatedElement(nestedElement); | |||
if (nestedElement instanceof ExecutionComponent) { | |||
ExecutionComponent component | |||
= (ExecutionComponent)nestedElement; | |||
ExecutionContext context = new ExecutionContext(frame, | |||
component, model.getLocation()); | |||
component.init(context, nestedElementName); | |||
configureElement(factory, nestedElement, model); | |||
component.validateComponent(); | |||
} else { | |||
configureElement(factory, nestedElement, model); | |||
} | |||
} catch (ExecutionException e) { | |||
e.setLocation(model.getLocation(), false); | |||
throw e; | |||
} catch (RuntimeException e) { | |||
throw new ExecutionException(e.getClass().getName() + ": " | |||
+ e.getMessage(), e, model.getLocation()); | |||
} | |||
} | |||
/** | |||
* Configure an element according to the given model. | |||
* | |||
* @param element the object to be configured | |||
* @param model the BuildElement describing the object in the build file | |||
* @param factory Ant Library factory associated with the element being | |||
* configured | |||
* @exception ExecutionException if the element cannot be configured | |||
*/ | |||
private void configureElement(AntLibFactory factory, Object element, | |||
BuildElement model) | |||
throws ExecutionException { | |||
Setter setter = getSetter(element.getClass()); | |||
// start by setting the attributes of this element | |||
for (Iterator i = model.getAttributeNames(); i.hasNext(); ) { | |||
String attributeName = (String)i.next(); | |||
String attributeValue = model.getAttributeValue(attributeName); | |||
if (!setter.supportsAttribute(attributeName)) { | |||
throw new ExecutionException(model.getType() | |||
+ " does not support the \"" + attributeName | |||
+ "\" attribute", model.getLocation()); | |||
} | |||
setter.setAttribute(element, attributeName, | |||
frame.replacePropertyRefs(attributeValue)); | |||
} | |||
String modelText = model.getText().trim(); | |||
if (modelText.length() != 0) { | |||
if (!setter.supportsText()) { | |||
throw new ExecutionException(model.getType() | |||
+ " does not support content", model.getLocation()); | |||
} | |||
setter.addText(element, | |||
frame.replacePropertyRefs(modelText)); | |||
} | |||
// now do the nested elements | |||
for (Iterator i = model.getNestedElements(); i.hasNext(); ) { | |||
BuildElement nestedElementModel = (BuildElement)i.next(); | |||
String nestedElementName = nestedElementModel.getType(); | |||
ImportInfo info = getDefinition(nestedElementName); | |||
if (element instanceof TaskContainer | |||
&& info != null | |||
&& info.getDefinitionType() == AntLibrary.TASKDEF | |||
&& !setter.supportsNestedElement(nestedElementName)) { | |||
// it is a nested task | |||
Task nestedTask | |||
= (Task)createComponent(nestedElementModel); | |||
TaskContainer container = (TaskContainer)element; | |||
container.addTask(nestedTask); | |||
} else { | |||
if (setter.supportsNestedAdder(nestedElementName)) { | |||
addNestedElement(factory, setter, element, | |||
nestedElementModel); | |||
} else if (setter.supportsNestedCreator(nestedElementName)) { | |||
createNestedElement(factory, setter, element, | |||
nestedElementModel); | |||
} else { | |||
throw new ExecutionException(model.getType() | |||
+ " does not support the \"" + nestedElementName | |||
+ "\" nested element", | |||
nestedElementModel.getLocation()); | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Define a new component | |||
* | |||
@@ -445,8 +834,8 @@ public class ComponentManager implements ComponentService { | |||
} | |||
Converter converter | |||
= libFactory.createConverter(converterClass); | |||
ExecutionContext context | |||
= new ExecutionContext(frame); | |||
ExecutionContext context = new ExecutionContext(frame, | |||
null, Location.UNKNOWN_LOCATION); | |||
converter.init(context); | |||
Class[] converterTypes = converter.getTypes(); | |||
for (int j = 0; j < converterTypes.length; ++j) { | |||
@@ -475,6 +864,5 @@ public class ComponentManager implements ComponentService { | |||
+ className, e); | |||
} | |||
} | |||
} | |||
@@ -52,88 +52,19 @@ | |||
* <http://www.apache.org/>. | |||
*/ | |||
package org.apache.ant.antcore.execution; | |||
import org.apache.ant.common.antlib.Task; | |||
import org.apache.ant.common.model.ModelElement; | |||
import org.apache.ant.common.util.ExecutionException; | |||
/** | |||
* This is the core's implementation of the AntContext for Tasks. | |||
* Core constants | |||
* | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
* @created 17 January 2002 | |||
* @created 20 February 2002 | |||
*/ | |||
public class TaskContext extends ExecutionContext { | |||
/** The task being managed by this context */ | |||
private Task task; | |||
/** | |||
* the loader used to load this task. Note that this is not necessarily | |||
* the loader which is used to load the Task class as loading may have | |||
* been delegated to a parent loader. | |||
*/ | |||
private ClassLoader loader; | |||
/** | |||
* Initilaise this context's environment | |||
* | |||
* @param frame the frame containing this context | |||
*/ | |||
public TaskContext(Frame frame) { | |||
super(frame); | |||
} | |||
/** | |||
* Get the task associated with this context | |||
* | |||
* @return the task instance | |||
*/ | |||
protected Task getTask() { | |||
return task; | |||
} | |||
/** | |||
* Gets the loader for this task | |||
* | |||
* @return the task's loader | |||
*/ | |||
protected ClassLoader getLoader() { | |||
return loader; | |||
} | |||
/** | |||
* Associate a task with this context | |||
* | |||
* @param task the task to be manager | |||
* @param loader the classloader | |||
* @param modelElement the model element associated with this context | |||
* @exception ExecutionException if the task cannot be initialized | |||
*/ | |||
protected void init(ClassLoader loader, Task task, | |||
ModelElement modelElement) throws ExecutionException { | |||
this.task = task; | |||
this.loader = loader; | |||
setModelElement(modelElement); | |||
task.init(this); | |||
} | |||
public abstract class Constants { | |||
/** The prefix for library ids that are automatically imported */ | |||
public static final String ANT_LIB_PREFIX = "ant."; | |||
/** | |||
* execute this context's task | |||
* | |||
* @exception ExecutionException if there is a problem executing the | |||
* task | |||
*/ | |||
protected void execute() throws ExecutionException { | |||
task.execute(); | |||
} | |||
/** The Ant aspect used to identify Ant metadata */ | |||
public static final String ANT_ASPECT = "ant"; | |||
/** | |||
* Destroy this context. The context can be reused for another task | |||
* after this one | |||
*/ | |||
protected void destroy() { | |||
task.destroy(); | |||
task = null; | |||
loader = null; | |||
} | |||
} | |||
@@ -58,13 +58,16 @@ import java.util.List; | |||
import java.util.Map; | |||
import org.apache.ant.antcore.modelparser.XMLProjectParser; | |||
import org.apache.ant.antcore.xml.XMLParseException; | |||
import org.apache.ant.common.antlib.AntContext; | |||
import org.apache.ant.common.antlib.Task; | |||
import org.apache.ant.common.model.Project; | |||
import org.apache.ant.common.service.ExecService; | |||
import org.apache.ant.common.util.ExecutionException; | |||
import org.apache.ant.init.InitUtils; | |||
import org.apache.ant.init.LoaderUtils; | |||
/** | |||
*This is the core's implementation of the Execution Service. | |||
* This is the core's implementation of the Execution Service. | |||
* | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
* @created 8 February 2002 | |||
@@ -132,5 +135,37 @@ public class CoreExecService implements ExecService { | |||
runBuild(frame.getProject(), properties, targets); | |||
} | |||
/** | |||
* Execute a task. The task should have already been initialised by | |||
* the core. This is checked | |||
* | |||
* @param task the task to be executed | |||
* @exception ExecutionException if there is an execution problem | |||
*/ | |||
public void executeTask(Task task) throws ExecutionException { | |||
AntContext context = task.getAntContext(); | |||
if (!(context instanceof ExecutionContext)) { | |||
throw new ExecutionException("The Task was not configured with an" | |||
+ " appropriate context"); | |||
} | |||
ExecutionContext execContext = (ExecutionContext)context; | |||
frame.getEventSupport().fireTaskStarted(task); | |||
Throwable failureCause = null; | |||
try { | |||
ClassLoader currentLoader | |||
= LoaderUtils.setContextLoader(execContext.getLoader()); | |||
task.execute(); | |||
LoaderUtils.setContextLoader(currentLoader); | |||
} catch (Throwable e) { | |||
ExecutionException ee = | |||
new ExecutionException(e.getClass().getName() + ": " | |||
+ e.getMessage(), e); | |||
failureCause = ee; | |||
throw ee; | |||
} finally { | |||
frame.getEventSupport().fireTaskFinished(task, failureCause); | |||
} | |||
} | |||
} | |||
@@ -54,8 +54,9 @@ | |||
package org.apache.ant.antcore.execution; | |||
import java.io.File; | |||
import org.apache.ant.common.antlib.AntContext; | |||
import org.apache.ant.common.model.ModelElement; | |||
import org.apache.ant.common.antlib.ExecutionComponent; | |||
import org.apache.ant.common.util.ExecutionException; | |||
import org.apache.ant.common.util.Location; | |||
/** | |||
* This is the core's implementation of the AntContext for all core objects. | |||
@@ -71,26 +72,32 @@ public class ExecutionContext implements AntContext { | |||
/** the event support instance used to manage build events */ | |||
private BuildEventSupport eventSupport; | |||
/** the model in the build model with which this context is associated */ | |||
private ModelElement modelElement; | |||
/** The location of the object associated with this context */ | |||
private Location location; | |||
/** the execution component associated with the context, if any */ | |||
private ExecutionComponent component; | |||
/** | |||
* the loader used to load this context. Note that this is not | |||
* necessarily the loader which is used to load the component as loading | |||
* may have been delegated to a parent loader. | |||
*/ | |||
private ClassLoader loader; | |||
/** | |||
* Initilaise this context's environment | |||
* | |||
* @param frame the frame containing this context | |||
* @param component the component associated with this context - may be null | |||
* @param location the location associated with the component | |||
*/ | |||
protected ExecutionContext(Frame frame) { | |||
protected ExecutionContext(Frame frame, ExecutionComponent component, | |||
Location location) { | |||
this.frame = frame; | |||
this.eventSupport = frame.getEventSupport(); | |||
} | |||
/** | |||
* Set the model element associated with this context | |||
* | |||
* @param modelElement the model element associated with this context | |||
*/ | |||
protected void setModelElement(ModelElement modelElement) { | |||
this.modelElement = modelElement; | |||
this.location = location; | |||
this.component = component; | |||
} | |||
/** | |||
@@ -107,19 +114,6 @@ public class ExecutionContext implements AntContext { | |||
return frame.getCoreService(serviceInterfaceClass); | |||
} | |||
/** | |||
* Get the model element associated with this context. If the context is | |||
* not associated with any particular model element, the project model | |||
* is returned. | |||
* | |||
* @return the model element. | |||
*/ | |||
public ModelElement getModelElement() { | |||
if (modelElement == null) { | |||
return frame.getProject(); | |||
} | |||
return modelElement; | |||
} | |||
/** | |||
* Get the base directory for this execution of this frame | |||
@@ -130,6 +124,15 @@ public class ExecutionContext implements AntContext { | |||
return frame.getBaseDir(); | |||
} | |||
/** | |||
* Gets the location associated with the ExecutionContext | |||
* | |||
* @return the location in the build model associated with this context. | |||
*/ | |||
public Location getLocation() { | |||
return location; | |||
} | |||
/** | |||
* Log a message as a build event | |||
* | |||
@@ -137,7 +140,7 @@ public class ExecutionContext implements AntContext { | |||
* @param level the priority level of the message | |||
*/ | |||
public void log(String message, int level) { | |||
Object source = modelElement; | |||
Object source = component; | |||
if (source == null) { | |||
source = frame.getProject(); | |||
if (source == null) { | |||
@@ -146,5 +149,32 @@ public class ExecutionContext implements AntContext { | |||
} | |||
eventSupport.fireMessageLogged(source, message, level); | |||
} | |||
/** | |||
* Sets the classLoader of the ExecutionContext | |||
* | |||
* @param loader the new classLoader value | |||
*/ | |||
protected void setClassLoader(ClassLoader loader) { | |||
this.loader = loader; | |||
} | |||
/** | |||
* Gets the loader for this task | |||
* | |||
* @return the task's loader | |||
*/ | |||
protected ClassLoader getLoader() { | |||
return loader; | |||
} | |||
/** | |||
* Gets the executionComponent of the ExecutionContext | |||
* | |||
* @return the executionComponent value | |||
*/ | |||
protected ExecutionComponent getExecutionComponent() { | |||
return component; | |||
} | |||
} | |||
@@ -59,14 +59,8 @@ import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.StringTokenizer; | |||
import org.apache.ant.antcore.antlib.AntLibrary; | |||
import org.apache.ant.antcore.antlib.ComponentLibrary; | |||
import org.apache.ant.antcore.config.AntConfig; | |||
import org.apache.ant.common.antlib.AntLibFactory; | |||
import org.apache.ant.common.antlib.DeferredTask; | |||
import org.apache.ant.common.antlib.ExecutionComponent; | |||
import org.apache.ant.common.antlib.Task; | |||
import org.apache.ant.common.antlib.TaskContainer; | |||
import org.apache.ant.common.event.BuildListener; | |||
import org.apache.ant.common.event.MessageLevel; | |||
import org.apache.ant.common.model.BuildElement; | |||
@@ -93,9 +87,6 @@ import org.apache.ant.init.InitConfig; | |||
* @created 14 January 2002 | |||
*/ | |||
public class Frame { | |||
/** The Ant aspect used to identify Ant metadata */ | |||
public static final String ANT_ASPECT = "ant"; | |||
/** the base dir of the project */ | |||
private File baseDir; | |||
@@ -105,9 +96,6 @@ public class Frame { | |||
/** The referenced frames corresponding to the referenced projects */ | |||
private Map referencedFrames = new HashMap(); | |||
/** Reflector objects used to configure Tasks from the Task models. */ | |||
private Map setters = new HashMap(); | |||
/** | |||
* The context of this execution. This contains all data object's | |||
* created by tasks that have been executed | |||
@@ -155,6 +143,11 @@ public class Frame { | |||
*/ | |||
private ComponentManager componentManager; | |||
/** | |||
* The core's execution Service | |||
*/ | |||
private CoreExecService execService; | |||
/** | |||
* Create an Execution Frame for the given project | |||
* | |||
@@ -172,20 +165,6 @@ public class Frame { | |||
this.initConfig = initConfig; | |||
} | |||
/** | |||
* Set the context loader of the current thread and returns the existing | |||
* classloader | |||
* | |||
* @param newLoader the new context loader | |||
* @return the old context loader | |||
*/ | |||
private static ClassLoader setContextLoader(ClassLoader newLoader) { | |||
Thread thread = Thread.currentThread(); | |||
ClassLoader currentLoader = thread.getContextClassLoader(); | |||
thread.setContextClassLoader(newLoader); | |||
return currentLoader; | |||
} | |||
/** | |||
* Sets the Project of the Frame | |||
* | |||
@@ -210,6 +189,18 @@ public class Frame { | |||
setMagicProperties(); | |||
} | |||
/** | |||
* Replace ${} style constructions in the given value with the string | |||
* value of the corresponding data values in the frame | |||
* | |||
* @param value the string to be scanned for property references. | |||
* @return the string with all property references replaced | |||
* @exception ExecutionException if any of the properties do not exist | |||
*/ | |||
public String replacePropertyRefs(String value) throws ExecutionException { | |||
return dataService.replacePropertyRefs(value); | |||
} | |||
/** | |||
* Set a value in this frame or any of its imported frames. | |||
* | |||
@@ -625,48 +616,29 @@ public class Frame { | |||
protected void executeTasks(Iterator taskIterator) | |||
throws ExecutionException { | |||
while (taskIterator.hasNext()) { | |||
Throwable failureCause = null; | |||
BuildElement model = (BuildElement)taskIterator.next(); | |||
// what sort of element is this. | |||
ImportInfo importInfo | |||
= componentManager.getDefinition(model.getType()); | |||
if (importInfo == null) { | |||
throw new ExecutionException("There is no definition for the <" | |||
+ model.getType() + "> element", model.getLocation()); | |||
} | |||
try { | |||
if (importInfo.getDefinitionType() == AntLibrary.TASKDEF) { | |||
TaskContext taskContext = configureTask(model); | |||
eventSupport.fireTaskStarted(model); | |||
ClassLoader currentLoader | |||
= setContextLoader(taskContext.getLoader()); | |||
taskContext.execute(); | |||
setContextLoader(currentLoader); | |||
taskContext.destroy(); | |||
Object component = componentManager.createComponent(model); | |||
if (component instanceof Task) { | |||
execService.executeTask((Task)component); | |||
} else { | |||
// typedef | |||
String typeId = model.getAspectValue(ANT_ASPECT, "id"); | |||
Object typeInstance = configureType(model.getType(), model); | |||
String typeId | |||
= model.getAspectValue(Constants.ANT_ASPECT, "id"); | |||
if (typeId != null) { | |||
setDataValue(typeId, typeInstance, true); | |||
setDataValue(typeId, component, true); | |||
} | |||
} | |||
} catch (AntException te) { | |||
ExecutionException e | |||
= new ExecutionException(te, te.getLocation()); | |||
e.setLocation(model.getLocation(), false); | |||
failureCause = e; | |||
throw e; | |||
} catch (RuntimeException e) { | |||
ExecutionException ee = | |||
new ExecutionException(e.getClass().getName() + ": " | |||
+ e.getMessage(), e, model.getLocation()); | |||
failureCause = ee; | |||
throw ee; | |||
} finally { | |||
eventSupport.fireTaskFinished(model, failureCause); | |||
} | |||
} | |||
@@ -737,30 +709,6 @@ public class Frame { | |||
executeTasks(taskIterator); | |||
} | |||
/** | |||
* Gets the setter for the given class | |||
* | |||
* @param c the class for which the reflector is desired | |||
* @return the reflector | |||
*/ | |||
private Setter getSetter(Class c) { | |||
if (setters.containsKey(c)) { | |||
return (Setter)setters.get(c); | |||
} | |||
Setter setter = null; | |||
if (DeferredTask.class.isAssignableFrom(c)) { | |||
setter = new DeferredSetter(); | |||
} else { | |||
ClassIntrospector introspector | |||
= new ClassIntrospector(c, componentManager.getConverters()); | |||
setter = introspector.getReflector(); | |||
} | |||
setters.put(c, setter); | |||
return setter; | |||
} | |||
/** | |||
* Determine the base directory for each frame in the frame hierarchy | |||
* | |||
@@ -806,383 +754,13 @@ public class Frame { | |||
config.isRemoteLibAllowed(), config.getLibraryPathsMap()); | |||
dataService = new CoreDataService(this, | |||
config.isUnsetPropertiesAllowed()); | |||
execService = new CoreExecService(this); | |||
services.put(FileService.class, fileService); | |||
services.put(ComponentService.class, componentManager); | |||
services.put(DataService.class, dataService); | |||
services.put(EventService.class, new CoreEventService(this)); | |||
services.put(ExecService.class, new CoreExecService(this)); | |||
} | |||
/** | |||
* Configure an element according to the given model. | |||
* | |||
* @param element the object to be configured | |||
* @param model the BuildElement describing the object in the build file | |||
* @param factory Ant Library factory associated with the element being | |||
* configured | |||
* @exception ExecutionException if the element cannot be configured | |||
*/ | |||
private void configureElement(AntLibFactory factory, Object element, | |||
BuildElement model) | |||
throws ExecutionException { | |||
Setter setter = getSetter(element.getClass()); | |||
// start by setting the attributes of this element | |||
for (Iterator i = model.getAttributeNames(); i.hasNext(); ) { | |||
String attributeName = (String)i.next(); | |||
String attributeValue = model.getAttributeValue(attributeName); | |||
if (!setter.supportsAttribute(attributeName)) { | |||
throw new ExecutionException(model.getType() | |||
+ " does not support the \"" + attributeName | |||
+ "\" attribute", model.getLocation()); | |||
} | |||
setter.setAttribute(element, attributeName, | |||
dataService.replacePropertyRefs(attributeValue)); | |||
} | |||
String modelText = model.getText().trim(); | |||
if (modelText.length() != 0) { | |||
if (!setter.supportsText()) { | |||
throw new ExecutionException(model.getType() | |||
+ " does not support content", model.getLocation()); | |||
} | |||
setter.addText(element, | |||
dataService.replacePropertyRefs(modelText)); | |||
} | |||
// now do the nested elements | |||
for (Iterator i = model.getNestedElements(); i.hasNext(); ) { | |||
BuildElement nestedElementModel = (BuildElement)i.next(); | |||
String nestedElementName = nestedElementModel.getType(); | |||
ImportInfo info = componentManager.getDefinition(nestedElementName); | |||
if (element instanceof TaskContainer | |||
&& info != null | |||
&& info.getDefinitionType() == AntLibrary.TASKDEF | |||
&& !setter.supportsNestedElement(nestedElementName)) { | |||
// it is a nested task | |||
TaskContext nestedContext | |||
= configureTask(nestedElementModel); | |||
TaskContainer container = (TaskContainer)element; | |||
// XXX what should we be adding - need to understand container | |||
// method of executing tasks | |||
container.addTask(nestedContext.getTask()); | |||
} else { | |||
if (setter.supportsNestedAdder(nestedElementName)) { | |||
addNestedElement(factory, setter, element, | |||
nestedElementModel); | |||
} else if (setter.supportsNestedCreator(nestedElementName)) { | |||
createNestedElement(factory, setter, element, | |||
nestedElementModel); | |||
} else { | |||
throw new ExecutionException(model.getType() | |||
+ " does not support the \"" + nestedElementName | |||
+ "\" nested element", | |||
nestedElementModel.getLocation()); | |||
} | |||
} | |||
} | |||
} | |||
/** | |||
* Create a nested element for the given object according to the model. | |||
* | |||
* @param setter the Setter instance of the container object | |||
* @param element the container object for which a nested element is | |||
* required. | |||
* @param model the build model for the nestd element | |||
* @param factory Ant Library factory associated with the element | |||
* creating the nested element | |||
* @exception ExecutionException if the nested element cannot be | |||
* created. | |||
*/ | |||
private void createNestedElement(AntLibFactory factory, Setter setter, | |||
Object element, BuildElement model) | |||
throws ExecutionException { | |||
String nestedElementName = model.getType(); | |||
try { | |||
Object nestedElement | |||
= setter.createElement(element, nestedElementName); | |||
factory.registerCreatedElement(nestedElement); | |||
if (nestedElement instanceof ExecutionComponent) { | |||
ExecutionComponent component | |||
= (ExecutionComponent)nestedElement; | |||
ExecutionContext context | |||
= new ExecutionContext(this); | |||
context.setModelElement(model); | |||
component.init(context); | |||
configureElement(factory, nestedElement, model); | |||
component.validateComponent(); | |||
} else { | |||
configureElement(factory, nestedElement, model); | |||
} | |||
} catch (ExecutionException e) { | |||
e.setLocation(model.getLocation(), false); | |||
throw e; | |||
} catch (RuntimeException e) { | |||
throw new ExecutionException(e.getClass().getName() + ": " | |||
+ e.getMessage(), e, model.getLocation()); | |||
} | |||
} | |||
/** | |||
* Create and add a nested element | |||
* | |||
* @param setter The Setter instance for the container element | |||
* @param element the container element in which the nested element will | |||
* be created | |||
* @param model the model of the nested element | |||
* @param factory Ant Library factory associated with the element to | |||
* which the attribute is to be added. | |||
* @exception ExecutionException if the nested element cannot be created | |||
*/ | |||
private void addNestedElement(AntLibFactory factory, Setter setter, | |||
Object element, BuildElement model) | |||
throws ExecutionException { | |||
String nestedElementName = model.getType(); | |||
Class nestedType = setter.getType(nestedElementName); | |||
// is there a polymorph indicator - look in Ant aspects | |||
String typeName = model.getAspectValue(ANT_ASPECT, "type"); | |||
String refId = model.getAspectValue(ANT_ASPECT, "refid"); | |||
if (refId != null && typeName != null) { | |||
throw new ExecutionException("Only one of " + ANT_ASPECT | |||
+ ":type and " + ANT_ASPECT | |||
+ ":refid may be specified at a time", model.getLocation()); | |||
} | |||
Object typeInstance = null; | |||
if (typeName != null) { | |||
// the build file has specified the actual type of the element. | |||
// we need to look up that type and use it | |||
typeInstance = configureType(typeName, model); | |||
} else if (refId != null) { | |||
// We have a reference to an existing instance. Need to check if | |||
// it is compatible with the type expected by the nested element's | |||
// adder method | |||
typeInstance = getDataValue(refId); | |||
if (model.getAttributeNames().hasNext() || | |||
model.getNestedElements().hasNext() || | |||
model.getText().length() != 0) { | |||
throw new ExecutionException("Element <" + nestedElementName | |||
+ "> is defined by reference and hence may not specify " | |||
+ "any attributes, nested elements or content", | |||
model.getLocation()); | |||
} | |||
if (typeInstance == null) { | |||
throw new ExecutionException("The given ant:refid value '" | |||
+ refId + "' is not defined", model.getLocation()); | |||
} | |||
} else if (nestedType != null) { | |||
// We need to create an instance of the class expected by the nested | |||
// element's adder method if that is possible | |||
if (nestedType.isInterface()) { | |||
throw new ExecutionException("No element can be created for " | |||
+ "nested element <" + nestedElementName + ">. Please " | |||
+ "provide a value by reference or specify the value type", | |||
model.getLocation()); | |||
} | |||
typeInstance = createTypeInstance(nestedType, factory, model, null); | |||
} else { | |||
throw new ExecutionException("The type of the <" | |||
+ nestedElementName + "> nested element is not known. " | |||
+ "Please specify by the type using the \"ant:type\" " | |||
+ "attribute or provide a reference to an instance with " | |||
+ "the \"ant:id\" attribute"); | |||
} | |||
// is the typeInstance compatible with the type expected | |||
// by the element's add method | |||
if (!nestedType.isInstance(typeInstance)) { | |||
if (refId != null) { | |||
throw new ExecutionException("The value specified by refId " | |||
+ refId + " is not compatible with the <" | |||
+ nestedElementName + "> nested element", | |||
model.getLocation()); | |||
} else if (typeName != null) { | |||
throw new ExecutionException("The type " | |||
+ typeName + " is not compatible with the <" | |||
+ nestedElementName + "> nested element", | |||
model.getLocation()); | |||
} | |||
} | |||
setter.addElement(element, nestedElementName, typeInstance); | |||
} | |||
/** | |||
* Create a Task and configure it according to the given model. | |||
* | |||
* @param model the model for the task from the build file | |||
* @return an execution context for managing the task | |||
* @exception ExecutionException if there is a problem configuring the | |||
* task | |||
*/ | |||
private TaskContext configureTask(BuildElement model) | |||
throws ExecutionException { | |||
String taskType = model.getType(); | |||
ImportInfo taskDefInfo = componentManager.getDefinition(taskType); | |||
if (taskDefInfo == null | |||
|| taskDefInfo.getDefinitionType() != AntLibrary.TASKDEF) { | |||
throw new ExecutionException("There is no defintion for a " | |||
+ "task of type <" + taskType + ">", model.getLocation()); | |||
} | |||
String className = taskDefInfo.getClassName(); | |||
ComponentLibrary componentLibrary | |||
= taskDefInfo.getComponentLibrary(); | |||
String localName = taskDefInfo.getLocalName(); | |||
try { | |||
ClassLoader taskClassLoader = componentLibrary.getClassLoader(); | |||
Class elementClass | |||
= Class.forName(className, true, taskClassLoader); | |||
AntLibFactory libFactory | |||
= componentManager.getLibFactory(componentLibrary); | |||
Object element | |||
= libFactory.createTaskInstance(elementClass, localName); | |||
Task task = null; | |||
if (element instanceof Task) { | |||
// create a Task context for the Task | |||
task = (Task)element; | |||
} else { | |||
task = new TaskAdapter(taskType, element); | |||
} | |||
// set the context loader while configuring the element | |||
ClassLoader currentLoader = setContextLoader(taskClassLoader); | |||
TaskContext taskContext = new TaskContext(this); | |||
taskContext.init(taskClassLoader, task, model); | |||
configureElement(libFactory, element, model); | |||
task.validateComponent(); | |||
setContextLoader(currentLoader); | |||
return taskContext; | |||
} catch (ClassNotFoundException e) { | |||
throw new ExecutionException("Class " + className | |||
+ " for task <" + taskType + "> was not found", e, | |||
model.getLocation()); | |||
} catch (NoClassDefFoundError e) { | |||
throw new ExecutionException("Could not load a dependent class (" | |||
+ e.getMessage() + ") for task " + taskType, | |||
e, model.getLocation()); | |||
} catch (InstantiationException e) { | |||
throw new ExecutionException("Unable to instantiate task class " | |||
+ className + " for task <" + taskType + ">", | |||
e, model.getLocation()); | |||
} catch (IllegalAccessException e) { | |||
throw new ExecutionException("Unable to access task class " | |||
+ className + " for task <" + taskType + ">", | |||
e, model.getLocation()); | |||
} catch (ExecutionException e) { | |||
e.setLocation(model.getLocation(), false); | |||
throw e; | |||
} catch (RuntimeException e) { | |||
throw new ExecutionException(e.getClass().getName() + ": " | |||
+ e.getMessage(), e, model.getLocation()); | |||
} | |||
} | |||
/** | |||
* Configure a type instance from the given build model. The name given | |||
* may not match the name in the model type value. This allows the | |||
* caller to provide a polymorphic type for the type model | |||
* | |||
* @param typeName the name of the type which should be created | |||
* @param model the model describing the type | |||
* @return an instance of the type, configured from the model | |||
* @exception ExecutionException if the type could not be created | |||
*/ | |||
private Object configureType(String typeName, BuildElement model) | |||
throws ExecutionException { | |||
ImportInfo typeDefInfo = componentManager.getDefinition(typeName); | |||
if (typeDefInfo == null | |||
|| typeDefInfo.getDefinitionType() != AntLibrary.TYPEDEF) { | |||
throw new ExecutionException("There is no defintion for a " | |||
+ "type <" + typeName + ">", model.getLocation()); | |||
} | |||
String className = typeDefInfo.getClassName(); | |||
ComponentLibrary componentLibrary | |||
= typeDefInfo.getComponentLibrary(); | |||
String localName = typeDefInfo.getLocalName(); | |||
try { | |||
ClassLoader typeClassLoader = componentLibrary.getClassLoader(); | |||
Class typeClass | |||
= Class.forName(className, true, typeClassLoader); | |||
ClassLoader currentLoader = setContextLoader(typeClassLoader); | |||
AntLibFactory libFactory | |||
= componentManager.getLibFactory(componentLibrary); | |||
Object typeInstance | |||
= createTypeInstance(typeClass, libFactory, model, localName); | |||
setContextLoader(currentLoader); | |||
return typeInstance; | |||
} catch (ClassNotFoundException e) { | |||
throw new ExecutionException("Class " + className | |||
+ " for type <" + typeName + "> was not found", e, | |||
model.getLocation()); | |||
} catch (NoClassDefFoundError e) { | |||
throw new ExecutionException("Could not load a dependent class (" | |||
+ e.getMessage() + ") for type " + typeName); | |||
} | |||
} | |||
/** | |||
* Create an instance of a type given its required class | |||
* | |||
* @param typeClass the class from which the instance should be created | |||
* @param model the model describing the required configuration of the | |||
* instance | |||
* @param libFactory the factory object of the typeClass's Ant library | |||
* @param localName the name of the type within its Ant library | |||
* @return an instance of the given class appropriately configured | |||
* @exception ExecutionException if there is a problem creating the type | |||
* instance | |||
*/ | |||
private Object createTypeInstance(Class typeClass, AntLibFactory libFactory, | |||
BuildElement model, String localName) | |||
throws ExecutionException { | |||
try { | |||
Object typeInstance | |||
= libFactory.createTypeInstance(typeClass, localName); | |||
if (typeInstance instanceof ExecutionComponent) { | |||
ExecutionComponent component = (ExecutionComponent)typeInstance; | |||
ExecutionContext context | |||
= new ExecutionContext(this); | |||
context.setModelElement(model); | |||
component.init(context); | |||
configureElement(libFactory, typeInstance, model); | |||
component.validateComponent(); | |||
} else { | |||
configureElement(libFactory, typeInstance, model); | |||
} | |||
return typeInstance; | |||
} catch (InstantiationException e) { | |||
throw new ExecutionException("Unable to instantiate type class " | |||
+ typeClass.getName() + " for type <" + model.getType() + ">", | |||
e, model.getLocation()); | |||
} catch (IllegalAccessException e) { | |||
throw new ExecutionException("Unable to access type class " | |||
+ typeClass.getName() + " for type <" + model.getType() + ">", | |||
e, model.getLocation()); | |||
} catch (ExecutionException e) { | |||
e.setLocation(model.getLocation(), false); | |||
throw e; | |||
} catch (RuntimeException e) { | |||
throw new ExecutionException(e.getClass().getName() + ": " | |||
+ e.getMessage(), e, model.getLocation()); | |||
} | |||
services.put(ExecService.class, execService); | |||
} | |||
} | |||
@@ -102,65 +102,48 @@ public class Ant1Factory extends StandardLibFactory { | |||
/** | |||
* Create an instance of the requested type class | |||
* Create an instance of the given component class | |||
* | |||
* @param typeClass the class from which an instance is required | |||
* @param localName the name of the type within its library | |||
* @return an instance of the requested class | |||
* @exception ExecutionException the instance could not be created. | |||
* @exception InstantiationException if the type cannot be instantiated | |||
* @exception IllegalAccessException if the type cannot be accessed | |||
* @param componentClass the class for which an instance is required | |||
* @param localName the name within the library under which the task is | |||
* defined | |||
* @return an instance of the required class | |||
* @exception InstantiationException if the class cannot be instantiated | |||
* @exception IllegalAccessException if the instance cannot be accessed | |||
* @exception ExecutionException if there is a problem creating the task | |||
*/ | |||
public Object createTypeInstance(Class typeClass, String localName) | |||
public Object createComponent(Class componentClass, String localName) | |||
throws InstantiationException, IllegalAccessException, | |||
ExecutionException { | |||
try { | |||
java.lang.reflect.Constructor ctor = null; | |||
java.lang.reflect.Constructor constructor = null; | |||
// DataType can have a "no arg" constructor or take a single | |||
// Project argument. | |||
Object o = null; | |||
Object component = null; | |||
try { | |||
ctor = typeClass.getConstructor(new Class[0]); | |||
o = ctor.newInstance(new Object[0]); | |||
constructor = componentClass.getConstructor(new Class[0]); | |||
component = constructor.newInstance(new Object[0]); | |||
} catch (NoSuchMethodException nse) { | |||
ctor = typeClass.getConstructor(new Class[]{Project.class}); | |||
o = ctor.newInstance(new Object[]{project}); | |||
constructor | |||
= componentClass.getConstructor(new Class[]{Project.class}); | |||
component = constructor.newInstance(new Object[]{project}); | |||
} | |||
if (o instanceof ProjectComponent) { | |||
((ProjectComponent)o).setProject(project); | |||
if (component instanceof ProjectComponent) { | |||
((ProjectComponent)component).setProject(project); | |||
} | |||
return o; | |||
return component; | |||
} catch (java.lang.reflect.InvocationTargetException ite) { | |||
Throwable t = ite.getTargetException(); | |||
String msg = "Could not create datatype of type: " | |||
+ typeClass.getName() + " due to " + t; | |||
String msg = "Could not create component of type: " | |||
+ componentClass.getName() + " due to " + t; | |||
throw new ExecutionException(msg, t); | |||
} catch (NoSuchMethodException e) { | |||
throw new ExecutionException("Unable to find an appropriate " | |||
+ "constructor for type " + typeClass.getName(), e); | |||
+ "constructor for component " + componentClass.getName(), e); | |||
} | |||
} | |||
/** | |||
* Create an instance of the requested task class | |||
* | |||
* @param taskClass the class from which an instance is required | |||
* @param localName the name of the task within its library | |||
* @return an instance of the requested class | |||
* @exception InstantiationException if the task cannot be instantiated | |||
* @exception IllegalAccessException if the task cannot be accessed | |||
*/ | |||
public Object createTaskInstance(Class taskClass, String localName) | |||
throws InstantiationException, IllegalAccessException { | |||
Object instance = taskClass.newInstance(); | |||
if (instance instanceof ProjectComponent) { | |||
((ProjectComponent)instance).setProject(project); | |||
} | |||
return instance; | |||
} | |||
/** | |||
* Create a converter. | |||
* | |||
@@ -474,7 +474,7 @@ public class Project implements org.apache.ant.common.event.BuildListener { | |||
public void targetStarted(org.apache.ant.common.event.BuildEvent event) { | |||
Target newTarget = new Target(this); | |||
org.apache.ant.common.model.Target realTarget = | |||
(org.apache.ant.common.model.Target)event.getModelElement(); | |||
(org.apache.ant.common.model.Target)event.getSource(); | |||
newTarget.setName(realTarget.getName()); | |||
targetStack.push(newTarget); | |||
fireTargetStarted(newTarget); | |||
@@ -487,7 +487,7 @@ public class Project implements org.apache.ant.common.event.BuildListener { | |||
*/ | |||
public void targetFinished(org.apache.ant.common.event.BuildEvent event) { | |||
org.apache.ant.common.model.Target realTarget = | |||
(org.apache.ant.common.model.Target)event.getModelElement(); | |||
(org.apache.ant.common.model.Target)event.getSource(); | |||
Target currentTarget = (Target)targetStack.pop(); | |||
fireTargetFinished(currentTarget, event.getCause()); | |||
currentTarget = null; | |||
@@ -881,7 +881,7 @@ public class Project implements org.apache.ant.common.event.BuildListener { | |||
try { | |||
task = (Task)c.newInstance(); | |||
task.setProject(this); | |||
task.init(context); | |||
task.init(context, taskType); | |||
return task; | |||
} catch (Throwable e) { | |||
throw new BuildException(e); | |||
@@ -69,6 +69,8 @@ public abstract class ProjectComponent { | |||
protected Location location; | |||
/** The core context for this component */ | |||
private AntContext context; | |||
/** The type of the component bneing created */ | |||
private String componentType; | |||
/** | |||
* Sets the project of the ProjectComponent | |||
@@ -108,16 +110,39 @@ public abstract class ProjectComponent { | |||
return location; | |||
} | |||
/** | |||
* Gets the componentType of the ProjectComponent | |||
* | |||
* @return the componentType value | |||
*/ | |||
public String getComponentType() { | |||
return componentType; | |||
} | |||
/** | |||
* Get the context associated with this component | |||
* | |||
* @return the AntContext | |||
*/ | |||
public AntContext getAntContext() { | |||
return context; | |||
} | |||
/** | |||
* Initialise this component | |||
* | |||
* @param context the core context for this component | |||
* @param componentType the component type of this component | |||
* @exception ExecutionException if the component cannot be initialized | |||
*/ | |||
public void init(AntContext context) throws ExecutionException { | |||
public void init(AntContext context, String componentType) | |||
throws ExecutionException { | |||
this.context = context; | |||
this.componentType = componentType; | |||
org.apache.ant.common.util.Location contextLocation | |||
= context.getModelElement().getLocation(); | |||
= context.getLocation(); | |||
if (contextLocation | |||
== org.apache.ant.common.util.Location.UNKNOWN_LOCATION) { | |||
@@ -129,11 +154,6 @@ public abstract class ProjectComponent { | |||
} | |||
} | |||
/** Destroy this component */ | |||
public void destroy() { | |||
// nothing to do | |||
} | |||
/** | |||
* Log a message as a build event | |||
* | |||
@@ -154,15 +174,5 @@ public abstract class ProjectComponent { | |||
public void log(String message) { | |||
log(message, Project.MSG_INFO); | |||
} | |||
/** | |||
* Get the context associated with this component | |||
* | |||
* @return the AntContext | |||
*/ | |||
protected AntContext getContext() { | |||
return context; | |||
} | |||
} | |||
@@ -54,8 +54,8 @@ | |||
package org.apache.tools.ant; | |||
import org.apache.ant.common.antlib.AntContext; | |||
import org.apache.ant.common.service.ExecService; | |||
import org.apache.ant.common.util.ExecutionException; | |||
import org.apache.ant.common.model.BuildElement; | |||
/** | |||
* Ant1 Task facade | |||
@@ -74,22 +74,6 @@ public abstract class Task extends ProjectComponent | |||
/** The description of this task */ | |||
protected String description = null; | |||
/** | |||
* Initialise this component | |||
* | |||
* @param context the core context for this component | |||
* @exception ExecutionException if the component cannot be initialized | |||
*/ | |||
public void init(AntContext context) throws ExecutionException { | |||
super.init(context); | |||
if (context.getModelElement() instanceof BuildElement) { | |||
BuildElement buildElement = (BuildElement)context.getModelElement(); | |||
taskType = buildElement.getType(); | |||
taskName = taskType; | |||
} | |||
} | |||
/** | |||
* Set the name to use in logging messages. | |||
* | |||
@@ -147,12 +131,39 @@ public abstract class Task extends ProjectComponent | |||
return description; | |||
} | |||
/** | |||
* Initialise this component | |||
* | |||
* @param context the core context for this component | |||
* @param componentType the component type of this component | |||
* @exception ExecutionException if the component cannot be initialized | |||
*/ | |||
public void init(AntContext context, String componentType) | |||
throws ExecutionException { | |||
super.init(context, componentType); | |||
taskType = componentType; | |||
taskName = componentType; | |||
} | |||
/** Validate this component */ | |||
public void validateComponent() { | |||
// no default validation for Ant1 tasks | |||
} | |||
/** Execute this task sending the appropriate build events */ | |||
public final void perform() { | |||
try { | |||
AntContext context = getAntContext(); | |||
ExecService execService | |||
= (ExecService)context.getCoreService(ExecService.class); | |||
execService.executeTask(this); | |||
} catch (ExecutionException e) { | |||
throw new BuildException(e); | |||
} | |||
} | |||
/** | |||
* Handle output captured for this task | |||
* | |||
@@ -122,7 +122,7 @@ public class ScriptBase extends AbstractTask implements DeferredTask { | |||
try { | |||
BSFManager manager = new BSFManager(); | |||
manager.declareBean("self", this, getClass()); | |||
manager.declareBean("context", getContext(), AntContext.class); | |||
manager.declareBean("context", getAntContext(), AntContext.class); | |||
// execute the script | |||
BSFEngine engine = manager.loadScriptingEngine(language); | |||
@@ -139,9 +139,9 @@ public class ScriptFactory extends StandardLibFactory { | |||
} | |||
/** | |||
* Create an instance of the given task class | |||
* Create an instance of the given component class | |||
* | |||
* @param taskClass the class for which an instance is required | |||
* @param componentClass the class for which an instance is required | |||
* @param localName the name within the library undeer which the task is | |||
* defined | |||
* @return an instance of the required class | |||
@@ -149,20 +149,20 @@ public class ScriptFactory extends StandardLibFactory { | |||
* @exception IllegalAccessException if the instance cannot be accessed | |||
* @exception ExecutionException if there is a problem creating the task | |||
*/ | |||
public Object createTaskInstance(Class taskClass, String localName) | |||
public Object createComponent(Class componentClass, String localName) | |||
throws InstantiationException, IllegalAccessException, | |||
ExecutionException { | |||
Object task = super.createTaskInstance(taskClass, localName); | |||
Object component = super.createComponent(componentClass, localName); | |||
if (task instanceof ScriptDef) { | |||
ScriptDef scriptDef = (ScriptDef)task; | |||
if (component instanceof ScriptDef) { | |||
ScriptDef scriptDef = (ScriptDef)component; | |||
scriptDef.setFactory(this); | |||
} else if (task instanceof ScriptBase) { | |||
ScriptBase scriptBase = (ScriptBase)task; | |||
} else if (component instanceof ScriptBase) { | |||
ScriptBase scriptBase = (ScriptBase)component; | |||
scriptBase.setFactory(this); | |||
scriptBase.setScriptName(localName); | |||
} | |||
return task; | |||
return component; | |||
} | |||
/** | |||
@@ -105,7 +105,7 @@ public class Ant extends AntBase { | |||
*/ | |||
public void execute() throws ExecutionException { | |||
if (baseDir == null) { | |||
baseDir = getContext().getBaseDir(); | |||
baseDir = getAntContext().getBaseDir(); | |||
} | |||
if (antFile == null) { | |||
antFile = new File(baseDir, "build.ant"); | |||
@@ -253,10 +253,13 @@ public abstract class AntBase extends AbstractTask { | |||
* Initialise this task | |||
* | |||
* @param context core's context | |||
* @param componentType the component type of this component (i.e its | |||
* defined name in the build file) | |||
* @exception ExecutionException if we can't access the data service | |||
*/ | |||
public void init(AntContext context) throws ExecutionException { | |||
super.init(context); | |||
public void init(AntContext context, String componentType) | |||
throws ExecutionException { | |||
super.init(context, componentType); | |||
dataService = (DataService)getCoreService(DataService.class); | |||
} | |||
@@ -70,7 +70,7 @@ public class AntCall extends AntBase { | |||
*/ | |||
public void execute() throws ExecutionException { | |||
setProperty(MagicProperties.BASEDIR, | |||
getContext().getBaseDir().getAbsolutePath()); | |||
getAntContext().getBaseDir().getAbsolutePath()); | |||
ExecService execService | |||
= (ExecService)getCoreService(ExecService.class); | |||
@@ -143,7 +143,7 @@ public class Import extends AbstractTask { | |||
* @exception ExecutionException if the components cannot be imported | |||
*/ | |||
public void execute() throws ExecutionException { | |||
AntContext context = getContext(); | |||
AntContext context = getAntContext(); | |||
ComponentService componentService = (ComponentService) | |||
context.getCoreService(ComponentService.class); | |||
if (ref != null) { | |||
@@ -150,7 +150,7 @@ public class LibPath extends AbstractTask { | |||
* the library | |||
*/ | |||
public void execute() throws ExecutionException { | |||
AntContext context = getContext(); | |||
AntContext context = getAntContext(); | |||
ComponentService componentService = (ComponentService) | |||
context.getCoreService(ComponentService.class); | |||
componentService.addLibPath(libraryId, url); | |||
@@ -148,7 +148,7 @@ public class LoadLib extends AbstractTask { | |||
* loaded. | |||
*/ | |||
public void execute() throws ExecutionException { | |||
AntContext context = getContext(); | |||
AntContext context = getAntContext(); | |||
ComponentService componentService = (ComponentService) | |||
context.getCoreService(ComponentService.class); | |||
componentService.loadLib(url.toString(), importAll); | |||
@@ -138,6 +138,7 @@ public class Builder { | |||
files.add(new File(TASKDEFS_ROOT, "LogStreamHandler.java")); | |||
files.add(new File(TASKDEFS_ROOT, "LogOutputStream.java")); | |||
files.add(new File(TASKDEFS_ROOT, "condition/Os.java")); | |||
files.add(new File(TASKDEFS_ROOT, "condition/Contains.java")); | |||
files.add(new File(TASKDEFS_ROOT, "condition/Condition.java")); | |||
files.add(new File(TASKDEFS_ROOT, "Available.java")); | |||
files.add(new File(TASKDEFS_ROOT, "Mkdir.java")); | |||
@@ -54,50 +54,73 @@ | |||
package org.apache.ant.cli; | |||
import java.io.PrintStream; | |||
import org.apache.ant.common.model.BuildElement; | |||
import org.apache.ant.common.model.Target; | |||
import org.apache.ant.common.antlib.ExecutionComponent; | |||
import org.apache.ant.common.antlib.Task; | |||
import org.apache.ant.common.event.BuildEvent; | |||
import org.apache.ant.common.event.MessageLevel; | |||
import org.apache.ant.common.model.Target; | |||
import org.apache.ant.common.util.AntException; | |||
import org.apache.ant.common.util.Location; | |||
import org.apache.ant.common.event.MessageLevel; | |||
/** | |||
* Writes build event to a PrintStream. Currently, it only writes which | |||
* targets are being executed, and any messages that get logged. | |||
* Writes build event to a PrintStream. Currently, it only writes which | |||
* targets are being executed, and any messages that get logged. | |||
* | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
* @created 15 January 2002 | |||
* @author <a href="mailto:conor@apache.org">Conor MacNeill</a> | |||
* @created 15 January 2002 | |||
*/ | |||
public class DefaultLogger implements BuildLogger { | |||
/** The stream where output should be written */ | |||
/** Standard field separator */ | |||
private static String lSep = System.getProperty("line.separator"); | |||
/** spacing to allow for task tags */ | |||
private static final int LEFT_COLUMN_SIZE = 12; | |||
/** The stream where output should be written */ | |||
private PrintStream out; | |||
/** The stream to where errors should be written */ | |||
/** The stream to where errors should be written */ | |||
private PrintStream err; | |||
/** The level of messages which should be let through */ | |||
/** The level of messages which should be let through */ | |||
private int messageOutputLevel = MessageLevel.MSG_ERR; | |||
/** Controls whether adornments are added */ | |||
/** Controls whether adornments are added */ | |||
private boolean emacsMode = false; | |||
/** The time at which the build started */ | |||
/** The time at which the build started */ | |||
private long startTime = System.currentTimeMillis(); | |||
/** Standard field separator */ | |||
private static String lSep = System.getProperty("line.separator"); | |||
/** spacing to allow for task tags */ | |||
private static final int LEFT_COLUMN_SIZE = 12; | |||
/** | |||
* Format the time into something readable | |||
* | |||
* @param millis Java millis value | |||
* @return the formatted time | |||
*/ | |||
protected static String formatTime(long millis) { | |||
long seconds = millis / 1000; | |||
long minutes = seconds / 60; | |||
if (minutes > 0) { | |||
return Long.toString(minutes) + " minute" | |||
+ (minutes == 1 ? " " : "s ") | |||
+ Long.toString(seconds % 60) + " second" | |||
+ (seconds % 60 == 1 ? "" : "s"); | |||
} else { | |||
return Long.toString(seconds) + " second" | |||
+ (seconds % 60 == 1 ? "" : "s"); | |||
} | |||
} | |||
/** | |||
* Set the messageOutputLevel this logger is to respond to. Only | |||
* messages with a message level lower than or equal to the given level | |||
* are output to the log. <P> | |||
* Set the messageOutputLevel this logger is to respond to. Only | |||
* messages with a message level lower than or equal to the given level | |||
* are output to the log. <P> | |||
* | |||
* Constants for the message levels are in Project.java. The order of | |||
* the levels, from least to most verbose, is MSG_ERR, MSG_WARN, | |||
* MSG_INFO, MSG_VERBOSE, MSG_DEBUG. The default message level for | |||
* DefaultLogger is Project.MSG_ERR. | |||
* Constants for the message levels are in Project.java. The order of | |||
* the levels, from least to most verbose, is MSG_ERR, MSG_WARN, | |||
* MSG_INFO, MSG_VERBOSE, MSG_DEBUG. The default message level for | |||
* DefaultLogger is Project.MSG_ERR. | |||
* | |||
* @param level the logging level for the logger. | |||
* @param level the logging level for the logger. | |||
*/ | |||
public void setMessageOutputLevel(int level) { | |||
this.messageOutputLevel = level; | |||
@@ -105,28 +128,27 @@ public class DefaultLogger implements BuildLogger { | |||
/** | |||
* Set the output stream to which this logger is to send its output. | |||
* Set the output stream to which this logger is to send its output. | |||
* | |||
* @param output the output stream for the logger. | |||
* @param output the output stream for the logger. | |||
*/ | |||
public void setOutputPrintStream(PrintStream output) { | |||
this.out = output; | |||
} | |||
/** | |||
* Set the output stream to which this logger is to send error | |||
* messages. | |||
* Set the output stream to which this logger is to send error messages. | |||
* | |||
* @param err the error stream for the logger. | |||
* @param err the error stream for the logger. | |||
*/ | |||
public void setErrorPrintStream(PrintStream err) { | |||
this.err = err; | |||
} | |||
/** | |||
* Set this logger to produce emacs (and other editor) friendly output. | |||
* Set this logger to produce emacs (and other editor) friendly output. | |||
* | |||
* @param emacsMode true if output is to be unadorned so that emacs and | |||
* @param emacsMode true if output is to be unadorned so that emacs and | |||
* other editors can parse files names, etc. | |||
*/ | |||
public void setEmacsMode(boolean emacsMode) { | |||
@@ -134,9 +156,9 @@ public class DefaultLogger implements BuildLogger { | |||
} | |||
/** | |||
* Report an exception | |||
* Report an exception | |||
* | |||
* @param t The exception to be reported. | |||
* @param t The exception to be reported. | |||
*/ | |||
public void reportException(Throwable t) { | |||
if (t instanceof AntException) { | |||
@@ -161,18 +183,18 @@ public class DefaultLogger implements BuildLogger { | |||
} | |||
/** | |||
* Description of the Method | |||
* Description of the Method | |||
* | |||
* @param event Description of Parameter | |||
* @param event Description of Parameter | |||
*/ | |||
public void buildStarted(BuildEvent event) { | |||
startTime = System.currentTimeMillis(); | |||
} | |||
/** | |||
* Description of the Method | |||
* Description of the Method | |||
* | |||
* @param event Description of Parameter | |||
* @param event Description of Parameter | |||
*/ | |||
public void buildFinished(BuildEvent event) { | |||
Throwable cause = event.getCause(); | |||
@@ -190,9 +212,9 @@ public class DefaultLogger implements BuildLogger { | |||
} | |||
/** | |||
* Description of the Method | |||
* Description of the Method | |||
* | |||
* @param event Description of Parameter | |||
* @param event Description of Parameter | |||
*/ | |||
public void targetStarted(BuildEvent event) { | |||
if (MessageLevel.MSG_INFO <= messageOutputLevel) { | |||
@@ -202,33 +224,33 @@ public class DefaultLogger implements BuildLogger { | |||
} | |||
/** | |||
* Description of the Method | |||
* Description of the Method | |||
* | |||
* @param event Description of Parameter | |||
* @param event Description of Parameter | |||
*/ | |||
public void targetFinished(BuildEvent event) { | |||
} | |||
/** | |||
* Description of the Method | |||
* Description of the Method | |||
* | |||
* @param event Description of Parameter | |||
* @param event Description of Parameter | |||
*/ | |||
public void taskStarted(BuildEvent event) { | |||
} | |||
/** | |||
* Description of the Method | |||
* Description of the Method | |||
* | |||
* @param event Description of Parameter | |||
* @param event Description of Parameter | |||
*/ | |||
public void taskFinished(BuildEvent event) { | |||
} | |||
/** | |||
* Description of the Method | |||
* Description of the Method | |||
* | |||
* @param event Description of Parameter | |||
* @param event Description of Parameter | |||
*/ | |||
public void messageLogged(BuildEvent event) { | |||
PrintStream logTo | |||
@@ -236,20 +258,26 @@ public class DefaultLogger implements BuildLogger { | |||
// Filter out messages based on priority | |||
if (event.getPriority() <= messageOutputLevel) { | |||
if (event.getModelElement() instanceof BuildElement) { | |||
// Print out the name of the task if we're in one | |||
BuildElement buildElement | |||
= (BuildElement)event.getModelElement(); | |||
String name = buildElement.getType(); | |||
String name = null; | |||
Object source = event.getSource(); | |||
if (source instanceof Task) { | |||
name = ((Task)source).getTaskName(); | |||
} | |||
if (name == null && source instanceof ExecutionComponent) { | |||
name = ((ExecutionComponent)source).getComponentType(); | |||
} | |||
if (name != null) { | |||
// Print out the name of the task if we're in one | |||
if (!emacsMode) { | |||
String msg = "[" + name + "] "; | |||
int indentSize = LEFT_COLUMN_SIZE - msg.length(); | |||
String tag = "[" + name + "] "; | |||
int indentSize = LEFT_COLUMN_SIZE - tag.length(); | |||
for (int i = 0; i < indentSize; i++) { | |||
logTo.print(" "); | |||
} | |||
logTo.print(msg); | |||
logTo.print(tag); | |||
} | |||
} | |||
@@ -257,27 +285,5 @@ public class DefaultLogger implements BuildLogger { | |||
logTo.println(event.getMessage()); | |||
} | |||
} | |||
/** | |||
* Format the time into something readable | |||
* | |||
* @param millis Java millis value | |||
* @return the formatted time | |||
*/ | |||
protected static String formatTime(long millis) { | |||
long seconds = millis / 1000; | |||
long minutes = seconds / 60; | |||
if (minutes > 0) { | |||
return Long.toString(minutes) + " minute" | |||
+ (minutes == 1 ? " " : "s ") | |||
+ Long.toString(seconds % 60) + " second" | |||
+ (seconds % 60 == 1 ? "" : "s"); | |||
} else { | |||
return Long.toString(seconds) + " second" | |||
+ (seconds % 60 == 1 ? "" : "s"); | |||
} | |||
} | |||
} | |||
@@ -65,15 +65,43 @@ public abstract class AbstractComponent implements ExecutionComponent { | |||
/** The components's context */ | |||
private AntContext context; | |||
/** | |||
* the type of the component. The type is the name of the component in | |||
* the build file. This may be different from the name under which this | |||
* componenent is known in its library due to aliasing | |||
*/ | |||
private String componentType; | |||
/** | |||
* Get this component's context | |||
* | |||
* @return the component context | |||
*/ | |||
public AntContext getAntContext() { | |||
return context; | |||
} | |||
/** | |||
* Gets the componentType of the AbstractComponent | |||
* | |||
* @return the componentType value | |||
*/ | |||
public String getComponentType() { | |||
return componentType; | |||
} | |||
/** | |||
* Initialise the component. The component may use the AntContext to | |||
* request services from the Ant core. | |||
* | |||
* @param context the component's context | |||
* @param componentType the type of the component | |||
* @exception ExecutionException if initialisation fails | |||
*/ | |||
public void init(AntContext context) throws ExecutionException { | |||
public void init(AntContext context, String componentType) | |||
throws ExecutionException { | |||
this.context = context; | |||
this.componentType = componentType; | |||
} | |||
/** | |||
@@ -87,15 +115,6 @@ public abstract class AbstractComponent implements ExecutionComponent { | |||
// no validation by default | |||
} | |||
/** | |||
* Get this component's context | |||
* | |||
* @return the component context | |||
*/ | |||
protected AntContext getContext() { | |||
return context; | |||
} | |||
/** | |||
* Short cut to get a core service instance | |||
* | |||
@@ -60,9 +60,26 @@ package org.apache.ant.common.antlib; | |||
* @created 16 January 2002 | |||
*/ | |||
public abstract class AbstractTask extends AbstractComponent implements Task { | |||
/** Task is about to be cleaned up */ | |||
public void destroy() { | |||
// do nothing here | |||
/** The name of this task. */ | |||
private String taskName; | |||
/** | |||
* Sets the taskName of the AbstractTask | |||
* | |||
* @param taskName the new taskName value | |||
*/ | |||
public final void setTaskName(String taskName) { | |||
this.taskName = taskName; | |||
} | |||
/** | |||
* Gets the taskName of the AbstractTask | |||
* | |||
* @return the taskName value | |||
*/ | |||
public final String getTaskName() { | |||
return taskName; | |||
} | |||
} | |||
@@ -53,9 +53,8 @@ | |||
*/ | |||
package org.apache.ant.common.antlib; | |||
import java.io.File; | |||
import org.apache.ant.common.model.ModelElement; | |||
import org.apache.ant.common.util.ExecutionException; | |||
import org.apache.ant.common.util.Location; | |||
/** | |||
* The AntContext is the interface through which the Ant container and the | |||
@@ -95,10 +94,10 @@ public interface AntContext { | |||
File getBaseDir(); | |||
/** | |||
* Get the model element associated with this context | |||
* Gets the location associated witj the AntContext | |||
* | |||
* @return the modelElement associated with this context | |||
* @return the location | |||
*/ | |||
ModelElement getModelElement(); | |||
Location getLocation(); | |||
} | |||
@@ -64,21 +64,6 @@ import org.apache.ant.common.util.ExecutionException; | |||
* @created 31 January 2002 | |||
*/ | |||
public interface AntLibFactory { | |||
/** | |||
* Create an instance of the given type class | |||
* | |||
* @param typeClass the class for which an instance is required | |||
* @param localName the name within the library under which the type is | |||
* defined | |||
* @return an instance of the required class | |||
* @exception InstantiationException if the class cannot be instantiated | |||
* @exception IllegalAccessException if the instance cannot be accessed | |||
* @exception ExecutionException if there is a problem creating the type | |||
*/ | |||
Object createTypeInstance(Class typeClass, String localName) | |||
throws InstantiationException, IllegalAccessException, | |||
ExecutionException; | |||
/** | |||
* Initialise the factory | |||
* | |||
@@ -88,9 +73,9 @@ public interface AntLibFactory { | |||
void init(AntContext context) throws ExecutionException; | |||
/** | |||
* Create an instance of the given task class | |||
* Create an instance of the given component class | |||
* | |||
* @param taskClass the class for which an instance is required | |||
* @param componentClass the class for which an instance is required | |||
* @param localName the name within the library under which the task is | |||
* defined | |||
* @return an instance of the required class | |||
@@ -98,7 +83,7 @@ public interface AntLibFactory { | |||
* @exception IllegalAccessException if the instance cannot be accessed | |||
* @exception ExecutionException if there is a problem creating the task | |||
*/ | |||
Object createTaskInstance(Class taskClass, String localName) | |||
Object createComponent(Class componentClass, String localName) | |||
throws InstantiationException, IllegalAccessException, | |||
ExecutionException; | |||
@@ -67,17 +67,34 @@ public interface ExecutionComponent { | |||
* services from the Ant core. | |||
* | |||
* @param context the Task's context | |||
* @param componentType the type of the component | |||
* @exception ExecutionException if the component cannot be initialised | |||
*/ | |||
void init(AntContext context) throws ExecutionException; | |||
void init(AntContext context, String componentType) | |||
throws ExecutionException; | |||
/** | |||
* Validate the component. This is called after the element has been | |||
* configured from its build model. The element may perform validation | |||
* of its configuration | |||
* | |||
* @exception ExecutionException if the component is not validly configured | |||
* @exception ExecutionException if the component is not validly | |||
* configured | |||
*/ | |||
void validateComponent() throws ExecutionException; | |||
/** | |||
* Get the AntContext associated with this component | |||
* | |||
* @return the component's context | |||
*/ | |||
AntContext getAntContext(); | |||
/** | |||
* Get the type of the component in the build file | |||
* | |||
* @return the type of the component | |||
*/ | |||
String getComponentType(); | |||
} | |||
@@ -66,9 +66,9 @@ public class StandardLibFactory implements AntLibFactory { | |||
private AntContext context; | |||
/** | |||
* Create an instance of the given task class | |||
* Create an instance of the given component class | |||
* | |||
* @param taskClass the class for which an instance is required | |||
* @param componentClass the class for which an instance is required | |||
* @param localName the name within the library under which the task is | |||
* defined | |||
* @return an instance of the required class | |||
@@ -76,27 +76,10 @@ public class StandardLibFactory implements AntLibFactory { | |||
* @exception IllegalAccessException if the instance cannot be accessed | |||
* @exception ExecutionException if there is a problem creating the task | |||
*/ | |||
public Object createTaskInstance(Class taskClass, String localName) | |||
public Object createComponent(Class componentClass, String localName) | |||
throws InstantiationException, IllegalAccessException, | |||
ExecutionException { | |||
return taskClass.newInstance(); | |||
} | |||
/** | |||
* Create an instance of the given type class | |||
* | |||
* @param typeClass the class for which an instance is required | |||
* @param localName the name within the library under which the type is | |||
* defined, if any. | |||
* @return an instance of the required class | |||
* @exception InstantiationException if the class cannot be instantiated | |||
* @exception IllegalAccessException if the instance cannot be accessed | |||
* @exception ExecutionException if there is a problem creating the type | |||
*/ | |||
public Object createTypeInstance(Class typeClass, String localName) | |||
throws InstantiationException, IllegalAccessException, | |||
ExecutionException { | |||
return typeClass.newInstance(); | |||
return componentClass.newInstance(); | |||
} | |||
/** | |||
@@ -68,7 +68,18 @@ public interface Task extends ExecutionComponent { | |||
*/ | |||
void execute() throws ExecutionException; | |||
/** Task is about to be cleaned up */ | |||
void destroy(); | |||
/** | |||
* Sets the taskName of the Task | |||
* | |||
* @param name the new taskName value | |||
*/ | |||
void setTaskName(String name); | |||
/** | |||
* Gets the taskName of the Task | |||
* | |||
* @return the taskName value | |||
*/ | |||
String getTaskName(); | |||
} | |||
@@ -54,7 +54,6 @@ | |||
package org.apache.ant.common.event; | |||
import java.util.EventObject; | |||
import org.apache.ant.common.model.ModelElement; | |||
/** | |||
* A BuildEvent indicates the occurence of a significant event in the build. | |||
@@ -170,18 +169,5 @@ public class BuildEvent extends EventObject { | |||
return cause; | |||
} | |||
/** | |||
* Gets the modelElement of the BuildEvent | |||
* | |||
* @return the model element this event is associated with | |||
*/ | |||
public ModelElement getModelElement() { | |||
Object source = getSource(); | |||
if (source instanceof ModelElement) { | |||
return (ModelElement)getSource(); | |||
} | |||
return null; | |||
} | |||
} | |||
@@ -158,5 +158,18 @@ public interface ComponentService { | |||
*/ | |||
void importFrameComponent(String relativeName, String alias) | |||
throws ExecutionException; | |||
/** | |||
* Create a component. The component will have a context but will not be | |||
* configured. It should be configured using the appropriate set methods | |||
* and then validated before being used. | |||
* | |||
* @param componentName the name of the component | |||
* @return the created component. The return type of this method depends | |||
* on the component type. | |||
* @exception ExecutionException if the component cannot be created | |||
*/ | |||
Object createComponent(String componentName) throws ExecutionException; | |||
} | |||
@@ -55,6 +55,7 @@ package org.apache.ant.common.service; | |||
import java.io.File; | |||
import java.util.List; | |||
import java.util.Map; | |||
import org.apache.ant.common.antlib.Task; | |||
import org.apache.ant.common.model.Project; | |||
import org.apache.ant.common.util.ExecutionException; | |||
@@ -97,5 +98,13 @@ public interface ExecService { | |||
void callTarget(Map properties, List targets) | |||
throws ExecutionException; | |||
/** | |||
* execute a task. The task should have already been initialised by | |||
* the core | |||
* | |||
* @param task the task to be executed. | |||
* @exception ExecutionException if there is a problem in execution. | |||
*/ | |||
void executeTask(Task task) throws ExecutionException; | |||
} | |||
@@ -267,5 +267,20 @@ public class LoaderUtils { | |||
} | |||
return urls; | |||
} | |||
/** | |||
* Set the context loader of the current thread and returns the existing | |||
* classloader | |||
* | |||
* @param newLoader the new context loader | |||
* @return the old context loader | |||
*/ | |||
public static ClassLoader setContextLoader(ClassLoader newLoader) { | |||
Thread thread = Thread.currentThread(); | |||
ClassLoader currentLoader = thread.getContextClassLoader(); | |||
thread.setContextClassLoader(newLoader); | |||
return currentLoader; | |||
} | |||
} | |||