git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269901 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -1,94 +0,0 @@ | |||||
| <html> | |||||
| <head> | |||||
| <meta http-equiv="Content-Language" content="en-us"> | |||||
| <title>Ant User Manual</title> | |||||
| </head> | |||||
| <body> | |||||
| <h2><a name="antjar">AntJar</a></h2> | |||||
| <h3>Description</h3> | |||||
| <p>An extension of the <a href="jar.html">Jar</a> task with special | |||||
| treatment for the library descriptor file that should end up in the | |||||
| <code>META-INF</code> directory of the Ant Archive.</p> | |||||
| <p>This task validates the provided library descriptor making certain | |||||
| it specifies the following SYSTEM ID: | |||||
| <b>"http://jakarta.apache.org/ant/AntlibV1_0.dtd"</b>. | |||||
| This DTD is defined as follows:</p> | |||||
| <pre> | |||||
| <?xml version='1.0' encoding="UTF8" ?> | |||||
| <!-- | |||||
| This file defines the XML format for ANT library descriptors. | |||||
| Descriptors must especify a DOCTYPE of | |||||
| "http://jakarta.apache.org/ant/Antlib-V1_0.dtd" | |||||
| as the SystemId for the document. | |||||
| --> | |||||
| <!-- Root element for the Antlib descriptor. --> | |||||
| <!ELEMENT antlib (task | type)* > | |||||
| <!ATTLIST antlib | |||||
| version CDATA #IMPLIED | |||||
| > | |||||
| <!-- Declaration of tasks contained in the library. --> | |||||
| <!ELEMENT task EMPTY> | |||||
| <!ATTLIST task | |||||
| name CDATA #REQUIRED | |||||
| class CDATA #REQUIRED | |||||
| > | |||||
| <!-- Declaration of datatypes contained in the library --> | |||||
| <!ELEMENT type EMPTY> | |||||
| <!ATTLIST type | |||||
| name CDATA #REQUIRED | |||||
| class CDATA #REQUIRED | |||||
| > | |||||
| </pre> | |||||
| <h3>Parameters</h3> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">antxml</td> | |||||
| <td valign="top">The library descriptor to use (META-INF/antlib.xml).</td> | |||||
| <td valign="top" align="center">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top"><b>Others...</b></td> | |||||
| <td valign="top">All attributes inherited form the | |||||
| <a href="jar.html">Jar task</a>.</td> | |||||
| <td valign="top" align="center"> </td> | |||||
| </tr> | |||||
| </table> | |||||
| <h3>Nested elements</h3> | |||||
| See the nested elements of the <a href="jar.html">Jar task</a>. | |||||
| <h3>Examples</h3> | |||||
| <pre> <antjar file="${dist}/lib/app.jar" | |||||
| antxml="${src}/applib.xml" basedir="${build}/classes"/></pre> | |||||
| <p>jars all files in the <code>${build}/classes</code> directory into a file | |||||
| called <code>app.jar</code> in the <code>${dist}/lib</code> directory and | |||||
| sets the content of <code>${src}/applib.xml</code> as the library descriptor | |||||
| in <code>META-INF/antlib.xml</code>.</p> | |||||
| <p>Here is a sample <code>META-INF/antlib.xml</code>:</p> | |||||
| <pre> | |||||
| <?xml version="1.0" encoding="UTF8" ?> | |||||
| <!DOCTYPE antlib SYSTEM "http://jakarta.apache.org/ant/Antlib-V1_0.dtd" > | |||||
| <antlib version="1.0" > | |||||
| <task name="case" class="org.apache.ant.contrib.Case" /> | |||||
| </antlib> | |||||
| </pre> | |||||
| <hr> | |||||
| <p align="center">Copyright © 2000,2001 Apache Software Foundation. All rights | |||||
| Reserved.</p> | |||||
| </body> | |||||
| </html> | |||||
| @@ -1,117 +0,0 @@ | |||||
| <html> | |||||
| <head> | |||||
| <meta http-equiv="Content-Language" content="en-us"> | |||||
| <title>Ant User Manual</title> | |||||
| </head> | |||||
| <body> | |||||
| <h2><a name="antlib">AntLib</a></h2> | |||||
| <h3>Description</h3> | |||||
| <p>Defines and loads any tasks and datatypes contained in an ANT library.</p> | |||||
| <p>It also allows the aliasing of the names being defined in order to avoid | |||||
| collisions and provides means to override definitions with the ones defined | |||||
| in the library.</p> | |||||
| Ant libraries can be loaded in the current classloader, which is more efficient, | |||||
| but requires the tasks to be in the path already (such as in the ant lib | |||||
| directory) - set <tt>useCurrentClassloader</tt> to true to enable this. | |||||
| It is also possible to add more libraries to the path, such as any | |||||
| libraries the task is dependent on. | |||||
| <h3>Parameters</h3> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">file</td> | |||||
| <td valign="top">The jar-file of the library.</td> | |||||
| <td align="center" valign="middle" rowspan="2">at least one of the two</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">library</td> | |||||
| <td valign="top">The name of a library relative to ${ant.home}/lib.</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">override</td> | |||||
| <td valign="top">Replace any existing definition with the same name. ("true"/"false"). When "false" already defined tasks | |||||
| and datatytes take precedence over those in the library. | |||||
| Default is "false" when omitted.</td> | |||||
| <td align="center" valign="top">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">useCurrentClassloader</td> | |||||
| <td valign="top">Set to "true" to avoid using a separate | |||||
| ClassLoader for the tasks in the library. Using this option requires | |||||
| that the library jar is already accessible by the ClassLoader of | |||||
| the project. Default is "false". | |||||
| </td> | |||||
| <td align="center" valign="top">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">classpath</td> | |||||
| <td valign="top">A | |||||
| <a href="../using.html#path">classpath</a> | |||||
| for extra libraries to pull in. | |||||
| </td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| </table> | |||||
| <h3><a name="nested">Parameters specified as nested elements</a></h3> | |||||
| <h4>alias</h4> | |||||
| <p>Specifies the usage of a different name from that defined in the library | |||||
| descriptor.</p> | |||||
| <table border="1" cellpadding="2" cellspacing="0"> | |||||
| <tr> | |||||
| <td valign="top"><b>Attribute</b></td> | |||||
| <td valign="top"><b>Description</b></td> | |||||
| <td align="center" valign="top"><b>Required</b></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">name</td> | |||||
| <td valign="top">The name used in the library descriptor.</td> | |||||
| <td valign="top" align="center">Yes</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">as</td> | |||||
| <td valign="top">The alias to use in the project.</td> | |||||
| <td valign="top" align="center">Yes</td> | |||||
| </tr> | |||||
| </table> | |||||
| <p>Specifies the usage of a different name from that defined in the library | |||||
| descriptor. This is used to deal with name clashes </p> | |||||
| <h4>classpath</h4> | |||||
| <h4>classpath</h4> | |||||
| A classpath of extra libraries to import to support this task. | |||||
| <h4>classpathref</h4> | |||||
| A reference to an existing classpath. | |||||
| <h3>Examples</h3> | |||||
| <pre> <antlib file="${build}/lib/mylib.jar"/></pre> | |||||
| <p>loads the definitions from the library located at | |||||
| <code>${build}/lib/ant.jar</code>.</p> | |||||
| <pre> <antlib library="optional.jar"/></pre> | |||||
| <p>loads the definitions from the library <code>optional.jar</code> | |||||
| located at <code>${ant.home}/lib</code>.</p> | |||||
| <pre> <antlib file="${build}/lib/mylib.jar"> | |||||
| <alias name="echo" as="myecho"/> | |||||
| </antlib> | |||||
| </pre> | |||||
| <p>loads the definitions from the library located at | |||||
| <code>${build}/lib/ant.jar</code> but uses the name | |||||
| "<code>myecho</code>" for the "<code>echo</code>" task | |||||
| declared in the library.</p> | |||||
| <hr><p align="center">Copyright © 2000,2001 Apache Software Foundation. All rights | |||||
| Reserved.</p> | |||||
| </body> | |||||
| </html> | |||||
| @@ -25,8 +25,6 @@ | |||||
| <a href="CoreTasks/overview.html">Overview</a><br><br> | <a href="CoreTasks/overview.html">Overview</a><br><br> | ||||
| <a href="CoreTasks/ant.html">Ant</a><br> | <a href="CoreTasks/ant.html">Ant</a><br> | ||||
| <a href="CoreTasks/antcall.html">AntCall</a><br> | <a href="CoreTasks/antcall.html">AntCall</a><br> | ||||
| <a href="CoreTasks/antlib.html">AntLib</a><br> | |||||
| <a href="CoreTasks/antjar.html">AntJar</a><br> | |||||
| <a href="CoreTasks/antstructure.html">AntStructure</a><br> | <a href="CoreTasks/antstructure.html">AntStructure</a><br> | ||||
| <a href="CoreTasks/apply.html">Apply/<i>ExecOn</i></a><br> | <a href="CoreTasks/apply.html">Apply/<i>ExecOn</i></a><br> | ||||
| <a href="CoreTasks/available.html">Available</a><br> | <a href="CoreTasks/available.html">Available</a><br> | ||||
| @@ -1,316 +0,0 @@ | |||||
| /* | |||||
| * The Apache Software License, Version 1.1 | |||||
| * | |||||
| * Copyright (c) 2000 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 "The Jakarta Project", "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.xml.sax.*; | |||||
| import javax.xml.parsers.*; | |||||
| import org.apache.tools.ant.*; | |||||
| import org.apache.tools.ant.types.ZipFileSet; | |||||
| import org.apache.tools.zip.*; | |||||
| import java.io.*; | |||||
| import java.util.*; | |||||
| /** | |||||
| * Creates a ANTLIB archive. Code is similar to the War class, but with | |||||
| * bonus dtd validation. | |||||
| * | |||||
| * @author doc and layout changes by steve loughran, steve_l@iseran.com | |||||
| * @author <a href="mailto:j_a_fernandez@yahoo.com">Jose Alberto Fernandez</a> | |||||
| * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||||
| * | |||||
| * @since ant1.5 | |||||
| */ | |||||
| public class Antjar extends Jar { | |||||
| /** | |||||
| * location of the xml descriptor (antxml attribute) | |||||
| */ | |||||
| private File libraryDescriptor; | |||||
| /** | |||||
| * status flag | |||||
| */ | |||||
| private boolean descriptorAdded; | |||||
| /** | |||||
| * Constructor for the Antjar object | |||||
| */ | |||||
| public Antjar() { | |||||
| super(); | |||||
| archiveType = "jar"; | |||||
| emptyBehavior = "create"; | |||||
| } | |||||
| /** | |||||
| * Sets the Antxml attribute of the Antjar object | |||||
| * | |||||
| * @param descriptor The new Antxml value | |||||
| */ | |||||
| public void setAntxml(File descriptor) { | |||||
| libraryDescriptor = descriptor; | |||||
| if (!libraryDescriptor.exists()) { | |||||
| throw new BuildException("Deployment descriptor: " + libraryDescriptor + " does not exist."); | |||||
| } | |||||
| //check | |||||
| validateDescriptor(); | |||||
| // Create a ZipFileSet for this file, and pass it up. | |||||
| ZipFileSet fs = new ZipFileSet(); | |||||
| fs.setDir(new File(libraryDescriptor.getParent())); | |||||
| fs.setIncludes(libraryDescriptor.getName()); | |||||
| fs.setFullpath(Antlib.ANT_DESCRIPTOR); | |||||
| super.addFileset(fs); | |||||
| } | |||||
| /** | |||||
| * override of superclass method; add check for | |||||
| * valid descriptor | |||||
| * @param zOut stream to init | |||||
| * @exception IOException io trouble | |||||
| * @exception BuildException other trouble | |||||
| */ | |||||
| protected void initZipOutputStream(ZipOutputStream zOut) | |||||
| throws IOException, BuildException { | |||||
| // If no antxml file is specified, it's an error. | |||||
| if (libraryDescriptor == null) { | |||||
| throw new BuildException("webxml attribute is required", location); | |||||
| } | |||||
| super.initZipOutputStream(zOut); | |||||
| } | |||||
| /** | |||||
| * override of parent method; warn if a second descriptor is added | |||||
| * | |||||
| * @param file file to add | |||||
| * @param zOut stream to add to | |||||
| * @param vPath the path to add it to in the zipfile | |||||
| * @exception IOException io trouble | |||||
| */ | |||||
| protected void zipFile(File file, ZipOutputStream zOut, String vPath) | |||||
| throws IOException { | |||||
| // If the file being added is META-INF/antlib.xml, we warn if it's not the | |||||
| // one specified in the "antxml" attribute - or if it's being added twice, | |||||
| // meaning the same file is specified by the "antxml" attribute and in | |||||
| // a <fileset> element. | |||||
| if (vPath.equalsIgnoreCase(Antlib.ANT_DESCRIPTOR)) { | |||||
| if (libraryDescriptor == null || !libraryDescriptor.equals(file) || descriptorAdded) { | |||||
| log("Warning: selected " + archiveType + " files include a " + | |||||
| Antlib.ANT_DESCRIPTOR + " which will be ignored " + | |||||
| "(please use antxml attribute to " + archiveType + " task)", Project.MSG_WARN); | |||||
| } | |||||
| else { | |||||
| super.zipFile(file, zOut, vPath); | |||||
| descriptorAdded = true; | |||||
| } | |||||
| } | |||||
| else { | |||||
| super.zipFile(file, zOut, vPath); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Make sure we don't think we already have a descriptor next time this | |||||
| * task gets executed. | |||||
| */ | |||||
| protected void cleanUp() { | |||||
| descriptorAdded = false; | |||||
| super.cleanUp(); | |||||
| } | |||||
| /** | |||||
| * validate the descriptor against the DTD | |||||
| * | |||||
| * @exception BuildException failure to validate | |||||
| */ | |||||
| protected void validateDescriptor() | |||||
| throws BuildException { | |||||
| SAXParserFactory saxFactory = SAXParserFactory.newInstance(); | |||||
| saxFactory.setValidating(true); | |||||
| InputStream is = null; | |||||
| try { | |||||
| SAXParser saxParser = saxFactory.newSAXParser(); | |||||
| Parser parser = saxParser.getParser(); | |||||
| is = new FileInputStream(libraryDescriptor); | |||||
| InputSource inputSource = new InputSource(is); | |||||
| inputSource.setSystemId("file:" + libraryDescriptor); | |||||
| project.log("Validating library descriptor: " + libraryDescriptor, | |||||
| Project.MSG_VERBOSE); | |||||
| saxParser.parse(inputSource, new AntLibraryValidator()); | |||||
| } | |||||
| catch (ParserConfigurationException exc) { | |||||
| throw new BuildException("Parser has not been configured correctly", exc); | |||||
| } | |||||
| catch (SAXParseException exc) { | |||||
| Location location = | |||||
| new Location(libraryDescriptor.toString(), | |||||
| exc.getLineNumber(), exc.getColumnNumber()); | |||||
| Throwable t = exc.getException(); | |||||
| if (t instanceof BuildException) { | |||||
| BuildException be = (BuildException) t; | |||||
| if (be.getLocation() == Location.UNKNOWN_LOCATION) { | |||||
| be.setLocation(location); | |||||
| } | |||||
| throw be; | |||||
| } | |||||
| throw new BuildException(exc.getMessage(), t, location); | |||||
| } | |||||
| catch (SAXException exc) { | |||||
| Throwable t = exc.getException(); | |||||
| if (t instanceof BuildException) { | |||||
| throw (BuildException) t; | |||||
| } | |||||
| throw new BuildException(exc.getMessage(), t); | |||||
| } | |||||
| catch (IOException exc) { | |||||
| throw new BuildException("Error reading library descriptor", exc); | |||||
| } | |||||
| finally { | |||||
| if (is != null) { | |||||
| try { | |||||
| is.close(); | |||||
| } | |||||
| catch (IOException ioe) { | |||||
| // ignore this | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Parses the document describing the content of the library. | |||||
| */ | |||||
| private class AntLibraryValidator extends HandlerBase { | |||||
| /** | |||||
| * flag to track whether the DOCTYPE was hit in the prolog | |||||
| */ | |||||
| private boolean doctypePresent = false; | |||||
| /** | |||||
| * doc locator | |||||
| */ | |||||
| private Locator locator = null; | |||||
| /** | |||||
| * Sets the DocumentLocator attribute of the AntLibraryValidator | |||||
| * object | |||||
| * | |||||
| * @param locator The new DocumentLocator value | |||||
| */ | |||||
| public void setDocumentLocator(Locator locator) { | |||||
| this.locator = locator; | |||||
| } | |||||
| /** | |||||
| * SAX callback handler | |||||
| * | |||||
| * @param tag XML tag | |||||
| * @param attrs attributes | |||||
| * @exception SAXParseException parse trouble | |||||
| */ | |||||
| public void startElement(String tag, AttributeList attrs) | |||||
| throws SAXParseException { | |||||
| // By the time an element is found | |||||
| // the DOCTYPE should have been found. | |||||
| if (!doctypePresent) { | |||||
| String msg = "Missing DOCTYPE declaration or wrong SYSTEM ID"; | |||||
| throw new SAXParseException(msg, locator); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Recognizes the DTD declaration for antlib and returns the corresponding | |||||
| * DTD definition from a resource. <P> | |||||
| * | |||||
| * To allow for future versions of the DTD format it will search | |||||
| * for any DTDs of the form "Antlib-V.*\.dtd". | |||||
| * | |||||
| * @param publicId public ID (ignored) | |||||
| * @param systemId system ID (matched against) | |||||
| * @return local DTD instance | |||||
| */ | |||||
| public InputSource resolveEntity(String publicId, | |||||
| String systemId) { | |||||
| log("Looking for entity with PublicID=" + publicId + | |||||
| " and SystemId=" + systemId, Project.MSG_VERBOSE); | |||||
| if (Antlib.matchDtdId(systemId)) { | |||||
| String resId = | |||||
| systemId.substring(Antlib.ANTLIB_DTD_URL.length()); | |||||
| InputSource is = | |||||
| new InputSource(this.getClass().getResourceAsStream(resId)); | |||||
| is.setSystemId(systemId); | |||||
| doctypePresent = true; | |||||
| return is; | |||||
| } | |||||
| return null; | |||||
| } | |||||
| //end inner class AntLibraryValidator | |||||
| } | |||||
| } | |||||
| @@ -1,27 +0,0 @@ | |||||
| <?xml version='1.0' encoding="UTF8" ?> | |||||
| <!-- | |||||
| This file defines the XML format for ANT library descriptors. | |||||
| Descriptors must especify a DOCTYPE using "Antlib-V1_0.dtd" | |||||
| as the SystemId for the document. | |||||
| --> | |||||
| <!-- Root element for the Antlib descriptor. --> | |||||
| <!ELEMENT antlib (task | type)* > | |||||
| <!ATTLIST antlib | |||||
| version CDATA #IMPLIED | |||||
| > | |||||
| <!-- Declaration of tasks contained in the library. --> | |||||
| <!ELEMENT task EMPTY> | |||||
| <!ATTLIST task | |||||
| name CDATA #REQUIRED | |||||
| class CDATA #REQUIRED | |||||
| > | |||||
| <!-- Declaration of datatypes contained in the library --> | |||||
| <!ELEMENT type EMPTY> | |||||
| <!ATTLIST type | |||||
| name CDATA #REQUIRED | |||||
| class CDATA #REQUIRED | |||||
| > | |||||
| @@ -1,711 +0,0 @@ | |||||
| /* | |||||
| * The Apache Software License, Version 1.1 | |||||
| * | |||||
| * Copyright (c) 1999 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 "The Jakarta Project", "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.*; | |||||
| import org.apache.tools.ant.types.*; | |||||
| import org.xml.sax.*; | |||||
| import javax.xml.parsers.*; | |||||
| import java.util.*; | |||||
| import java.util.zip.*; | |||||
| import java.io.*; | |||||
| /** | |||||
| * Make available the tasks and types from an Ant library. <pre> | |||||
| * <antlib library="libname.jar" > | |||||
| * <alias name="nameOnLib" as="newName" /> | |||||
| * </antlib> | |||||
| * | |||||
| * <antlib file="libname.jar" override="true" /> | |||||
| * </pre> | |||||
| * | |||||
| * @author minor changes by steve loughran, steve_l@iseran.com | |||||
| * @author <a href="j_a_fernandez@yahoo.com">Jose Alberto Fernandez</a> | |||||
| * @since ant1.5 | |||||
| */ | |||||
| public class Antlib extends Task { | |||||
| /* | |||||
| * implements DeclaringTask | |||||
| */ | |||||
| /** | |||||
| * library attribute | |||||
| */ | |||||
| private String library = null; | |||||
| /** | |||||
| * file attribute | |||||
| */ | |||||
| private File file = null; | |||||
| /** | |||||
| * override attribute | |||||
| */ | |||||
| private boolean override = false; | |||||
| /** | |||||
| * attribute to control classloader use | |||||
| */ | |||||
| private boolean useCurrentClassloader = false; | |||||
| /** | |||||
| * classpath to build up | |||||
| */ | |||||
| private Path classpath = null; | |||||
| /** | |||||
| * our little xml parse | |||||
| */ | |||||
| private SAXParserFactory saxFactory; | |||||
| /** | |||||
| * table of aliases | |||||
| */ | |||||
| private Vector aliases = new Vector(); | |||||
| /** | |||||
| * Location of descriptor in library | |||||
| */ | |||||
| public static String ANT_DESCRIPTOR = "META-INF/antlib.xml"; | |||||
| /** | |||||
| * Prefix name for DTD of descriptor | |||||
| */ | |||||
| public static String ANTLIB_DTD_URL = | |||||
| "http://jakarta.apache.org/ant/"; | |||||
| /** | |||||
| * prefix of the antlib | |||||
| */ | |||||
| public static String ANTLIB_DTD_PREFIX = "Antlib-V"; | |||||
| /** | |||||
| * version counter | |||||
| */ | |||||
| public static String ANTLIB_DTD_VERSION = "1_0"; | |||||
| /** | |||||
| * dtd file extension | |||||
| */ | |||||
| public static String ANTLIB_DTD_EXT = ".dtd"; | |||||
| /** | |||||
| * constructor creates a validating sax parser | |||||
| */ | |||||
| public Antlib() { | |||||
| super(); | |||||
| saxFactory = SAXParserFactory.newInstance(); | |||||
| saxFactory.setValidating(true); | |||||
| } | |||||
| /** | |||||
| * constructor binds to a project as well as setting up internal state | |||||
| * | |||||
| * @param p Description of Parameter | |||||
| */ | |||||
| public Antlib(Project p) { | |||||
| this(); | |||||
| setProject(p); | |||||
| } | |||||
| /** | |||||
| * Set name of library to load. The library is located in $ANT_HOME/lib. | |||||
| * | |||||
| * @param lib the name of library relative to $ANT_HOME/lib. | |||||
| */ | |||||
| public void setLibrary(String lib) { | |||||
| this.library = lib; | |||||
| } | |||||
| /** | |||||
| * Set file location of library to load. | |||||
| * | |||||
| * @param file the jar file for the library. | |||||
| */ | |||||
| public void setFile(File file) { | |||||
| this.file = file; | |||||
| } | |||||
| /** | |||||
| * Set whether to override any existing definitions. | |||||
| * | |||||
| * @param override if true new definitions will replace existing ones. | |||||
| */ | |||||
| public void setOverride(boolean override) { | |||||
| this.override = override; | |||||
| } | |||||
| /** | |||||
| * Set whether to use a new classloader or not. Default is <code>false</code> | |||||
| * . This property is mostly used by the core when loading core tasks. | |||||
| * | |||||
| * @param useCurrentClassloader if true the current classloader will | |||||
| * be used to load the definitions. | |||||
| */ | |||||
| public void setUseCurrentClassloader(boolean useCurrentClassloader) { | |||||
| this.useCurrentClassloader = useCurrentClassloader; | |||||
| } | |||||
| /** | |||||
| * Create new Alias element. | |||||
| * | |||||
| * @return Description of the Returned Value | |||||
| */ | |||||
| public Alias createAlias() { | |||||
| Alias als = new Alias(); | |||||
| aliases.add(als); | |||||
| return als; | |||||
| } | |||||
| /** | |||||
| * Set the classpath to be used for this compilation | |||||
| * | |||||
| * @param cp The new Classpath value | |||||
| */ | |||||
| public void setClasspath(Path cp) { | |||||
| if (classpath == null) { | |||||
| classpath = cp; | |||||
| } | |||||
| else { | |||||
| classpath.append(cp); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * create a nested classpath element. | |||||
| * | |||||
| * @return classpath to use | |||||
| */ | |||||
| public Path createClasspath() { | |||||
| if (classpath == null) { | |||||
| classpath = new Path(project); | |||||
| } | |||||
| return classpath.createPath(); | |||||
| } | |||||
| /** | |||||
| * Adds a reference to a CLASSPATH defined elsewhere | |||||
| * | |||||
| * @param r The new ClasspathRef value | |||||
| */ | |||||
| public void setClasspathRef(Reference r) { | |||||
| createClasspath().setRefid(r); | |||||
| } | |||||
| /** | |||||
| * actually do the work of loading the library | |||||
| * | |||||
| * @exception BuildException Description of Exception | |||||
| * @todo maybe have failonerror support for missing file? | |||||
| */ | |||||
| public void execute() | |||||
| throws BuildException { | |||||
| File realFile = file; | |||||
| if (library != null) { | |||||
| if (file != null) { | |||||
| String msg = "You cannot specify both file and library."; | |||||
| throw new BuildException(msg, location); | |||||
| } | |||||
| // For the time being libraries live in $ANT_HOME/lib. | |||||
| // The idea being that we would not load all the jars there anymore | |||||
| String home = project.getProperty("ant.home"); | |||||
| if (home == null) { | |||||
| throw new BuildException("ANT_HOME not set as required."); | |||||
| } | |||||
| realFile = new File(new File(home, "lib"), library); | |||||
| } | |||||
| else if (file == null) { | |||||
| String msg = "Must specify either library or file attribute."; | |||||
| throw new BuildException(msg, location); | |||||
| } | |||||
| if (!realFile.exists()) { | |||||
| String msg = "Cannot find library: " + realFile; | |||||
| throw new BuildException(msg, location); | |||||
| } | |||||
| //open the descriptor | |||||
| InputStream is = getDescriptor(realFile); | |||||
| if (is == null) { | |||||
| String msg = "Missing descriptor on library: " + realFile; | |||||
| throw new BuildException(msg, location); | |||||
| } | |||||
| ClassLoader classloader=null; | |||||
| if (useCurrentClassloader && classpath != null) { | |||||
| log("ignoring the useCurrentClassloader option as a classpath is defined", | |||||
| Project.MSG_WARN); | |||||
| useCurrentClassloader=false; | |||||
| } | |||||
| if (!useCurrentClassloader) { | |||||
| classloader = makeClassLoader(realFile); | |||||
| } | |||||
| //parse it and evaluate it. | |||||
| evaluateDescriptor(classloader, processAliases(), is); | |||||
| } | |||||
| /** | |||||
| * Load definitions directly from an external XML file. | |||||
| * | |||||
| * @param xmlfile XML file in the Antlib format. | |||||
| * @exception BuildException failure to open the file | |||||
| */ | |||||
| public void loadDefinitions(File xmlfile) | |||||
| throws BuildException { | |||||
| try { | |||||
| InputStream is = new FileInputStream(xmlfile); | |||||
| loadDefinitions(is); | |||||
| } | |||||
| catch (IOException io) { | |||||
| throw new BuildException("Cannot read file: " + file, io); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Load definitions directly from InputStream. | |||||
| * | |||||
| * @param is InputStream for the Antlib descriptor. | |||||
| * @exception BuildException trouble | |||||
| */ | |||||
| public void loadDefinitions(InputStream is) | |||||
| throws BuildException { | |||||
| evaluateDescriptor(null, processAliases(), is); | |||||
| } | |||||
| /** | |||||
| * get a descriptor from the library file | |||||
| * | |||||
| * @param file jarfile to open | |||||
| * @return input stream to the Descriptor | |||||
| * @exception BuildException io trouble, or it isnt a zipfile | |||||
| */ | |||||
| private InputStream getDescriptor(File file) | |||||
| throws BuildException { | |||||
| try { | |||||
| final ZipFile zipfile = new ZipFile(file); | |||||
| ZipEntry entry = zipfile.getEntry(ANT_DESCRIPTOR); | |||||
| if (entry == null) { | |||||
| return null; | |||||
| } | |||||
| // Guarantee that when Entry is closed so does the zipfile instance. | |||||
| return | |||||
| new FilterInputStream(zipfile.getInputStream(entry)) { | |||||
| public void close() | |||||
| throws IOException { | |||||
| super.close(); | |||||
| zipfile.close(); | |||||
| } | |||||
| }; | |||||
| } | |||||
| catch (ZipException ze) { | |||||
| throw new BuildException("Not a library file.", ze, location); | |||||
| } | |||||
| catch (IOException ioe) { | |||||
| throw new BuildException("Cannot read library content.", | |||||
| ioe, location); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * turn the alias list to a property hashtable | |||||
| * | |||||
| * @return generated property hashtable | |||||
| */ | |||||
| private Properties processAliases() { | |||||
| Properties p = new Properties(); | |||||
| for (Enumeration e = aliases.elements(); e.hasMoreElements(); ) { | |||||
| Alias a = (Alias) e.nextElement(); | |||||
| p.put(a.name, a.as); | |||||
| } | |||||
| return p; | |||||
| } | |||||
| /** | |||||
| * create the classpath for this library from the file passed in and | |||||
| * any classpath parameters | |||||
| * | |||||
| * @param file library file to use | |||||
| * @return classloader using te | |||||
| * @exception BuildException trouble creating the classloader | |||||
| */ | |||||
| protected ClassLoader makeClassLoader(File file) | |||||
| throws BuildException { | |||||
| Path clspath = new Path(project); | |||||
| clspath.setLocation(file); | |||||
| //append any build supplied classpath | |||||
| if (classpath != null) { | |||||
| clspath.append(classpath); | |||||
| } | |||||
| AntClassLoader al = new AntClassLoader(project, clspath, true); | |||||
| return al; | |||||
| } | |||||
| /** | |||||
| * parse the antlib descriptor | |||||
| * | |||||
| * @param cl optional classloader | |||||
| * @param als alias list as property hashtable | |||||
| * @param is input stream to descriptor | |||||
| * @exception BuildException trouble | |||||
| */ | |||||
| protected void evaluateDescriptor(ClassLoader cl, | |||||
| Properties als, InputStream is) | |||||
| throws BuildException { | |||||
| try { | |||||
| SAXParser saxParser = saxFactory.newSAXParser(); | |||||
| Parser parser = saxParser.getParser(); | |||||
| InputSource inputSource = new InputSource(is); | |||||
| //inputSource.setSystemId(uri); //URI is nasty for jar entries | |||||
| project.log("parsing descriptor for library: " + file, | |||||
| Project.MSG_VERBOSE); | |||||
| saxParser.parse(inputSource, new AntLibraryHandler(cl, als)); | |||||
| } | |||||
| catch (ParserConfigurationException exc) { | |||||
| throw new BuildException("Parser has not been configured correctly", exc); | |||||
| } | |||||
| catch (SAXParseException exc) { | |||||
| Location location = | |||||
| new Location(ANT_DESCRIPTOR, | |||||
| exc.getLineNumber(), exc.getColumnNumber()); | |||||
| Throwable t = exc.getException(); | |||||
| if (t instanceof BuildException) { | |||||
| BuildException be = (BuildException) t; | |||||
| if (be.getLocation() == Location.UNKNOWN_LOCATION) { | |||||
| be.setLocation(location); | |||||
| } | |||||
| throw be; | |||||
| } | |||||
| throw new BuildException(exc.getMessage(), t, location); | |||||
| } | |||||
| catch (SAXException exc) { | |||||
| Throwable t = exc.getException(); | |||||
| if (t instanceof BuildException) { | |||||
| throw (BuildException) t; | |||||
| } | |||||
| throw new BuildException(exc.getMessage(), t); | |||||
| } | |||||
| catch (IOException exc) { | |||||
| throw new BuildException("Error reading library descriptor", exc); | |||||
| } | |||||
| finally { | |||||
| if (is != null) { | |||||
| try { | |||||
| is.close(); | |||||
| } | |||||
| catch (IOException ioe) { | |||||
| // ignore this | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * get a DTD URI from url, prefix and extension | |||||
| * | |||||
| * @return URI for this dtd version | |||||
| */ | |||||
| public static String dtdVersion() { | |||||
| return ANTLIB_DTD_URL + ANTLIB_DTD_PREFIX + | |||||
| ANTLIB_DTD_VERSION + ANTLIB_DTD_EXT; | |||||
| } | |||||
| /** | |||||
| * compare system ID with the dtd string | |||||
| * -ignoring any version number | |||||
| * @param systemId Description of Parameter | |||||
| * @return true if this is a an ant library descriptor | |||||
| */ | |||||
| public static boolean matchDtdId(String systemId) { | |||||
| return (systemId != null && | |||||
| systemId.startsWith(ANTLIB_DTD_URL + ANTLIB_DTD_PREFIX) && | |||||
| systemId.endsWith(ANTLIB_DTD_EXT)); | |||||
| } | |||||
| /** | |||||
| * Parses the document describing the content of the | |||||
| * library. An inner class for access to Project.log | |||||
| */ | |||||
| private class AntLibraryHandler extends HandlerBase { | |||||
| /** | |||||
| * our classloader | |||||
| */ | |||||
| private final ClassLoader classloader; | |||||
| /** | |||||
| * the aliases | |||||
| */ | |||||
| private final Properties aliasMap; | |||||
| /** | |||||
| * doc locator | |||||
| */ | |||||
| private Locator locator = null; | |||||
| /** | |||||
| * Constructor for the AntLibraryHandler object | |||||
| * | |||||
| * @param cl optional classloader | |||||
| * @param als alias list | |||||
| */ | |||||
| AntLibraryHandler(ClassLoader classloader, Properties als) { | |||||
| this.classloader = classloader; | |||||
| this.aliasMap = als; | |||||
| } | |||||
| /** | |||||
| * Sets the DocumentLocator attribute of the AntLibraryHandler | |||||
| * object | |||||
| * | |||||
| * @param locator The new DocumentLocator value | |||||
| */ | |||||
| public void setDocumentLocator(Locator locator) { | |||||
| this.locator = locator; | |||||
| } | |||||
| /** | |||||
| * SAX callback handler | |||||
| * | |||||
| * @param tag XML tag | |||||
| * @param attrs attributes | |||||
| * @exception SAXParseException parse trouble | |||||
| */ | |||||
| public void startElement(String tag, AttributeList attrs) | |||||
| throws SAXParseException { | |||||
| if ("antlib".equals(tag)) { | |||||
| // No attributes to worry about | |||||
| return; | |||||
| } | |||||
| if ("task".equals(tag) || "type".equals(tag)) { | |||||
| String name = null; | |||||
| String className = null; | |||||
| for (int i = 0, last = attrs.getLength(); i < last; i++) { | |||||
| String key = attrs.getName(i); | |||||
| String value = attrs.getValue(i); | |||||
| if (key.equals("name")) { | |||||
| name = value; | |||||
| } | |||||
| else if (key.equals("class")) { | |||||
| className = value; | |||||
| } | |||||
| else { | |||||
| throw new SAXParseException("Unexpected attribute \"" | |||||
| + key + "\"", locator); | |||||
| } | |||||
| } | |||||
| if (name == null || className == null) { | |||||
| String msg = "Underspecified " + tag + " declaration."; | |||||
| throw new SAXParseException(msg, locator); | |||||
| } | |||||
| try { | |||||
| //check for name alias | |||||
| String alias = aliasMap.getProperty(name); | |||||
| if (alias != null) { | |||||
| name = alias; | |||||
| } | |||||
| //catch an attempted override of an existing name | |||||
| if (!override && inUse(name)) { | |||||
| String msg = "Cannot override " + tag + ": " + name; | |||||
| log(msg, Project.MSG_WARN); | |||||
| return; | |||||
| } | |||||
| //load the named class | |||||
| Class cls; | |||||
| if(classloader==null) { | |||||
| cls=Class.forName(className); | |||||
| } | |||||
| else { | |||||
| cls=classloader.loadClass(className); | |||||
| } | |||||
| //register it as a task or a datatype | |||||
| if (tag.equals("task")) { | |||||
| project.addTaskDefinition(name, cls); | |||||
| } | |||||
| else { | |||||
| project.addDataTypeDefinition(name, cls); | |||||
| } | |||||
| } | |||||
| catch (ClassNotFoundException cnfe) { | |||||
| String msg = "Class " + className + | |||||
| " cannot be found"; | |||||
| throw new SAXParseException(msg, locator, cnfe); | |||||
| } | |||||
| catch (NoClassDefFoundError ncdfe) { | |||||
| String msg = "Class " + className + | |||||
| " cannot be found"; | |||||
| throw new SAXParseException(msg, locator); | |||||
| } | |||||
| } | |||||
| else { | |||||
| throw new SAXParseException("Unexpected element \"" + | |||||
| tag + "\"", | |||||
| locator); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * test for a name being in use already | |||||
| * | |||||
| * @param name the name to test | |||||
| * @return true if it is a task or a datatype | |||||
| */ | |||||
| private boolean inUse(String name) { | |||||
| return (project.getTaskDefinitions().get(name) != null || | |||||
| project.getDataTypeDefinitions().get(name) != null); | |||||
| } | |||||
| /** | |||||
| * Recognizes the DTD declaration for antlib and returns the corresponding | |||||
| * DTD definition from a resource. <P> | |||||
| * | |||||
| * To allow for future versions of the DTD format it will search | |||||
| * for any DTDs of the form "Antlib-V.*\.dtd". | |||||
| * | |||||
| * @param publicId public ID (ignored) | |||||
| * @param systemId system ID (matched against) | |||||
| * @return local DTD instance | |||||
| */ | |||||
| public InputSource resolveEntity(String publicId, | |||||
| String systemId) { | |||||
| log("Looking for entiry with PublicID=" + publicId + | |||||
| " and SystemId=" + systemId, Project.MSG_VERBOSE); | |||||
| if (matchDtdId(systemId)) { | |||||
| String resId = systemId.substring(ANTLIB_DTD_URL.length()); | |||||
| InputSource is = | |||||
| new InputSource(this.getClass().getResourceAsStream(resId)); | |||||
| is.setSystemId(systemId); | |||||
| return is; | |||||
| } | |||||
| return null; | |||||
| } | |||||
| //end inner class AntLibraryHandler | |||||
| } | |||||
| /** | |||||
| * this class is used for alias elements | |||||
| * | |||||
| * @author slo | |||||
| * @created 11 November 2001 | |||||
| */ | |||||
| public static class Alias { | |||||
| /** | |||||
| * Description of the Field | |||||
| */ | |||||
| private String name; | |||||
| /** | |||||
| * Description of the Field | |||||
| */ | |||||
| private String as; | |||||
| /** | |||||
| * Sets the Name attribute of the Alias object | |||||
| * | |||||
| * @param name The new Name value | |||||
| */ | |||||
| public void setName(String name) { | |||||
| this.name = name; | |||||
| } | |||||
| /** | |||||
| * Sets the As attribute of the Alias object | |||||
| * | |||||
| * @param as The new As value | |||||
| */ | |||||
| public void setAs(String as) { | |||||
| this.as = as; | |||||
| } | |||||
| //end inner class alias | |||||
| } | |||||
| //end class Antlib | |||||
| } | |||||
| @@ -53,8 +53,6 @@ parallel=org.apache.tools.ant.taskdefs.Parallel | |||||
| sequential=org.apache.tools.ant.taskdefs.Sequential | sequential=org.apache.tools.ant.taskdefs.Sequential | ||||
| condition=org.apache.tools.ant.taskdefs.ConditionTask | condition=org.apache.tools.ant.taskdefs.ConditionTask | ||||
| dependset=org.apache.tools.ant.taskdefs.DependSet | dependset=org.apache.tools.ant.taskdefs.DependSet | ||||
| antlib=org.apache.tools.ant.taskdefs.Antlib | |||||
| antjar=org.apache.tools.ant.taskdefs.Antjar | |||||
| # optional tasks | # optional tasks | ||||
| script=org.apache.tools.ant.taskdefs.optional.Script | script=org.apache.tools.ant.taskdefs.optional.Script | ||||