diff --git a/proposal/mutant/build.xml b/proposal/mutant/build.xml
index b5af3e7ab..90f67cdd8 100644
--- a/proposal/mutant/build.xml
+++ b/proposal/mutant/build.xml
@@ -46,7 +46,7 @@
-
+
@@ -54,7 +54,7 @@
-
+
@@ -66,7 +66,7 @@
-
+
@@ -78,7 +78,7 @@
-
+
@@ -98,7 +98,7 @@
-
+
@@ -126,7 +126,7 @@
-
+
@@ -155,7 +155,7 @@
-
+
diff --git a/proposal/mutant/build/ant1compat.xml b/proposal/mutant/build/ant1compat.xml
index 459456961..c7593bfc4 100644
--- a/proposal/mutant/build/ant1compat.xml
+++ b/proposal/mutant/build/ant1compat.xml
@@ -431,7 +431,8 @@
-
+
-
+
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 96297897b..4aee9573d 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
@@ -184,7 +184,6 @@ public class ComponentManager implements ComponentService {
if (importAll || doAuto) {
importLibrary(libraryId);
}
- addAspects((AntLibrary) antLibraries.get(libraryId));
}
} catch (MalformedURLException e) {
throw new ExecutionException("Unable to load libraries from "
@@ -265,6 +264,7 @@ public class ComponentManager implements ComponentService {
importLibraryDef(library, defName, null);
}
addConverters(library);
+ addAspects(library);
}
/**
@@ -288,6 +288,7 @@ public class ComponentManager implements ComponentService {
}
importLibraryDef(library, defName, alias);
addConverters(library);
+ addAspects(library);
}
/**
@@ -392,7 +393,7 @@ public class ComponentManager implements ComponentService {
return (AntLibFactory) libFactories.get(libraryId);
}
ExecutionContext context
- = new ExecutionContext(frame, null, Location.UNKNOWN_LOCATION);
+ = new ExecutionContext(frame, null, null);
AntLibFactory libFactory = componentLibrary.getFactory(context);
if (libFactory == null) {
libFactory = new StandardLibFactory();
@@ -511,7 +512,7 @@ public class ComponentManager implements ComponentService {
// initialise the component with it.
if (execComponent != null) {
ExecutionContext context
- = new ExecutionContext(frame, execComponent, location);
+ = new ExecutionContext(frame, execComponent, model);
context.setClassLoader(componentLoader);
execComponent.init(context, componentName);
}
@@ -604,98 +605,6 @@ public class ComponentManager implements ComponentService {
return setter;
}
- /**
- * Create a component - handles all the variations
- *
- * @param loader the component's classloader
- * @param componentClass The class of the component.
- * @param componentName The component's name in the global context
- * @param addTaskAdapter whether the component should add a Task adapter
- * to make this component a Task.
- * @param localName The name of the component within its library
- * @param model the BuildElement model of the component's configuration
- * @param factory the facrtory object used to create the component
- * @return the required component potentially wrapped in a wrapper object.
- * @exception ExecutionException if the component cannot be created
- */
- private Object createComponent(ClassLoader loader, AntLibFactory factory,
- Class componentClass, String componentName,
- String localName, boolean addTaskAdapter,
- BuildElement model)
- throws ExecutionException {
- // set the location to unknown unless we have a build model to use
- Location location = Location.UNKNOWN_LOCATION;
- if (model != null) {
- location = model.getLocation();
- }
-
- try {
- // create the component using the factory
- Object component
- = factory.createComponent(componentClass, localName);
-
- // wrap the component in an adapter if required.
- ExecutionComponent execComponent = null;
- if (addTaskAdapter) {
- if (component instanceof Task) {
- execComponent = (Task) component;
- } else {
- execComponent = new TaskAdapter(componentName, component);
- }
- } else if (component instanceof ExecutionComponent) {
- execComponent = (ExecutionComponent) component;
- }
-
- // set the context loader to that for the component
- ClassLoader currentLoader
- = LoaderUtils.setContextLoader(loader);
-
- // if the component is an execution component create a context and
- // initialise the component with it.
- if (execComponent != null) {
- ExecutionContext context
- = new ExecutionContext(frame, execComponent, location);
- context.setClassLoader(loader);
- execComponent.init(context, componentName);
- }
-
- // if we have a model, use it to configure the component. Otherwise
- // the caller is expected to configure thre object
- if (model != null) {
- configureElement(factory, component, model);
- // if the component is an execution component and we have a
- // model, validate it
- if (execComponent != null) {
- execComponent.validateComponent();
- }
- }
-
- // reset the loader
- LoaderUtils.setContextLoader(currentLoader);
-
- // if we have an execution component, potentially a wrapper,
- // return it otherwise the component directly
- if (execComponent != null) {
- return execComponent;
- } else {
- return component;
- }
- } catch (InstantiationException e) {
- throw new ExecutionException("Unable to instantiate component "
- + "class " + componentClass.getName() + " for component <"
- + componentName + ">", e, location);
- } catch (IllegalAccessException e) {
- throw new ExecutionException("Unable to access task class "
- + componentClass.getName() + " for component <"
- + componentName + ">", e, location);
- } catch (ExecutionException e) {
- e.setLocation(location, false);
- throw e;
- } catch (RuntimeException e) {
- throw new ExecutionException(e, location);
- }
- }
-
/**
* Create an instance of a type given its required class
*
@@ -718,8 +627,8 @@ public class ComponentManager implements ComponentService {
if (typeInstance instanceof ExecutionComponent) {
ExecutionComponent component
= (ExecutionComponent) typeInstance;
- ExecutionContext context = new ExecutionContext(frame,
- component, model.getLocation());
+ ExecutionContext context
+ = new ExecutionContext(frame, component, model);
component.init(context, localName);
configureElement(libFactory, typeInstance, model);
component.validateComponent();
@@ -761,8 +670,10 @@ public class ComponentManager implements ComponentService {
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");
+ String typeName
+ = model.getAspectAttributeValue(Constants.ANT_ASPECT, "type");
+ String refId
+ = model.getAspectAttributeValue(Constants.ANT_ASPECT, "refid");
if (refId != null && typeName != null) {
throw new ExecutionException("Only one of " + Constants.ANT_ASPECT
+ ":type and " + Constants.ANT_ASPECT
@@ -849,8 +760,8 @@ public class ComponentManager implements ComponentService {
if (nestedElement instanceof ExecutionComponent) {
ExecutionComponent component
= (ExecutionComponent) nestedElement;
- ExecutionContext context = new ExecutionContext(frame,
- component, model.getLocation());
+ ExecutionContext context
+ = new ExecutionContext(frame, component, model);
component.init(context, nestedElementName);
configureElement(factory, nestedElement, model);
component.validateComponent();
@@ -865,6 +776,30 @@ public class ComponentManager implements ComponentService {
}
}
+ /**
+ * configure an object with attribtes from the given map
+ *
+ * @param object the object to be configured.
+ * @param attributeValues a map containing named attribute values.
+ *
+ * @exception ExecutionException if the object does not support an
+ * attribute in the map.
+ */
+ public void configureAttributes(Object object, Map attributeValues)
+ throws ExecutionException {
+ Setter setter = getSetter(object.getClass());
+ for (Iterator i = attributeValues.keySet().iterator(); i.hasNext();) {
+ String attributeName = (String) i.next();
+ String attributeValue = (String) attributeValues.get(attributeName);
+ if (!setter.supportsAttribute(attributeName)) {
+ throw new ExecutionException(object.getClass().getName()
+ + " does not support the \"" + attributeName
+ + "\" attribute");
+ }
+ setter.setAttribute(object, attributeName,
+ frame.replacePropertyRefs(attributeValue));
+ }
+ }
/**
* Configure an element according to the given model.
@@ -985,8 +920,8 @@ public class ComponentManager implements ComponentService {
+ " does not implement the Aspect interface");
}
Aspect aspect = (Aspect) libFactory.createInstance(aspectClass);
- ExecutionContext context = new ExecutionContext(frame,
- null, Location.UNKNOWN_LOCATION);
+ ExecutionContext context
+ = new ExecutionContext(frame, null, null);
aspect.init(context);
aspects.add(aspect);
}
@@ -1045,8 +980,8 @@ public class ComponentManager implements ComponentService {
}
Converter converter
= (Converter) libFactory.createInstance(converterClass);
- ExecutionContext context = new ExecutionContext(frame,
- null, Location.UNKNOWN_LOCATION);
+ ExecutionContext context
+ = new ExecutionContext(frame, null, null);
converter.init(context);
Class[] converterTypes = converter.getTypes();
for (int j = 0; j < converterTypes.length; ++j) {
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 889624e00..2f17c4521 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
@@ -60,10 +60,13 @@ import java.util.Map;
import org.apache.ant.antcore.modelparser.XMLProjectParser;
import org.apache.ant.antcore.xml.XMLParseException;
import org.apache.ant.common.antlib.Task;
+import org.apache.ant.common.antlib.AntContext;
import org.apache.ant.common.model.Project;
+import org.apache.ant.common.model.BuildElement;
import org.apache.ant.common.service.ExecService;
import org.apache.ant.common.util.ExecutionException;
import org.apache.ant.init.InitUtils;
+import org.apache.ant.common.model.AspectValueCollection;
/**
* This is the core's implementation of the Execution Service.
@@ -98,8 +101,54 @@ public class CoreExecService implements ExecService {
* @exception ExecutionException if there is an execution problem
*/
public void executeTask(Task task) throws ExecutionException {
- frame.executeTask(task);
+ ExecutionContext execContext = getTaskExecutionContext(task);
+
+ BuildElement model = execContext.getModel();
+ AspectValueCollection aspectValues = null;
+ if (model != null) {
+ aspectValues = model.getAspectAttributes();
+ }
+ frame.executeTask(task, aspectValues);
+ }
+
+ /**
+ * Retrieve the execution context from a task and verify that the context
+ * is valid.
+ *
+ * @param task the task.
+ * @return the task's execution context.
+ *
+ * @exception ExecutionException if the task's context is not valid.
+ */
+ private ExecutionContext getTaskExecutionContext(Task task)
+ throws ExecutionException {
+ AntContext context = task.getAntContext();
+
+ if (!(context instanceof ExecutionContext)) {
+ throw new ExecutionException("The Task was not configured with an"
+ + " appropriate context");
+ }
+ return (ExecutionContext) context;
+ }
+
+ /**
+ * Execute a task with a set of aspect values. Normally aspect values come
+ * from a build model but not all tasks will be created from a build model.
+ * Some may be created dynamically and configured programatically. This
+ * method allows aspect values to provided for execution of such tasks since
+ * by their nature, aspect values are not part of the task configuration.
+ *
+ * @param task the task to be executed
+ * @param aspectValues the aspect attribute values.
+ * @exception ExecutionException if there is an execution problem
+ */
+ public void executeTask(Task task, AspectValueCollection aspectValues)
+ throws ExecutionException {
+ ExecutionContext execContext = getTaskExecutionContext(task);
+
+ frame.executeTask(task, aspectValues);
}
+
/**
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 2287a4ca7..c91539c7f 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
@@ -56,6 +56,7 @@ import org.apache.ant.common.antlib.AntContext;
import org.apache.ant.common.antlib.ExecutionComponent;
import org.apache.ant.common.util.ExecutionException;
import org.apache.ant.common.util.Location;
+import org.apache.ant.common.model.BuildElement;
/**
* This is the core's implementation of the AntContext for all core objects.
@@ -71,8 +72,8 @@ public class ExecutionContext implements AntContext {
/** the event support instance used to manage build events */
private BuildEventSupport eventSupport;
- /** The location of the object associated with this context */
- private Location location;
+ /** The build model associated with this context. */
+ private BuildElement model;
/** the execution component associated with the context, if any */
private ExecutionComponent component;
@@ -89,13 +90,13 @@ public class ExecutionContext implements AntContext {
*
* @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
+ * @param model the build model associated with this component if any.
*/
protected ExecutionContext(Frame frame, ExecutionComponent component,
- Location location) {
+ BuildElement model) {
this.frame = frame;
this.eventSupport = frame.getEventSupport();
- this.location = location;
+ this.model = model;
this.component = component;
}
@@ -120,7 +121,10 @@ public class ExecutionContext implements AntContext {
* @return the location in the build model associated with this context.
*/
public Location getLocation() {
- return location;
+ if (model == null) {
+ return Location.UNKNOWN_LOCATION;
+ }
+ return model.getLocation();
}
/**
@@ -166,5 +170,14 @@ public class ExecutionContext implements AntContext {
protected ExecutionComponent getExecutionComponent() {
return component;
}
+
+ /**
+ * Get the build model associated with this context.
+ *
+ * @return the build model or null if there is no build model.
+ */
+ protected BuildElement getModel() {
+ return model;
+ }
}
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 b963d8d2a..301009df6 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
@@ -65,12 +65,12 @@ import java.util.Set;
import org.apache.ant.antcore.config.AntConfig;
import org.apache.ant.common.antlib.Task;
import org.apache.ant.common.antlib.Aspect;
-import org.apache.ant.common.antlib.AntContext;
import org.apache.ant.common.event.BuildListener;
import org.apache.ant.common.event.MessageLevel;
import org.apache.ant.common.model.BuildElement;
import org.apache.ant.common.model.Project;
import org.apache.ant.common.model.Target;
+import org.apache.ant.common.model.AspectValueCollection;
import org.apache.ant.common.service.ComponentService;
import org.apache.ant.common.service.DataService;
import org.apache.ant.common.service.EventService;
@@ -860,36 +860,32 @@ public class Frame implements DemuxOutputReceiver {
}
/**
- * Execute a task notifiying all registered aspects of the fact
- *
- * @param task the Task instance to execute.
+ * Execute a task with the given aspect values.
*
+ * @param task the task to be executed.
+ * @param aspectValues the collection of aspect attribute values.
* @exception ExecutionException if the task has a problem.
*/
- protected void executeTask(Task task) throws ExecutionException {
+ protected void executeTask(Task task, AspectValueCollection aspectValues)
+ throws ExecutionException {
List aspects = componentManager.getAspects();
Map aspectContexts = new HashMap();
for (Iterator i = aspects.iterator(); i.hasNext();) {
Aspect aspect = (Aspect) i.next();
- Object context = aspect.preExecuteTask(task);
- aspectContexts.put(aspect, context);
+ Object aspectContext = aspect.preExecuteTask(task, aspectValues);
+ if (aspectContext != null) {
+ aspectContexts.put(aspect, aspectContext);
+ }
}
if (aspectContexts.size() != 0) {
aspectContextsMap.put(task, aspectContexts);
}
- AntContext context = task.getAntContext();
-
- if (!(context instanceof ExecutionContext)) {
- throw new ExecutionException("The Task was not configured with an"
- + " appropriate context");
- }
- ExecutionContext execContext = (ExecutionContext) context;
-
eventSupport.fireTaskStarted(task);
Throwable failureCause = null;
+ ExecutionContext execContext = (ExecutionContext) task.getAntContext();
try {
ClassLoader currentLoader
= LoaderUtils.setContextLoader(execContext.getClassLoader());
@@ -949,7 +945,7 @@ public class Frame implements DemuxOutputReceiver {
}
if (component instanceof Task) {
- executeTask((Task) component);
+ execService.executeTask((Task) component);
}
} catch (ExecutionException e) {
e.setLocation(model.getLocation(), false);
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/BuildElementHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/BuildElementHandler.java
index 7695ff754..df406840e 100644
--- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/BuildElementHandler.java
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/BuildElementHandler.java
@@ -93,7 +93,7 @@ public class BuildElementHandler extends ModelElementHandler {
buildElement.addAttribute(attributeName,
getAttribute(attributeName));
}
- buildElement.setAspects(getAspects());
+ buildElement.addAspectAttributes(getAspectAttributes());
}
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/ProjectHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/ProjectHandler.java
index 7b37970a6..1d8db526b 100644
--- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/ProjectHandler.java
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/ProjectHandler.java
@@ -133,7 +133,7 @@ public class ProjectHandler extends ModelElementHandler {
project.setDefaultTarget(getAttribute(DEFAULT_ATTR));
project.setBase(getAttribute(BASEDIR_ATTR));
project.setName(getAttribute(NAME_ATTR));
- project.setAspects(getAspects());
+ project.addAspectAttributes(getAspectAttributes());
}
}
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/TargetHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/TargetHandler.java
index 2f98316c6..5469f3f25 100644
--- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/TargetHandler.java
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/TargetHandler.java
@@ -105,7 +105,7 @@ public class TargetHandler extends ModelElementHandler {
target = new Target(getLocation(), getAttribute(NAME_ATTR));
setModelElement(target);
target.setDescription(getAttribute(DESC_ATTR));
- target.setAspects(getAspects());
+ target.addAspectAttributes(getAspectAttributes());
String depends = getAttribute(DEPENDS_ATTR);
if (depends != null) {
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ElementHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ElementHandler.java
index 189302a68..6e576eff3 100755
--- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ElementHandler.java
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/xml/ElementHandler.java
@@ -101,7 +101,7 @@ public abstract class ElementHandler extends DefaultHandler {
private Map elementAttributes;
/** The aspect attributes read from the element definition */
- private Map aspects;
+ private Map aspectAttributes;
/** The content of this element */
private String content;
@@ -150,8 +150,8 @@ public abstract class ElementHandler extends DefaultHandler {
*
* @return The aspect attributes.
*/
- public Map getAspects() {
- return aspects;
+ public Map getAspectAttributes() {
+ return aspectAttributes;
}
/**
@@ -313,14 +313,14 @@ public abstract class ElementHandler extends DefaultHandler {
*/
protected final void processAttributes(Attributes attributes)
throws SAXParseException {
- aspects = new HashMap();
+ aspectAttributes = new HashMap();
elementAttributes = new HashMap();
int length = attributes.getLength();
for (int i = 0; i < length; ++i) {
String attributeName = attributes.getQName(i);
String attributeValue = attributes.getValue(i);
if (attributeName.indexOf(":") != -1) {
- aspects.put(attributeName, attributeValue);
+ aspectAttributes.put(attributeName, attributeValue);
} else {
validateAttribute(attributeName, attributeValue);
elementAttributes.put(attributeName, attributeValue);
diff --git a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntAspect.java b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntAspect.java
index 0cefe5c10..0a1eea592 100644
--- a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntAspect.java
+++ b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntAspect.java
@@ -52,11 +52,16 @@
* .
*/
package org.apache.ant.antlib.system;
+
+import java.util.Map;
import org.apache.ant.common.antlib.AbstractAspect;
import org.apache.ant.common.antlib.AntContext;
+import org.apache.ant.common.antlib.Task;
import org.apache.ant.common.service.DataService;
+import org.apache.ant.common.service.ComponentService;
import org.apache.ant.common.util.ExecutionException;
import org.apache.ant.common.model.BuildElement;
+import org.apache.ant.common.model.AspectValueCollection;
/**
* The Ant aspect - handles all ant aspects
@@ -70,6 +75,9 @@ public class AntAspect extends AbstractAspect {
/** The core's data service implementation */
private DataService dataService = null;
+ /** The core's component service */
+ private ComponentService componentService = null;
+
/**
* Initialise the aspect with a context.
*
@@ -79,6 +87,8 @@ public class AntAspect extends AbstractAspect {
public void init(AntContext context) throws ExecutionException {
super.init(context);
dataService = (DataService) context.getCoreService(DataService.class);
+ componentService
+ = (ComponentService) context.getCoreService(ComponentService.class);
}
/**
@@ -95,7 +105,7 @@ public class AntAspect extends AbstractAspect {
*/
public Object postCreateComponent(Object component, BuildElement model)
throws ExecutionException {
- String typeId = model.getAspectValue(ANT_ASPECT, "id");
+ String typeId = model.getAspectAttributeValue(ANT_ASPECT, "id");
if (typeId != null) {
dataService.setMutableDataValue(typeId, component);
@@ -103,5 +113,51 @@ public class AntAspect extends AbstractAspect {
return null;
}
+
+ /**
+ * This join point is activated just prior to task execution.
+ *
+ * @param task the task being executed.
+ * @param aspectValues a collection of aspect attribute values for use
+ * during the task execution.
+ *
+ * @return an objectwhich indicates that this aspect wishes to
+ * be notified after execution has been completed, in which case the obkect
+ * is returned to provide the aspect its context. If this returns null
+ * the aspect's postExecuteTask method will not be invoked.
+ * @exception ExecutionException if the aspect cannot process the task.
+ */
+ public Object preExecuteTask(Task task, AspectValueCollection aspectValues)
+ throws ExecutionException {
+ AntAspectContext aspectContext = new AntAspectContext();
+ Map antAspectValues = aspectValues.getAttributes(ANT_ASPECT);
+ if (antAspectValues == null) {
+ return null;
+ }
+
+ componentService.configureAttributes(aspectContext, antAspectValues);
+ if (aspectContext.isRequired()) {
+ return aspectContext;
+ }
+ return null;
+ }
+
+ /**
+ * This join point is activated after a task has executed. The aspect
+ * may override the task's failure cause by returning a new failure.
+ *
+ * @param context the context the aspect provided in preExecuteTask.
+ * @param failureCause the current failure reason for the task.
+ *
+ * @return a new failure reason or null if the task is not to fail.
+ */
+ public Throwable postExecuteTask(Object context, Throwable failureCause) {
+ AntAspectContext aspectContext = (AntAspectContext) context;
+ if (!aspectContext.getFailOnError()) {
+ return null;
+ }
+ return super.postExecuteTask(context, failureCause);
+ }
+
}
diff --git a/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntAspectContext.java b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntAspectContext.java
new file mode 100644
index 000000000..00ec71df4
--- /dev/null
+++ b/proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntAspectContext.java
@@ -0,0 +1,94 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.ant.antlib.system;
+
+/**
+ * The context for the Ant Aspect
+ *
+ * @author Conor MacNeill
+ */
+public class AntAspectContext {
+ /** Indicates if the task's execution should not fail */
+ private boolean failOnError = true;
+
+ /**
+ * Set the flag covering whether a task failure halts the build.
+ *
+ * @param failOnError false if the build should continue.
+ */
+ public void setFailOnError(boolean failOnError) {
+ this.failOnError = failOnError;
+ }
+
+ /**
+ * Indicate whether a task failure halts the build.
+ *
+ * @return true if a task error causes the build to fail.
+ */
+ public boolean getFailOnError() {
+ return failOnError;
+ }
+
+ /**
+ * Indicate if this aspect context is required - i.e. whether the
+ * aspect needs to be reactivated after task execution
+ *
+ * @return true if the context should be used and the aspect reactivated
+ * after task execution.
+ */
+ public boolean isRequired() {
+ return failOnError != true;
+ }
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractAspect.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractAspect.java
index a762ca8c2..01fdd1b0f 100644
--- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractAspect.java
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractAspect.java
@@ -55,6 +55,7 @@ package org.apache.ant.common.antlib;
import org.apache.ant.common.util.ExecutionException;
import org.apache.ant.common.model.BuildElement;
+import org.apache.ant.common.model.AspectValueCollection;
/**
* An implementation of the Aspect interface providing default behaviour.
@@ -109,14 +110,17 @@ public class AbstractAspect implements Aspect {
* This join point is activated just prior to task execution.
*
* @param task the task being executed.
+ * @param aspectValues a collection of aspect attribute values for use
+ * during the task execution.
*
- * @return an objectwhich indicates that this aspect wishes to
+ * @return an object which indicates that this aspect wishes to
* be notified after execution has been completed, in which case the obkect
* is returned to provide the aspect its context. If this returns null
* the aspect's postExecuteTask method will not be invoked.
* @exception ExecutionException if the aspect cannot process the task.
*/
- public Object preExecuteTask(Task task) throws ExecutionException {
+ public Object preExecuteTask(Task task, AspectValueCollection aspectValues)
+ throws ExecutionException {
return null;
}
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 02770ce99..58946bcce 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
@@ -88,15 +88,8 @@ public interface AntContext {
/**
* Gets the location associated with the AntContext
*
- * @return the location
+ * @return the location which may be the unknown location
*/
Location getLocation();
-
- /**
- * Get the classloader associated with this context
- *
- * @return a classloader instance.
- */
- ClassLoader getClassLoader();
}
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Aspect.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Aspect.java
index bf07fe3ff..3e3efdbb4 100644
--- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Aspect.java
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Aspect.java
@@ -55,6 +55,7 @@ package org.apache.ant.common.antlib;
import org.apache.ant.common.util.ExecutionException;
import org.apache.ant.common.model.BuildElement;
+import org.apache.ant.common.model.AspectValueCollection;
/**
* An aspect is a component which is activated across all task and
@@ -93,14 +94,17 @@ public interface Aspect {
* This join point is activated just prior to task execution.
*
* @param task the task being executed.
- *
- * @return an objectwhich indicates that this aspect wishes to
+ * @param aspectValues a collection of aspect attribute values for use
+ * during the task execution - may be null if no aspect values are
+ * provided.
+ * @return an object which indicates that this aspect wishes to
* be notified after execution has been completed, in which case the obkect
* is returned to provide the aspect its context. If this returns null
* the aspect's postExecuteTask method will not be invoked.
* @exception ExecutionException if the aspect cannot process the task.
*/
- Object preExecuteTask(Task task) throws ExecutionException;
+ Object preExecuteTask(Task task, AspectValueCollection aspectValues)
+ throws ExecutionException;
/**
* This join point is activated after a task has executed. The aspect
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/model/AspectValueCollection.java b/proposal/mutant/src/java/common/org/apache/ant/common/model/AspectValueCollection.java
new file mode 100644
index 000000000..3c0f6db46
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/model/AspectValueCollection.java
@@ -0,0 +1,134 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.ant.common.model;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * The AspectValueCollection holds aspect values for a range of aspects.
+ * Values can be retrieved for a particular aspect attribute or all attributes
+ * of a given aspect.
+ *
+ * @author Conor MacNeill
+ * @created 11 January 2002
+ */
+public class AspectValueCollection {
+ /** The aspects defined for this element. */
+ private Map aspectMaps = new HashMap();
+
+ /**
+ * Set the aspect attribute values.
+ *
+ * The attributes are sorted into their various aspects
+ *
+ * @param attributes a Map of aspect attributes values. The keys are the
+ * aspect
+ */
+ public void addAttributes(Map attributes) {
+ for (Iterator i = attributes.keySet().iterator(); i.hasNext();) {
+ String attributeName = (String) i.next();
+ int separator = attributeName.indexOf(":");
+ if (separator != -1) {
+ String aspectName = attributeName.substring(0, separator);
+ String name = attributeName.substring(separator + 1);
+ if (aspectName.length() != 0 && name.length() != 0) {
+ Map prefixMap = (Map) aspectMaps.get(aspectName);
+ if (prefixMap == null) {
+ prefixMap = new HashMap();
+ aspectMaps.put(aspectName, prefixMap);
+ }
+ prefixMap.put(name, attributes.get(attributeName));
+ }
+ }
+ }
+ }
+
+ /**
+ * Get an iterator on the aspects which have been given values on this
+ * element
+ *
+ * @return an iterator of Strings , being the aspects which have been
+ * given values on this element.
+ */
+ public Iterator getNames() {
+ return aspectMaps.keySet().iterator();
+ }
+
+ /**
+ * Get the set of attribute values related to the given aspect
+ *
+ * @param aspectName the aspect name
+ * @return a map of the attribute values for the given aspect.
+ */
+ public Map getAttributes(String aspectName) {
+ return (Map) aspectMaps.get(aspectName);
+ }
+
+ /**
+ * Get the value of a single aspect attribute
+ *
+ * @param aspectName the prefix which identifies the aspectr
+ * @param keyName the attribute name
+ * @return the aspect value
+ */
+ public String getAttributeValue(String aspectName, String keyName) {
+ Map aspectAttributes = getAttributes(aspectName);
+ if (aspectAttributes == null) {
+ return null;
+ }
+ return (String) aspectAttributes.get(keyName);
+ }
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/model/ModelElement.java b/proposal/mutant/src/java/common/org/apache/ant/common/model/ModelElement.java
index 4c84b12af..4bb9643d4 100644
--- a/proposal/mutant/src/java/common/org/apache/ant/common/model/ModelElement.java
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/model/ModelElement.java
@@ -52,7 +52,7 @@
* .
*/
package org.apache.ant.common.model;
-import java.util.HashMap;
+
import java.util.Iterator;
import java.util.Map;
@@ -67,8 +67,8 @@ import org.apache.ant.common.util.Location;
* @created 11 January 2002
*/
public abstract class ModelElement {
- /** The aspects defined for this element. */
- private Map aspectMaps;
+ /** The aspectValues defined for this element. */
+ private AspectValueCollection aspectValues = new AspectValueCollection();
/** The starting location of this element */
private Location location = Location.UNKNOWN_LOCATION;
@@ -107,28 +107,13 @@ public abstract class ModelElement {
}
/**
- * Set the aspects of this element
+ * Adds aspect related attributes of this element
*
- * @param aspects a Map of apects that relate to this model element.
+ * @param aspectAttributes a Map of aspect realted attributes that pertain
+ * to this model element.
*/
- public void setAspects(Map aspects) {
- aspectMaps = new HashMap();
- for (Iterator i = aspects.keySet().iterator(); i.hasNext();) {
- String aspectName = (String) i.next();
- int separator = aspectName.indexOf(":");
- if (separator != -1) {
- String prefix = aspectName.substring(0, separator);
- String name = aspectName.substring(separator + 1);
- if (prefix.length() != 0 && name.length() != 0) {
- Map prefixMap = (Map) aspectMaps.get(prefix);
- if (prefixMap == null) {
- prefixMap = new HashMap();
- aspectMaps.put(prefix, prefixMap);
- }
- prefixMap.put(name, aspects.get(aspectName));
- }
- }
- }
+ public void addAspectAttributes(Map aspectAttributes) {
+ aspectValues.addAttributes(aspectAttributes);
}
/**
@@ -159,39 +144,44 @@ public abstract class ModelElement {
}
/**
- * Get an iterator on the aspects which have been given values on this
+ * Get an iterator on the aspectValues which have been given values on this
* element
*
- * @return an iterator of Strings , being the aspects which have been
+ * @return an iterator of Strings , being the aspectValues which have been
* given values on this element.
*/
public Iterator getAspectNames() {
- return aspectMaps.keySet().iterator();
+ return aspectValues.getNames();
}
/**
* Get the set of attribute values related to the given aspect
*
- * @param aspectPrefix the aspect identifier
+ * @param aspectName the aspect identifier
* @return a map of the attribute values for the given aspect.
*/
- public Map getAspectAttributes(String aspectPrefix) {
- return (Map) aspectMaps.get(aspectPrefix);
+ public Map getAspectAttributes(String aspectName) {
+ return aspectValues.getAttributes(aspectName);
}
/**
* Get the value of a single aspect attribute
*
- * @param aspectPrefix the prefix which identifies the aspectr
+ * @param aspectName the aspect name
* @param keyName the attribute name
* @return the aspect value
*/
- public String getAspectValue(String aspectPrefix, String keyName) {
- Map aspectAttributes = getAspectAttributes(aspectPrefix);
- if (aspectAttributes == null) {
- return null;
- }
- return (String) aspectAttributes.get(keyName);
+ public String getAspectAttributeValue(String aspectName, String keyName) {
+ return aspectValues.getAttributeValue(aspectName, keyName);
+ }
+
+ /**
+ * Get the complete collection of aspect attribute values.
+ *
+ * @return an AspectValueCollection instance.
+ */
+ public AspectValueCollection getAspectAttributes() {
+ return aspectValues;
}
}
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 d4b8f66a7..885375adf 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
@@ -53,9 +53,11 @@
*/
package org.apache.ant.common.service;
import java.net.URL;
+import java.util.Map;
import org.apache.ant.common.antlib.AntLibFactory;
import org.apache.ant.common.util.ExecutionException;
+
/**
* The Component Service is used to manage the definitions that Ant uses at
* runtime. It supports the following operations
@@ -186,5 +188,17 @@ public interface ComponentService {
*/
Object createComponent(String libraryId, String localName)
throws ExecutionException;
+
+ /**
+ * Configure an object with attribtes from the given map
+ *
+ * @param object the object to be configured.
+ * @param attributeValues a map containing named attribute values.
+ *
+ * @exception ExecutionException if the object does not support an
+ * attribute in the map.
+ */
+ void configureAttributes(Object object, Map attributeValues)
+ 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 7f73f59aa..35f6bf99c 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
@@ -58,6 +58,7 @@ 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;
+import org.apache.ant.common.model.AspectValueCollection;
/**
* The ExecService provides executiuon services to tasks
@@ -133,6 +134,21 @@ public interface ExecService {
void executeTask(Task task) throws ExecutionException;
+ /**
+ * Execute a task with a set of aspect values. Normally aspect values come
+ * from a build model but not all tasks will be created from a build model.
+ * Some may be created dynamically and configured programatically. This
+ * method allows aspect values to provided for execution of such tasks since
+ * by their nature, aspect values are not part of the task configuration.
+ *
+ * @param task the task to be executed
+ * @param aspectValues the aspect attribute values.
+ * @exception ExecutionException if there is an execution problem
+ */
+ void executeTask(Task task, AspectValueCollection aspectValues)
+ throws ExecutionException;
+
+
/**
* get the name of the project associated with this execution.
*