git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272721 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -440,21 +440,40 @@ public class ComponentManager implements ComponentService { | |||||
| * @exception ExecutionException if there is a problem creating or | * @exception ExecutionException if there is a problem creating or | ||||
| * configuring the component | * configuring the component | ||||
| */ | */ | ||||
| protected Object createComponent(String componentName, BuildElement model) | |||||
| private Object createComponent(String componentName, BuildElement model) | |||||
| throws ExecutionException { | 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 | // is there a polymorph indicator - look in Ant aspects | ||||
| String typeName | String typeName | ||||
| = model.getAspectAttributeValue(Constants.ANT_ASPECT, "type"); | = 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; | Object typeInstance = null; | ||||
| if (typeName != null) { | if (typeName != null) { | ||||
| // the build file has specified the actual type of the element. | // the build file has specified the actual type of the element. | ||||
| // we need to look up that type and use it | // we need to look up that type and use it | ||||
| typeInstance = createComponent(typeName, model); | 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) { | } else if (nestedType != null) { | ||||
| // We need to create an instance of the class expected by the nested | // We need to create an instance of the class expected by the nested | ||||
| // element's adder method if that is possible | // 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 | // is the typeInstance compatible with the type expected | ||||
| // by the element's add method | // by the element's add method | ||||
| if (!nestedType.isInstance(typeInstance)) { | 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); | setter.addElement(element, nestedElementName, typeInstance); | ||||
| } | } | ||||
| @@ -781,23 +768,28 @@ public class ComponentManager implements ComponentService { | |||||
| * | * | ||||
| * @param object the object to be configured. | * @param object the object to be configured. | ||||
| * @param attributeValues a map containing named attribute values. | * @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 | * @exception ExecutionException if the object does not support an | ||||
| * attribute in the map. | * attribute in the map. | ||||
| */ | */ | ||||
| public void configureAttributes(Object object, Map attributeValues) | |||||
| public void configureAttributes(Object object, Map attributeValues, | |||||
| boolean ignoreUnsupported) | |||||
| throws ExecutionException { | throws ExecutionException { | ||||
| Setter setter = getSetter(object.getClass()); | Setter setter = getSetter(object.getClass()); | ||||
| for (Iterator i = attributeValues.keySet().iterator(); i.hasNext();) { | for (Iterator i = attributeValues.keySet().iterator(); i.hasNext();) { | ||||
| String attributeName = (String) i.next(); | String attributeName = (String) i.next(); | ||||
| String attributeValue = (String) attributeValues.get(attributeName); | String attributeValue = (String) attributeValues.get(attributeName); | ||||
| if (!setter.supportsAttribute(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)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -868,6 +868,7 @@ public class Frame implements DemuxOutputReceiver { | |||||
| */ | */ | ||||
| protected void executeTask(Task task, AspectValueCollection aspectValues) | protected void executeTask(Task task, AspectValueCollection aspectValues) | ||||
| throws ExecutionException { | throws ExecutionException { | ||||
| List aspects = componentManager.getAspects(); | List aspects = componentManager.getAspects(); | ||||
| Map aspectContexts = new HashMap(); | Map aspectContexts = new HashMap(); | ||||
| for (Iterator i = aspects.iterator(); i.hasNext();) { | for (Iterator i = aspects.iterator(); i.hasNext();) { | ||||
| @@ -897,6 +898,7 @@ public class Frame implements DemuxOutputReceiver { | |||||
| } | } | ||||
| // Now call back the aspects that registered interest | // Now call back the aspects that registered interest | ||||
| Set activeAspects = aspectContexts.keySet(); | Set activeAspects = aspectContexts.keySet(); | ||||
| for (Iterator i = activeAspects.iterator(); i.hasNext();) { | for (Iterator i = activeAspects.iterator(); i.hasNext();) { | ||||
| Aspect aspect = (Aspect) i.next(); | Aspect aspect = (Aspect) i.next(); | ||||
| @@ -932,18 +934,8 @@ public class Frame implements DemuxOutputReceiver { | |||||
| BuildElement model = (BuildElement) taskIterator.next(); | BuildElement model = (BuildElement) taskIterator.next(); | ||||
| // what sort of element is this. | // what sort of element is this. | ||||
| List aspects = componentManager.getAspects(); | |||||
| try { | try { | ||||
| Object component = componentManager.createComponent(model); | 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) { | if (component instanceof Task) { | ||||
| execService.executeTask((Task) component); | execService.executeTask((Task) component); | ||||
| } | } | ||||
| @@ -91,6 +91,41 @@ public class AntAspect extends AbstractAspect { | |||||
| = (ComponentService) context.getCoreService(ComponentService.class); | = (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 | * This join point is activated after a component has been created and | ||||
| * configured. If the aspect wishes, an object can be returned in place | * 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); | dataService.setMutableDataValue(typeId, component); | ||||
| } | } | ||||
| return null; | |||||
| return super.postCreateComponent(component, model); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -135,7 +170,8 @@ public class AntAspect extends AbstractAspect { | |||||
| return null; | return null; | ||||
| } | } | ||||
| componentService.configureAttributes(aspectContext, antAspectValues); | |||||
| componentService.configureAttributes(aspectContext, antAspectValues, | |||||
| true); | |||||
| if (aspectContext.isRequired()) { | if (aspectContext.isRequired()) { | ||||
| return aspectContext; | return aspectContext; | ||||
| } | } | ||||
| @@ -88,7 +88,23 @@ public class AbstractAspect implements Aspect { | |||||
| return context; | 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 | * This join point is activated after a component has been created and | ||||
| * configured. If the aspect wishes, an object can be returned in place | * 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) | public Object postCreateComponent(Object component, BuildElement model) | ||||
| throws ExecutionException { | throws ExecutionException { | ||||
| return null; | |||||
| return component; | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -111,8 +127,8 @@ public class AbstractAspect implements Aspect { | |||||
| * | * | ||||
| * @param task the task being executed. | * @param task the task being executed. | ||||
| * @param aspectValues a collection of aspect attribute values for use | * @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 | * @return an object which indicates that this aspect wishes to | ||||
| * be notified after execution has been completed, in which case the obkect | * be notified after execution has been completed, in which case the obkect | ||||
| * is returned to provide the aspect its context. If this returns null | * is returned to provide the aspect its context. If this returns null | ||||
| @@ -75,6 +75,21 @@ public interface Aspect { | |||||
| throws ExecutionException; | 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 | * This join point is activated after a component has been created and | ||||
| * configured. If the aspect wishes, an object can be returned in place | * 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 component the component that has been created. | ||||
| * @param model the Build model used to create the component. | * @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. | * @exception ExecutionException if the aspect cannot process the component. | ||||
| */ | */ | ||||
| Object postCreateComponent(Object component, BuildElement model) | Object postCreateComponent(Object component, BuildElement model) | ||||
| @@ -190,15 +190,17 @@ public interface ComponentService { | |||||
| throws ExecutionException; | 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 object the object to be configured. | ||||
| * @param attributeValues a map containing named attribute values. | * @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 | * @exception ExecutionException if the object does not support an | ||||
| * attribute in the map. | * attribute in the map. | ||||
| */ | */ | ||||
| void configureAttributes(Object object, Map attributeValues) | |||||
| void configureAttributes(Object object, Map attributeValues, | |||||
| boolean ignoreUnsupported) | |||||
| throws ExecutionException; | throws ExecutionException; | ||||
| } | } | ||||