git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271281 13f79535-47bb-0310-9956-ffa450edef68master
@@ -0,0 +1,60 @@ | |||||
<?xml version='1.0' ?> | |||||
<project name="antlib" default="all"> | |||||
<property name='orig' location='../../..' /> | |||||
<property name='orig-build' location='${orig}/build' /> | |||||
<property name='orig-classes' location='${orig-build}/classes' /> | |||||
<property name='build' location='build' /> | |||||
<property name='dist' location='dist' /> | |||||
<property name='classes' location='${build}/classes' /> | |||||
<property name="debug" value="true" /> | |||||
<property name="deprecation" value="false" /> | |||||
<property name="optimize" value="true" /> | |||||
<target name='init'> | |||||
<ant target='build' dir='${orig}' inheritAll='false' /> | |||||
<mkdir dir='${classes}' /> | |||||
<copy toDir='${classes}' preservelastmodified='true' > | |||||
<fileset dir='${orig-classes}'> | |||||
<include name='**' /> | |||||
<exclude name='org/apache/tools/ant/Project.class' /> | |||||
<exclude name='org/apache/tools/ant/TaskAdapter.class' /> | |||||
<exclude name='org/apache/tools/ant/taskdefs/Ant.class' /> | |||||
</fileset> | |||||
</copy> | |||||
</target> | |||||
<target name='all' depends='init, build' /> | |||||
<target name='fullbuild' depends='init, compile'> | |||||
<ant target='internal_dist' dir='${orig}'> | |||||
<property name="build.dir" value="${build}"/> | |||||
<property name="dist.dir" value="${dist}"/> | |||||
</ant> | |||||
</target> | |||||
<target name='build' depends='init, compile'> | |||||
<ant target='dist-lite' dir='${orig}'> | |||||
<property name="build.dir" value="${build}"/> | |||||
<property name="dist.dir" value="${dist}"/> | |||||
</ant> | |||||
</target> | |||||
<target name='compile'> | |||||
<javac srcdir='src/main' destdir='${classes}' | |||||
debug="${debug}" | |||||
deprecation="${deprecation}" | |||||
optimize="${optimize}"> | |||||
<include name='**/*.java'/> | |||||
</javac> | |||||
</target> | |||||
<target name='clean'> | |||||
<delete dir='${build}' /> | |||||
</target> | |||||
<target name='cleanall' depends='clean'> | |||||
<delete dir='${dist}' /> | |||||
</target> | |||||
</project> |
@@ -12,41 +12,50 @@ | |||||
<p>An extension of the <a href="jar.html">Jar</a> task with special | <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 | treatment for the library descriptor file that should end up in the | ||||
<code>META-INF</code> directory of the Ant Archive.</p> | <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> | |||||
<p> | |||||
Descriptors must follow the following rules, although there is no fix DTD | |||||
for them: | |||||
<pre> | <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. --> | <!-- Root element for the Antlib descriptor. --> | ||||
<!ELEMENT antlib (task | type)* > | |||||
<!ATTLIST antlib | |||||
version CDATA #IMPLIED | |||||
> | |||||
<!ELEMENT antlib (role | <i>rolename</i>)* > | |||||
<!-- Declaration of tasks contained in the library. --> | |||||
<!ELEMENT task EMPTY> | |||||
<!ATTLIST task | |||||
<!-- Declaration of roles contained in the library. --> | |||||
<!ELEMENT role EMPTY> | |||||
<!ATTLIST role | |||||
name CDATA #REQUIRED | name CDATA #REQUIRED | ||||
class CDATA #REQUIRED | class CDATA #REQUIRED | ||||
proxy CDATA #IMPLIED | |||||
> | > | ||||
<!-- Declaration of datatypes contained in the library --> | <!-- Declaration of datatypes contained in the library --> | ||||
<!ELEMENT type EMPTY> | |||||
<!ATTLIST type | |||||
<!ELEMENT <i>rolename</i> EMPTY> | |||||
<!ATTLIST <i>rolename</i> | |||||
name CDATA #REQUIRED | name CDATA #REQUIRED | ||||
class CDATA #REQUIRED | class CDATA #REQUIRED | ||||
> | > | ||||
</pre> | </pre> | ||||
There are two predefined roles: <i><b>task</b></i> and <i><b>datatype</b></i>. | |||||
<p> | |||||
<h4>Role definition</h4> | |||||
The <b>name</b> of the role. This name is used when specifying | |||||
elements for this role. | |||||
<p> | |||||
The <b>class</b> defining a role must be an interface containing a | |||||
unique void method with only one argument whose type is the that of | |||||
elements declared on the role. | |||||
<p> | |||||
The <b>proxy</b> defined in a role specifies a class that can be used | |||||
to bridge between the type expected by the role and the type of | |||||
elements declared for that role. | |||||
<h4>Element definition</h4> | |||||
Any element whose name is that of a role declares an element for that role. | |||||
<p> | |||||
The <b>name</b> defined the name of the element to use in the buildfile | |||||
to specify the element being declared. | |||||
<p> | |||||
The <b>class</b> the class defining the element. | |||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
@@ -78,7 +87,6 @@ in <code>META-INF/antlib.xml</code>.</p> | |||||
<p>Here is a sample <code>META-INF/antlib.xml</code>:</p> | <p>Here is a sample <code>META-INF/antlib.xml</code>:</p> | ||||
<pre> | <pre> | ||||
<?xml version="1.0" encoding="UTF8" ?> | <?xml version="1.0" encoding="UTF8" ?> | ||||
<!DOCTYPE antlib SYSTEM "http://jakarta.apache.org/ant/Antlib-V1_0.dtd" > | |||||
<antlib version="1.0" > | <antlib version="1.0" > | ||||
<task name="case" class="org.apache.ant.contrib.Case" /> | <task name="case" class="org.apache.ant.contrib.Case" /> | ||||
@@ -9,16 +9,38 @@ | |||||
<h2><a name="antlib">AntLib</a></h2> | <h2><a name="antlib">AntLib</a></h2> | ||||
<h3>Description</h3> | <h3>Description</h3> | ||||
<p>Defines and loads any tasks and datatypes contained in an ANT library.</p> | |||||
<p>Defines and loads elements contained in an ANT library.</p> | |||||
<p>It also allows the aliasing of the names being defined in order to avoid | <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 | collisions and provides means to override definitions with the ones defined | ||||
in the library.</p> | in the library.</p> | ||||
Ant libraries can be loaded in the current classloader, which is more efficient, | |||||
Ant libraries are associated with ClassLoaders identified by the | |||||
<tt>loaderid</tt> attribute. If no loader is specified a default loader | |||||
will be used. Ant libraries specifying the same loader are loaded by the | |||||
same ClassLoader as long as the libraries are defined on the same project. | |||||
Classloaders with the same ID in a subproject have the corresponding | |||||
classloader in the parent project as their parent classloader. | |||||
<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 | 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. | directory) - set <tt>useCurrentClassloader</tt> to true to enable this. | ||||
It is also possible to add more libraries to the path, such as any | It is also possible to add more libraries to the path, such as any | ||||
libraries the task is dependent on. | libraries the task is dependent on. | ||||
<p> | |||||
Ant libraries define objects of several types: | |||||
<ol> | |||||
<li> <b>Roles</b>: Define an interface to be implemented by elements | |||||
(usually tasks) that accept subelements of the specified role. | |||||
Roles may also define a proxy class which may be applied to an element | |||||
in order to make it compatible with the role. | |||||
</li> | |||||
<li> <b>Tasks</b>: define elements that belong to the predefined | |||||
role "task". | |||||
<li> <b>Data types</b>: define elements that belong to the predefined role | |||||
"datatype". | |||||
<li> <b>Other role elements</b>: declare elements for other roles that | |||||
have been previously defined. | |||||
</ol> | |||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
@@ -33,11 +55,13 @@ libraries the task is dependent on. | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">library</td> | <td valign="top">library</td> | ||||
<td valign="top">The name of a library relative to ${ant.home}/lib.</td> | |||||
<td valign="top">The name of a library relative to ${ant.home}/antlib.</td> | |||||
</tr> | </tr> | ||||
<tr> | <tr> | ||||
<td valign="top">override</td> | <td valign="top">override</td> | ||||
<td valign="top">Replace any existing definition with the same name. ("true"/"false"). When "false" already defined tasks | |||||
<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. | and datatytes take precedence over those in the library. | ||||
Default is "false" when omitted.</td> | Default is "false" when omitted.</td> | ||||
<td align="center" valign="top">No</td> | <td align="center" valign="top">No</td> | ||||
@@ -59,12 +83,20 @@ libraries the task is dependent on. | |||||
</td> | </td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">loaderid</td> | |||||
<td valign="top">The ID of the ClassLoader to use to load the classes | |||||
defined in this library. If omitted a default per project ClassLoader | |||||
will be used. | |||||
</td> | |||||
<td valign="top" align="center">No</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<h3><a name="nested">Parameters specified as nested elements</a></h3> | <h3><a name="nested">Parameters specified as nested elements</a></h3> | ||||
<h4>alias</h4> | <h4>alias</h4> | ||||
<p>Specifies the usage of a different name from that defined in the library | <p>Specifies the usage of a different name from that defined in the library | ||||
descriptor.</p> | |||||
descriptor. Applies only to element definitions (not role declarations).</p> | |||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
<td valign="top"><b>Attribute</b></td> | <td valign="top"><b>Attribute</b></td> | ||||
@@ -85,10 +117,9 @@ descriptor.</p> | |||||
<p>Specifies the usage of a different name from that defined in the library | <p>Specifies the usage of a different name from that defined in the library | ||||
descriptor. This is used to deal with name clashes </p> | descriptor. This is used to deal with name clashes </p> | ||||
<h4>classpath</h4> | |||||
<h4>classpath</h4> | <h4>classpath</h4> | ||||
A classpath of extra libraries to import to support this task. | |||||
A classpath of extra libraries to import to support this library. | |||||
<h4>classpathref</h4> | <h4>classpathref</h4> | ||||
A reference to an existing classpath. | A reference to an existing classpath. | ||||
@@ -0,0 +1,69 @@ | |||||
/* | |||||
* 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; | |||||
public interface RoleAdapter { | |||||
/** | |||||
* Set the object being adapted. | |||||
* @param o the object being adapted | |||||
*/ | |||||
public void setProxy(Object o); | |||||
/** | |||||
* Get the object adapted by this class. | |||||
* @return the object being adapted, if any. | |||||
*/ | |||||
public Object getProxy(); | |||||
} |
@@ -0,0 +1,491 @@ | |||||
/* | |||||
* 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; | |||||
import java.lang.reflect.InvocationTargetException; | |||||
import java.lang.reflect.Method; | |||||
import java.lang.reflect.Modifier; | |||||
import java.util.*; | |||||
import org.apache.tools.ant.types.Path; | |||||
public class SymbolTable { | |||||
/** Parent symbol table */ | |||||
private SymbolTable parentTable; | |||||
/** Project associated with this symbol table */ | |||||
private Project project; | |||||
/** The table of roles available to this Project */ | |||||
private Hashtable roles = new Hashtable(); | |||||
/** The table of loaders active on this Project */ | |||||
private Hashtable loaders = new Hashtable(); | |||||
/** | |||||
* Table of per role definitions. | |||||
*/ | |||||
private Hashtable defs = new Hashtable(); | |||||
/** | |||||
* Parameters for checking adapters. | |||||
*/ | |||||
private static final Class[] CHECK_ADAPTER_PARAMS = | |||||
new Class[]{Class.class, Project.class}; | |||||
/** | |||||
* Create a top level Symbol table. | |||||
*/ | |||||
public SymbolTable() { | |||||
} | |||||
/** | |||||
* Create a symbol table inheriting the definitions | |||||
* from that defined in the calling Project. | |||||
* @param p the calling project | |||||
*/ | |||||
public SymbolTable(Project p) { | |||||
parentTable = p.getSymbols(); | |||||
} | |||||
/** | |||||
* Set the project associated with this symbol table. | |||||
* @param p the project for this symbol table | |||||
*/ | |||||
public void setProject(Project p) { | |||||
this.project = p; | |||||
} | |||||
/** | |||||
* Find all the roles supported by a Class | |||||
* on this symbol table. | |||||
* @param clz the class to analyze | |||||
* @return an array of roles supported by the class | |||||
*/ | |||||
public String[] findRoles(final Class clz) { | |||||
Vector list = new Vector(); | |||||
findRoles(clz, list); | |||||
return (String[])list.toArray(new String[list.size()]); | |||||
} | |||||
/** | |||||
* Collect the roles for the class | |||||
* @param clz the class being inspected | |||||
* @param list the roles collected up to this point | |||||
*/ | |||||
private void findRoles(final Class clz, Vector list) { | |||||
for (Enumeration e = roles.keys(); e.hasMoreElements();) { | |||||
String role = (String) e.nextElement(); | |||||
if (((Role) roles.get(role)).isImplementedBy(clz)) { | |||||
list.addElement(role); | |||||
} | |||||
} | |||||
if (parentTable != null) findRoles(clz, list); | |||||
} | |||||
/** | |||||
* Get the Role definition | |||||
* @param role the name of the role | |||||
* @return the method used to support objects on this role | |||||
*/ | |||||
public Role getRole(String role) { | |||||
Role r = (Role) roles.get(role); | |||||
if (r == null && parentTable != null) { | |||||
return parentTable.getRole(role); | |||||
} | |||||
return r; | |||||
} | |||||
/** | |||||
* Add a new role definition to this project. | |||||
* @param role the name of the role | |||||
* @param rclz the interface used to specify support for the role. | |||||
* @param aclz the optional adapter class | |||||
* @return whether the role replaced a different definition | |||||
*/ | |||||
public boolean addRole(String role, Class rclz, Class aclz) { | |||||
// Check if role already declared | |||||
Role old = getRole(role); | |||||
if (old != null && old.isSameAsFor(rclz, aclz) | |||||
) { | |||||
project.log("Ignoring override for role " + role | |||||
+ ", it is already defined by the same definition.", | |||||
project.MSG_VERBOSE); | |||||
return false; | |||||
} | |||||
// Role interfaces should only contain one method | |||||
roles.put(role, new Role(rclz, aclz)); | |||||
return (old != null); | |||||
} | |||||
/** | |||||
* Verify if the interface is valid. | |||||
* @param clz the interface to validate | |||||
* @return the method defined by the interface | |||||
*/ | |||||
private Method validInterface(Class clz) { | |||||
Method m[] = clz.getDeclaredMethods(); | |||||
if (m.length == 1 | |||||
&& java.lang.Void.TYPE.equals(m[0].getReturnType())) { | |||||
Class args[] = m[0].getParameterTypes(); | |||||
if (args.length == 1 | |||||
&& !java.lang.String.class.equals(args[0]) | |||||
&& !args[0].isArray() | |||||
&& !args[0].isPrimitive()) { | |||||
return m[0]; | |||||
} | |||||
else { | |||||
throw new BuildException("Invalid role interface method in: " | |||||
+ clz.getName()); | |||||
} | |||||
} | |||||
else { | |||||
throw new BuildException("More than one method on role interface"); | |||||
} | |||||
} | |||||
/** | |||||
* Verify if the adapter is valid with respect to the interface. | |||||
* @param clz the class adapter to validate | |||||
* @param mtd the method whose only argument must match | |||||
* @return the static method to use for validating adaptees | |||||
*/ | |||||
private Method validAdapter(Class clz, Method mtd) { | |||||
if (clz == null) return null; | |||||
checkClass(clz); | |||||
if (!mtd.getParameterTypes()[0].isAssignableFrom(clz)) { | |||||
String msg = "Adapter " + clz.getName() + | |||||
" is incompatible with role interface " + | |||||
mtd.getDeclaringClass().getName(); | |||||
throw new BuildException(msg); | |||||
} | |||||
String msg = "Class " + clz.getName() + " is not an adapter: "; | |||||
if (!RoleAdapter.class.isAssignableFrom(clz)) { | |||||
throw new BuildException(msg + "does not implement RoleAdapter"); | |||||
} | |||||
try { | |||||
Method chk = clz.getMethod("checkClass", CHECK_ADAPTER_PARAMS); | |||||
if (!Modifier.isStatic(chk.getModifiers())) { | |||||
throw new BuildException(msg + "checkClass() is not static"); | |||||
} | |||||
return chk; | |||||
} | |||||
catch(NoSuchMethodException nme){ | |||||
throw new BuildException(msg + "checkClass() not found", nme); | |||||
} | |||||
} | |||||
/** | |||||
* Get the specified loader for the project. | |||||
* @param name the name of the loader | |||||
* @return the corresponding ANT classloader | |||||
*/ | |||||
private AntClassLoader getLoader(String name) { | |||||
AntClassLoader cl = (AntClassLoader) loaders.get(name); | |||||
if (cl == null && parentTable != null) { | |||||
return parentTable.getLoader(name); | |||||
} | |||||
return cl; | |||||
} | |||||
/** | |||||
* Add the specified class-path to a loader. | |||||
* If the loader is defined in an ancestor project then a new | |||||
* classloader inheritin from the one already existing | |||||
* will be created, otherwise the path willbe added to the existing | |||||
* ClassLoader. | |||||
* @param name the name of the loader to use. | |||||
* @param clspath the path to be added to the classloader | |||||
*/ | |||||
public ClassLoader addToLoader(String name, Path clspath) { | |||||
// Find if the loader is already defined in the current project | |||||
AntClassLoader cl = (AntClassLoader) loaders.get(name); | |||||
if (cl == null) { | |||||
// Is it inherited from the calling project | |||||
if (parentTable != null) { | |||||
cl = parentTable.getLoader(name); | |||||
} | |||||
cl = new AntClassLoader(cl, project, clspath, true); | |||||
loaders.put(name, cl); | |||||
} | |||||
else { | |||||
// Add additional path to the existing definition | |||||
String[] pathElements = clspath.list(); | |||||
for (int i = 0; i < pathElements.length; ++i) { | |||||
try { | |||||
cl.addPathElement(pathElements[i]); | |||||
} | |||||
catch (BuildException e) { | |||||
// ignore path elements invalid relative to the project | |||||
} | |||||
} | |||||
} | |||||
return cl; | |||||
} | |||||
/** | |||||
* Add a new type of element to a role. | |||||
* @param role the role for this Class. | |||||
* @param name the name of the element for this Class | |||||
* @param clz the Class being declared | |||||
* @return the old definition | |||||
*/ | |||||
public Class add(String role, String name, Class clz) { | |||||
// Find the role definition | |||||
Role r = getRole(role); | |||||
if (r == null) { | |||||
throw new BuildException("Unknown role: " + role); | |||||
} | |||||
// Check if it is already defined | |||||
Class old = get(role, name); | |||||
if (old != null) { | |||||
if (old.equals(clz)) { | |||||
project.log("Ignoring override for "+ role + " " + name | |||||
+ ", it is already defined by the same class.", | |||||
project.MSG_VERBOSE); | |||||
return old; | |||||
} | |||||
else { | |||||
project.log("Trying to override old definition of " + | |||||
role + " " + name, | |||||
project.MSG_WARN); | |||||
} | |||||
} | |||||
checkClass(clz); | |||||
// Check that the Class is compatible with the role definition | |||||
r.verifyAdaptability(role, clz); | |||||
// Record the new type | |||||
Hashtable defTable = (Hashtable)defs.get(role); | |||||
if (defTable == null) { | |||||
defTable = new Hashtable(); | |||||
defs.put(role, defTable); | |||||
} | |||||
defTable.put(name, clz); | |||||
return old; | |||||
} | |||||
/** | |||||
* Checks a class, whether it is suitable for serving in ANT. | |||||
* @throws BuildException and logs as Project.MSG_ERR for | |||||
* conditions, that will cause execution to fail. | |||||
*/ | |||||
void checkClass(final Class clz) | |||||
throws BuildException { | |||||
if(!Modifier.isPublic(clz.getModifiers())) { | |||||
final String message = clz + " is not public"; | |||||
project.log(message, Project.MSG_ERR); | |||||
throw new BuildException(message); | |||||
} | |||||
if(Modifier.isAbstract(clz.getModifiers())) { | |||||
final String message = clz + " is abstract"; | |||||
project.log(message, Project.MSG_ERR); | |||||
throw new BuildException(message); | |||||
} | |||||
try { | |||||
// Class can have a "no arg" constructor or take a single | |||||
// Project argument. | |||||
// don't have to check for public, since | |||||
// getConstructor finds public constructors only. | |||||
try { | |||||
clz.getConstructor(new Class[0]); | |||||
} catch (NoSuchMethodException nse) { | |||||
clz.getConstructor(new Class[] {Project.class}); | |||||
} | |||||
} catch(NoSuchMethodException e) { | |||||
final String message = | |||||
"No valid public constructor in " + clz; | |||||
project.log(message, Project.MSG_ERR); | |||||
throw new BuildException(message); | |||||
} | |||||
} | |||||
/** | |||||
* Get the class in the role identified with the element name. | |||||
* @param role the role to look into. | |||||
* @param name the name of the element to sea | |||||
* @return the Class implementation | |||||
*/ | |||||
public Class get(String role, String name) { | |||||
Hashtable defTable = (Hashtable)defs.get(role); | |||||
if (defTable != null) { | |||||
Class clz = (Class)defTable.get(name); | |||||
if (clz != null) return clz; | |||||
} | |||||
if (parentTable != null) { | |||||
return parentTable.get(role, name); | |||||
} | |||||
return null; | |||||
} | |||||
/** | |||||
* Get a Hashtable that is usable for manipulating Tasks, | |||||
* @return a Hashtable that delegates to the Symbol table. | |||||
*/ | |||||
public Hashtable getTaskDefinitions() { | |||||
return new SymbolHashtable("task"); | |||||
} | |||||
/** | |||||
* Get a Hashtable that is usable for manipulating Datatypes, | |||||
* @return a Hashtable that delegates to the Symbol table. | |||||
*/ | |||||
public Hashtable getDataTypeDefinitions() { | |||||
return new SymbolHashtable("datatype"); | |||||
} | |||||
/** | |||||
* Hashtable implementation that delegates | |||||
* the search operations to the Symbol table | |||||
*/ | |||||
private class SymbolHashtable extends Hashtable { | |||||
final String role; | |||||
SymbolHashtable(String role) { | |||||
this.role = role; | |||||
} | |||||
public synchronized Object put(Object key, Object value) { | |||||
return SymbolTable.this.add(role, (String) key, (Class) value); | |||||
} | |||||
public synchronized Object get(Object key) { | |||||
return SymbolTable.this.get(role, (String)key); | |||||
} | |||||
} | |||||
/** | |||||
* The definition of a role | |||||
*/ | |||||
public class Role { | |||||
private Method interfaceMethod; | |||||
private Method adapterVerifier; | |||||
/** | |||||
* Creates a new Role object | |||||
* @param roleClz the class that defines the role | |||||
* @param adapterClz the class for the adapter, or null if none | |||||
*/ | |||||
Role(Class roleClz, Class adapterClz) { | |||||
interfaceMethod = validInterface(roleClz); | |||||
adapterVerifier = validAdapter(adapterClz, interfaceMethod); | |||||
} | |||||
/** | |||||
* Get the method used to set on interface | |||||
*/ | |||||
public Method getInterfaceMethod() { | |||||
return interfaceMethod; | |||||
} | |||||
/** | |||||
* Instantiate a new adapter for this role. | |||||
*/ | |||||
public RoleAdapter createAdapter() { | |||||
if (adapterVerifier == null) return null; | |||||
try { | |||||
return (RoleAdapter) | |||||
adapterVerifier.getDeclaringClass().newInstance(); | |||||
} | |||||
catch(BuildException be) { | |||||
throw be; | |||||
} | |||||
catch(Exception e) { | |||||
throw new BuildException(e); | |||||
} | |||||
} | |||||
/** | |||||
* Verify if the class can be adapted to use by the role | |||||
* @param role the name of the role to verify | |||||
* @param clz the class to verify | |||||
*/ | |||||
public void verifyAdaptability(String role, Class clz) { | |||||
if (interfaceMethod.getParameterTypes()[0].isAssignableFrom(clz)) { | |||||
return; | |||||
} | |||||
if (adapterVerifier == null) { | |||||
String msg = "Class " + clz.getName() + | |||||
" incompatible with role: " + role; | |||||
throw new BuildException(msg); | |||||
} | |||||
try { | |||||
try { | |||||
adapterVerifier.invoke(null, | |||||
new Object[]{clz, project}); | |||||
} | |||||
catch (InvocationTargetException ite) { | |||||
throw ite.getTargetException(); | |||||
} | |||||
} | |||||
catch(BuildException be) { throw be; } | |||||
catch(Error err) {throw err; } | |||||
catch(Throwable t) { | |||||
throw new BuildException(t); | |||||
} | |||||
} | |||||
public boolean isSameAsFor(Class clz, Class pclz) { | |||||
return interfaceMethod.getDeclaringClass().equals(clz) && | |||||
((adapterVerifier == null && pclz == null) || | |||||
adapterVerifier.getDeclaringClass().equals(pclz)); | |||||
} | |||||
public boolean isImplementedBy(Class clz) { | |||||
return interfaceMethod.getDeclaringClass().isAssignableFrom(clz); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,168 @@ | |||||
/* | |||||
* The Apache Software License, Version 1.1 | |||||
* | |||||
* Copyright (c) 2000-2001 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; | |||||
import java.lang.reflect.Method; | |||||
/** | |||||
* Use introspection to "adapt" an arbitrary Bean ( not extending Task, but with similar | |||||
* patterns). | |||||
* | |||||
* @author costin@dnt.ro | |||||
* @author j_a_fernandez@yahoo.com | |||||
*/ | |||||
public class TaskAdapter extends Task implements RoleAdapter { | |||||
Object proxy; | |||||
/** | |||||
* Checks a class, whether it is suitable to be adapted by TaskAdapter. | |||||
* | |||||
* Checks conditions only, which are additionally required for a tasks | |||||
* adapted by TaskAdapter. Thus, this method should be called by | |||||
* {@link Project#checkTaskClass}. | |||||
* | |||||
* Throws a BuildException and logs as Project.MSG_ERR for | |||||
* conditions, that will cause the task execution to fail. | |||||
* Logs other suspicious conditions with Project.MSG_WARN. | |||||
*/ | |||||
public static void checkTaskClass(final Class taskClass, final Project project) { | |||||
// This code is for backward compatibility | |||||
checkClass(taskClass, project); | |||||
} | |||||
/** | |||||
* Checks a class, whether it is suitable to be adapted. | |||||
* | |||||
* Checks conditions only, which are additionally required for a tasks | |||||
* adapted by TaskAdapter. | |||||
* | |||||
* Throws a BuildException and logs as Project.MSG_ERR for | |||||
* conditions, that will cause the task execution to fail. | |||||
* Logs other suspicious conditions with Project.MSG_WARN. | |||||
*/ | |||||
public static void checkClass(final Class taskClass, final Project project) { | |||||
// don't have to check for interface, since then | |||||
// taskClass would be abstract too. | |||||
try { | |||||
final Method executeM = taskClass.getMethod( "execute", null ); | |||||
// don't have to check for public, since | |||||
// getMethod finds public method only. | |||||
// don't have to check for abstract, since then | |||||
// taskClass would be abstract too. | |||||
if(!Void.TYPE.equals(executeM.getReturnType())) { | |||||
final String message = "return type of execute() should be void but was \""+executeM.getReturnType()+"\" in " + taskClass; | |||||
project.log(message, Project.MSG_WARN); | |||||
} | |||||
} catch(NoSuchMethodException e) { | |||||
final String message = "No public execute() in " + taskClass; | |||||
project.log(message, Project.MSG_ERR); | |||||
throw new BuildException(message); | |||||
} | |||||
} | |||||
/** | |||||
* Do the execution. | |||||
*/ | |||||
public void execute() throws BuildException { | |||||
Method setProjectM = null; | |||||
try { | |||||
Class c = proxy.getClass(); | |||||
setProjectM = | |||||
c.getMethod( "setProject", new Class[] {Project.class}); | |||||
if(setProjectM != null) { | |||||
setProjectM.invoke(proxy, new Object[] {project}); | |||||
} | |||||
} catch (NoSuchMethodException e) { | |||||
// ignore this if the class being used as a task does not have | |||||
// a set project method. | |||||
} catch( Exception ex ) { | |||||
log("Error setting project in " + proxy.getClass(), | |||||
Project.MSG_ERR); | |||||
throw new BuildException( ex ); | |||||
} | |||||
Method executeM=null; | |||||
try { | |||||
Class c=proxy.getClass(); | |||||
executeM=c.getMethod( "execute", new Class[0] ); | |||||
if( executeM == null ) { | |||||
log("No public execute() in " + proxy.getClass(), Project.MSG_ERR); | |||||
throw new BuildException("No public execute() in " + proxy.getClass()); | |||||
} | |||||
executeM.invoke(proxy, null); | |||||
return; | |||||
} catch( Exception ex ) { | |||||
log("Error in " + proxy.getClass(), Project.MSG_ERR); | |||||
throw new BuildException( ex ); | |||||
} | |||||
} | |||||
/** | |||||
* Set the target object class | |||||
*/ | |||||
public void setProxy(Object o) { | |||||
this.proxy = o; | |||||
} | |||||
public Object getProxy() { | |||||
return this.proxy ; | |||||
} | |||||
} |
@@ -0,0 +1,475 @@ | |||||
/* | |||||
* The Apache Software License, Version 1.1 | |||||
* | |||||
* Copyright (c) 2000-2002 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.Task; | |||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.ProjectComponent; | |||||
import org.apache.tools.ant.BuildListener; | |||||
import org.apache.tools.ant.DefaultLogger; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.ProjectHelper; | |||||
import org.apache.tools.ant.util.FileUtils; | |||||
import java.io.File; | |||||
import java.io.PrintStream; | |||||
import java.io.FileOutputStream; | |||||
import java.io.IOException; | |||||
import java.lang.reflect.Method; | |||||
import java.util.Vector; | |||||
import java.util.Hashtable; | |||||
import java.util.Enumeration; | |||||
/** | |||||
* Call Ant in a sub-project | |||||
* | |||||
* <pre> | |||||
* <target name="foo" depends="init"> | |||||
* <ant antfile="build.xml" target="bar" > | |||||
* <property name="property1" value="aaaaa" /> | |||||
* <property name="foo" value="baz" /> | |||||
* </ant></SPAN> | |||||
* </target></SPAN> | |||||
* | |||||
* <target name="bar" depends="init"> | |||||
* <echo message="prop is ${property1} ${foo}" /> | |||||
* </target> | |||||
* </pre> | |||||
* | |||||
* | |||||
* @author costin@dnt.ro | |||||
*/ | |||||
public class Ant extends Task { | |||||
/** the basedir where is executed the build file */ | |||||
private File dir = null; | |||||
/** the build.xml file (can be absolute) in this case dir will be ignored */ | |||||
private String antFile = null; | |||||
/** the target to call if any */ | |||||
private String target = null; | |||||
/** the output */ | |||||
private String output = null; | |||||
/** should we inherit properties from the parent ? */ | |||||
private boolean inheritAll = true; | |||||
/** should we inherit references from the parent ? */ | |||||
private boolean inheritRefs = false; | |||||
/** the properties to pass to the new project */ | |||||
private Vector properties = new Vector(); | |||||
/** the references to pass to the new project */ | |||||
private Vector references = new Vector(); | |||||
/** the temporary project created to run the build file */ | |||||
private Project newProject; | |||||
/** | |||||
* If true, inherit all properties from parent Project | |||||
* If false, inherit only userProperties and those defined | |||||
* inside the ant call itself | |||||
*/ | |||||
public void setInheritAll(boolean value) { | |||||
inheritAll = value; | |||||
} | |||||
/** | |||||
* If true, inherit all references from parent Project | |||||
* If false, inherit only those defined | |||||
* inside the ant call itself | |||||
*/ | |||||
public void setInheritRefs(boolean value) { | |||||
inheritRefs = value; | |||||
} | |||||
public void init() { | |||||
newProject = new Project(project); | |||||
newProject.setJavaVersionProperty(); | |||||
// newProject.addTaskDefinition("property", | |||||
// (Class)project.getTaskDefinitions().get("property")); | |||||
} | |||||
private void reinit() { | |||||
init(); | |||||
final int count = properties.size(); | |||||
for (int i = 0; i < count; i++) { | |||||
Property p = (Property) properties.elementAt(i); | |||||
Property newP = (Property) newProject.createTask("property"); | |||||
newP.setName(p.getName()); | |||||
if (p.getValue() != null) { | |||||
newP.setValue(p.getValue()); | |||||
} | |||||
if (p.getFile() != null) { | |||||
newP.setFile(p.getFile()); | |||||
} | |||||
if (p.getResource() != null) { | |||||
newP.setResource(p.getResource()); | |||||
} | |||||
properties.setElementAt(newP, i); | |||||
} | |||||
} | |||||
private void initializeProject() { | |||||
Vector listeners = project.getBuildListeners(); | |||||
final int count = listeners.size(); | |||||
for (int i = 0; i < count; i++) { | |||||
newProject.addBuildListener((BuildListener)listeners.elementAt(i)); | |||||
} | |||||
if (output != null) { | |||||
try { | |||||
PrintStream out = new PrintStream(new FileOutputStream(output)); | |||||
DefaultLogger logger = new DefaultLogger(); | |||||
logger.setMessageOutputLevel(Project.MSG_INFO); | |||||
logger.setOutputPrintStream(out); | |||||
logger.setErrorPrintStream(out); | |||||
newProject.addBuildListener(logger); | |||||
} | |||||
catch( IOException ex ) { | |||||
log( "Ant: Can't set output to " + output ); | |||||
} | |||||
} | |||||
// Hashtable taskdefs = project.getTaskDefinitions(); | |||||
// Enumeration et = taskdefs.keys(); | |||||
// while (et.hasMoreElements()) { | |||||
// String taskName = (String) et.nextElement(); | |||||
// if (taskName.equals("property")) { | |||||
// // we have already added this taskdef in #init | |||||
// continue; | |||||
// } | |||||
// Class taskClass = (Class) taskdefs.get(taskName); | |||||
// newProject.addTaskDefinition(taskName, taskClass); | |||||
// } | |||||
// Hashtable typedefs = project.getDataTypeDefinitions(); | |||||
// Enumeration e = typedefs.keys(); | |||||
// while (e.hasMoreElements()) { | |||||
// String typeName = (String) e.nextElement(); | |||||
// Class typeClass = (Class) typedefs.get(typeName); | |||||
// newProject.addDataTypeDefinition(typeName, typeClass); | |||||
// } | |||||
// set user-defined or all properties from calling project | |||||
Hashtable prop1; | |||||
if (inheritAll) { | |||||
prop1 = project.getProperties(); | |||||
} else { | |||||
prop1 = project.getUserProperties(); | |||||
// set Java built-in properties separately, | |||||
// b/c we won't inherit them. | |||||
newProject.setSystemProperties(); | |||||
} | |||||
Enumeration e = prop1.keys(); | |||||
while (e.hasMoreElements()) { | |||||
String arg = (String) e.nextElement(); | |||||
if ("basedir".equals(arg) || "ant.file".equals(arg)) { | |||||
// basedir and ant.file get special treatment in execute() | |||||
continue; | |||||
} | |||||
String value = (String) prop1.get(arg); | |||||
if (inheritAll){ | |||||
newProject.setProperty(arg, value); | |||||
} else { | |||||
newProject.setUserProperty(arg, value); | |||||
} | |||||
} | |||||
} | |||||
protected void handleOutput(String line) { | |||||
if (newProject != null) { | |||||
newProject.demuxOutput(line, false); | |||||
} else { | |||||
super.handleOutput(line); | |||||
} | |||||
} | |||||
protected void handleErrorOutput(String line) { | |||||
if (newProject != null) { | |||||
newProject.demuxOutput(line, true); | |||||
} else { | |||||
super.handleErrorOutput(line); | |||||
} | |||||
} | |||||
/** | |||||
* Do the execution. | |||||
*/ | |||||
public void execute() throws BuildException { | |||||
try { | |||||
if (newProject == null) { | |||||
reinit(); | |||||
} | |||||
if ( (dir == null) && (inheritAll) ) { | |||||
dir = project.getBaseDir(); | |||||
} | |||||
initializeProject(); | |||||
if (dir != null) { | |||||
newProject.setBaseDir(dir); | |||||
newProject.setUserProperty("basedir" , dir.getAbsolutePath()); | |||||
} else { | |||||
dir = project.getBaseDir(); | |||||
} | |||||
overrideProperties(); | |||||
if (antFile == null) { | |||||
antFile = "build.xml"; | |||||
} | |||||
File file = FileUtils.newFileUtils().resolveFile(dir, antFile); | |||||
antFile = file.getAbsolutePath(); | |||||
newProject.setUserProperty( "ant.file" , antFile ); | |||||
ProjectHelper.configureProject(newProject, new File(antFile)); | |||||
if (target == null) { | |||||
target = newProject.getDefaultTarget(); | |||||
} | |||||
addReferences(); | |||||
// Are we trying to call the target in which we are defined? | |||||
if (newProject.getBaseDir().equals(project.getBaseDir()) && | |||||
newProject.getProperty("ant.file").equals(project.getProperty("ant.file")) && | |||||
getOwningTarget() != null && | |||||
target.equals(this.getOwningTarget().getName())) { | |||||
throw new BuildException("ant task calling its own parent target"); | |||||
} | |||||
newProject.executeTarget(target); | |||||
} finally { | |||||
// help the gc | |||||
newProject = null; | |||||
} | |||||
} | |||||
/** | |||||
* Override the properties in the new project with the one | |||||
* explicitly defined as nested elements here. | |||||
*/ | |||||
private void overrideProperties() throws BuildException { | |||||
Enumeration e = properties.elements(); | |||||
while (e.hasMoreElements()) { | |||||
Property p = (Property) e.nextElement(); | |||||
p.setProject(newProject); | |||||
p.execute(); | |||||
} | |||||
} | |||||
/** | |||||
* Add the references explicitly defined as nested elements to the | |||||
* new project. Also copy over all references that don't override | |||||
* existing references in the new project if inheritall has been | |||||
* requested. | |||||
*/ | |||||
private void addReferences() throws BuildException { | |||||
Hashtable thisReferences = (Hashtable) project.getReferences().clone(); | |||||
Hashtable newReferences = newProject.getReferences(); | |||||
Enumeration e; | |||||
if (references.size() > 0) { | |||||
for(e = references.elements(); e.hasMoreElements();) { | |||||
Reference ref = (Reference)e.nextElement(); | |||||
String refid = ref.getRefId(); | |||||
if (refid == null) { | |||||
throw new BuildException("the refid attribute is required for reference elements"); | |||||
} | |||||
if (!thisReferences.containsKey(refid)) { | |||||
log("Parent project doesn't contain any reference '" | |||||
+ refid + "'", | |||||
Project.MSG_WARN); | |||||
continue; | |||||
} | |||||
thisReferences.remove(refid); | |||||
String toRefid = ref.getToRefid(); | |||||
if (toRefid == null) { | |||||
toRefid = refid; | |||||
} | |||||
copyReference(refid, toRefid); | |||||
} | |||||
} | |||||
// Now add all references that are not defined in the | |||||
// subproject, if inheritRefs is true | |||||
if (inheritRefs) { | |||||
for(e = thisReferences.keys(); e.hasMoreElements();) { | |||||
String key = (String)e.nextElement(); | |||||
if (newReferences.containsKey(key)) { | |||||
continue; | |||||
} | |||||
copyReference(key, key); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* Try to clone and reconfigure the object referenced by oldkey in | |||||
* the parent project and add it to the new project with the key | |||||
* newkey. | |||||
* | |||||
* <p>If we cannot clone it, copy the referenced object itself and | |||||
* keep our fingers crossed.</p> | |||||
*/ | |||||
private void copyReference(String oldKey, String newKey) { | |||||
Object orig = project.getReference(oldKey); | |||||
Class c = orig.getClass(); | |||||
Object copy = orig; | |||||
try { | |||||
Method cloneM = c.getMethod("clone", new Class[0]); | |||||
if (cloneM != null) { | |||||
copy = cloneM.invoke(orig, new Object[0]); | |||||
} | |||||
} catch (Exception e) { | |||||
// not Clonable | |||||
} | |||||
if (copy instanceof ProjectComponent) { | |||||
((ProjectComponent) copy).setProject(newProject); | |||||
} else { | |||||
try { | |||||
Method setProjectM = | |||||
c.getMethod( "setProject", new Class[] {Project.class}); | |||||
if(setProjectM != null) { | |||||
setProjectM.invoke(copy, new Object[] {newProject}); | |||||
} | |||||
} catch (NoSuchMethodException e) { | |||||
// ignore this if the class being referenced does not have | |||||
// a set project method. | |||||
} catch(Exception e2) { | |||||
String msg = "Error setting new project instance for reference with id " | |||||
+ oldKey; | |||||
throw new BuildException(msg, e2, location); | |||||
} | |||||
} | |||||
newProject.addReference(newKey, copy); | |||||
} | |||||
/** | |||||
* ... | |||||
*/ | |||||
public void setDir(File d) { | |||||
this.dir = d; | |||||
} | |||||
/** | |||||
* set the build file, it can be either absolute or relative. | |||||
* If it is absolute, <tt>dir</tt> will be ignored, if it is | |||||
* relative it will be resolved relative to <tt>dir</tt>. | |||||
*/ | |||||
public void setAntfile(String s) { | |||||
// @note: it is a string and not a file to handle relative/absolute | |||||
// otherwise a relative file will be resolved based on the current | |||||
// basedir. | |||||
this.antFile = s; | |||||
} | |||||
/** | |||||
* set the target to execute. If none is defined it will | |||||
* execute the default target of the build file | |||||
*/ | |||||
public void setTarget(String s) { | |||||
this.target = s; | |||||
} | |||||
public void setOutput(String s) { | |||||
this.output = s; | |||||
} | |||||
/** create a property to pass to the new project as a 'user property' */ | |||||
public Property createProperty() { | |||||
if (newProject == null) { | |||||
reinit(); | |||||
} | |||||
Property p = new Property(true); | |||||
p.setProject(newProject); | |||||
p.setTaskName("property"); | |||||
properties.addElement( p ); | |||||
return p; | |||||
} | |||||
/** | |||||
* create a reference element that identifies a data type that | |||||
* should be carried over to the new project. | |||||
*/ | |||||
public void addReference(Reference r) { | |||||
references.addElement(r); | |||||
} | |||||
/** | |||||
* Helper class that implements the nested <reference> | |||||
* element of <ant> and <antcall>. | |||||
*/ | |||||
public static class Reference | |||||
extends org.apache.tools.ant.types.Reference { | |||||
public Reference() {super();} | |||||
private String targetid=null; | |||||
public void setToRefid(String targetid) { this.targetid=targetid; } | |||||
public String getToRefid() { return targetid; } | |||||
} | |||||
} |
@@ -107,9 +107,6 @@ public class Antjar extends Jar { | |||||
throw new BuildException("Deployment descriptor: " + libraryDescriptor + " does not exist."); | throw new BuildException("Deployment descriptor: " + libraryDescriptor + " does not exist."); | ||||
} | } | ||||
//check | |||||
validateDescriptor(); | |||||
// Create a ZipFileSet for this file, and pass it up. | // Create a ZipFileSet for this file, and pass it up. | ||||
ZipFileSet fs = new ZipFileSet(); | ZipFileSet fs = new ZipFileSet(); | ||||
fs.setDir(new File(libraryDescriptor.getParent())); | fs.setDir(new File(libraryDescriptor.getParent())); | ||||
@@ -130,7 +127,7 @@ public class Antjar extends Jar { | |||||
throws IOException, BuildException { | throws IOException, BuildException { | ||||
// If no antxml file is specified, it's an error. | // If no antxml file is specified, it's an error. | ||||
if (libraryDescriptor == null) { | if (libraryDescriptor == null) { | ||||
throw new BuildException("webxml attribute is required", location); | |||||
throw new BuildException("antxml attribute is required", location); | |||||
} | } | ||||
super.initZipOutputStream(zOut); | super.initZipOutputStream(zOut); | ||||
@@ -177,140 +174,4 @@ public class Antjar extends Jar { | |||||
super.cleanUp(); | 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 | |||||
} | |||||
} | } | ||||
@@ -76,9 +76,11 @@ import java.io.*; | |||||
* @since ant1.5 | * @since ant1.5 | ||||
*/ | */ | ||||
public class Antlib extends Task { | public class Antlib extends Task { | ||||
/* | |||||
* implements DeclaringTask | |||||
/** | |||||
* The named classloader to use. | |||||
* Defaults to the default classLoader. | |||||
*/ | */ | ||||
private String loaderId = ""; | |||||
/** | /** | ||||
* library attribute | * library attribute | ||||
@@ -177,6 +179,15 @@ public class Antlib extends Task { | |||||
this.file = file; | this.file = file; | ||||
} | } | ||||
/** | |||||
* Set the ClassLoader to use for this library. | |||||
* | |||||
* @param id the id for the ClassLoader to use, | |||||
* if other than the default. | |||||
*/ | |||||
public void setLoaderid(String id) { | |||||
this.loaderId = id; | |||||
} | |||||
/** | /** | ||||
* Set whether to override any existing definitions. | * Set whether to override any existing definitions. | ||||
@@ -189,8 +200,9 @@ public class Antlib extends Task { | |||||
/** | /** | ||||
* 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. | |||||
* 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 | * @param useCurrentClassloader if true the current classloader will | ||||
* be used to load the definitions. | * be used to load the definitions. | ||||
@@ -264,7 +276,7 @@ public class Antlib extends Task { | |||||
String msg = "You cannot specify both file and library."; | String msg = "You cannot specify both file and library."; | ||||
throw new BuildException(msg, location); | throw new BuildException(msg, location); | ||||
} | } | ||||
// For the time being libraries live in $ANT_HOME/lib. | |||||
// For the time being libraries live in $ANT_HOME/antlib. | |||||
// The idea being that we would not load all the jars there anymore | // The idea being that we would not load all the jars there anymore | ||||
String home = project.getProperty("ant.home"); | String home = project.getProperty("ant.home"); | ||||
@@ -272,7 +284,7 @@ public class Antlib extends Task { | |||||
throw new BuildException("ANT_HOME not set as required."); | throw new BuildException("ANT_HOME not set as required."); | ||||
} | } | ||||
realFile = new File(new File(home, "lib"), library); | |||||
realFile = new File(new File(home, "antlib"), library); | |||||
} | } | ||||
else if (file == null) { | else if (file == null) { | ||||
String msg = "Must specify either library or file attribute."; | String msg = "Must specify either library or file attribute."; | ||||
@@ -406,8 +418,7 @@ public class Antlib extends Task { | |||||
if (classpath != null) { | if (classpath != null) { | ||||
clspath.append(classpath); | clspath.append(classpath); | ||||
} | } | ||||
AntClassLoader al = new AntClassLoader(project, clspath, true); | |||||
return al; | |||||
return project.getSymbols().addToLoader(loaderId, clspath); | |||||
} | } | ||||
@@ -473,30 +484,6 @@ public class Antlib extends Task { | |||||
} | } | ||||
/** | |||||
* 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 | * Parses the document describing the content of the | ||||
* library. An inner class for access to Project.log | * library. An inner class for access to Project.log | ||||
@@ -516,6 +503,14 @@ public class Antlib extends Task { | |||||
*/ | */ | ||||
private Locator locator = null; | private Locator locator = null; | ||||
private int level = 0; | |||||
private SymbolTable symbols = null; | |||||
private String name = null; | |||||
private String className = null; | |||||
private String adapter = null; | |||||
/** | /** | ||||
* Constructor for the AntLibraryHandler object | * Constructor for the AntLibraryHandler object | ||||
* | * | ||||
@@ -525,9 +520,9 @@ public class Antlib extends Task { | |||||
AntLibraryHandler(ClassLoader classloader, Properties als) { | AntLibraryHandler(ClassLoader classloader, Properties als) { | ||||
this.classloader = classloader; | this.classloader = classloader; | ||||
this.aliasMap = als; | this.aliasMap = als; | ||||
this.symbols = project.getSymbols(); | |||||
} | } | ||||
/** | /** | ||||
* Sets the DocumentLocator attribute of the AntLibraryHandler | * Sets the DocumentLocator attribute of the AntLibraryHandler | ||||
* object | * object | ||||
@@ -538,6 +533,35 @@ public class Antlib extends Task { | |||||
this.locator = locator; | this.locator = locator; | ||||
} | } | ||||
private void parseAttributes(String tag, AttributeList attrs) | |||||
throws SAXParseException { | |||||
name = null; | |||||
className = null; | |||||
adapter = 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 if ("role".equals(tag) && key.equals("adapter")) { | |||||
adapter = value; | |||||
} | |||||
else { | |||||
throw new SAXParseException("Unexpected attribute \"" | |||||
+ key + "\"", locator); | |||||
} | |||||
} | |||||
if (name == null || className == null) { | |||||
String msg = "Underspecified " + tag + " declaration."; | |||||
throw new SAXParseException(msg, locator); | |||||
} | |||||
} | |||||
/** | /** | ||||
* SAX callback handler | * SAX callback handler | ||||
@@ -548,121 +572,105 @@ public class Antlib extends Task { | |||||
*/ | */ | ||||
public void startElement(String tag, AttributeList attrs) | public void startElement(String tag, AttributeList attrs) | ||||
throws SAXParseException { | throws SAXParseException { | ||||
level ++; | |||||
if ("antlib".equals(tag)) { | if ("antlib".equals(tag)) { | ||||
if (level > 1) { | |||||
throw new SAXParseException("Unexpected element: " + tag, | |||||
locator); | |||||
} | |||||
// No attributes to worry about | // No attributes to worry about | ||||
return; | 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); | |||||
} | |||||
if (level == 1) { | |||||
throw new SAXParseException("Missing antlib root element", | |||||
locator); | |||||
} | |||||
// Must have the two attributes declared | |||||
parseAttributes(tag, attrs); | |||||
try { | |||||
if ("role".equals(tag)) { | |||||
if (isRoleInUse(name)) { | |||||
String msg = "Cannot override role: " + name; | |||||
log(msg, Project.MSG_WARN); | |||||
return; | |||||
} | |||||
// Defining a new role | |||||
symbols.addRole(name, loadClass(className), | |||||
(adapter == null? | |||||
null : loadClass(adapter))); | |||||
return; | |||||
} | |||||
// Defining a new element kind | |||||
//check for name alias | |||||
String alias = aliasMap.getProperty(name); | |||||
if (alias != null) { | |||||
name = alias; | |||||
} | |||||
//catch an attempted override of an existing name | |||||
if (!override && isInUse(tag, name)) { | |||||
String msg = "Cannot override " + tag + ": " + name; | |||||
log(msg, Project.MSG_WARN); | |||||
return; | |||||
} | |||||
symbols.add(tag, name, loadClass(className)); | |||||
} | |||||
catch(BuildException be) { | |||||
throw new SAXParseException(be.getMessage(), locator, be); | |||||
} | |||||
} | } | ||||
public void endElement(String tag) { | |||||
level--; | |||||
} | |||||
private Class loadClass(String className) | |||||
throws SAXParseException { | |||||
try { | |||||
//load the named class | |||||
Class cls; | |||||
if(classloader==null) { | |||||
cls=Class.forName(className); | |||||
} | |||||
else { | |||||
cls=classloader.loadClass(className); | |||||
} | |||||
return 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); | |||||
} | |||||
} | |||||
/** | /** | ||||
* test for a name being in use already | |||||
* test for a name being in use already on this role | |||||
* | * | ||||
* @param name the name to test | * @param name the name to test | ||||
* @return true if it is a task or a datatype | * @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); | |||||
private boolean isInUse(String role, String name) { | |||||
return (symbols.get(role, 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". | |||||
* test for a role name being in use already | |||||
* | * | ||||
* @param publicId public ID (ignored) | |||||
* @param systemId system ID (matched against) | |||||
* @return local DTD instance | |||||
* @param name the name to test | |||||
* @return true if it is a task or a datatype | |||||
*/ | */ | ||||
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; | |||||
private boolean isRoleInUse(String name) { | |||||
return (symbols.getRole(name) != null); | |||||
} | } | ||||
//end inner class AntLibraryHandler | //end inner class AntLibraryHandler | ||||
} | } | ||||