Browse Source

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
master
Conor MacNeill 23 years ago
parent
commit
d571dff958
6 changed files with 127 additions and 75 deletions
  1. +46
    -54
      proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ComponentManager.java
  2. +2
    -10
      proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java
  3. +38
    -2
      proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntAspect.java
  4. +20
    -4
      proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractAspect.java
  5. +16
    -2
      proposal/mutant/src/java/common/org/apache/ant/common/antlib/Aspect.java
  6. +5
    -3
      proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java

+ 46
- 54
proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ComponentManager.java View File

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




+ 2
- 10
proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java View File

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


+ 38
- 2
proposal/mutant/src/java/antlibs/system/org/apache/ant/antlib/system/AntAspect.java View File

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


+ 20
- 4
proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractAspect.java View File

@@ -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


+ 16
- 2
proposal/mutant/src/java/common/org/apache/ant/common/antlib/Aspect.java View File

@@ -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)


+ 5
- 3
proposal/mutant/src/java/common/org/apache/ant/common/service/ComponentService.java View File

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



Loading…
Cancel
Save