Browse Source

Jose Alberto Fernandez's ant descriptor loader

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269898 13f79535-47bb-0310-9956-ffa450edef68
master
Steve Loughran 23 years ago
parent
commit
1e469669cf
7 changed files with 1269 additions and 0 deletions
  1. +94
    -0
      docs/manual/CoreTasks/antjar.html
  2. +117
    -0
      docs/manual/CoreTasks/antlib.html
  3. +2
    -0
      docs/manual/coretasklist.html
  4. +316
    -0
      src/main/org/apache/tools/ant/taskdefs/Antjar.java
  5. +27
    -0
      src/main/org/apache/tools/ant/taskdefs/Antlib-V1_0.dtd
  6. +711
    -0
      src/main/org/apache/tools/ant/taskdefs/Antlib.java
  7. +2
    -0
      src/main/org/apache/tools/ant/taskdefs/defaults.properties

+ 94
- 0
docs/manual/CoreTasks/antjar.html View File

@@ -0,0 +1,94 @@
<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>&quot;http://jakarta.apache.org/ant/AntlibV1_0.dtd&quot;</b>.
This DTD is defined as follows:</p>
<pre>
&lt;?xml version='1.0' encoding="UTF8" ?&gt;

&lt;!--
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.
--&gt;

&lt;!-- Root element for the Antlib descriptor. --&gt;
&lt;!ELEMENT antlib (task | type)* &gt;
&lt;!ATTLIST antlib
version CDATA #IMPLIED
&gt;

&lt;!-- Declaration of tasks contained in the library. --&gt;
&lt;!ELEMENT task EMPTY&gt;
&lt;!ATTLIST task
name CDATA #REQUIRED
class CDATA #REQUIRED
&gt;

&lt;!-- Declaration of datatypes contained in the library --&gt;
&lt;!ELEMENT type EMPTY&gt;
&lt;!ATTLIST type
name CDATA #REQUIRED
class CDATA #REQUIRED
&gt;

</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> &lt;jar file=&quot;${dist}/lib/app.jar&quot;
antxml=&quot;${src}/applib.xml&quot; basedir=&quot;${build}/classes&quot;/&gt;</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>
&lt;?xml version="1.0" encoding="UTF8" ?&gt;
&lt;!DOCTYPE antlib SYSTEM "http://jakarta.apache.org/ant/Antlib-V1_0.dtd" &gt;

&lt;antlib version="1.0" &gt;
&lt;task name="case" class="org.apache.ant.contrib.Case" /&gt;
&lt;/antlib&gt;

</pre>
<hr>
<p align="center">Copyright &copy; 2000,2001 Apache Software Foundation. All rights
Reserved.</p>

</body>
</html>


+ 117
- 0
docs/manual/CoreTasks/antlib.html View File

@@ -0,0 +1,117 @@
<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. (&quot;true&quot;/&quot;false&quot;). When &quot;false&quot; already defined tasks
and datatytes take precedence over those in the library.
Default is &quot;false&quot; when omitted.</td>
<td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">useCurrentClassloader</td>
<td valign="top">Set to &quot;true&quot; 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 &quot;false&quot;.
</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> &lt;antlib file=&quot;${build}/lib/mylib.jar&quot;/&gt;</pre>
<p>loads the definitions from the library located at
<code>${build}/lib/ant.jar</code>.</p>
<pre> &lt;antlib library=&quot;optional.jar&quot;/&gt;</pre>
<p>loads the definitions from the library <code>optional.jar</code>
located at <code>${ant.home}/lib</code>.</p>
<pre> &lt;antlib file=&quot;${build}/lib/mylib.jar&quot&gt;
&lt;alias name=&quot;echo&quot; as=&quot;myecho&quot;/&gt;
&lt;/antlib&gt;
</pre>
<p>loads the definitions from the library located at
<code>${build}/lib/ant.jar</code> but uses the name
&quot;<code>myecho</code>&quot; for the &quot;<code>echo</code>&quot; task
declared in the library.</p>

<hr><p align="center">Copyright &copy; 2000,2001 Apache Software Foundation. All rights
Reserved.</p>

</body>
</html>


+ 2
- 0
docs/manual/coretasklist.html View File

@@ -25,6 +25,8 @@
<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>


+ 316
- 0
src/main/org/apache/tools/ant/taskdefs/Antjar.java View File

@@ -0,0 +1,316 @@
/*
* 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
}
}


+ 27
- 0
src/main/org/apache/tools/ant/taskdefs/Antlib-V1_0.dtd View File

@@ -0,0 +1,27 @@
<?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
>

+ 711
- 0
src/main/org/apache/tools/ant/taskdefs/Antlib.java View File

@@ -0,0 +1,711 @@
/*
* 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>
* &lt;antlib library="libname.jar" &gt;
* &lt;alias name="nameOnLib" as="newName" /&gt;
* &lt;/antlib&gt;
*
* &lt;antlib file="libname.jar" override="true" /&gt;
* </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
}



+ 2
- 0
src/main/org/apache/tools/ant/taskdefs/defaults.properties View File

@@ -53,6 +53,8 @@ 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


Loading…
Cancel
Save