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]