diff --git a/src/main/org/apache/tools/ant/AntTypeDefinition.java b/src/main/org/apache/tools/ant/AntTypeDefinition.java
index 32c1b14c2..a51482fd7 100644
--- a/src/main/org/apache/tools/ant/AntTypeDefinition.java
+++ b/src/main/org/apache/tools/ant/AntTypeDefinition.java
@@ -38,6 +38,23 @@ public class AntTypeDefinition {
private Class adaptToClass;
private String className;
private ClassLoader classLoader;
+ private boolean restrict = false;
+
+ /**
+ * Set the restrict attribute.
+ * @param restrict the value to set.
+ */
+ public void setRestrict(boolean restrict) {
+ this.restrict = restrict;
+ }
+
+ /**
+ * Get the restrict attribute.
+ * @return the restrict attribute.
+ */
+ public boolean isRestrict() {
+ return restrict;
+ }
/**
* Set the definition's name.
@@ -129,7 +146,7 @@ public class AntTypeDefinition {
* class and the definition class is not
* assignable from the assignable class.
* @param project the current project.
- * @return the exposed class.
+ * @return the exposed class - may return null if upable to load the class
*/
public Class getExposedClass(Project project) {
if (adaptToClass != null) {
@@ -327,6 +344,7 @@ public class AntTypeDefinition {
return (other != null && other.getClass() == getClass()
&& other.getTypeClass(project).equals(getTypeClass(project))
&& other.getExposedClass(project).equals(getExposedClass(project))
+ && other.restrict == restrict
&& other.adapterClass == adapterClass
&& other.adaptToClass == adaptToClass);
}
@@ -349,7 +367,8 @@ public class AntTypeDefinition {
|| !extractClassname(adapterClass).equals(
extractClassname(other.adapterClass))
|| !extractClassname(adaptToClass).equals(
- extractClassname(other.adaptToClass))) {
+ extractClassname(other.adaptToClass))
+ || restrict != other.restrict) {
return false;
}
// all the names are the same: check if the class path of the loader
diff --git a/src/main/org/apache/tools/ant/ComponentHelper.java b/src/main/org/apache/tools/ant/ComponentHelper.java
index 89666f4b8..4be9f125c 100644
--- a/src/main/org/apache/tools/ant/ComponentHelper.java
+++ b/src/main/org/apache/tools/ant/ComponentHelper.java
@@ -33,6 +33,8 @@ import java.util.Set;
import java.util.Stack;
import java.util.List;
import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
import org.apache.tools.ant.taskdefs.Typedef;
import org.apache.tools.ant.taskdefs.Definer;
@@ -56,6 +58,9 @@ import org.apache.tools.ant.util.FileUtils;
* @since Ant1.6
*/
public class ComponentHelper {
+ /** Map of component name to lists of restricted definitions */
+ private Map restrictedDefinitions = new HashMap();
+
/** Map from component name to anttypedefinition */
private AntTypeTable antTypeTable;
@@ -123,6 +128,14 @@ public class ComponentHelper {
// {tasks, types}
private static Properties[] defaultDefinitions = new Properties[2];
+ /**
+ * Get the project.
+ * @return the project owner of this helper.
+ */
+ public Project getProject() {
+ return project;
+ }
+
/**
* Find a project component for a specific project, creating
* it if it does not exist.
@@ -196,6 +209,14 @@ public class ComponentHelper {
for (Iterator i = helper.checkedNamespaces.iterator(); i.hasNext();) {
checkedNamespaces.add(i.next());
}
+
+ // Add the restricted definitions
+ for (Iterator i = helper.restrictedDefinitions.entrySet().iterator();
+ i.hasNext();) {
+ Map.Entry entry = (Map.Entry) i.next();
+ restrictedDefinitions.put(
+ entry.getKey(), new ArrayList((List) entry.getValue()));
+ }
}
/**
@@ -395,6 +416,15 @@ public class ComponentHelper {
return typeClassDefinitions;
}
+ /**
+ * This returns a list of restricted definitions for a name.
+ * @param componentName the name to use.
+ * @return the list of restricted definitions for a particular name.
+ */
+ public List getRestrictedDefinitions(String componentName) {
+ return (List) restrictedDefinitions.get(componentName);
+ }
+
/**
* Adds a new datatype definition.
* Attempting to override an existing definition with an
@@ -423,7 +453,11 @@ public class ComponentHelper {
* @param def an AntTypeDefinition
value.
*/
public void addDataTypeDefinition(AntTypeDefinition def) {
- updateDataTypeDefinition(def);
+ if (!def.isRestrict()) {
+ updateDataTypeDefinition(def);
+ } else {
+ updateRestrictedDefinition(def);
+ }
}
/**
@@ -607,6 +641,31 @@ public class ComponentHelper {
return sameValidity && (!defValid || def.sameDefinition(old, project));
}
+ /**
+ * update the restricted definition table with a new or
+ * modified definition.
+ */
+ private void updateRestrictedDefinition(AntTypeDefinition def) {
+ String name = def.getName();
+ synchronized (restrictedDefinitions) {
+ List list = (List) restrictedDefinitions.get(name);
+ if (list == null) {
+ list = new ArrayList();
+ restrictedDefinitions.put(name, list);
+ }
+ // Check if the classname is already present and remove it
+ // if it is
+ for (Iterator i = list.iterator(); i.hasNext();) {
+ AntTypeDefinition current = (AntTypeDefinition) i.next();
+ if (current.getClassName().equals(def.getClassName())) {
+ i.remove();
+ break;
+ }
+ }
+ list.add(def);
+ }
+ }
+
/**
* Update the component definition table with a new or
* modified definition.
diff --git a/src/main/org/apache/tools/ant/IntrospectionHelper.java b/src/main/org/apache/tools/ant/IntrospectionHelper.java
index cbedda447..9961c0b56 100644
--- a/src/main/org/apache/tools/ant/IntrospectionHelper.java
+++ b/src/main/org/apache/tools/ant/IntrospectionHelper.java
@@ -1383,28 +1383,33 @@ public final class IntrospectionHelper {
}
ComponentHelper helper = ComponentHelper.getComponentHelper(project);
- Object addedObject = null;
- Method addMethod = null;
- Class clazz = helper.getComponentClass(elementName);
- if (clazz == null) {
- return null;
- }
- addMethod = findMatchingMethod(clazz, addTypeMethods);
- if (addMethod == null) {
+ MethodAndObject restricted = createRestricted(
+ helper, elementName, addTypeMethods);
+ MethodAndObject topLevel = createTopLevel(
+ helper, elementName, addTypeMethods);
+
+ if (restricted == null && topLevel == null) {
return null;
}
- addedObject = helper.createComponent(elementName);
- if (addedObject == null) {
- return null;
+
+ if (restricted != null && topLevel != null) {
+ throw new BuildException(
+ "ambiguous: type and component definitions for "
+ + elementName);
}
- Object rObject = addedObject;
- if (addedObject instanceof PreSetDef.PreSetDefinition) {
- rObject = ((PreSetDef.PreSetDefinition) addedObject).createObject(project);
+
+ MethodAndObject methodAndObject
+ = restricted != null ? restricted : topLevel;
+
+ Object rObject = methodAndObject.object;
+ if (methodAndObject.object instanceof PreSetDef.PreSetDefinition) {
+ rObject = ((PreSetDef.PreSetDefinition) methodAndObject.object)
+ .createObject(project);
}
- final Object nestedObject = addedObject;
+ final Object nestedObject = methodAndObject.object;
final Object realObject = rObject;
-
- return new NestedCreator(addMethod) {
+
+ return new NestedCreator(methodAndObject.method) {
Object create(Project project, Object parent, Object ignore)
throws InvocationTargetException, IllegalAccessException {
if (!getMethod().getName().endsWith("Configured")) {
@@ -1460,6 +1465,9 @@ public final class IntrospectionHelper {
* @return a matching Method
; null if none found.
*/
private Method findMatchingMethod(Class paramClass, List methods) {
+ if (paramClass == null) {
+ return null;
+ }
Class matchedClass = null;
Method matchedMethod = null;
@@ -1486,4 +1494,91 @@ public final class IntrospectionHelper {
int ends = (MAX_REPORT_NESTED_TEXT - ELLIPSIS.length()) / 2;
return new StringBuffer(text).replace(ends, text.length() - ends, ELLIPSIS).toString();
}
+
+
+ private class MethodAndObject {
+ private Method method;
+ private Object object;
+ public MethodAndObject(Method method, Object object) {
+ this.method = method;
+ this.object = object;
+ }
+ }
+
+ /**
+ *
+ */
+ private AntTypeDefinition findRestrictedDefinition(
+ ComponentHelper helper, String componentName, List methods) {
+ AntTypeDefinition definition = null;
+ Class matchedDefinitionClass = null;
+
+ List definitions = helper.getRestrictedDefinitions(componentName);
+ if (definitions == null) {
+ return null;
+ }
+ for (int i = 0; i < definitions.size(); ++i) {
+ AntTypeDefinition d = (AntTypeDefinition) definitions.get(i);
+ Class exposedClass = d.getExposedClass(helper.getProject());
+ if (exposedClass == null) {
+ continue;
+ }
+ Method method = findMatchingMethod(exposedClass, methods);
+ if (method == null) {
+ continue;
+ }
+ if (matchedDefinitionClass != null) {
+ throw new BuildException(
+ "ambiguous: restricted definitions for "
+ + componentName + " " +
+ matchedDefinitionClass + " and " + exposedClass);
+ }
+ matchedDefinitionClass = exposedClass;
+ definition = d;
+ }
+ return definition;
+ }
+
+ private MethodAndObject createRestricted(
+ ComponentHelper helper, String elementName, List addTypeMethods) {
+
+ Project project = helper.getProject();
+
+ AntTypeDefinition restrictedDefinition =
+ findRestrictedDefinition(helper, elementName, addTypeMethods);
+
+ if (restrictedDefinition == null) {
+ return null;
+ }
+
+ Method addMethod = findMatchingMethod(
+ restrictedDefinition.getExposedClass(project), addTypeMethods);
+ if (addMethod == null) {
+ throw new BuildException(
+ "Ant Internal Error - contract mismatch for "
+ + elementName);
+ }
+ Object addedObject = restrictedDefinition.create(project);
+ if (addedObject == null) {
+ throw new BuildException(
+ "Failed to create object " + elementName
+ + " of type " + restrictedDefinition.getTypeClass(project));
+ }
+ return new MethodAndObject(addMethod, addedObject);
+ }
+
+ private MethodAndObject createTopLevel(
+ ComponentHelper helper, String elementName, List methods) {
+ Class clazz = helper.getComponentClass(elementName);
+ if (clazz == null) {
+ return null;
+ }
+ Method addMethod = findMatchingMethod(clazz, addTypeMethods);
+ if (addMethod == null) {
+ return null;
+ }
+ Object addedObject = helper.createComponent(elementName);
+ return new MethodAndObject(addMethod, addedObject);
+ }
+
}
diff --git a/src/main/org/apache/tools/ant/antlib.xml b/src/main/org/apache/tools/ant/antlib.xml
new file mode 100644
index 000000000..d274d09f4
--- /dev/null
+++ b/src/main/org/apache/tools/ant/antlib.xml
@@ -0,0 +1,135 @@
+
+
+