Index: src/main/org/apache/tools/ant/UnknownElement.java
===================================================================
--- src/main/org/apache/tools/ant/UnknownElement.java (revision 452068)
+++ src/main/org/apache/tools/ant/UnknownElement.java (working copy)
@@ -180,20 +180,15 @@
if (getWrapper().getId() != null) {
this.getOwningTarget().replaceChild(this, (Task) realThing);
}
- }
+ }
-
- // configure attributes of the object and it's children. If it is
- // a task container, defer the configuration till the task container
- // attempts to use the task
-
if (task != null) {
task.maybeConfigure();
} else {
getWrapper().maybeConfigure(getProject());
}
- handleChildren(realThing, getWrapper());
+ handleChildren(realThing, null);
}
/**
@@ -301,6 +296,50 @@
children.add(child);
}
+ private void recurHandleChild(
+ ComponentHelper helper, Object parent, UnknownElement child) {
+ // MacroFragment ?
+ if (child.getTag().indexOf('-') != -1) {
+ Class componentClass = helper.getComponentClass(
+ child.getComponentName());
+ if ((componentClass != null) &&
+ (MacroFragment.class.isAssignableFrom(componentClass))) {
+ child.maybeConfigure();
+
+ MacroFragment macroFragment = (MacroFragment) child.realThing;
+
+ List replaced = macroFragment.getUnknownElements(child);
+ for (Iterator i = replaced.iterator(); i.hasNext();) {
+ recurHandleChild(
+ helper, parent, (UnknownElement) i.next());
+ }
+ return;
+ }
+ }
+ // not a macro fragment - a "Normal" element
+ IntrospectionHelper ih = IntrospectionHelper.getHelper(
+ getProject(), parent.getClass());
+ try {
+ if (!handleChild(
+ getNamespace(), ih, parent, child)) {
+ if (!(parent instanceof TaskContainer)) {
+ ih.throwNotSupported(getProject(), parent,
+ child.getTag());
+ } else {
+ // a task container - anything could happen
+ // - just add the child to the container
+ TaskContainer container = (TaskContainer) parent;
+ container.addTask(child);
+ }
+ }
+ } catch (UnsupportedElementException ex) {
+ throw new BuildException(
+ getWrapper().getElementTag()
+ + " doesn't support the nested \"" + ex.getElement()
+ + "\" element.", ex);
+ }
+ }
+
/**
* Creates child elements, creates children of the children
* (recursively), and sets attributes of the child elements.
@@ -308,50 +347,27 @@
* @param parent The configured object for the parent.
* Must not be null
.
*
- * @param parentWrapper The wrapper containing child wrappers
- * to be configured. Must not be null
- * if there are any children.
+ * @param notUsed Not used.
*
* @exception BuildException if the children cannot be configured.
*/
protected void handleChildren(
Object parent,
- RuntimeConfigurable parentWrapper)
+ RuntimeConfigurable notUsed)
throws BuildException {
+ if (children == null) {
+ return;
+ }
+
+ ComponentHelper helper = ComponentHelper.getComponentHelper(
+ getProject());
+
if (parent instanceof TypeAdapter) {
parent = ((TypeAdapter) parent).getProxy();
}
- String parentUri = getNamespace();
- Class parentClass = parent.getClass();
- IntrospectionHelper ih = IntrospectionHelper.getHelper(getProject(), parentClass);
-
-
- if (children != null) {
- Iterator it = children.iterator();
- for (int i = 0; it.hasNext(); i++) {
- RuntimeConfigurable childWrapper = parentWrapper.getChild(i);
- UnknownElement child = (UnknownElement) it.next();
- try {
- if (!handleChild(
- parentUri, ih, parent, child, childWrapper)) {
- if (!(parent instanceof TaskContainer)) {
- ih.throwNotSupported(getProject(), parent,
- child.getTag());
- } else {
- // a task container - anything could happen - just add the
- // child to the container
- TaskContainer container = (TaskContainer) parent;
- container.addTask(child);
- }
- }
- } catch (UnsupportedElementException ex) {
- throw new BuildException(
- parentWrapper.getElementTag()
- + " doesn't support the nested \"" + ex.getElement()
- + "\" element.", ex);
- }
- }
+ for (Iterator i = children.iterator(); i.hasNext();) {
+ recurHandleChild(helper, parent, (UnknownElement) i.next());
}
}
@@ -528,10 +544,12 @@
private boolean handleChild(
String parentUri,
IntrospectionHelper ih,
- Object parent, UnknownElement child,
- RuntimeConfigurable childWrapper) {
+ Object parent, UnknownElement child) {
+ RuntimeConfigurable childWrapper = child.getWrapper();
+
String childName = ProjectHelper.genComponentName(
child.getNamespace(), child.getTag());
+
if (ih.supportsNestedElement(parentUri, childName)) {
IntrospectionHelper.Creator creator =
ih.getElementCreator(
@@ -556,7 +574,7 @@
((ProjectComponent) realChild).setLocation(child.getLocation());
}
childWrapper.maybeConfigure(getProject());
- child.handleChildren(realChild, childWrapper);
+ child.handleChildren(realChild, null);
creator.store();
return true;
}
Index: src/main/org/apache/tools/ant/MacroFragment.java
===================================================================
--- src/main/org/apache/tools/ant/MacroFragment.java (revision 0)
+++ src/main/org/apache/tools/ant/MacroFragment.java (revision 0)
@@ -0,0 +1,7 @@
+package org.apache.tools.ant;
+
+import java.util.List;
+
+public interface MacroFragment {
+ public List getUnknownElements(UnknownElement el);
+}
Index: src/main/org/apache/tools/ant/taskdefs/MacroDef.java
===================================================================
--- src/main/org/apache/tools/ant/taskdefs/MacroDef.java (revision 452068)
+++ src/main/org/apache/tools/ant/taskdefs/MacroDef.java (working copy)
@@ -40,7 +40,7 @@
*
* @since Ant 1.6
*/
-public class MacroDef extends AntlibDefinition {
+public class MacroDef extends AntlibDefinition {
private NestedSequential nestedSequential;
private String name;
@@ -50,6 +50,7 @@
private String textName = null;
private Text text = null;
private boolean hasImplicitElement = false;
+ private boolean fragment = false;
/**
* Name of the definition
@@ -122,14 +123,31 @@
* @return a sequential element to be configured.
*/
public NestedSequential createSequential() {
- if (this.nestedSequential != null) {
- throw new BuildException("Only one sequential allowed");
+ if (nestedSequential != null) {
+ throw new BuildException(
+ "Only one sequential or fragment allowed");
}
this.nestedSequential = new NestedSequential();
return this.nestedSequential;
}
+
/**
+ * This is the fragment nested element of the macrodef.
+ *
+ * @return a sequential element to be configured.
+ */
+ public NestedSequential createFragment() {
+ if (nestedSequential != null) {
+ throw new BuildException(
+ "Only one sequential or fragment allowed");
+ }
+ fragment = true;
+ this.nestedSequential = new NestedSequential();
+ return this.nestedSequential;
+ }
+
+ /**
* The class corresponding to the sequential nested element.
* This is a simple task container.
*/
@@ -329,17 +347,28 @@
*/
public void execute() {
if (nestedSequential == null) {
- throw new BuildException("Missing sequential element");
+ throw new BuildException("Missing sequential or fragment element");
}
if (name == null) {
throw new BuildException("Name not specified");
}
+ if (fragment) {
+ if (name.indexOf('-') == -1) {
+ throw new BuildException(
+ "fragment macro name must contain a '-'");
+ }
+ }
+
name = ProjectHelper.genComponentName(getURI(), name);
MyAntTypeDefinition def = new MyAntTypeDefinition(this);
def.setName(name);
- def.setClass(MacroInstance.class);
+ if (fragment) {
+ def.setClass(MacroFragmentTask.class);
+ } else {
+ def.setClass(MacroInstance.class);
+ }
ComponentHelper helper = ComponentHelper.getComponentHelper(
getProject());
Index: src/main/org/apache/tools/ant/taskdefs/MacroInstance.java
===================================================================
--- src/main/org/apache/tools/ant/taskdefs/MacroInstance.java (revision 452068)
+++ src/main/org/apache/tools/ant/taskdefs/MacroInstance.java (working copy)
@@ -242,7 +242,7 @@
this.text = text;
}
- private UnknownElement copy(UnknownElement ue) {
+ protected UnknownElement copy(UnknownElement ue) {
UnknownElement ret = new UnknownElement(ue.getTag());
ret.setNamespace(ue.getNamespace());
ret.setProject(getProject());
@@ -327,13 +327,7 @@
return ret;
}
- /**
- * Execute the templates instance.
- * Copies the unknown element, substitutes the attributes,
- * and calls perform on the unknown element.
- *
- */
- public void execute() {
+ protected void doParams() {
presentElements = new HashMap();
getNsElements();
processTasks();
@@ -386,7 +380,21 @@
"Unknown attribute" + (copyKeys.size() > 1 ? "s " : " ")
+ copyKeys);
}
-
+ }
+
+ protected void clearParams() {
+ presentElements = null;
+ localAttributes = null;
+ }
+
+ /**
+ * Execute the templates instance.
+ * Copies the unknown element, substitutes the attributes,
+ * and calls perform on the unknown element.
+ *
+ */
+ public void execute() {
+ doParams();
// need to set the project on unknown element
UnknownElement c = copy(macroDef.getNestedTask());
c.init();
@@ -401,8 +409,7 @@
throw ex;
}
} finally {
- presentElements = null;
- localAttributes = null;
+ clearParams();
}
}
}
Index: src/main/org/apache/tools/ant/taskdefs/MacroFragmentTask.java
===================================================================
--- src/main/org/apache/tools/ant/taskdefs/MacroFragmentTask.java (revision 0)
+++ src/main/org/apache/tools/ant/taskdefs/MacroFragmentTask.java (revision 0)
@@ -0,0 +1,16 @@
+package org.apache.tools.ant.taskdefs;
+import java.util.List;
+import org.apache.tools.ant.MacroFragment;
+import org.apache.tools.ant.UnknownElement;
+
+public class MacroFragmentTask extends MacroInstance
+ implements MacroFragment {
+ public List getUnknownElements(UnknownElement el) {
+ try {
+ doParams();
+ return copy(getMacroDef().getNestedTask()).getChildren();
+ } finally {
+ clearParams();
+ }
+ }
+}