This is patch 7204 the fourth patch of the antlib + ns enhancement. The issues reported by Stephan will need be addressed, so the implementation may change before ant 1.6 is released. PR: 19897 git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274930 13f79535-47bb-0310-9956-ffa450edef68master
@@ -9,23 +9,43 @@ | |||||
<h2><a name="typedef">Typedef</a></h2> | <h2><a name="typedef">Typedef</a></h2> | ||||
<h3>Description</h3> | <h3>Description</h3> | ||||
<p>Adds a data type definition to the current project, such that this | |||||
new type can be used in the current project. Two attributes are | |||||
needed, the name that identifies this data type uniquely, and the full | |||||
name of the class (including the packages) that implements this | |||||
type.</p> | |||||
<p>You can also define a group of data types at once using the file or | |||||
resource attributes. These attributes point to files in the format of | |||||
Java property files. Each line defines a single data type in the | |||||
format:</p> | |||||
<pre> | |||||
typename=fully.qualified.java.classname | |||||
</pre> | |||||
<p>Typedef should be used to add your own tasks and types to the system. Data | |||||
types are things like <a href="../using.html#path">paths</a> or <a | |||||
href="../CoreTypes/fileset.html">filesets</a> that can be defined at | |||||
the project level and referenced via their ID attribute.</p> | |||||
<p>Custom data types usually need custom tasks to put them to good use.</p> | |||||
<p> | |||||
Adds a task or a data type definition to the current project | |||||
such that this new type or task can be used in the current project. | |||||
</p> | |||||
<p> | |||||
Tasks are any class that extend org.apache.tools.ant.Task or | |||||
a class that is adapted to a Task using an adapter class. | |||||
</p> | |||||
<p> | |||||
Data types are things like <a href="../using.html#path">paths</a> or | |||||
<a href="../CoreTypes/fileset.html">filesets</a> that can be defined at | |||||
the project level and referenced via their ID attribute. | |||||
Custom data types usually need custom tasks to put them to good use. | |||||
</p> | |||||
<p> | |||||
Two attributes are needed to make a definition, | |||||
the name that identifies this data type uniquely, and the full | |||||
name of the class (including the packages) that implements this | |||||
type. | |||||
</p> | |||||
<p> | |||||
You can also define a group of definitions at once using the file or | |||||
resource attributes. These attributes point to files in the format of | |||||
Java property files or an xml format. | |||||
</p> | |||||
<p> | |||||
For property files each line defines a single data type in the | |||||
format:</p> | |||||
<pre> | |||||
typename=fully.qualified.java.classname | |||||
</pre> | |||||
<p> | |||||
The xml format is described below in the <a href="#antlib">Antlib</a> | |||||
section. | |||||
</p> | |||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
@@ -55,6 +75,19 @@ the project level and referenced via their ID attribute.</p> | |||||
<td valign="top">Name of the resouce to load definitions from.</td> | <td valign="top">Name of the resouce to load definitions from.</td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">format</td> | |||||
<td valign="top">The format of the file or resource. The values | |||||
are "properties" or "xml". If the value is "properties" the file/resource | |||||
is a property file contains name to classname pairs. If the value | |||||
is "xml", the file/resource is an xml file/resource structured according | |||||
to <a href="#antlib">Antlib</a>. | |||||
The default is "properties" unless the file/resorce name ends with | |||||
".xml", in which case the format attribute will have the value "xml". | |||||
(introduced in ant1.6) | |||||
</td> | |||||
<td valign="top" align="center">No</td> | |||||
</tr> | |||||
<tr> | <tr> | ||||
<td valign="top">classpath</td> <td valign="top">the classpath to | <td valign="top">classpath</td> <td valign="top">the classpath to | ||||
use when looking up <code>classname</code>.</td> <td | use when looking up <code>classname</code>.</td> <td | ||||
@@ -102,15 +135,51 @@ the project level and referenced via their ID attribute.</p> | |||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
</table> | </table> | ||||
<h3>Parameters specified as nested elements</h3> | |||||
<h4>classpath</h4> | |||||
<p><code>Typedef</code>'s <i>classpath</i> attribute is a | |||||
<a href="../using.html#path">PATH like structure</a> and can also be set | |||||
via a nested <i>classpath</i> element.</p> | |||||
<h3>Parameters specified as nested elements</h3> | |||||
<h4>classpath</h4> | |||||
<p><code>Typedef</code>'s <i>classpath</i> attribute is a | |||||
<a href="../using.html#path">PATH like structure</a> and can also be set | |||||
via a nested <i>classpath</i> element.</p> | |||||
<h3>Examples</h3> | <h3>Examples</h3> | ||||
<pre> <typedef name="urlset" classname="com.mydomain.URLSet"/></pre> | |||||
<p>makes a data type called <code>urlset</code> available to Ant. The | |||||
class <code>com.mydomain.URLSet</code> implements this type.</p> | |||||
The following fragment defines define a type called <i>urlset</i>. | |||||
<pre> | |||||
<typedef name="urlset" classname="com.mydomain.URLSet"/> </pre> | |||||
The data type is now availabe to Ant. The | |||||
class <code>com.mydomain.URLSet</code> implements this type.</p> | |||||
<p> | |||||
Assuming a class <i>org.acme.ant.RunnableAdapter</i> that | |||||
extends Task and implements <i>org.apache.tools.ant.TypeAdapter</i>, | |||||
and in the execute method invokes <i>run</i> on the proxied object, | |||||
one may use a Runnable class as an Ant task. The following fragment | |||||
defines a task called <i>runclock</i>. | |||||
<pre> | |||||
<typedef name="runclock" | |||||
classname="com.acme.ant.RunClock" | |||||
adapter="org.acme.ant.RunnableAdapter"/> | |||||
</pre> | |||||
<h3><a name="antlib">Antlib xml format</a></h3> | |||||
An antlib file is an xml file with a root element of "antlib". | |||||
Antlib is actually a <a href="sequential.html">Sequential</a> task with | |||||
special treatment for tasks that are ant definition tasks - like typedef | |||||
and <a href="taskdef.html">Taskdef</a>. | |||||
A group of tasks and types may be defined together in an antlib | |||||
file. For example the file <i>sample.xml</i> contains the following: | |||||
<pre> | |||||
<?xml version="1.0"?> | |||||
<antlib> | |||||
<typedef name="if" classname="org.acme.ant.If"/> | |||||
<typedef name="scriptpathmapper" | |||||
classname="org.acme.ant.ScriptPathMapper" | |||||
onerror="ignore"/> | |||||
</antlib> | |||||
</pre> | |||||
It defines two types or tasks, <i>if</i> and <i>scriptpathmapper</i>. | |||||
This antlib file may be used in a build script as follows: | |||||
<pre> | |||||
<typedef file="sample.xml"/> | |||||
</pre> | |||||
<hr> | <hr> | ||||
<p align="center">Copyright © 2001-2003 Apache Software | <p align="center">Copyright © 2001-2003 Apache Software | ||||
@@ -0,0 +1,17 @@ | |||||
<?xml version="1.0"?> | |||||
<project name="test"> | |||||
<property name="testcases.dir" location="../../../../build/testcases"/> | |||||
<path id="testclasses"> | |||||
<pathelement location="${testcases.dir}" /> | |||||
<pathelement path="${java.class.path}" /> | |||||
</path> | |||||
<target name="antlib.file"> | |||||
<typedef file="test.antlib.xml" | |||||
classpathref="testclasses"/> | |||||
<mytask/> | |||||
</target> | |||||
</project> |
@@ -0,0 +1,6 @@ | |||||
<?xml version="1.0"?> | |||||
<antlib> | |||||
<typedef | |||||
name="mytask" onerror="ignore" | |||||
classname="org.apache.tools.ant.taskdefs.AntlibTest$MyTask"/> | |||||
</antlib> |
@@ -57,8 +57,10 @@ package org.apache.tools.ant.helper; | |||||
import java.io.File; | import java.io.File; | ||||
import java.io.FileInputStream; | import java.io.FileInputStream; | ||||
import java.io.FileNotFoundException; | import java.io.FileNotFoundException; | ||||
import java.io.InputStream; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.UnsupportedEncodingException; | import java.io.UnsupportedEncodingException; | ||||
import java.net.URL; | |||||
import java.util.Hashtable; | import java.util.Hashtable; | ||||
import java.util.Stack; | import java.util.Stack; | ||||
@@ -75,6 +77,7 @@ import org.apache.tools.ant.util.FileUtils; | |||||
import org.apache.tools.ant.ProjectHelper; | import org.apache.tools.ant.ProjectHelper; | ||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.Target; | import org.apache.tools.ant.Target; | ||||
import org.apache.tools.ant.Task; | |||||
import org.apache.tools.ant.RuntimeConfigurable; | import org.apache.tools.ant.RuntimeConfigurable; | ||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.Location; | import org.apache.tools.ant.Location; | ||||
@@ -102,6 +105,31 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
*/ | */ | ||||
private static FileUtils fu = FileUtils.newFileUtils(); | private static FileUtils fu = FileUtils.newFileUtils(); | ||||
/** | |||||
* Parse an unknown element from a url | |||||
* | |||||
* @param project the current project | |||||
* @param source the url containing the task | |||||
* @return a configured task | |||||
* @exception BuildException if an error occurs | |||||
*/ | |||||
public UnknownElement parseUnknownElement(Project project, URL source) | |||||
throws BuildException { | |||||
Target dummyTarget = new Target(); | |||||
dummyTarget.setProject(project); | |||||
AntXMLContext context = new AntXMLContext(project); | |||||
context.addTarget(dummyTarget); | |||||
context.setImplicitTarget(dummyTarget); | |||||
parse(context.getProject(), source, | |||||
new RootHandler(context, elementHandler)); | |||||
Task[] tasks = dummyTarget.getTasks(); | |||||
if (tasks.length != 1) { | |||||
throw new BuildException("No tasks defined"); | |||||
} | |||||
return (UnknownElement) tasks[0]; | |||||
} | |||||
/** | /** | ||||
* Parse a source xml input. | * Parse a source xml input. | ||||
* | * | ||||
@@ -127,11 +155,11 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
// we are in an imported file. | // we are in an imported file. | ||||
context.setIgnoreProjectTag(true); | context.setIgnoreProjectTag(true); | ||||
context.getCurrentTarget().startImportedTasks(); | context.getCurrentTarget().startImportedTasks(); | ||||
parse(project, source, new RootHandler(context)); | |||||
parse(project, source, new RootHandler(context, mainHandler)); | |||||
context.getCurrentTarget().endImportedTasks(); | context.getCurrentTarget().endImportedTasks(); | ||||
} else { | } else { | ||||
// top level file | // top level file | ||||
parse(project, source, new RootHandler(context)); | |||||
parse(project, source, new RootHandler(context, mainHandler)); | |||||
// Execute the top-level target | // Execute the top-level target | ||||
context.getImplicitTarget().execute(); | context.getImplicitTarget().execute(); | ||||
} | } | ||||
@@ -152,22 +180,33 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
AntXMLContext context = handler.context; | AntXMLContext context = handler.context; | ||||
File buildFile = null; | File buildFile = null; | ||||
URL url = null; | |||||
String buildFileName = null; | |||||
if (source instanceof File) { | if (source instanceof File) { | ||||
buildFile = (File) source; | buildFile = (File) source; | ||||
// } else if (source instanceof InputStream) { | |||||
// } else if (source instanceof URL) { | |||||
// } else if (source instanceof InputSource) { | |||||
buildFile = new File(buildFile.getAbsolutePath()); | |||||
context.setBuildFile(buildFile); | |||||
buildFileName = buildFile.toString(); | |||||
// } else if (source instanceof InputStream ) { | |||||
} else if (source instanceof URL) { | |||||
if (handler.getCurrentAntHandler() != elementHandler) { | |||||
throw new BuildException( | |||||
"Source " + source.getClass().getName() | |||||
+ " not supported by this plugin for " | |||||
+ " non task xml"); | |||||
} | |||||
url = (URL) source; | |||||
buildFileName = url.toString(); | |||||
// } else if (source instanceof InputSource ) { | |||||
} else { | } else { | ||||
throw new BuildException("Source " + source.getClass().getName() | throw new BuildException("Source " + source.getClass().getName() | ||||
+ " not supported by this plugin"); | |||||
+ " not supported by this plugin"); | |||||
} | } | ||||
FileInputStream inputStream = null; | |||||
InputStream inputStream = null; | |||||
InputSource inputSource = null; | InputSource inputSource = null; | ||||
buildFile = new File(buildFile.getAbsolutePath()); | |||||
context.setBuildFile(buildFile); | |||||
try { | try { | ||||
/** | /** | ||||
@@ -175,13 +214,21 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
*/ | */ | ||||
XMLReader parser = JAXPUtils.getNamespaceXMLReader(); | XMLReader parser = JAXPUtils.getNamespaceXMLReader(); | ||||
String uri = fu.toURI(buildFile.getAbsolutePath()); | |||||
String uri = null; | |||||
if (buildFile != null) { | |||||
uri = fu.toURI(buildFile.getAbsolutePath()); | |||||
inputStream = new FileInputStream(buildFile); | |||||
} else { | |||||
inputStream = url.openStream(); | |||||
uri = url.toString(); // ?? OK ?? | |||||
} | |||||
inputStream = new FileInputStream(buildFile); | |||||
inputSource = new InputSource(inputStream); | inputSource = new InputSource(inputStream); | ||||
inputSource.setSystemId(uri); | |||||
project.log("parsing buildfile " + buildFile | |||||
+ " with URI = " + uri, Project.MSG_VERBOSE); | |||||
if (uri != null) { | |||||
inputSource.setSystemId(uri); | |||||
} | |||||
project.log("parsing buildfile " + buildFileName | |||||
+ "with URI = " + uri, Project.MSG_VERBOSE); | |||||
DefaultHandler hb = handler; | DefaultHandler hb = handler; | ||||
@@ -357,13 +404,22 @@ public class ProjectHelper2 extends ProjectHelper { | |||||
* Creates a new RootHandler instance. | * Creates a new RootHandler instance. | ||||
* | * | ||||
* @param context The context for the handler. | * @param context The context for the handler. | ||||
* @param rootHandler The handler for the root element. | |||||
*/ | */ | ||||
public RootHandler(AntXMLContext context) { | |||||
currentHandler = ProjectHelper2.mainHandler; | |||||
public RootHandler(AntXMLContext context, AntHandler rootHandler) { | |||||
currentHandler = rootHandler; | |||||
antHandlers.push(currentHandler); | antHandlers.push(currentHandler); | ||||
this.context = context; | this.context = context; | ||||
} | } | ||||
/** | |||||
* Returns the current ant handler object. | |||||
* @return the current ant handler. | |||||
*/ | |||||
public AntHandler getCurrentAntHandler() { | |||||
return currentHandler; | |||||
} | |||||
/** | /** | ||||
* Resolves file: URIs relative to the build file. | * Resolves file: URIs relative to the build file. | ||||
* | * | ||||
@@ -0,0 +1,190 @@ | |||||
/* | |||||
* 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; | |||||
import java.io.IOException; | |||||
import java.net.URL; | |||||
import java.util.ArrayList; | |||||
import java.util.Iterator; | |||||
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.Project; | |||||
import org.apache.tools.ant.Task; | |||||
import org.apache.tools.ant.Target; | |||||
import org.apache.tools.ant.helper.ProjectHelper2; | |||||
import org.apache.tools.ant.UnknownElement; | |||||
/** | |||||
* Antlib task. | |||||
* | |||||
* @author Peter Reilly | |||||
* | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public class Antlib extends Task implements TaskContainer { | |||||
// | |||||
// Static | |||||
// | |||||
/** The name of this task */ | |||||
public static final String TAG = "antlib"; | |||||
/** | |||||
* Static method to read an ant lib definition from | |||||
* a url. | |||||
* | |||||
* @param project the current project | |||||
* @param antlibUrl the url to read the definitions from | |||||
* @return the ant lib task | |||||
*/ | |||||
public static Antlib createAntlib(Project project, URL antlibUrl) { | |||||
// Check if we can contact the URL | |||||
try { | |||||
antlibUrl.openConnection().connect(); | |||||
} catch (IOException ex) { | |||||
throw new BuildException( | |||||
"Unable to find " + antlibUrl, ex); | |||||
} | |||||
// Should be safe to parse | |||||
try { | |||||
ProjectHelper2 parser = new ProjectHelper2(); | |||||
UnknownElement ue = | |||||
parser.parseUnknownElement(project, antlibUrl); | |||||
// Check name is "antlib" | |||||
if (!(ue.getTag().equals(TAG))) { | |||||
throw new BuildException( | |||||
"Unexpected tag " + ue.getTag() + " expecting " + | |||||
TAG, ue.getLocation()); | |||||
} | |||||
Antlib antlib = new Antlib(); | |||||
antlib.setProject(project); | |||||
antlib.setLocation(ue.getLocation()); | |||||
antlib.init(); | |||||
ue.configure(antlib); | |||||
return antlib; | |||||
} catch (BuildException ex) { | |||||
Location location = ex.getLocation(); | |||||
if (location == null) { | |||||
throw ex; | |||||
} | |||||
throw new BuildException( | |||||
"Error in " | |||||
+ System.getProperty("line.separator") | |||||
+ location.toString() | |||||
+ " " + ex.getMessage()); | |||||
} | |||||
} | |||||
// | |||||
// Instance | |||||
// | |||||
private ClassLoader classLoader; | |||||
private String prefix; | |||||
private List tasks = new ArrayList(); | |||||
/** | |||||
* Set the class loader for this antlib. | |||||
* This class loader is used for any tasks that | |||||
* derive from Definer. | |||||
* | |||||
* @param classLoader the class loader | |||||
*/ | |||||
protected void setClassLoader(ClassLoader classLoader) { | |||||
this.classLoader = classLoader; | |||||
} | |||||
private ClassLoader getClassLoader() { | |||||
if (classLoader == null) { | |||||
classLoader = Antlib.class.getClassLoader(); | |||||
} | |||||
return classLoader; | |||||
} | |||||
/** | |||||
* add a task to the list of tasks | |||||
* | |||||
* @param nestedTask Nested task to execute in antlibe | |||||
*/ | |||||
public void addTask(Task nestedTask) { | |||||
tasks.add(nestedTask); | |||||
} | |||||
/** | |||||
* Execute the nested tasks, setting the classloader for | |||||
* any tasks that derive from Definer. | |||||
*/ | |||||
public void execute() { | |||||
for (Iterator i = tasks.iterator(); i.hasNext();) { | |||||
UnknownElement ue = (UnknownElement) i.next(); | |||||
ue.maybeConfigure(); | |||||
Task t = ue.getTask(); | |||||
if (t == null) { | |||||
continue; | |||||
} | |||||
if (t instanceof Definer) { | |||||
Definer d = (Definer) t; | |||||
d.setInternalClassLoader(getClassLoader()); | |||||
} | |||||
t.init(); | |||||
t.execute(); | |||||
} | |||||
} | |||||
} |
@@ -59,12 +59,14 @@ import java.io.IOException; | |||||
import java.io.InputStream; | import java.io.InputStream; | ||||
import java.net.URL; | import java.net.URL; | ||||
import java.util.Enumeration; | import java.util.Enumeration; | ||||
import java.util.Locale; | |||||
import java.util.Properties; | import java.util.Properties; | ||||
import org.apache.tools.ant.AntTypeDefinition; | import org.apache.tools.ant.AntTypeDefinition; | ||||
import org.apache.tools.ant.AntClassLoader; | import org.apache.tools.ant.AntClassLoader; | ||||
import org.apache.tools.ant.ComponentHelper; | import org.apache.tools.ant.ComponentHelper; | ||||
import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
import org.apache.tools.ant.Location; | |||||
import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
import org.apache.tools.ant.Task; | import org.apache.tools.ant.Task; | ||||
import org.apache.tools.ant.types.Path; | import org.apache.tools.ant.types.Path; | ||||
@@ -88,6 +90,7 @@ public abstract class Definer extends Task { | |||||
private String resource; | private String resource; | ||||
private ClasspathUtils.Delegate cpDelegate; | private ClasspathUtils.Delegate cpDelegate; | ||||
private int format = Format.PROPERTIES; | |||||
private boolean definerSet = false; | private boolean definerSet = false; | ||||
private ClassLoader internalClassLoader; | private ClassLoader internalClassLoader; | ||||
private int onError = OnError.FAIL; | private int onError = OnError.FAIL; | ||||
@@ -129,6 +132,24 @@ public abstract class Definer extends Task { | |||||
} | } | ||||
} | } | ||||
/** | |||||
* Enumerated type for format attribute | |||||
* | |||||
* @see EnumeratedAttribute | |||||
*/ | |||||
public static class Format extends EnumeratedAttribute { | |||||
/** Enumerated values */ | |||||
public static final int PROPERTIES = 0, XML = 1; | |||||
/** | |||||
* get the values | |||||
* @return an array of the allowed values for this attribute. | |||||
*/ | |||||
public String[] getValues() { | |||||
return new String[] {"properties", "xml"}; | |||||
} | |||||
} | |||||
/** | /** | ||||
* What to do if there is an error in loading the class. | * What to do if there is an error in loading the class. | ||||
* <dl> | * <dl> | ||||
@@ -143,6 +164,14 @@ public abstract class Definer extends Task { | |||||
this.onError = onError.getIndex(); | this.onError = onError.getIndex(); | ||||
} | } | ||||
/** | |||||
* Sets the format of the file or resource | |||||
* @param format the enumerated value - xml or properties | |||||
*/ | |||||
public void setFormat(Format format) { | |||||
this.format = format.getIndex(); | |||||
} | |||||
/** | /** | ||||
* @param reverseLoader if true a delegated loader will take precedence over | * @param reverseLoader if true a delegated loader will take precedence over | ||||
* the parent | * the parent | ||||
@@ -289,7 +318,15 @@ public abstract class Definer extends Task { | |||||
return; | return; | ||||
} | } | ||||
loadProperties(al, url); | |||||
if (url.toString().toLowerCase(Locale.US).endsWith(".xml")) { | |||||
format = Format.XML; | |||||
} | |||||
if (format == Format.PROPERTIES) { | |||||
loadProperties(al, url); | |||||
} else { | |||||
loadAntlib(al, url); | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -359,6 +396,30 @@ public abstract class Definer extends Task { | |||||
} | } | ||||
} | } | ||||
/** | |||||
* Load an antlib from a url. | |||||
* | |||||
* @param classLoader the classloader to use. | |||||
* @param url the url to load the definitions from. | |||||
*/ | |||||
private void loadAntlib(ClassLoader classLoader, URL url) { | |||||
try { | |||||
Antlib antlib = Antlib.createAntlib(getProject(), url); | |||||
antlib.setClassLoader(classLoader); | |||||
antlib.perform(); | |||||
} catch (BuildException ex) { | |||||
Location location = ex.getLocation(); | |||||
if (location == null) { | |||||
throw ex; | |||||
} | |||||
throw new BuildException( | |||||
"Error in " | |||||
+ System.getProperty("line.separator") | |||||
+ getLocation().toString() | |||||
+ " " + ex.getMessage()); | |||||
} | |||||
} | |||||
/** | /** | ||||
* create a classloader for this definition | * create a classloader for this definition | ||||
* @return the classloader from the cpDelegate | * @return the classloader from the cpDelegate | ||||
@@ -543,7 +604,7 @@ public abstract class Definer extends Task { | |||||
} catch (NoClassDefFoundError ncdfe) { | } catch (NoClassDefFoundError ncdfe) { | ||||
String msg = getTaskName() + " A class needed by class " | String msg = getTaskName() + " A class needed by class " | ||||
+ classname + " cannot be found: " + ncdfe.getMessage(); | + classname + " cannot be found: " + ncdfe.getMessage(); | ||||
throw new BuildException(msg, ncdfe, location); | |||||
throw new BuildException(msg, ncdfe, getLocation()); | |||||
} | } | ||||
} catch (BuildException ex) { | } catch (BuildException ex) { | ||||
switch (onError) { | switch (onError) { | ||||
@@ -0,0 +1,84 @@ | |||||
/* | |||||
* 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; | |||||
import org.apache.tools.ant.BuildFileTest; | |||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.Task; | |||||
/** | |||||
* @author Peter Reilly | |||||
*/ | |||||
public class AntlibTest extends BuildFileTest { | |||||
public AntlibTest(String name) { | |||||
super(name); | |||||
} | |||||
public void setUp() { | |||||
configureProject("src/etc/testcases/taskdefs/antlib.xml"); | |||||
} | |||||
public void testAntlibFile() { | |||||
expectLog("antlib.file", "MyTask called"); | |||||
} | |||||
public static class MyTask extends Task { | |||||
public void execute() { | |||||
log("MyTask called"); | |||||
} | |||||
} | |||||
} | |||||