from a property file. Submitted by: <cmanolache@yahoo.com> git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269355 13f79535-47bb-0310-9956-ffa450edef68master
@@ -31,6 +31,10 @@ Changes that could break older environments: | |||
* The output generated by the xml formatter for <junit> has changed | |||
again, it doesn't format the numeric value in the time attribute anymore. | |||
* Pattern matching rules have changes slightly, the pattern foo* | |||
doesn't match files contained in a directory named foo - use foo/* | |||
instead. | |||
Other changes: | |||
-------------- | |||
@@ -120,6 +124,9 @@ Other changes: | |||
* <junit> can now optionally set a property on test failure. | |||
* <taskdef> can now define several tasks at once, reading the | |||
name/classname pairs from a property file or resource. | |||
Fixed bugs: | |||
----------- | |||
@@ -13,6 +13,13 @@ | |||
used in the current project. Two attributes are needed, the name that identifies | |||
this task uniquely, and the full name of the class (including the packages) that | |||
implements this task.</p> | |||
<p>You can also define a group of tasks at once using the file or | |||
resource attributes. These attributes point to files in the format of | |||
Java property files. Each line defines a single task in the | |||
format:</p> | |||
<pre> | |||
taskname=fully.qualified.java.classname | |||
</pre> | |||
<p>Taskdef should be used to add your own tasks to the system. See also "<a | |||
href="../develop.html#writingowntask">Writing your own task</a>".</p> | |||
<h3>Parameters</h3> | |||
@@ -25,17 +32,32 @@ href="../develop.html#writingowntask">Writing your own task</a>".</p> | |||
<tr> | |||
<td valign="top">name</td> | |||
<td valign="top">the name of the task</td> | |||
<td valign="top" align="center">Yes</td> | |||
<td valign="top" align="center">Yes, unless file or resource have | |||
been specified.</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">classname</td> | |||
<td valign="top">the full class name implementing the task</td> | |||
<td valign="top" align="center">Yes</td> | |||
<td valign="top" align="center">Yes, unless file or resource have | |||
been specified.</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">file</td> | |||
<td valign="top">Name of the property file to load | |||
taskname/classname pairs from.</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">resource</td> | |||
<td valign="top">Name of the property resource to load | |||
taskname/classname pairs from.</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">classpath</td> <td valign="top">the classpath to | |||
use when looking up <code>classname</code>.</td> <td | |||
align="center" valign="top">No</td> | |||
use when looking up <code>classname</code> or | |||
<code>resource</code>.</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
</table> | |||
<h3>Parameters specified as nested elements</h3> | |||
@@ -14,6 +14,13 @@ new type can be used in the current project. Two attributes are | |||
needed, the name that identifies this data type uniquely, and the full | |||
name of the class (including the packages) that implements this | |||
type.</p> | |||
<p>You can also define a group of data types at once using the file or | |||
resource attributes. These attributes point to files in the format of | |||
Java property files. Each line defines a single data type in the | |||
format:</p> | |||
<pre> | |||
typename=fully.qualified.java.classname | |||
</pre> | |||
<p>Typedef should be used to add your own types to the system. Data | |||
types are things like <a href="../using.html#path">paths</a> or <a | |||
href="../CoreTypes/fileset.html">filesets</a> that can be defined at | |||
@@ -29,12 +36,26 @@ the project level and referenced via their ID attribute.</p> | |||
<tr> | |||
<td valign="top">name</td> | |||
<td valign="top">the name of the data type</td> | |||
<td valign="top" align="center">Yes</td> | |||
<td valign="top" align="center">Yes, unless file or resource have | |||
been specified.</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">classname</td> | |||
<td valign="top">the full class name implementing the data type</td> | |||
<td valign="top" align="center">Yes</td> | |||
<td valign="top" align="center">Yes, unless file or resource have | |||
been specified.</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">file</td> | |||
<td valign="top">Name of the property file to load | |||
typename/classname pairs from.</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">resource</td> | |||
<td valign="top">Name of the property resource to load | |||
typename/classname pairs from.</td> | |||
<td valign="top" align="center">No</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">classpath</td> <td valign="top">the classpath to | |||
@@ -57,17 +57,22 @@ package org.apache.tools.ant.taskdefs; | |||
import org.apache.tools.ant.*; | |||
import org.apache.tools.ant.types.*; | |||
import java.util.*; | |||
import java.io.*; | |||
/** | |||
* Base class for Taskdef and Typedef - does all the classpath | |||
* handling and and class loading. | |||
* | |||
* @author costin@dnt.ro | |||
* @author Costin Manolache | |||
* @author <a href="stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
*/ | |||
public abstract class Definer extends Task { | |||
private String name; | |||
private String value; | |||
private Path classpath; | |||
private File file; | |||
private String resource; | |||
public void setClasspath(Path classpath) { | |||
if (this.classpath == null) { | |||
@@ -89,24 +94,73 @@ public abstract class Definer extends Task { | |||
} | |||
public void execute() throws BuildException { | |||
if (name==null || value==null ) { | |||
String msg = "name or classname attributes of " | |||
+ getTaskName() + " element " | |||
+ "are undefined"; | |||
throw new BuildException(msg); | |||
} | |||
try { | |||
AntClassLoader al = null; | |||
if (classpath != null) { | |||
al = new AntClassLoader(project, classpath); | |||
} else { | |||
al = new AntClassLoader(project, Path.systemClasspath); | |||
AntClassLoader al=createLoader(); | |||
if (file==null && resource==null ) { | |||
// simple case - one definition | |||
if ( name==null || value==null ) { | |||
String msg = "name or classname attributes of " | |||
+ getTaskName() + " element " | |||
+ "are undefined"; | |||
throw new BuildException(msg); | |||
} | |||
// need to load Task via system classloader or the new | |||
// task we want to define will never be a Task but always | |||
// be wrapped into a TaskAdapter. | |||
al.addSystemPackageRoot("org.apache.tools.ant"); | |||
addDefinition( al, name, value ); | |||
} else { | |||
try { | |||
if (name != null || value != null) { | |||
String msg = "You must not specify name or value " | |||
+ "together with file or resource."; | |||
throw new BuildException(msg, location); | |||
} | |||
if (file != null && resource != null) { | |||
String msg = "You must not specify both, file and resource."; | |||
throw new BuildException(msg, location); | |||
} | |||
Properties props=new Properties(); | |||
InputStream is=null; | |||
if( file != null ) { | |||
log("Loading definitions from file " + file, | |||
Project.MSG_VERBOSE); | |||
is=new FileInputStream( file ); | |||
if (is == null) { | |||
log("Could not load definitions from file " + file | |||
+ ". It doesn\'t exist.", Project.MSG_WARN); | |||
} | |||
} | |||
if( resource!=null ) { | |||
log("Loading definitions from resource " + resource, | |||
Project.MSG_VERBOSE); | |||
is=al.getResourceAsStream( resource ); | |||
if (is == null) { | |||
log("Could not load definitions from resource " | |||
+ resource + ". It could not be found.", | |||
Project.MSG_WARN); | |||
} | |||
} | |||
if( is!=null ) { | |||
props.load( is ); | |||
Enumeration keys=props.keys(); | |||
while( keys.hasMoreElements() ) { | |||
String n=(String)keys.nextElement(); | |||
String v=props.getProperty( n ); | |||
addDefinition( al, n, v ); | |||
} | |||
} | |||
} catch( IOException ex ) { | |||
throw new BuildException(ex, location); | |||
} | |||
} | |||
} | |||
private void addDefinition( ClassLoader al, String name, String value ) { | |||
try { | |||
Class c = al.loadClass(value); | |||
AntClassLoader.initializeClass(c); | |||
addDefinition(name, c); | |||
@@ -120,7 +174,30 @@ public abstract class Definer extends Task { | |||
throw new BuildException(msg, ncdfe, location); | |||
} | |||
} | |||
private AntClassLoader createLoader() { | |||
AntClassLoader al = null; | |||
if (classpath != null) { | |||
al = new AntClassLoader(project, classpath); | |||
} else { | |||
al = new AntClassLoader(project, Path.systemClasspath); | |||
} | |||
// need to load Task via system classloader or the new | |||
// task we want to define will never be a Task but always | |||
// be wrapped into a TaskAdapter. | |||
al.addSystemPackageRoot("org.apache.tools.ant"); | |||
return al; | |||
} | |||
public void setFile( File file ) { | |||
this.file=file; | |||
} | |||
public void setResource( String res ) { | |||
this.resource=res; | |||
} | |||
public void setName( String name) { | |||
this.name = name; | |||
} | |||