From 9931a12c723b640bcc8f96c889bc5f59cd72a3b6 Mon Sep 17 00:00:00 2001 From: Peter Reilly Date: Tue, 18 Nov 2003 10:51:41 +0000 Subject: [PATCH] Implement namespace uri scoping nested elements of types/tasks use the same NS uri as the task/type. also cleanup macrodef attribute handling git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275639 13f79535-47bb-0310-9956-ffa450edef68 --- docs/manual/CoreTypes/antlib.html | 6 +- .../apache/tools/ant/IntrospectionHelper.java | 72 +++++++++++++++- .../org/apache/tools/ant/ProjectHelper.java | 17 ++++ src/main/org/apache/tools/ant/Task.java | 2 +- .../org/apache/tools/ant/UnknownElement.java | 22 +++-- .../tools/ant/helper/ProjectHelper2.java | 3 +- .../tools/ant/taskdefs/MacroInstance.java | 85 ++++++++++++++----- 7 files changed, 171 insertions(+), 36 deletions(-) diff --git a/docs/manual/CoreTypes/antlib.html b/docs/manual/CoreTypes/antlib.html index 9d626a395..6bdbd87f5 100644 --- a/docs/manual/CoreTypes/antlib.html +++ b/docs/manual/CoreTypes/antlib.html @@ -133,9 +133,9 @@ <sequential> <current:if> <current:isallowed test="${action}"/> - <then> - <do/> - </then> + <current:then> + <current:do/> + </current:then> </current:if> </sequential> </macrodef> diff --git a/src/main/org/apache/tools/ant/IntrospectionHelper.java b/src/main/org/apache/tools/ant/IntrospectionHelper.java index c7301d00d..a89d38835 100644 --- a/src/main/org/apache/tools/ant/IntrospectionHelper.java +++ b/src/main/org/apache/tools/ant/IntrospectionHelper.java @@ -642,6 +642,52 @@ public final class IntrospectionHelper implements BuildListener { return nc; } + private NestedCreator getNestedCreator( + Project project, String parentUri, Object parent, + String elementName) throws BuildException { + + String uri = ProjectHelper.extractUriFromComponentName(elementName); + String name = ProjectHelper.extractNameFromComponentName(elementName); + + NestedCreator nc = null; + if (uri.equals(parentUri)) { // || uri.equals("")) { + nc = (NestedCreator) nestedCreators.get( + name.toLowerCase(Locale.US)); + } + if (nc == null) { + nc = createAddTypeCreator(project, parent, elementName); + } + if (nc == null && parent instanceof DynamicConfigurator) { + DynamicConfigurator dc = (DynamicConfigurator) parent; + final Object nestedElement = dc.createDynamicElement(elementName); + if (nestedElement != null) { + nc = new NestedCreator() { + public boolean isPolyMorphic() { + return false; + } + public Class getElementClass() { + return null; + } + + public Object getRealObject() { + return null; + } + + public Object create( + Project project, Object parent, Object ignore) { + return nestedElement; + } + public void store(Object parent, Object child) { + } + }; + } + } + if (nc == null) { + throwNotSupported(project, parent, elementName); + } + return nc; + } + /** * Creates a named nested element. Depending on the results of the * initial introspection, either a method in the given parent instance @@ -692,6 +738,7 @@ public final class IntrospectionHelper implements BuildListener { * for an element of a parent. * * @param project Project to which the parent object belongs. + * @param parentUri The namespace uri of the parent object. * @param parent Parent object used to create the creator object to * create and store and instance of a subelement. * @param elementName Name of the element to create an instance of. @@ -699,8 +746,9 @@ public final class IntrospectionHelper implements BuildListener { */ public Creator getElementCreator( - Project project, Object parent, String elementName) { - NestedCreator nc = getNestedCreator(project, parent, elementName); + Project project, String parentUri, Object parent, String elementName) { + NestedCreator nc = getNestedCreator( + project, parentUri, parent, elementName); return new Creator(project, parent, nc); } @@ -718,6 +766,26 @@ public final class IntrospectionHelper implements BuildListener { || addTypeMethods.size() != 0; } + /** + * Indicate if this element supports a nested element of the + * given name. + * + * @param parentUri the uri of the parent + * @param elementName the name of the nested element being checked + * + * @return true if the given nested element is supported + */ + public boolean supportsNestedElement(String parentUri, String elementName) { + String uri = ProjectHelper.extractUriFromComponentName(elementName); + String name = ProjectHelper.extractNameFromComponentName(elementName); + + return ( + nestedCreators.containsKey(name.toLowerCase(Locale.US)) + && (uri.equals(parentUri))) // || uri.equals(""))) + || DynamicConfigurator.class.isAssignableFrom(bean) + || addTypeMethods.size() != 0; + } + /** * Stores a named nested element using a storage method determined * by the initial introspection. If no appropriate storage method diff --git a/src/main/org/apache/tools/ant/ProjectHelper.java b/src/main/org/apache/tools/ant/ProjectHelper.java index 92765e5b8..f00ad9fcb 100644 --- a/src/main/org/apache/tools/ant/ProjectHelper.java +++ b/src/main/org/apache/tools/ant/ProjectHelper.java @@ -525,12 +525,29 @@ public class ProjectHelper { * @return The uri or "" if not present */ public static String extractUriFromComponentName(String componentName) { + if (componentName == null) { + return ""; + } int index = componentName.lastIndexOf(':'); if (index == -1) { return ""; } return componentName.substring(0, index); } + + /** + * extract the element name from a component name + * + * @param componentName The stringified form for {uri, name} + * @return The element name of the component + */ + public static String extractNameFromComponentName(String componentName) { + int index = componentName.lastIndexOf(':'); + if (index == -1) { + return componentName; + } + return componentName.substring(index+1); + } /** * Add location to build exception. diff --git a/src/main/org/apache/tools/ant/Task.java b/src/main/org/apache/tools/ant/Task.java index d1409c4ca..a437cb02e 100644 --- a/src/main/org/apache/tools/ant/Task.java +++ b/src/main/org/apache/tools/ant/Task.java @@ -493,7 +493,7 @@ public abstract class Task extends ProjectComponent { * * @return the type of task */ - protected String getTaskType() { + public String getTaskType() { return taskType; } diff --git a/src/main/org/apache/tools/ant/UnknownElement.java b/src/main/org/apache/tools/ant/UnknownElement.java index 3e7cf8cd3..6dc3aaa33 100644 --- a/src/main/org/apache/tools/ant/UnknownElement.java +++ b/src/main/org/apache/tools/ant/UnknownElement.java @@ -336,13 +336,15 @@ public class UnknownElement extends Task { * * @exception BuildException if the children cannot be configured. */ - protected void handleChildren(Object parent, - RuntimeConfigurable parentWrapper) + protected void handleChildren( + Object parent, + RuntimeConfigurable parentWrapper) throws BuildException { if (parent instanceof TypeAdapter) { parent = ((TypeAdapter) parent).getProxy(); } + String parentUri = getNamespace(); Class parentClass = parent.getClass(); IntrospectionHelper ih = IntrospectionHelper.getHelper(parentClass); @@ -352,8 +354,8 @@ public class UnknownElement extends Task { for (int i = 0; it.hasNext(); i++) { RuntimeConfigurable childWrapper = parentWrapper.getChild(i); UnknownElement child = (UnknownElement) it.next(); - if (!handleChild(ih, parent, child, - childWrapper)) { + if (!handleChild( + parentUri, ih, parent, child, childWrapper)) { if (!(parent instanceof TaskContainer)) { ih.throwNotSupported(getProject(), parent, child.getTag()); @@ -548,14 +550,16 @@ public class UnknownElement extends Task { * * @return whether the creation has been successful */ - private boolean handleChild(IntrospectionHelper ih, - Object parent, UnknownElement child, - RuntimeConfigurable childWrapper) { + private boolean handleChild( + String parentUri, + IntrospectionHelper ih, + Object parent, UnknownElement child, + RuntimeConfigurable childWrapper) { String childName = ProjectHelper.genComponentName( child.getNamespace(), child.getTag()); - if (ih.supportsNestedElement(childName)) { + if (ih.supportsNestedElement(parentUri, childName)) { IntrospectionHelper.Creator creator = - ih.getElementCreator(getProject(), parent, childName); + ih.getElementCreator(getProject(), parentUri, parent, childName); creator.setPolyType(childWrapper.getPolyType()); Object realChild = creator.create(); if (realChild instanceof PreSetDef.PreSetDefinition) { diff --git a/src/main/org/apache/tools/ant/helper/ProjectHelper2.java b/src/main/org/apache/tools/ant/helper/ProjectHelper2.java index 5b5a498a9..1d8c5ce11 100644 --- a/src/main/org/apache/tools/ant/helper/ProjectHelper2.java +++ b/src/main/org/apache/tools/ant/helper/ProjectHelper2.java @@ -939,8 +939,9 @@ public class ProjectHelper2 extends ProjectHelper { UnknownElement task = new UnknownElement(tag); task.setProject(context.getProject()); task.setNamespace(uri); - //XXX task.setTaskType(qname); task.setQName(qname); + task.setTaskType( + ProjectHelper.genComponentName(task.getNamespace(), tag)); task.setTaskName(qname); Location location = new Location(context.getLocator().getSystemId(), diff --git a/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java b/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java index f5c8337ab..cdab476b0 100644 --- a/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java +++ b/src/main/org/apache/tools/ant/taskdefs/MacroInstance.java @@ -84,8 +84,10 @@ import org.apache.tools.ant.UnknownElement; public class MacroInstance extends Task implements DynamicConfigurator { private MacroDef macroDef; private Map map = new HashMap(); - private Map elements = new HashMap(); + private Map nsElements = null; + private Map presentElements = new HashMap(); private Hashtable localProperties = new Hashtable(); + /** * Called from MacroDef.MyAntTypeDefinition#create() @@ -114,17 +116,33 @@ public class MacroInstance extends Task implements DynamicConfigurator { * has already been seen */ public Object createDynamicElement(String name) throws BuildException { - if (macroDef.getElements().get(name) == null) { + if (getNsElements().get(name) == null) { throw new BuildException("unsupported element " + name); } - if (elements.get(name) != null) { + if (presentElements.get(name) != null) { throw new BuildException("Element " + name + " already present"); } Element ret = new Element(); - elements.put(name, ret); + presentElements.put(name, ret); return ret; } + private Map getNsElements() { + if (nsElements == null) { + nsElements = new HashMap(); + String myUri = ProjectHelper.extractUriFromComponentName( + getTaskType()); + for (Iterator i = macroDef.getElements().entrySet().iterator(); + i.hasNext();) { + Map.Entry entry = (Map.Entry) i.next(); + nsElements.put(ProjectHelper.genComponentName( + myUri, (String) entry.getKey()), + entry.getValue()); + } + } + return nsElements; + } + /** * Embedded element in macro instance */ @@ -148,18 +166,38 @@ public class MacroInstance extends Task implements DynamicConfigurator { } } + private static final int STATE_NORMAL = 0; + private static final int STATE_EXPECT_BRACKET = 1; + private static final int STATE_EXPECT_NAME = 2; + private String macroSubs(String s, Map macroMapping) { StringBuffer ret = new StringBuffer(); - StringBuffer macroName = new StringBuffer(); + StringBuffer macroName = null; boolean inMacro = false; + int state = STATE_NORMAL; for (int i = 0; i < s.length(); ++i) { - if (s.charAt(i) == '$') { - inMacro = true; - } else { - if (inMacro) { - if (s.charAt(i) == '{') { - continue; - } else if (s.charAt(i) == '}') { + char ch = s.charAt(i); + switch (state) { + case STATE_NORMAL: + if (ch == '$') { + state = 1; + } else { + ret.append(ch); + } + break; + case STATE_EXPECT_BRACKET: + if (ch == '{') { + state = 2; + macroName = new StringBuffer(); + } else { + state = 0; + ret.append('$'); + ret.append(ch); + } + break; + case STATE_EXPECT_NAME: + if (ch == '}') { + state = 0; String name = macroName.toString(); String value = (String) macroMapping.get(name); if (value == null) { @@ -167,16 +205,23 @@ public class MacroInstance extends Task implements DynamicConfigurator { } else { ret.append(value); } - macroName = new StringBuffer(); - inMacro = false; + macroName = null; } else { macroName.append(s.charAt(i)); } - } else { - ret.append(s.charAt(i)); - } } } + switch (state) { + case STATE_NORMAL: + break; + case STATE_EXPECT_BRACKET: + ret.append('$'); + break; + case STATE_EXPECT_NAME: + ret.append("${"); + ret.append(macroName.toString()); + break; + } return ret.toString(); } @@ -212,15 +257,15 @@ public class MacroInstance extends Task implements DynamicConfigurator { while (e.hasMoreElements()) { RuntimeConfigurable r = (RuntimeConfigurable) e.nextElement(); UnknownElement unknownElement = (UnknownElement) r.getProxy(); - String tag = unknownElement.getTag(); + String tag = unknownElement.getTaskType(); MacroDef.TemplateElement templateElement = - (MacroDef.TemplateElement) macroDef.getElements().get(tag); + (MacroDef.TemplateElement) getNsElements().get(tag); if (templateElement == null) { UnknownElement child = copy(unknownElement); rc.addChild(child.getWrapper()); ret.addChild(child); } else { - Element element = (Element) elements.get(tag); + Element element = (Element) presentElements.get(tag); if (element == null) { if (!templateElement.isOptional()) { throw new BuildException(