Skip to content

Commit ca5799f

Browse files
author
Peter Reilly
committed
Add ns support
Also split Definer.java in a base class (DefBase) to allow it to be used for other defining tasks Also add AntlibInterface to allow antlib to set uri and classloader for other tasks/types that Definer. Bugzilla: 19897 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@275064 13f79535-47bb-0310-9956-ffa450edef68
1 parent aeee702 commit ca5799f

File tree

10 files changed

+650
-173
lines changed

10 files changed

+650
-173
lines changed

src/main/org/apache/tools/ant/ComponentHelper.java

Lines changed: 106 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,19 @@
5858

5959
import java.util.Enumeration;
6060
import java.util.Hashtable;
61+
import java.util.HashSet;
6162
import java.util.Iterator;
6263
import java.util.Properties;
64+
import java.util.Set;
65+
import java.util.Stack;
6366

6467
import java.util.Vector;
6568
import java.io.InputStream;
6669
import java.io.IOException;
6770
import java.lang.reflect.Modifier;
6871

72+
import org.apache.tools.ant.taskdefs.Typedef;
73+
6974
/**
7075
* Component creation and configuration.
7176
*
@@ -98,6 +103,17 @@ public class ComponentHelper {
98103
/** flag to rebuild typeClassDefinitions */
99104
private boolean rebuildTypeClassDefinitions = true;
100105

