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 | ||||