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/ant.html">Ant</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/apply.html">Apply/<i>ExecOn</i></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 | |||
condition=org.apache.tools.ant.taskdefs.ConditionTask | |||
dependset=org.apache.tools.ant.taskdefs.DependSet | |||
antlib=org.apache.tools.ant.taskdefs.Antlib | |||
antjar=org.apache.tools.ant.taskdefs.Antjar | |||
# optional tasks | |||
script=org.apache.tools.ant.taskdefs.optional.Script | |||