106+
/** Set of namespaces that have been checked for antlibs */
107+
private Set checkedNamespaces = new HashSet();
108+
109+
/**
110+
* Stack of antlib contexts used to resolve definitions while
111+
* processing antlib
112+
*/
113+
private Stack antLibStack = new Stack();
114+
/** current antlib context */
115+
private AntTypeTable antLibTypeTable = null;
116+
101117
/**
102118
* Map from task names to vectors of created tasks
103119
* (String to Vector of Task). This is used to invalidate tasks if
@@ -175,32 +191,38 @@ public void initSubProject(ComponentHelper helper) {
175191
AntTypeDefinition def = (AntTypeDefinition) i.next();
176192
antTypeTable.put(def.getName(), def);
177193
}
194+
// add the parsed namespaces of the parent project
195+
checkedNamespaces.add(helper.checkedNamespaces);
178196
}
179197

180198
/** Factory method to create the components.
181199
*
182200
* This should be called by UnknownElement.
183201
*
184-
* @param ue The component helper has access via ue to the entire XML tree.
185-
* @param ns Namespace. Also available as ue.getNamespace()
186-
* @param taskName The element name. Also available as ue.getTag()
202+
* @param ue The Unknown Element creating this component
203+
* @param ns Namespace URI. Also available as ue.getNamespace()
204+
* @param componentType The component type,
205+
* Also available as ue.getComponentName()
187206
* @return the created component
188207
* @throws BuildException if an error occuries
189208
*/
190209
public Object createComponent(UnknownElement ue,
191210
String ns,
192-
String taskName)
211+
String componentType)
193212
throws BuildException {
194-
Object component = createComponent(taskName);
213+
Object component = createComponent(componentType);
195214
if (component == null) {
196215
return null;
197216
}
198217

199218
if (component instanceof Task) {
200219
Task task = (Task) component;
201-
task.setTaskType(taskName);
202-
task.setTaskName(taskName);
203-
addCreatedTask(taskName, task);
220+
task.setLocation(ue.getLocation());
221+
task.setTaskType(componentType);
222+
task.setTaskName(ue.getTaskName());
223+
task.setOwningTarget(ue.getOwningTarget());
224+
task.init();
225+
addCreatedTask(componentType, task);
204226
}
205227

206228
return component;
@@ -215,7 +237,11 @@ public Object createComponent(UnknownElement ue,
215237
* @return the class if found or null if not.
216238
*/
217239
public Object createComponent(String componentName) {
218-
return antTypeTable.create(componentName);
240+
AntTypeDefinition def = getDefinition(componentName);
241+
if (def == null) {
242+
return null;
243+
}
244+
return def.create(project);
219245
}
220246

221247
/**
@@ -227,7 +253,11 @@ public Object createComponent(String componentName) {
227253
* @return the class if found or null if not.
228254
*/
229255
public Class getComponentClass(String componentName) {
230-
return antTypeTable.getExposedClass(componentName);
256+
AntTypeDefinition def = getDefinition(componentName);
257+
if (def == null) {
258+
return null;
259+
}
260+
return def.getExposedClass(project);
231261
}
232262

233263
/**
@@ -236,7 +266,15 @@ public Class getComponentClass(String componentName) {
236266
* @return the ant definition or null if not present
237267
*/
238268
public AntTypeDefinition getDefinition(String componentName) {
239-
return antTypeTable.getDefinition(componentName);
269+
checkNamespace(componentName);
270+
AntTypeDefinition ret = null;
271+
if (antLibTypeTable != null && componentName.indexOf(':') == -1) {
272+
ret = antLibTypeTable.getDefinition(componentName);
273+
}
274+
if (ret == null) {
275+
ret = antTypeTable.getDefinition(componentName);
276+
}
277+
return ret;
240278
}
241279

242280
/**
@@ -474,15 +512,15 @@ public Task createTask(String taskType) throws BuildException {
474512
* creation fails.
475513
*/
476514
private Task createNewTask(String taskType) throws BuildException {
477-
Class c = antTypeTable.getExposedClass(taskType);
515+
Class c = getComponentClass(taskType);
478516
if (c == null) {
479517
return null;
480518
}
481519

482520
if (!(Task.class.isAssignableFrom(c))) {
483521
return null;
484522
}
485-
Task task = (Task) antTypeTable.create(taskType);
523+
Task task = (Task) createComponent(taskType);
486524
if (task == null) {
487525
return null;
488526
}
@@ -557,7 +595,7 @@ private void invalidateCreatedTasks(String type) {
557595
* instance creation fails.
558596
*/
559597
public Object createDataType(String typeName) throws BuildException {
560-
return antTypeTable.create(typeName);
598+
return createComponent(typeName);
561599
}
562600

563601
/**
@@ -660,6 +698,31 @@ private void updateDataTypeDefinition(AntTypeDefinition def) {
660698
project.log(" +Datatype " + name + " " + def.getClassName(),
661699
Project.MSG_DEBUG);
662700
antTypeTable.put(name, def);
701+
702+
if (antLibTypeTable != null && name.lastIndexOf(':') != -1) {
703+
String baseName = name.substring(name.lastIndexOf(':') + 1);
704+
antLibTypeTable.put(baseName, def);
705+
}
706+
}
707+
}
708+
709+
/**
710+
* Called at the start of processing an antlib
711+
*/
712+
public void enterAntLib() {
713+
antLibTypeTable = new AntTypeTable(project);
714+
antLibStack.push(antLibTypeTable);
715+
}
716+
717+
/**
718+
* Called at the end of processing an antlib
719+
*/
720+
public void exitAntLib() {
721+
antLibStack.pop();
722+
if (antLibStack.size() != 0) {
723+
antLibTypeTable = (AntTypeTable) antLibStack.peek();
724+
} else {
725+
antLibTypeTable = null;
663726
}
664727
}
665728

@@ -751,6 +814,35 @@ private void initTypes() {
751814
}
752815
}
753816

817+
/**
818+
* called for each component name, check if the
819+
* associated URI has been examined for antlibs.
820+
*/
821+
private void checkNamespace(String componentName) {
822+
if (componentName.indexOf(':') == -1) {
823+
return; // not a namespaced name
824+
}
825+
826+
String uri = ProjectHelper.extractUriFromComponentName(componentName);
827+
if (!uri.startsWith(ProjectHelper.ANTLIB_URI)) {
828+
return; // namespace that does not contain antlib
829+
}
830+
if (checkedNamespaces.contains(uri)) {
831+
return; // Alreay processed
832+
}
833+
checkedNamespaces.add(uri);
834+
Typedef definer = new Typedef();
835+
definer.setProject(project);
836+
definer.setURI(uri);
837+
definer.setResource(
838+
uri.substring("antlib:".length()).replace('.', '/')
839+
+ "/antlib.xml");
840+
// a fishing expedition :- ignore errors if antlib not present
841+
definer.setOnError(new Typedef.OnError("ignore"));
842+
definer.init();
843+
definer.execute();
844+
}
845+
754846
/**
755847
* map that contains the component definitions
756848
*/

src/main/org/apache/tools/ant/ProjectHelper.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@
8585
* @author duncan@x180.com
8686
*/
8787
public class ProjectHelper {
88+
/** The URI for ant name space */
89+
public static final String ANT_CORE_URI = "ant:core";
90+
91+
/** The URI for defined types/tasks - the format is antlib:<package> */
92+
public static final String ANTLIB_URI = "antlib:";
93+
8894
/**
8995
* Name of JVM system property which provides the name of the
9096
* ProjectHelper class to use.
@@ -493,5 +499,34 @@ public static void parsePropertyString(String value, Vector fragments,
493499
PropertyHelper.parsePropertyStringDefault(value, fragments,
494500
propertyRefs);
495501
}
502+
/**
503+
* Map a namespaced {uri,name} to an internal string format.
504+
* For BC purposes the names from the ant core uri will be
505+
* mapped to "name", other names will be mapped to
506+
* uri + ":" + name.
507+
* @param uri The namepace URI
508+
* @param name The localname
509+
* @return The stringified form of the ns name
510+
*/
511+
public static String genComponentName(String uri, String name) {
512+
if (uri == null || uri.equals("") || uri.equals(ANT_CORE_URI)) {
513+
return name;
514+
}
515+
return uri + ":" + name;
516+
}
517+
518+
/**
519+
* extract a uri from a component name
520+
*
521+
* @param componentName The stringified form for {uri, name}
522+
* @return The uri or "" if not present
523+
*/
524+
public static String extractUriFromComponentName(String componentName) {
525+
int index = componentName.lastIndexOf(':');
526+
if (index == -1) {
527+
return "";
528+
}
529+
return componentName.substring(0, index);
530+
}
496531
//end class
497532
}

src/main/org/apache/tools/ant/RuntimeConfigurable.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,14 @@ public String getPolyType() {
176176
return polyType;
177177
}
178178

179+
/**
180+
* set the polymorphic type for this element
181+
* @param polyType the ant component type name, null if not set
182+
*/
183+
public void setPolyType(String polyType) {
184+
this.polyType = polyType;
185+
}
186+
179187
/**
180188
* Sets the attributes for the wrapped element.
181189
*
@@ -260,10 +268,10 @@ RuntimeConfigurable getChild(int index) {
260268

261269
/**
262270
* Returns an enumeration of all child wrappers.
263-
*
271+
* @return an enumeration of the child wrappers.
264272
* @since Ant 1.5.1
265273
*/
266-
Enumeration getChildren() {
274+
public Enumeration getChildren() {
267275
if (children != null) {
268276
return Collections.enumeration(children);
269277
} else {

src/main/org/apache/tools/ant/UnknownElement.java

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ public class UnknownElement extends Task {
8181
*/
8282
private String namespace;
8383

84+
/**
85+
* Holds the namespace qname of the element.
86+
*/
87+
private String qname;
88+
8489
/**
8590
* The real object after it has been loaded.
8691
*/
@@ -129,6 +134,24 @@ public void setNamespace(String namespace) {
129134
this.namespace = namespace;
130135
}
131136

137+
/** Return the qname of the XML element associated with this component.
138+
*
139+
* @return namespace Qname used in the element declaration.
140+
*/
141+
public String getQName() {
142+
return qname;
143+
}
144+
145+
/** Set the namespace qname of the XML element.
146+
* This method is typically called by the XML processor.
147+
*
148+
* @param qname the qualified name of the element
149+
*/
150+
public void setQName(String qname) {
151+
this.qname = qname;
152+
}
153+
154+
132155
/**
133156
* Get the RuntimeConfigurable instance for this UnknownElement, containing
134157
* the configuration information.
@@ -334,6 +357,13 @@ protected void handleChildren(Object parent,
334357
}
335358
}
336359

360+
/**
361+
* @return the component name - uses ProjectHelper#genComponentName()
362+
*/
363+
protected String getComponentName() {
364+
return ProjectHelper.genComponentName(getNamespace(), getTag());
365+
}
366+
337367
/**
338368
* Creates a named task or data type. If the real object is a task,
339369
* it is configured up to the init() stage.
@@ -345,12 +375,17 @@ protected void handleChildren(Object parent,
345375
* @return the task or data type represented by the given unknown element.
346376
*/
347377
protected Object makeObject(UnknownElement ue, RuntimeConfigurable w) {
348-
Object o = makeTask(ue, w);
378+
ComponentHelper helper = ComponentHelper.getComponentHelper(
379+
getProject());
380+
String name = ue.getComponentName();
381+
Object o = helper.createComponent(ue, ue.getNamespace(), name);
349382
if (o == null) {
350-
o = getProject().createDataType(ue.getTag());
383+
throw getNotFoundException("task or type", name);
351384
}
352-
if (o == null) {
353-
throw getNotFoundException("task or type", ue.getTag());
385+
if (o instanceof Task) {
386+
Task task = (Task) o;
387+
task.setOwningTarget(getOwningTarget());
388+
task.init();
354389
}
355390
return o;
356391
}

0 commit comments

Comments
 (0)