From d571dff958cd85b5083a2a829f84e35b4abe4434 Mon Sep 17 00:00:00 2001 From: Conor MacNeill Date: Fri, 17 May 2002 12:20:38 +0000 Subject: [PATCH] Convert refids to an aspect based implementation git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272721 13f79535-47bb-0310-9956-ffa450edef68 --- .../antcore/execution/ComponentManager.java | 100 ++++++++---------- .../apache/ant/antcore/execution/Frame.java | 12 +-- .../apache/ant/antlib/system/AntAspect.java | 40 ++++++- .../ant/common/antlib/AbstractAspect.java | 24 ++++- .../org/apache/ant/common/antlib/Aspect.java | 18 +++- .../ant/common/service/ComponentService.java | 8 +- 6 files changed, 127 insertions(+), 75 deletions(-) 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 4aee9573d..a2aa510f2 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 @@ -440,21 +440,40 @@ public class ComponentManager implements ComponentService { * @exception ExecutionException if there is a problem creating or * configuring the component */ - protected Object createComponent(String componentName, BuildElement model) + private Object createComponent(String componentName, BuildElement model) throws ExecutionException { - ImportInfo importInfo = getImport(componentName); - if (importInfo == null) { - throw new ExecutionException("There is no definition of the <" - + componentName + "> component"); + Object component = null; + if (model != null) { + for (Iterator i = aspects.iterator(); i.hasNext();) { + Aspect aspect = (Aspect) i.next(); + component = aspect.preCreateComponent(component, model); + } } - String className = importInfo.getClassName(); - - ComponentLibrary componentLibrary - = importInfo.getComponentLibrary(); - - return createComponentFromDef(componentName, componentLibrary, - importInfo.getDefinition(), model); + + if (component == null) { + ImportInfo importInfo = getImport(componentName); + if (importInfo == null) { + throw new ExecutionException("There is no definition of the <" + + componentName + "> component"); + } + String className = importInfo.getClassName(); + + ComponentLibrary componentLibrary + = importInfo.getComponentLibrary(); + + component = createComponentFromDef(componentName, componentLibrary, + importInfo.getDefinition(), model); + } + + if (model != null) { + for (Iterator i = aspects.iterator(); i.hasNext();) { + Aspect aspect = (Aspect) i.next(); + component = aspect.postCreateComponent(component, model); + } + } + + return component; } /** @@ -672,36 +691,12 @@ public class ComponentManager implements ComponentService { // is there a polymorph indicator - look in Ant aspects 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 - + ":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 @@ -723,17 +718,9 @@ public class ComponentManager implements ComponentService { // 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()); - } + throw new ExecutionException("The type " + + typeName + " is not compatible with the <" + + nestedElementName + "> nested element", model.getLocation()); } setter.addElement(element, nestedElementName, typeInstance); } @@ -781,23 +768,28 @@ public class ComponentManager implements ComponentService { * * @param object the object to be configured. * @param attributeValues a map containing named attribute values. - * + * @param ignoreUnsupported if this is true, attribute names for which no + * setter method exists are ignored. * @exception ExecutionException if the object does not support an * attribute in the map. */ - public void configureAttributes(Object object, Map attributeValues) + public void configureAttributes(Object object, Map attributeValues, + boolean ignoreUnsupported) 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"); + if (!ignoreUnsupported) { + throw new ExecutionException(object.getClass().getName() + + " does not support the \"" + attributeName + + "\" attribute"); + } + } else { + setter.setAttribute(object, attributeName, + frame.replacePropertyRefs(attributeValue)); } - setter.setAttribute(object, attributeName, - frame.replacePropertyRefs(attributeValue)); } } 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 301009df6..6c9a3802c 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 @@ -868,6 +868,7 @@ public class Frame implements DemuxOutputReceiver { */ protected void executeTask(Task task, AspectValueCollection aspectValues) throws ExecutionException { + List aspects = componentManager.getAspects(); Map aspectContexts = new HashMap(); for (Iterator i = aspects.iterator(); i.hasNext();) { @@ -897,6 +898,7 @@ public class Frame implements DemuxOutputReceiver { } // Now call back the aspects that registered interest + Set activeAspects = aspectContexts.keySet(); for (Iterator i = activeAspects.iterator(); i.hasNext();) { Aspect aspect = (Aspect) i.next(); @@ -932,18 +934,8 @@ public class Frame implements DemuxOutputReceiver { BuildElement model = (BuildElement) taskIterator.next(); // what sort of element is this. - List aspects = componentManager.getAspects(); try { Object component = componentManager.createComponent(model); - for (Iterator i = aspects.iterator(); i.hasNext();) { - Aspect aspect = (Aspect) i.next(); - Object replacement - = aspect.postCreateComponent(component, model); - if (replacement != null) { - component = replacement; - } - } - if (component instanceof Task) { execService.executeTask((Task) component); } 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 0a1eea592..53dc57b73 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 @@ -91,6 +91,41 @@ public class AntAspect extends AbstractAspect { = (ComponentService) context.getCoreService(ComponentService.class); } + + /** + * This join point is activated before a component has been created. + * The aspect can return an object to be used rather than the core creating + * the object. + * + * @param component the component that has been created. This will be null + * unless another aspect has created the component + * @param model the Build model that applies to the component + * + * @return a component to use. + * @exception ExecutionException if the aspect cannot process the component. + */ + public Object preCreateComponent(Object component, BuildElement model) + throws ExecutionException { + String refId = model.getAspectAttributeValue(ANT_ASPECT, "refid"); + if (refId != null) { + if (model.getAttributeNames().hasNext() || + model.getNestedElements().hasNext() || + model.getText().length() != 0) { + throw new ExecutionException("Element <" + model.getType() + + "> is defined by reference and hence may not specify " + + "any attributes, nested elements or content", + model.getLocation()); + } + Object referredComponent = dataService.getDataValue(refId); + if (referredComponent == null) { + throw new ExecutionException("The given ant:refid value '" + + refId + "' is not defined", model.getLocation()); + } + return referredComponent; + } + return component; + } + /** * This join point is activated after a component has been created and * configured. If the aspect wishes, an object can be returned in place @@ -111,7 +146,7 @@ public class AntAspect extends AbstractAspect { dataService.setMutableDataValue(typeId, component); } - return null; + return super.postCreateComponent(component, model); } /** @@ -135,7 +170,8 @@ public class AntAspect extends AbstractAspect { return null; } - componentService.configureAttributes(aspectContext, antAspectValues); + componentService.configureAttributes(aspectContext, antAspectValues, + true); if (aspectContext.isRequired()) { return aspectContext; } 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 01fdd1b0f..c178aff3e 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 @@ -88,7 +88,23 @@ public class AbstractAspect implements Aspect { return context; } - + /** + * This join point is activated before a component is to be created. + * The aspect can return an object to be used rather than the core creating + * the object. + * + * @param component the component that has been created. This will be null + * unless another aspect has created the component + * @param model the Build model that applies to the component + * + * @return a component to use. + * @exception ExecutionException if the aspect cannot process the component. + */ + public Object preCreateComponent(Object component, BuildElement model) + throws ExecutionException { + return component; + } + /** * This join point is activated after a component has been created and * configured. If the aspect wishes, an object can be returned in place @@ -103,7 +119,7 @@ public class AbstractAspect implements Aspect { */ public Object postCreateComponent(Object component, BuildElement model) throws ExecutionException { - return null; + return component; } /** @@ -111,8 +127,8 @@ public class AbstractAspect implements Aspect { * * @param task the task being executed. * @param aspectValues a collection of aspect attribute values for use - * during the task execution. - * + * 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 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 3e3efdbb4..fe1a3bdf5 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 @@ -75,6 +75,21 @@ public interface Aspect { throws ExecutionException; + /** + * This join point is activated before a component has been created. + * The aspect can return an object to be used rather than the core creating + * the object. + * + * @param component the component that has been created. This will be null + * unless another aspect has created the component + * @param model the Build model that applies to the component + * + * @return a component to use. + * @exception ExecutionException if the aspect cannot process the component. + */ + Object preCreateComponent(Object component, BuildElement model) + throws ExecutionException; + /** * This join point is activated after a component has been created and * configured. If the aspect wishes, an object can be returned in place @@ -83,8 +98,7 @@ public interface Aspect { * @param component the component that has been created. * @param model the Build model used to create the component. * - * @return a replacement for the component if desired. If null is returned - * the current component is used. + * @return a component to use * @exception ExecutionException if the aspect cannot process the component. */ Object postCreateComponent(Object component, BuildElement model) 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 885375adf..c14b5bfb2 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 @@ -190,15 +190,17 @@ public interface ComponentService { throws ExecutionException; /** - * Configure an object with attribtes from the given map + * configure an object with attribtes from the given map * * @param object the object to be configured. * @param attributeValues a map containing named attribute values. - * + * @param ignoreUnsupported if this is true, attribute names for which no + * setter method exists are ignored. * @exception ExecutionException if the object does not support an * attribute in the map. */ - void configureAttributes(Object object, Map attributeValues) + void configureAttributes(Object object, Map attributeValues, + boolean ignoreUnsupported) throws ExecutionException; }