peterreilly 2003/07/24 06:48:46
Modified: docs/manual/CoreTasks typedef.html
src/main/org/apache/tools/ant/helper ProjectHelper2.java
src/main/org/apache/tools/ant/taskdefs Definer.java
Added: src/etc/testcases/taskdefs antlib.xml test.antlib.xml
src/main/org/apache/tools/ant/taskdefs Antlib.java
src/testcases/org/apache/tools/ant/taskdefs AntlibTest.java
Log:
Add antlib xml functionality
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
Revision Changes Path
1.8 +94 -25 ant/docs/manual/CoreTasks/typedef.html
Index: typedef.html
===================================================================
RCS file: /home/cvs/ant/docs/manual/CoreTasks/typedef.html,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- typedef.html 26 Jun 2003 08:54:27 -0000 1.7
+++ typedef.html 24 Jul 2003 13:48:45 -0000 1.8
@@ -9,23 +9,43 @@
<h2><a name="typedef">Typedef</a></h2>
<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>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -56,6 +76,19 @@
<td valign="top" align="center">No</td>
</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>
<td valign="top">classpath</td> <td valign="top">the classpath to
use when looking up <code>classname</code>.</td> <td
align="center" valign="top">No</td>
@@ -102,15 +135,51 @@
<td valign="top" align="center">No</td>
</tr>
</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>
-<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>
<p align="center">Copyright © 2001-2003 Apache Software
1.1 ant/src/etc/testcases/taskdefs/antlib.xml
Index: antlib.xml
===================================================================
<?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>
1.1 ant/src/etc/testcases/taskdefs/test.antlib.xml
Index: test.antlib.xml
===================================================================
<?xml version="1.0"?>
<antlib>
<typedef
name="mytask" onerror="ignore"
classname="org.apache.tools.ant.taskdefs.AntlibTest$MyTask"/>
</antlib>
1.27 +72 -16
ant/src/main/org/apache/tools/ant/helper/ProjectHelper2.java
Index: ProjectHelper2.java
===================================================================
RCS file:
/home/cvs/ant/src/main/org/apache/tools/ant/helper/ProjectHelper2.java,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- ProjectHelper2.java 23 Jul 2003 10:24:39 -0000 1.26
+++ ProjectHelper2.java 24 Jul 2003 13:48:45 -0000 1.27
@@ -57,8 +57,10 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.InputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.net.URL;
import java.util.Hashtable;
import java.util.Stack;
@@ -75,6 +77,7 @@
import org.apache.tools.ant.ProjectHelper;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Target;
+import org.apache.tools.ant.Task;
import org.apache.tools.ant.RuntimeConfigurable;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Location;
@@ -103,6 +106,31 @@
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.
*
* @param project the current project
@@ -127,11 +155,11 @@
// we are in an imported file.
context.setIgnoreProjectTag(true);
context.getCurrentTarget().startImportedTasks();
- parse(project, source, new RootHandler(context));
+ parse(project, source, new RootHandler(context, mainHandler));
context.getCurrentTarget().endImportedTasks();
} else {
// top level file
- parse(project, source, new RootHandler(context));
+ parse(project, source, new RootHandler(context, mainHandler));
// Execute the top-level target
context.getImplicitTarget().execute();
}
@@ -152,22 +180,33 @@
AntXMLContext context = handler.context;
File buildFile = null;
+ URL url = null;
+ String buildFileName = null;
if (source instanceof File) {
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 {
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;
- buildFile = new File(buildFile.getAbsolutePath());
- context.setBuildFile(buildFile);
try {
/**
@@ -175,13 +214,21 @@
*/
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.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;
@@ -357,11 +404,20 @@
* Creates a new RootHandler instance.
*
* @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);
this.context = context;
+ }
+
+ /**
+ * Returns the current ant handler object.
+ * @return the current ant handler.
+ */
+ public AntHandler getCurrentAntHandler() {
+ return currentHandler;
}
/**
1.39 +63 -2 ant/src/main/org/apache/tools/ant/taskdefs/Definer.java
Index: Definer.java
===================================================================
RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Definer.java,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -r1.38 -r1.39
--- Definer.java 22 Jul 2003 16:40:32 -0000 1.38
+++ Definer.java 24 Jul 2003 13:48:45 -0000 1.39
@@ -59,12 +59,14 @@
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
+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;
@@ -88,6 +90,7 @@
private String resource;
private ClasspathUtils.Delegate cpDelegate;
+ private int format = Format.PROPERTIES;
private boolean definerSet = false;
private ClassLoader internalClassLoader;
private int onError = OnError.FAIL;
@@ -130,6 +133,24 @@
}
/**
+ * 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.
* <dl>
* <li>error - throw build exception</li>
@@ -144,6 +165,14 @@
}
/**
+ * 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
* the parent
* @deprecated stop using this attribute
@@ -289,7 +318,15 @@
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);
+ }
}
}
@@ -360,6 +397,30 @@
}
/**
+ * 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
* @return the classloader from the cpDelegate
*/
@@ -543,7 +604,7 @@
} catch (NoClassDefFoundError ncdfe) {
String msg = getTaskName() + " A class needed by class "
+ classname + " cannot be found: " + ncdfe.getMessage();
- throw new BuildException(msg, ncdfe, location);
+ throw new BuildException(msg, ncdfe, getLocation());
}
} catch (BuildException ex) {
switch (onError) {
1.3 +146 -667 ant/src/main/org/apache/tools/ant/taskdefs/Antlib.java
1.1
ant/src/testcases/org/apache/tools/ant/taskdefs/AntlibTest.java
Index: AntlibTest.java
===================================================================
/*
* 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 [EMAIL PROTECTED]
*
* 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");
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]