git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@564787 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -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 | |||
| @@ -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 <code>AntTypeDefinition</code> 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. | |||
| @@ -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 <code>Method</code>; 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); | |||
| } | |||
| } | |||
| @@ -0,0 +1,135 @@ | |||
| <?xml version="1.0"?> | |||
| <!-- | |||
| /* | |||
| * Licensed to the Apache Software Foundation (ASF) under one or more | |||
| * contributor license agreements. See the NOTICE file distributed with | |||
| * this work for additional information regarding copyright ownership. | |||
| * The ASF licenses this file to You under the Apache License, Version 2.0 | |||
| * (the "License"); you may not use this file except in compliance with | |||
| * the License. You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| --> | |||
| <antlib> | |||
| <!-- | |||
| This is the ant lib definition for ant. | |||
| Currently it only contains componentdefinitions (restricted | |||
| types that are not allowed at the top level) | |||
| - conditions, selectors and comparators | |||
| (those that are not top-level types (taskdefs or typedefs). | |||
| defined in defaults.properties of taskdefs and types | |||
| packages). | |||
| This is currently experimental and it is most | |||
| likely that these definitions will be placed | |||
| in a Java Ant definition class. | |||
| --> | |||
| <!-- conditions --> | |||
| <componentdef name="and" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.And"/> | |||
| <componentdef name="contains" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.Contains"/> | |||
| <componentdef name="equals" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.Equals"/> | |||
| <componentdef name="filesmatch" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.FilesMatch"/> | |||
| <componentdef name="hasfreespace" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.HasFreeSpace"/> | |||
| <componentdef name="hasmethod" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.HasMethod"/> | |||
| <componentdef name="http" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.Http"/> | |||
| <componentdef name="isfailure" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.IsFailure"/> | |||
| <componentdef name="isfalse" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.IsFalse"/> | |||
| <componentdef name="isreachable" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.IsReachable"/> | |||
| <componentdef name="isreference" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.IsReference"/> | |||
| <componentdef name="isset" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.IsSet"/> | |||
| <componentdef name="issigned" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.IsSigned"/> | |||
| <componentdef name="istrue" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.IsTrue"/> | |||
| <componentdef name="matches" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.Matches"/> | |||
| <componentdef name="not" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Not"/> | |||
| <componentdef name="or" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.Or"/> | |||
| <componentdef name="os" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.Os"/> | |||
| <componentdef name="parsersupports" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.ParserSupports"/> | |||
| <componentdef name="resourcecontains" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.ResourceContains"/> | |||
| <componentdef name="resourcesmatch" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.ResourcesMatch"/> | |||
| <componentdef name="socket" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.Socket"/> | |||
| <componentdef name="typefound" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.TypeFound"/> | |||
| <componentdef name="xor" onerror="ignore" | |||
| classname="org.apache.tools.ant.taskdefs.condition.Xor"/> | |||
| <!-- selectors --> | |||
| <componentdef name="and" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.selectors.And" /> | |||
| <componentdef name="compare" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Compare" /> | |||
| <componentdef name="contains" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.selectors.ContainsSelector" /> | |||
| <componentdef name="containsregexp" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.selectors.ContainsRegexpSelector" /> | |||
| <componentdef name="date" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Date" /> | |||
| <componentdef name="exists" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Exists" /> | |||
| <componentdef name="instanceof" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.selectors.InstanceOf" /> | |||
| <componentdef name="majority" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Majority" /> | |||
| <componentdef name="modified" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector" /> | |||
| <componentdef name="name" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Name" /> | |||
| <componentdef name="none" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.selectors.None" /> | |||
| <componentdef name="not" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Not" /> | |||
| <componentdef name="or" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Or" /> | |||
| <componentdef name="size" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Size" /> | |||
| <componentdef name="type" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.selectors.Type" /> | |||
| <!-- comparators --> | |||
| <componentdef name="name" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Name" /> | |||
| <componentdef name="size" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Size" /> | |||
| <componentdef name="date" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Date" /> | |||
| <componentdef name="exists" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Exists" /> | |||
| <componentdef name="type" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Type" /> | |||
| <componentdef name="content" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Content" /> | |||
| <componentdef name="reverse" onerror="ignore" | |||
| classname="org.apache.tools.ant.types.resources.comparators.Reverse" /> | |||
| </antlib> | |||
| @@ -0,0 +1,44 @@ | |||
| /* | |||
| * Licensed to the Apache Software Foundation (ASF) under one or more | |||
| * contributor license agreements. See the NOTICE file distributed with | |||
| * this work for additional information regarding copyright ownership. | |||
| * The ASF licenses this file to You under the Apache License, Version 2.0 | |||
| * (the "License"); you may not use this file except in compliance with | |||
| * the License. You may obtain a copy of the License at | |||
| * | |||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, software | |||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| * See the License for the specific language governing permissions and | |||
| * limitations under the License. | |||
| * | |||
| */ | |||
| package org.apache.tools.ant.taskdefs; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.TaskAdapter; | |||
| /** | |||
| * Adds a compenent definition to the current project. | |||
| * used in the current project. Two attributes are needed, the name that identifies | |||
| * this compenent uniquely, and the full name of the class ( | |||
| * including the packages) that | |||
| * implements this component.</p> | |||
| * @since Ant 1.8 | |||
| * @ant.task category="internal" | |||
| */ | |||
| public class Componentdef extends Definer { | |||
| /** | |||
| * Default constructor. | |||
| * Creates a new ComponentDef instance. | |||
| * Sets the restrict attribute to true. | |||
| */ | |||
| public Componentdef() { | |||
| setRestrict(true); | |||
| } | |||
| } | |||
| @@ -66,6 +66,7 @@ public abstract class Definer extends DefBase { | |||
| private String classname; | |||
| private File file; | |||
| private String resource; | |||
| private boolean restrict = false; | |||
| private int format = Format.PROPERTIES; | |||
| private boolean definerSet = false; | |||
| @@ -144,6 +145,16 @@ public abstract class Definer extends DefBase { | |||
| } | |||
| } | |||
| /** | |||
| * The restrict attribute. | |||
| * If this is true, only use this definition in add(X). | |||
| * @param restrict the value to set. | |||
| */ | |||
| protected void setRestrict(boolean restrict) { | |||
| this.restrict = restrict; | |||
| } | |||
| /** | |||
| * What to do if there is an error in loading the class. | |||
| * <dl> | |||
| @@ -597,6 +608,7 @@ public abstract class Definer extends DefBase { | |||
| def.setClass(cl); | |||
| def.setAdapterClass(adapterClass); | |||
| def.setAdaptToClass(adaptToClass); | |||
| def.setRestrict(restrict); | |||
| def.setClassLoader(al); | |||
| if (cl != null) { | |||
| def.checkClass(getProject()); | |||
| @@ -35,11 +35,7 @@ import org.apache.tools.ant.taskdefs.UpToDate; | |||
| * | |||
| * @since Ant 1.4 | |||
| */ | |||
| public abstract class ConditionBase extends ProjectComponent | |||
| implements DynamicElement { | |||
| private static final String CONDITION_ANTLIB | |||
| = "antlib:org.apache.tools.ant.types.conditions:"; | |||
| public abstract class ConditionBase extends ProjectComponent { | |||
| /** | |||
| * name of the component | |||
| @@ -284,23 +280,4 @@ public abstract class ConditionBase extends ProjectComponent | |||
| conditions.addElement(c); | |||
| } | |||
| /** | |||
| * Create a dynamically discovered condition. Built-in conditions can | |||
| * be discovered from the org.apache.tools.ant.taskdefs.condition | |||
| * antlib. | |||
| * @param name the condition to create. | |||
| * @return the dynamic condition if found, null otherwise. | |||
| */ | |||
| public Object createDynamicElement(String name) { | |||
| Object cond = ComponentHelper.getComponentHelper(getProject()) | |||
| .createComponent(CONDITION_ANTLIB + name); | |||
| if (!(cond instanceof Condition)) { | |||
| return null; | |||
| } | |||
| log("Dynamically discovered '" + name + "' " + cond, | |||
| Project.MSG_DEBUG); | |||
| add((Condition) cond); | |||
| return cond; | |||
| } | |||
| } | |||
| @@ -12,6 +12,7 @@ bzip2=org.apache.tools.ant.taskdefs.BZip2 | |||
| checksum=org.apache.tools.ant.taskdefs.Checksum | |||
| chmod=org.apache.tools.ant.taskdefs.Chmod | |||
| classloader=org.apache.tools.ant.taskdefs.Classloader | |||
| componentdef=org.apache.tools.ant.taskdefs.Componentdef | |||
| concat=org.apache.tools.ant.taskdefs.Concat | |||
| condition=org.apache.tools.ant.taskdefs.ConditionTask | |||
| copy=org.apache.tools.ant.taskdefs.Copy | |||