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-ffa450edef68master
| @@ -58,14 +58,19 @@ import org.apache.tools.ant.util.WeakishReference; | |||
| import java.util.Enumeration; | |||
| import java.util.Hashtable; | |||
| import java.util.HashSet; | |||
| import java.util.Iterator; | |||
| import java.util.Properties; | |||
| import java.util.Set; | |||
| import java.util.Stack; | |||
| import java.util.Vector; | |||
| import java.io.InputStream; | |||
| import java.io.IOException; | |||
| import java.lang.reflect.Modifier; | |||
| import org.apache.tools.ant.taskdefs.Typedef; | |||
| /** | |||
| * Component creation and configuration. | |||
| * | |||
| @@ -98,6 +103,17 @@ public class ComponentHelper { | |||
| /** flag to rebuild typeClassDefinitions */ | |||
| private boolean rebuildTypeClassDefinitions = true; | |||
| /** Set of namespaces that have been checked for antlibs */ | |||
| private Set checkedNamespaces = new HashSet(); | |||
| /** | |||
| * Stack of antlib contexts used to resolve definitions while | |||
| * processing antlib | |||
| */ | |||
| private Stack antLibStack = new Stack(); | |||
| /** current antlib context */ | |||
| private AntTypeTable antLibTypeTable = null; | |||
| /** | |||
| * Map from task names to vectors of created tasks | |||
| * (String to Vector of Task). This is used to invalidate tasks if | |||
| @@ -175,32 +191,38 @@ public class ComponentHelper { | |||
| AntTypeDefinition def = (AntTypeDefinition) i.next(); | |||
| antTypeTable.put(def.getName(), def); | |||
| } | |||
| // add the parsed namespaces of the parent project | |||
| checkedNamespaces.add(helper.checkedNamespaces); | |||
| } | |||
| /** Factory method to create the components. | |||
| * | |||
| * This should be called by UnknownElement. | |||
| * | |||
| * @param ue The component helper has access via ue to the entire XML tree. | |||
| * @param ns Namespace. Also available as ue.getNamespace() | |||
| * @param taskName The element name. Also available as ue.getTag() | |||
| * @param ue The Unknown Element creating this component | |||
| * @param ns Namespace URI. Also available as ue.getNamespace() | |||
| * @param componentType The component type, | |||
| * Also available as ue.getComponentName() | |||
| * @return the created component | |||
| * @throws BuildException if an error occuries | |||
| */ | |||
| public Object createComponent(UnknownElement ue, | |||
| String ns, | |||
| String taskName) | |||
| String componentType) | |||
| throws BuildException { | |||
| Object component = createComponent(taskName); | |||
| Object component = createComponent(componentType); | |||
| if (component == null) { | |||
| return null; | |||
| } | |||
| if (component instanceof Task) { | |||
| Task task = (Task) component; | |||
| task.setTaskType(taskName); | |||
| task.setTaskName(taskName); | |||
| addCreatedTask(taskName, task); | |||
| task.setLocation(ue.getLocation()); | |||
| task.setTaskType(componentType); | |||
| task.setTaskName(ue.getTaskName()); | |||
| task.setOwningTarget(ue.getOwningTarget()); | |||
| task.init(); | |||
| addCreatedTask(componentType, task); | |||
| } | |||
| return component; | |||
| @@ -215,7 +237,11 @@ public class ComponentHelper { | |||
| * @return the class if found or null if not. | |||
| */ | |||
| public Object createComponent(String componentName) { | |||
| return antTypeTable.create(componentName); | |||
| AntTypeDefinition def = getDefinition(componentName); | |||
| if (def == null) { | |||
| return null; | |||
| } | |||
| return def.create(project); | |||
| } | |||
| /** | |||
| @@ -227,7 +253,11 @@ public class ComponentHelper { | |||
| * @return the class if found or null if not. | |||
| */ | |||
| public Class getComponentClass(String componentName) { | |||
| return antTypeTable.getExposedClass(componentName); | |||
| AntTypeDefinition def = getDefinition(componentName); | |||
| if (def == null) { | |||
| return null; | |||
| } | |||
| return def.getExposedClass(project); | |||
| } | |||
| /** | |||
| @@ -236,7 +266,15 @@ public class ComponentHelper { | |||
| * @return the ant definition or null if not present | |||
| */ | |||
| public AntTypeDefinition getDefinition(String componentName) { | |||
| return antTypeTable.getDefinition(componentName); | |||
| checkNamespace(componentName); | |||
| AntTypeDefinition ret = null; | |||
| if (antLibTypeTable != null && componentName.indexOf(':') == -1) { | |||
| ret = antLibTypeTable.getDefinition(componentName); | |||
| } | |||
| if (ret == null) { | |||
| ret = antTypeTable.getDefinition(componentName); | |||
| } | |||
| return ret; | |||
| } | |||
| /** | |||
| @@ -474,7 +512,7 @@ public class ComponentHelper { | |||
| * creation fails. | |||
| */ | |||
| private Task createNewTask(String taskType) throws BuildException { | |||
| Class c = antTypeTable.getExposedClass(taskType); | |||
| Class c = getComponentClass(taskType); | |||
| if (c == null) { | |||
| return null; | |||
| } | |||
| @@ -482,7 +520,7 @@ public class ComponentHelper { | |||
| if (!(Task.class.isAssignableFrom(c))) { | |||
| return null; | |||
| } | |||
| Task task = (Task) antTypeTable.create(taskType); | |||
| Task task = (Task) createComponent(taskType); | |||
| if (task == null) { | |||
| return null; | |||
| } | |||
| @@ -557,7 +595,7 @@ public class ComponentHelper { | |||
| * instance creation fails. | |||
| */ | |||
| public Object createDataType(String typeName) throws BuildException { | |||
| return antTypeTable.create(typeName); | |||
| return createComponent(typeName); | |||
| } | |||
| /** | |||
| @@ -660,6 +698,31 @@ public class ComponentHelper { | |||
| project.log(" +Datatype " + name + " " + def.getClassName(), | |||
| Project.MSG_DEBUG); | |||
| antTypeTable.put(name, def); | |||
| if (antLibTypeTable != null && name.lastIndexOf(':') != -1) { | |||
| String baseName = name.substring(name.lastIndexOf(':') + 1); | |||
| antLibTypeTable.put(baseName, def); | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * Called at the start of processing an antlib | |||
| */ | |||
| public void enterAntLib() { | |||
| antLibTypeTable = new AntTypeTable(project); | |||
| antLibStack.push(antLibTypeTable); | |||
| } | |||
| /** | |||
| * Called at the end of processing an antlib | |||
| */ | |||
| public void exitAntLib() { | |||
| antLibStack.pop(); | |||
| if (antLibStack.size() != 0) { | |||
| antLibTypeTable = (AntTypeTable) antLibStack.peek(); | |||
| } else { | |||
| antLibTypeTable = null; | |||
| } | |||
| } | |||
| @@ -751,6 +814,35 @@ public class ComponentHelper { | |||
| } | |||
| } | |||
| /** | |||
| * called for each component name, check if the | |||
| * associated URI has been examined for antlibs. | |||
| */ | |||
| private void checkNamespace(String componentName) { | |||
| if (componentName.indexOf(':') == -1) { | |||
| return; // not a namespaced name | |||
| } | |||
| String uri = ProjectHelper.extractUriFromComponentName(componentName); | |||
| if (!uri.startsWith(ProjectHelper.ANTLIB_URI)) { | |||
| return; // namespace that does not contain antlib | |||
| } | |||
| if (checkedNamespaces.contains(uri)) { | |||
| return; // Alreay processed | |||
| } | |||
| checkedNamespaces.add(uri); | |||
| Typedef definer = new Typedef(); | |||
| definer.setProject(project); | |||
| definer.setURI(uri); | |||
| definer.setResource( | |||
| uri.substring("antlib:".length()).replace('.', '/') | |||
| + "/antlib.xml"); | |||
| // a fishing expedition :- ignore errors if antlib not present | |||
| definer.setOnError(new Typedef.OnError("ignore")); | |||
| definer.init(); | |||
| definer.execute(); | |||
| } | |||
| /** | |||
| * map that contains the component definitions | |||
| */ | |||
| @@ -85,6 +85,12 @@ import org.xml.sax.AttributeList; | |||
| * @author duncan@x180.com | |||
| */ | |||
| public class ProjectHelper { | |||
| /** The URI for ant name space */ | |||
| public static final String ANT_CORE_URI = "ant:core"; | |||
| /** The URI for defined types/tasks - the format is antlib:<package> */ | |||
| public static final String ANTLIB_URI = "antlib:"; | |||
| /** | |||
| * Name of JVM system property which provides the name of the | |||
| * ProjectHelper class to use. | |||
| @@ -493,5 +499,34 @@ public class ProjectHelper { | |||
| PropertyHelper.parsePropertyStringDefault(value, fragments, | |||
| propertyRefs); | |||
| } | |||
| /** | |||
| * Map a namespaced {uri,name} to an internal string format. | |||
| * For BC purposes the names from the ant core uri will be | |||
| * mapped to "name", other names will be mapped to | |||
| * uri + ":" + name. | |||
| * @param uri The namepace URI | |||
| * @param name The localname | |||
| * @return The stringified form of the ns name | |||
| */ | |||
| public static String genComponentName(String uri, String name) { | |||
| if (uri == null || uri.equals("") || uri.equals(ANT_CORE_URI)) { | |||
| return name; | |||
| } | |||
| return uri + ":" + name; | |||
| } | |||
| /** | |||
| * extract a uri from a component name | |||
| * | |||
| * @param componentName The stringified form for {uri, name} | |||
| * @return The uri or "" if not present | |||
| */ | |||
| public static String extractUriFromComponentName(String componentName) { | |||
| int index = componentName.lastIndexOf(':'); | |||
| if (index == -1) { | |||
| return ""; | |||
| } | |||
| return componentName.substring(0, index); | |||
| } | |||
| //end class | |||
| } | |||
| @@ -176,6 +176,14 @@ public class RuntimeConfigurable implements Serializable { | |||
| return polyType; | |||
| } | |||
| /** | |||
| * set the polymorphic type for this element | |||
| * @param polyType the ant component type name, null if not set | |||
| */ | |||
| public void setPolyType(String polyType) { | |||
| this.polyType = polyType; | |||
| } | |||
| /** | |||
| * Sets the attributes for the wrapped element. | |||
| * | |||
| @@ -260,10 +268,10 @@ public class RuntimeConfigurable implements Serializable { | |||
| /** | |||
| * Returns an enumeration of all child wrappers. | |||
| * | |||
| * @return an enumeration of the child wrappers. | |||
| * @since Ant 1.5.1 | |||
| */ | |||
| Enumeration getChildren() { | |||
| public Enumeration getChildren() { | |||
| if (children != null) { | |||
| return Collections.enumeration(children); | |||
| } else { | |||
| @@ -81,6 +81,11 @@ public class UnknownElement extends Task { | |||
| */ | |||
| private String namespace; | |||
| /** | |||
| * Holds the namespace qname of the element. | |||
| */ | |||
| private String qname; | |||
| /** | |||
| * The real object after it has been loaded. | |||
| */ | |||
| @@ -129,6 +134,24 @@ public class UnknownElement extends Task { | |||
| this.namespace = namespace; | |||
| } | |||
| /** Return the qname of the XML element associated with this component. | |||
| * | |||
| * @return namespace Qname used in the element declaration. | |||
| */ | |||
| public String getQName() { | |||
| return qname; | |||
| } | |||
| /** Set the namespace qname of the XML element. | |||
| * This method is typically called by the XML processor. | |||
| * | |||
| * @param qname the qualified name of the element | |||
| */ | |||
| public void setQName(String qname) { | |||
| this.qname = qname; | |||
| } | |||
| /** | |||
| * Get the RuntimeConfigurable instance for this UnknownElement, containing | |||
| * the configuration information. | |||
| @@ -334,6 +357,13 @@ public class UnknownElement extends Task { | |||
| } | |||
| } | |||
| /** | |||
| * @return the component name - uses ProjectHelper#genComponentName() | |||
| */ | |||
| protected String getComponentName() { | |||
| return ProjectHelper.genComponentName(getNamespace(), getTag()); | |||
| } | |||
| /** | |||
| * Creates a named task or data type. If the real object is a task, | |||
| * it is configured up to the init() stage. | |||
| @@ -345,12 +375,17 @@ public class UnknownElement extends Task { | |||
| * @return the task or data type represented by the given unknown element. | |||
| */ | |||
| protected Object makeObject(UnknownElement ue, RuntimeConfigurable w) { | |||
| Object o = makeTask(ue, w); | |||
| ComponentHelper helper = ComponentHelper.getComponentHelper( | |||
| getProject()); | |||
| String name = ue.getComponentName(); | |||
| Object o = helper.createComponent(ue, ue.getNamespace(), name); | |||
| if (o == null) { | |||
| o = getProject().createDataType(ue.getTag()); | |||
| throw getNotFoundException("task or type", name); | |||
| } | |||
| if (o == null) { | |||
| throw getNotFoundException("task or type", ue.getTag()); | |||
| if (o instanceof Task) { | |||
| Task task = (Task) o; | |||
| task.setOwningTarget(getOwningTarget()); | |||
| task.init(); | |||
| } | |||
| return o; | |||
| } | |||
| @@ -54,6 +54,10 @@ | |||
| package org.apache.tools.ant.helper; | |||
| import java.io.File; | |||
| import java.util.ArrayList; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import java.util.Vector; | |||
| import org.xml.sax.Locator; | |||
| @@ -120,6 +124,11 @@ public class AntXMLContext { | |||
| * when processing a particular build file. | |||
| */ | |||
| private boolean ignoreProjectTag = false; | |||
| /** Keeps track of prefix -> uri mapping during parsing */ | |||
| private Map prefixMapping = new HashMap(); | |||
| /** | |||
| * constructor | |||
| * @param project the project to which this antxml context belongs to | |||
| @@ -263,7 +272,7 @@ public class AntXMLContext { | |||
| /** | |||
| * sets the implicit target | |||
| * @param target | |||
| * @param target the implicit target | |||
| */ | |||
| public void setImplicitTarget(Target target) { | |||
| this.implicitTarget = target; | |||
| @@ -284,6 +293,8 @@ public class AntXMLContext { | |||
| * <p> | |||
| * This method was moved out of the configure method to allow | |||
| * it to be executed at parse time. | |||
| * @param element the current element | |||
| * @param attr attributes of the current element | |||
| */ | |||
| public void configureId(Object element, Attributes attr) { | |||
| String id = attr.getValue("id"); | |||
| @@ -323,6 +334,48 @@ public class AntXMLContext { | |||
| public void setIgnoreProjectTag(boolean flag) { | |||
| this.ignoreProjectTag = flag; | |||
| } | |||
| /** | |||
| * Called during parsing, stores the prefix to uri mapping. | |||
| * | |||
| * @param prefix a namespace prefix | |||
| * @param uri a namespace uri | |||
| */ | |||
| public void startPrefixMapping(String prefix, String uri) { | |||
| List list = (List) prefixMapping.get(prefix); | |||
| if (list == null) { | |||
| list = new ArrayList(); | |||
| prefixMapping.put(prefix, list); | |||
| } | |||
| list.add(uri); | |||
| } | |||
| /** | |||
| * End of prefix to uri mapping. | |||
| * | |||
| * @param prefix the namespace prefix | |||
| */ | |||
| public void endPrefixMapping(String prefix) { | |||
| List list = (List) prefixMapping.get(prefix); | |||
| if (list == null || list.size() == 0) { | |||
| return; // Should not happen | |||
| } | |||
| list.remove(list.size() - 1); | |||
| } | |||
| /** | |||
| * prefix to namespace uri mapping | |||
| * | |||
| * @param prefix the prefix to map | |||
| * @return the uri for this prefix, null if not present | |||
| */ | |||
| public String getPrefixMapping(String prefix) { | |||
| List list = (List) prefixMapping.get(prefix); | |||
| if (list == null || list.size() == 0) { | |||
| return null; | |||
| } | |||
| return (String) list.get(list.size() - 1); | |||
| } | |||
| } | |||
| @@ -474,6 +474,9 @@ public class ProjectHelper2 extends ProjectHelper { | |||
| */ | |||
| public void startElement(String uri, String tag, String qname, Attributes attrs) | |||
| throws SAXParseException { | |||
| if (uri.equals(ANT_CORE_URI)) { | |||
| uri = ""; | |||
| } | |||
| AntHandler next | |||
| = currentHandler.onStartChild(uri, tag, qname, attrs, context); | |||
| antHandlers.push(currentHandler); | |||
| @@ -506,6 +509,9 @@ public class ProjectHelper2 extends ProjectHelper { | |||
| * | |||
| */ | |||
| public void endElement(String uri, String name, String qName) throws SAXException { | |||
| if (uri.equals(ANT_CORE_URI)) { | |||
| uri = ""; | |||
| } | |||
| currentHandler.onEndElement(uri, name, context); | |||
| AntHandler prev = (AntHandler) antHandlers.pop(); | |||
| currentHandler = prev; | |||
| @@ -526,6 +532,25 @@ public class ProjectHelper2 extends ProjectHelper { | |||
| throws SAXParseException { | |||
| currentHandler.characters(buf, start, count, context); | |||
| } | |||
| /** | |||
| * Start a namespace prefix to uri mapping | |||
| * | |||
| * @param prefix the namespace prefix | |||
| * @param uri the namespace uri | |||
| */ | |||
| public void startPrefixMapping(String prefix, String uri) { | |||
| context.startPrefixMapping(prefix, uri); | |||
| } | |||
| /** | |||
| * End a namepace prefix to uri mapping | |||
| * | |||
| * @param prefix the prefix that is not mapped anymore | |||
| */ | |||
| public void endPrefixMapping(String prefix) { | |||
| context.endPrefixMapping(prefix); | |||
| } | |||
| } | |||
| /** | |||
| @@ -550,7 +575,7 @@ public class ProjectHelper2 extends ProjectHelper { | |||
| Attributes attrs, | |||
| AntXMLContext context) | |||
| throws SAXParseException { | |||
| if (qname.equals("project")) { | |||
| if (name.equals("project") && uri.equals("")) { | |||
| return ProjectHelper2.projectHandler; | |||
| } else { | |||
| // if (context.importlevel > 0) { | |||
| @@ -610,7 +635,7 @@ public class ProjectHelper2 extends ProjectHelper { | |||
| */ | |||
| for (int i = 0; i < attrs.getLength(); i++) { | |||
| String key = attrs.getQName(i); | |||
| String key = attrs.getLocalName(i); | |||
| String value = attrs.getValue(i); | |||
| if (key.equals("default")) { | |||
| @@ -715,7 +740,7 @@ public class ProjectHelper2 extends ProjectHelper { | |||
| Attributes attrs, | |||
| AntXMLContext context) | |||
| throws SAXParseException { | |||
| if (qname.equals("target")) { | |||
| if (name.equals("target") && uri.equals("")) { | |||
| return ProjectHelper2.targetHandler; | |||
| } else { | |||
| return ProjectHelper2.elementHandler; | |||
| @@ -761,7 +786,7 @@ public class ProjectHelper2 extends ProjectHelper { | |||
| context.addTarget(target); | |||
| for (int i = 0; i < attrs.getLength(); i++) { | |||
| String key = attrs.getQName(i); | |||
| String key = attrs.getLocalName(i); | |||
| String value = attrs.getValue(i); | |||
| if (key.equals("name")) { | |||
| @@ -904,7 +929,7 @@ public class ProjectHelper2 extends ProjectHelper { | |||
| task.setNamespace(uri); | |||
| task.setProject(context.getProject()); | |||
| //XXX task.setTaskType(qname); | |||
| task.setQName(qname); | |||
| task.setTaskName(qname); | |||
| Location location = new Location(context.getLocator().getSystemId(), | |||
| @@ -930,8 +955,26 @@ public class ProjectHelper2 extends ProjectHelper { | |||
| = new RuntimeConfigurable(task, task.getTaskName()); | |||
| for (int i = 0; i < attrs.getLength(); i++) { | |||
| wrapper.setAttribute(attrs.getQName(i), | |||
| attrs.getValue(i)); | |||
| String name = attrs.getLocalName(i); | |||
| String value = attrs.getValue(i); | |||
| // PR: Hack for ant-type value | |||
| // an ant-type is a component name which can | |||
| // be namespaced, need to extract the name | |||
| // and convert from qualifed name to uri/name | |||
| if (name.equals("ant-type")) { | |||
| int index = value.indexOf(":"); | |||
| if (index != -1) { | |||
| String prefix = value.substring(0, index); | |||
| String mappedUri = context.getPrefixMapping(prefix); | |||
| if (mappedUri == null) { | |||
| throw new BuildException( | |||
| "Unable to find XML NS prefix " + prefix); | |||
| } | |||
| value = ProjectHelper.genComponentName( | |||
| mappedUri, value.substring(index + 1)); | |||
| } | |||
| } | |||
| wrapper.setAttribute(name, value); | |||
| } | |||
| if (parentWrapper != null) { | |||
| @@ -62,7 +62,7 @@ import java.util.List; | |||
| import org.apache.tools.ant.TaskContainer; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Location; | |||
| import org.apache.tools.ant.ComponentHelper; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.helper.ProjectHelper2; | |||
| @@ -124,6 +124,7 @@ public class Antlib extends Task implements TaskContainer { | |||
| // | |||
| private ClassLoader classLoader; | |||
| private String prefix; | |||
| private String uri = ""; | |||
| private List tasks = new ArrayList(); | |||
| /** | |||
| @@ -137,6 +138,14 @@ public class Antlib extends Task implements TaskContainer { | |||
| this.classLoader = classLoader; | |||
| } | |||
| /** | |||
| * Set the URI for this antlib. | |||
| * @param uri the namespace uri | |||
| */ | |||
| protected void setURI(String uri) { | |||
| this.uri = uri; | |||
| } | |||
| private ClassLoader getClassLoader() { | |||
| if (classLoader == null) { | |||
| classLoader = Antlib.class.getClassLoader(); | |||
| @@ -158,20 +167,28 @@ public class Antlib extends Task implements TaskContainer { | |||
| * any tasks that derive from Definer. | |||
| */ | |||
| public void execute() { | |||
| for (Iterator i = tasks.iterator(); i.hasNext();) { | |||
| UnknownElement ue = (UnknownElement) i.next(); | |||
| ue.maybeConfigure(); | |||
| setLocation(ue.getLocation()); | |||
| Task t = ue.getTask(); | |||
| if (t == null) { | |||
| continue; | |||
| } | |||
| if (t instanceof Definer) { | |||
| Definer d = (Definer) t; | |||
| d.setInternalClassLoader(getClassLoader()); | |||
| ComponentHelper helper = | |||
| ComponentHelper.getComponentHelper(getProject()); | |||
| helper.enterAntLib(); | |||
| try { | |||
| for (Iterator i = tasks.iterator(); i.hasNext();) { | |||
| UnknownElement ue = (UnknownElement) i.next(); | |||
| ue.maybeConfigure(); | |||
| setLocation(ue.getLocation()); | |||
| Task t = ue.getTask(); | |||
| if (t == null) { | |||
| continue; | |||
| } | |||
| if (t instanceof AntlibInterface) { | |||
| AntlibInterface d = (AntlibInterface) t; | |||
| d.setURI(uri); | |||
| d.setAntlibClassLoader(getClassLoader()); | |||
| } | |||
| t.init(); | |||
| t.execute(); | |||
| } | |||
| t.init(); | |||
| t.execute(); | |||
| } finally { | |||
| helper.exitAntLib(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,81 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 2003 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| * modification, are permitted provided that the following conditions | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * | |||
| * 2. Redistributions in binary form must reproduce the above copyright | |||
| * notice, this list of conditions and the following disclaimer in | |||
| * the documentation and/or other materials provided with the | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * Apache Software Foundation (http://www.apache.org/)." | |||
| * Alternately, this acknowlegement may appear in the software itself, | |||
| * if and wherever such third-party acknowlegements normally appear. | |||
| * | |||
| * 4. The names "Ant" and "Apache Software | |||
| * Foundation" must not be used to endorse or promote products derived | |||
| * from this software without prior written permission. For written | |||
| * permission, please contact apache@apache.org. | |||
| * | |||
| * 5. Products derived from this software may not be called "Apache" | |||
| * nor may "Apache" appear in their names without prior written | |||
| * permission of the Apache Group. | |||
| * | |||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
| * SUCH DAMAGE. | |||
| * ==================================================================== | |||
| * | |||
| * This software consists of voluntary contributions made by many | |||
| * individuals on behalf of the Apache Software Foundation. For more | |||
| * information on the Apache Software Foundation, please see | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant.taskdefs; | |||
| /** | |||
| * Interface for tasks that should be informed when | |||
| * they are loaded in antlib's. | |||
| * For handling uri and and class loading. | |||
| * | |||
| * @author Peter Reilly | |||
| * | |||
| * @since Ant 1.6 | |||
| */ | |||
| public interface AntlibInterface { | |||
| /** | |||
| * The URI for this definition. | |||
| * @param uri the namespace URI | |||
| */ | |||
| void setURI(String uri); | |||
| /** | |||
| * Set the class loader of the loading object | |||
| * | |||
| * @param classLoader a <code>ClassLoader</code> value | |||
| */ | |||
| void setAntlibClassLoader(ClassLoader classLoader); | |||
| } | |||
| @@ -0,0 +1,234 @@ | |||
| /* | |||
| * The Apache Software License, Version 1.1 | |||
| * | |||
| * Copyright (c) 2001-2003 The Apache Software Foundation. All rights | |||
| * reserved. | |||
| * | |||
| * Redistribution and use in source and binary forms, with or without | |||
| * modification, are permitted provided that the following conditions | |||
| * are met: | |||
| * | |||
| * 1. Redistributions of source code must retain the above copyright | |||
| * notice, this list of conditions and the following disclaimer. | |||
| * | |||
| * 2. Redistributions in binary form must reproduce the above copyright | |||
| * notice, this list of conditions and the following disclaimer in | |||
| * the documentation and/or other materials provided with the | |||
| * distribution. | |||
| * | |||
| * 3. The end-user documentation included with the redistribution, if | |||
| * any, must include the following acknowlegement: | |||
| * "This product includes software developed by the | |||
| * Apache Software Foundation (http://www.apache.org/)." | |||
| * Alternately, this acknowlegement may appear in the software itself, | |||
| * if and wherever such third-party acknowlegements normally appear. | |||
| * | |||
| * 4. The names "Ant" and "Apache Software | |||
| * Foundation" must not be used to endorse or promote products derived | |||
| * from this software without prior written permission. For written | |||
| * permission, please contact apache@apache.org. | |||
| * | |||
| * 5. Products derived from this software may not be called "Apache" | |||
| * nor may "Apache" appear in their names without prior written | |||
| * permission of the Apache Group. | |||
| * | |||
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
| * SUCH DAMAGE. | |||
| * ==================================================================== | |||
| * | |||
| * This software consists of voluntary contributions made by many | |||
| * individuals on behalf of the Apache Software Foundation. For more | |||
| * information on the Apache Software Foundation, please see | |||
| * <http://www.apache.org/>. | |||
| */ | |||
| package org.apache.tools.ant.taskdefs; | |||
| import org.apache.tools.ant.AntClassLoader; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.ProjectHelper; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.types.Path; | |||
| import org.apache.tools.ant.types.Reference; | |||
| import org.apache.tools.ant.util.ClasspathUtils; | |||
| /** | |||
| * Base class for Definitions | |||
| * handling uri and and class loading. | |||
| * (This was part of Definer) | |||
| * | |||
| * @author Costin Manolache | |||
| * @author Stefan Bodewig | |||
| * @author Peter Reilly | |||
| * | |||
| * @since Ant 1.6 | |||
| */ | |||
| public abstract class DefBase extends Task implements AntlibInterface { | |||
| private String uri = ""; | |||
| private ClassLoader internalClassLoader; | |||
| private ClassLoader createdLoader; | |||
| private ClasspathUtils.Delegate cpDelegate; | |||
| /** | |||
| * The URI for this definition. | |||
| * If the URI is "ant:core", the uri will be set to "". (This | |||
| * is the default uri). | |||
| * URIs that start with "ant:" and are not | |||
| * "ant:core" are reserved and are not allowed in this context. | |||
| * @param uri the namespace URI | |||
| * @throws BuildException if a reserved URI is used | |||
| */ | |||
| public void setURI(String uri) throws BuildException { | |||
| if (uri.equals(ProjectHelper.ANT_CORE_URI)) { | |||
| uri = ""; | |||
| } | |||
| if (uri.startsWith("ant:") && !uri.startsWith("antlib:")) { | |||
| throw new BuildException("Attempt to use use a reserved URI " + uri); | |||
| } | |||
| this.uri = uri; | |||
| } | |||
| /** | |||
| * @return the namespace uri for this definition | |||
| */ | |||
| public String getUri() { | |||
| return uri; | |||
| } | |||
| /** | |||
| * Set the class loader, overrides the cpDelagate | |||
| * classloader. | |||
| * | |||
| * @param classLoader a <code>ClassLoader</code> value | |||
| */ | |||
| public void setAntlibClassLoader(ClassLoader classLoader) { | |||
| this.internalClassLoader = classLoader; | |||
| } | |||
| /** | |||
| * @param reverseLoader if true a delegated loader will take precedence over | |||
| * the parent | |||
| * @deprecated stop using this attribute | |||
| * @ant.attribute ignore="true" | |||
| */ | |||
| public void setReverseLoader(boolean reverseLoader) { | |||
| this.cpDelegate.setReverseLoader(reverseLoader); | |||
| log("The reverseloader attribute is DEPRECATED. It will be removed", | |||
| Project.MSG_WARN); | |||
| } | |||
| /** | |||
| * @return the class path path for this definition | |||
| */ | |||
| public Path getClasspath() { | |||
| return cpDelegate.getClasspath(); | |||
| } | |||
| /** | |||
| * @return the reverse loader attribute of the classpath delegate. | |||
| */ | |||
| public boolean isReverseLoader() { | |||
| return cpDelegate.isReverseLoader(); | |||
| } | |||
| /** | |||
| * Returns the loader id of the class path Delegate. | |||
| * @return the loader id | |||
| */ | |||
| public String getLoaderId() { | |||
| return cpDelegate.getClassLoadId(); | |||
| } | |||
| /** | |||
| * Returns the class path id of the class path delegate. | |||
| * @return the class path id | |||
| */ | |||
| public String getClasspathId() { | |||
| return cpDelegate.getClassLoadId(); | |||
| } | |||
| /** | |||
| * Set the classpath to be used when searching for component being defined | |||
| * | |||
| * @param classpath an Ant Path object containing the classpath. | |||
| */ | |||
| public void setClasspath(Path classpath) { | |||
| this.cpDelegate.setClasspath(classpath); | |||
| } | |||
| /** | |||
| * Create the classpath to be used when searching for component being | |||
| * defined | |||
| * @return the classpath of the this definition | |||
| */ | |||
| public Path createClasspath() { | |||
| return this.cpDelegate.createClasspath(); | |||
| } | |||
| /** | |||
| * reference to a classpath to use when loading the files. | |||
| * To actually share the same loader, set loaderref as well | |||
| * @param r the reference to the classpath | |||
| */ | |||
| public void setClasspathRef(Reference r) { | |||
| this.cpDelegate.setClasspathref(r); | |||
| } | |||
| /** | |||
| * Use the reference to locate the loader. If the loader is not | |||
| * found, taskdef will use the specified classpath and register it | |||
| * with the specified name. | |||
| * | |||
| * This allow multiple taskdef/typedef to use the same class loader, | |||
| * so they can be used together. It eliminate the need to | |||
| * put them in the CLASSPATH. | |||
| * | |||
| * @param r the reference to locate the loader. | |||
| * @since Ant 1.5 | |||
| */ | |||
| public void setLoaderRef(Reference r) { | |||
| this.cpDelegate.setLoaderRef(r); | |||
| } | |||
| /** | |||
| * create a classloader for this definition | |||
| * @return the classloader from the cpDelegate | |||
| */ | |||
| protected ClassLoader createLoader() { | |||
| if (internalClassLoader != null) { | |||
| return internalClassLoader; | |||
| } | |||
| if (createdLoader == null) { | |||
| createdLoader = this.cpDelegate.getClassLoader(); | |||
| // need to load Task via system classloader or the new | |||
| // task we want to define will never be a Task but always | |||
| // be wrapped into a TaskAdapter. | |||
| ((AntClassLoader) createdLoader) | |||
| .addSystemPackageRoot("org.apache.tools.ant"); | |||
| } | |||
| return createdLoader; | |||
| } | |||
| /** | |||
| * @see org.apache.tools.ant.Task#init() | |||
| * @since Ant 1.6 | |||
| */ | |||
| public void init() throws BuildException { | |||
| this.cpDelegate = ClasspathUtils.getDelegate(this); | |||
| super.init(); | |||
| } | |||
| } | |||
| @@ -63,32 +63,29 @@ import java.util.Locale; | |||
| import java.util.Properties; | |||
| import org.apache.tools.ant.AntTypeDefinition; | |||
| import org.apache.tools.ant.AntClassLoader; | |||
| import org.apache.tools.ant.ComponentHelper; | |||
| import org.apache.tools.ant.BuildException; | |||
| import org.apache.tools.ant.Location; | |||
| import org.apache.tools.ant.Project; | |||
| import org.apache.tools.ant.Task; | |||
| import org.apache.tools.ant.types.Path; | |||
| import org.apache.tools.ant.types.Reference; | |||
| import org.apache.tools.ant.util.ClasspathUtils; | |||
| import org.apache.tools.ant.ProjectHelper; | |||
| import org.apache.tools.ant.types.EnumeratedAttribute; | |||
| /** | |||
| * Base class for Taskdef and Typedef - does all the classpath | |||
| * handling and and class loading. | |||
| * Base class for Taskdef and Typedef - handles all | |||
| * the attributes for Typedef. The uri and class | |||
| * handling is handled by DefBase | |||
| * | |||
| * @author Costin Manolache | |||
| * @author Stefan Bodewig | |||
| * @author Peter Reilly | |||
| * | |||
| * @since Ant 1.4 | |||
| */ | |||
| public abstract class Definer extends Task { | |||
| public abstract class Definer extends DefBase { | |||
| private String name; | |||
| private String classname; | |||
| private File file; | |||
| private String resource; | |||
| private ClasspathUtils.Delegate cpDelegate; | |||
| private int format = Format.PROPERTIES; | |||
| private boolean definerSet = false; | |||
| @@ -172,18 +169,6 @@ public abstract class Definer extends Task { | |||
| this.format = format.getIndex(); | |||
| } | |||
| /** | |||
| * @param reverseLoader if true a delegated loader will take precedence over | |||
| * the parent | |||
| * @deprecated stop using this attribute | |||
| * @ant.attribute ignore="true" | |||
| */ | |||
| public void setReverseLoader(boolean reverseLoader) { | |||
| this.cpDelegate.setReverseLoader(reverseLoader); | |||
| log("The reverseloader attribute is DEPRECATED. It will be removed", | |||
| Project.MSG_WARN); | |||
| } | |||
| /** | |||
| * @return the name for this definition | |||
| */ | |||
| @@ -191,13 +176,6 @@ public abstract class Definer extends Task { | |||
| return name; | |||
| } | |||
| /** | |||
| * @return the class path path for this definition | |||
| */ | |||
| public Path getClasspath() { | |||
| return cpDelegate.getClasspath(); | |||
| } | |||
| /** | |||
| * @return the file containing definitions | |||
| */ | |||
| @@ -212,72 +190,6 @@ public abstract class Definer extends Task { | |||
| return resource; | |||
| } | |||
| /** | |||
| * @return the reverse loader attribute of the classpath delegate. | |||
| */ | |||
| public boolean isReverseLoader() { | |||
| return cpDelegate.isReverseLoader(); | |||
| } | |||
| /** | |||
| * Returns the loader id of the class path Delegate. | |||
| * @return the loader id | |||
| */ | |||
| public String getLoaderId() { | |||
| return cpDelegate.getClassLoadId(); | |||
| } | |||
| /** | |||
| * Returns the class path id of the class path delegate. | |||
| * @return the class path id | |||
| */ | |||
| public String getClasspathId() { | |||
| return cpDelegate.getClassLoadId(); | |||
| } | |||
| /** | |||
| * Set the classpath to be used when searching for component being defined | |||
| * | |||
| * @param classpath an Ant Path object containing the classpath. | |||
| */ | |||
| public void setClasspath(Path classpath) { | |||
| this.cpDelegate.setClasspath(classpath); | |||
| } | |||
| /** | |||
| * Create the classpath to be used when searching for component being | |||
| * defined | |||
| * @return the classpath of the this definition | |||
| */ | |||
| public Path createClasspath() { | |||
| return this.cpDelegate.createClasspath(); | |||
| } | |||
| /** | |||
| * reference to a classpath to use when loading the files. | |||
| * To actually share the same loader, set loaderref as well | |||
| * @param r the reference to the classpath | |||
| */ | |||
| public void setClasspathRef(Reference r) { | |||
| this.cpDelegate.setClasspathref(r); | |||
| } | |||
| /** | |||
| * Use the reference to locate the loader. If the loader is not | |||
| * found, taskdef will use the specified classpath and register it | |||
| * with the specified name. | |||
| * | |||
| * This allow multiple taskdef/typedef to use the same class loader, | |||
| * so they can be used together. It eliminate the need to | |||
| * put them in the CLASSPATH. | |||
| * | |||
| * @param r the reference to locate the loader. | |||
| * @since Ant 1.5 | |||
| */ | |||
| public void setLoaderRef(Reference r) { | |||
| this.cpDelegate.setLoaderRef(r); | |||
| } | |||
| /** | |||
| * Run the definition. | |||
| @@ -406,6 +318,7 @@ public abstract class Definer extends Task { | |||
| try { | |||
| Antlib antlib = Antlib.createAntlib(getProject(), url); | |||
| antlib.setClassLoader(classLoader); | |||
| antlib.setURI(getUri()); | |||
| antlib.perform(); | |||
| } catch (BuildException ex) { | |||
| Location exLocation = ex.getLocation(); | |||
| @@ -420,23 +333,6 @@ public abstract class Definer extends Task { | |||
| } | |||
| } | |||
| /** | |||
| * create a classloader for this definition | |||
| * @return the classloader from the cpDelegate | |||
| */ | |||
| protected ClassLoader createLoader() { | |||
| if (internalClassLoader != null) { | |||
| return internalClassLoader; | |||
| } | |||
| ClassLoader al = this.cpDelegate.getClassLoader(); | |||
| // need to load Task via system classloader or the new | |||
| // task we want to define will never be a Task but always | |||
| // be wrapped into a TaskAdapter. | |||
| ((AntClassLoader) al).addSystemPackageRoot("org.apache.tools.ant"); | |||
| return al; | |||
| } | |||
| /** | |||
| * Name of the property file to load | |||
| * ant name/classname pairs from. | |||
| @@ -474,7 +370,7 @@ public abstract class Definer extends Task { | |||
| definerSet = true; | |||
| this.name = name; | |||
| } | |||
| /** | |||
| * Returns the classname of the object we are defining. | |||
| * May be <code>null</code>. | |||
| @@ -541,25 +437,6 @@ public abstract class Definer extends Task { | |||
| } | |||
| /** | |||
| * Set the class loader, overrides the cpDelagate | |||
| * classloader. | |||
| * | |||
| * @param classLoader a <code>ClassLoader</code> value | |||
| */ | |||
| protected void setInternalClassLoader(ClassLoader classLoader) { | |||
| this.internalClassLoader = classLoader; | |||
| } | |||
| /** | |||
| * @see org.apache.tools.ant.Task#init() | |||
| * @since Ant 1.6 | |||
| */ | |||
| public void init() throws BuildException { | |||
| this.cpDelegate = ClasspathUtils.getDelegate(this); | |||
| super.init(); | |||
| } | |||
| /** | |||
| * Add a definition using the attributes of Definer | |||
| * | |||
| @@ -573,6 +450,8 @@ public abstract class Definer extends Task { | |||
| Class cl = null; | |||
| try { | |||
| try { | |||
| name = ProjectHelper.genComponentName(getUri(), name); | |||
| if (onError != OnError.IGNORE) { | |||
| cl = Class.forName(classname, true, al); | |||
| } | |||