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 | |||
* 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)); | |||
} | |||
} | |||
@@ -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); | |||
} | |||
@@ -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; | |||
} | |||
@@ -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 | |||
@@ -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) | |||
@@ -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; | |||
} | |||