diff --git a/proposal/mutant/bootstrap.sh b/proposal/mutant/bootstrap.sh index eb418e850..1eb4ca0a1 100755 --- a/proposal/mutant/bootstrap.sh +++ b/proposal/mutant/bootstrap.sh @@ -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 diff --git a/proposal/mutant/build.sh b/proposal/mutant/build.sh index c536e75cc..753bef805 100755 --- a/proposal/mutant/build.sh +++ b/proposal/mutant/build.sh @@ -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 $@ diff --git a/proposal/mutant/build/ant1compat.xml b/proposal/mutant/build/ant1compat.xml index 5a9ba3781..ec8ea5c16 100644 --- a/proposal/mutant/build/ant1compat.xml +++ b/proposal/mutant/build/ant1compat.xml @@ -28,8 +28,8 @@ - - + + diff --git a/proposal/mutant/docs.xml b/proposal/mutant/docs.xml deleted file mode 100644 index ca7cf5149..000000000 --- a/proposal/mutant/docs.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - AnakiaTask is not present! Please check to make sure that - velocity.jar is in your classpath. - - - - - - - - - - - - - - diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java index 077caec44..462e25639 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java @@ -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(); diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ComponentManager.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ComponentManager.java index 24c7c0b52..d6612e27a 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ComponentManager.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ComponentManager.java @@ -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); } } - } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskContext.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Constants.java old mode 100755 new mode 100644 similarity index 55% rename from proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskContext.java rename to proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Constants.java index d5a56f085..a48c4994c --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/TaskContext.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Constants.java @@ -52,88 +52,19 @@ * . */ 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 Conor MacNeill - * @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; - } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/CoreExecService.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/CoreExecService.java index a81aad2c7..fa3c670d7 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/CoreExecService.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/CoreExecService.java @@ -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 Conor MacNeill * @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); + } + } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionContext.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionContext.java index 1ddf88c4b..1babfbfd5 100755 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionContext.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionContext.java @@ -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; + } } diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java index 64284a4fe..dd0b7e683 100644 --- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java +++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java @@ -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); } } diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Ant1Factory.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Ant1Factory.java index c521b7412..3d3167faf 100644 --- a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Ant1Factory.java +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Ant1Factory.java @@ -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. * diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Project.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Project.java index 8362b37b9..a45c31abb 100644 --- a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Project.java +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Project.java @@ -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); diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectComponent.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectComponent.java index 2accd420e..759fa5367 100644 --- a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectComponent.java +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/ProjectComponent.java @@ -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; - } } diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java index 70ceace6c..1b036962e 100644 --- a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java +++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java @@ -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 * diff --git a/proposal/mutant/src/java/antlibs/script/org/apache/ant/antlib/script/ScriptBase.java b/proposal/mutant/src/java/antlibs/script/org/apache/ant/antlib/script/ScriptBase.java index 5efda01ff..143362652 100644 --- a/proposal/mutant/src/java/antlibs/script/org/apache/ant/antlib/script/ScriptBase.java +++ b/proposal/mutant/src/java/antlibs/script/org/apache/ant/antlib/script/ScriptBase.java @@ -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); diff --git a/proposal/mutant/src/java/antlibs/script/org/apache/ant/antlib/script/ScriptFactory.java b/proposal/mutant/src/java/antlibs/script/org/apache/ant/antlib/script/ScriptFactory.java index 53d3c0ad6..7e8f92b8f 100644 --- a/proposal/mutant/src/java/antlibs/script/org/apache/ant/antlib/script/ScriptFactory.java +++ b/proposal/mutant/src/java/antlibs/script/org/apache/ant/antlib/script/ScriptFactory.java @@ -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; } /** diff --git a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Ant.java b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Ant.java index 3c55c0d0c..73f9a48ba 100644 --- a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Ant.java +++ b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Ant.java @@ -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"); diff --git a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntBase.java b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntBase.java index 3a892ea6c..915283a70 100644 --- a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntBase.java +++ b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntBase.java @@ -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); } diff --git a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntCall.java b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntCall.java index ce47eb21b..b357d2263 100644 --- a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntCall.java +++ b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntCall.java @@ -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); diff --git a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Import.java b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Import.java index fa1803fc5..86946da4c 100644 --- a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Import.java +++ b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/Import.java @@ -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) { diff --git a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/LibPath.java b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/LibPath.java index c25703344..23c6f827d 100644 --- a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/LibPath.java +++ b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/LibPath.java @@ -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); diff --git a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/LoadLib.java b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/LoadLib.java index 061f4e70c..c8fd7c9fe 100644 --- a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/LoadLib.java +++ b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/LoadLib.java @@ -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); diff --git a/proposal/mutant/src/java/bootstrap/org/apache/ant/builder/Builder.java b/proposal/mutant/src/java/bootstrap/org/apache/ant/builder/Builder.java index 530c7fdb8..09c1a8d6f 100644 --- a/proposal/mutant/src/java/bootstrap/org/apache/ant/builder/Builder.java +++ b/proposal/mutant/src/java/bootstrap/org/apache/ant/builder/Builder.java @@ -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")); diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/DefaultLogger.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/DefaultLogger.java index 55e9304d9..7e4164b78 100755 --- a/proposal/mutant/src/java/cli/org/apache/ant/cli/DefaultLogger.java +++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/DefaultLogger.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 Conor MacNeill - * @created 15 January 2002 + * @author Conor MacNeill + * @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.

+ * 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.

* - * 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"); - } - - } } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractComponent.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractComponent.java index 7ce50cf3b..8ce2a8122 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractComponent.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractComponent.java @@ -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 * diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java index eb1449f21..6cccaa9ba 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java @@ -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; } + } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntContext.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntContext.java index b16f36e1b..1f4ac3525 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntContext.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntContext.java @@ -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(); } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntLibFactory.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntLibFactory.java index ce6736c62..95461273f 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntLibFactory.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AntLibFactory.java @@ -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; diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/ExecutionComponent.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/ExecutionComponent.java index ba524a23d..a1dcd820d 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/ExecutionComponent.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/ExecutionComponent.java @@ -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(); } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/StandardLibFactory.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/StandardLibFactory.java index 8f86faaff..c37a0b7e7 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/StandardLibFactory.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/StandardLibFactory.java @@ -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(); } /** diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Task.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Task.java index a3f8a3af5..da16f1dd5 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Task.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Task.java @@ -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(); } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildEvent.java b/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildEvent.java index 4785b6609..9d492f710 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildEvent.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/event/BuildEvent.java @@ -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; - } } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java b/proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java index 6fdc7bcaf..ad2a223bb 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java @@ -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; + } diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/service/ExecService.java b/proposal/mutant/src/java/common/org/apache/ant/common/service/ExecService.java index 6e31723ee..fcdf28ed2 100644 --- a/proposal/mutant/src/java/common/org/apache/ant/common/service/ExecService.java +++ b/proposal/mutant/src/java/common/org/apache/ant/common/service/ExecService.java @@ -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; } diff --git a/proposal/mutant/src/java/init/org/apache/ant/init/LoaderUtils.java b/proposal/mutant/src/java/init/org/apache/ant/init/LoaderUtils.java index fd551e885..bf3f57079 100755 --- a/proposal/mutant/src/java/init/org/apache/ant/init/LoaderUtils.java +++ b/proposal/mutant/src/java/init/org/apache/ant/init/LoaderUtils.java @@ -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; + } + }