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 | |||