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 | * The output generated by the xml formatter for <junit> has changed | ||||
again, it doesn't format the numeric value in the time attribute anymore. | 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: | Other changes: | ||||
-------------- | -------------- | ||||
@@ -120,6 +124,9 @@ Other changes: | |||||
* <junit> can now optionally set a property on test failure. | * <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: | Fixed bugs: | ||||
----------- | ----------- | ||||
@@ -13,6 +13,13 @@ | |||||
used in the current project. Two attributes are needed, the name that identifies | 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 | this task uniquely, and the full name of the class (including the packages) that | ||||
implements this task.</p> | 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 | <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> | href="../develop.html#writingowntask">Writing your own task</a>".</p> | ||||
<h3>Parameters</h3> | <h3>Parameters</h3> | ||||
@@ -25,17 +32,32 @@ href="../develop.html#writingowntask">Writing your own task</a>".</p> | |||||
<tr> | <tr> | ||||
<td valign="top">name</td> | <td valign="top">name</td> | ||||
<td valign="top">the name of the task</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> | ||||
<tr> | <tr> | ||||
<td valign="top">classname</td> | <td valign="top">classname</td> | ||||
<td valign="top">the full class name implementing the task</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> | ||||
<tr> | <tr> | ||||
<td valign="top">classpath</td> <td valign="top">the classpath to | <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> | </tr> | ||||
</table> | </table> | ||||
<h3>Parameters specified as nested elements</h3> | <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 | needed, the name that identifies this data type uniquely, and the full | ||||
name of the class (including the packages) that implements this | name of the class (including the packages) that implements this | ||||
type.</p> | 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 | <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 | types are things like <a href="../using.html#path">paths</a> or <a | ||||
href="../CoreTypes/fileset.html">filesets</a> that can be defined at | 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> | <tr> | ||||
<td valign="top">name</td> | <td valign="top">name</td> | ||||
<td valign="top">the name of the data type</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> | ||||
<tr> | <tr> | ||||
<td valign="top">classname</td> | <td valign="top">classname</td> | ||||
<td valign="top">the full class name implementing the data type</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> | ||||
<tr> | <tr> | ||||
<td valign="top">classpath</td> <td valign="top">the classpath to | <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.*; | ||||
import org.apache.tools.ant.types.*; | import org.apache.tools.ant.types.*; | ||||
import java.util.*; | |||||
import java.io.*; | |||||
/** | /** | ||||
* Base class for Taskdef and Typedef - does all the classpath | * Base class for Taskdef and Typedef - does all the classpath | ||||
* handling and and class loading. | * handling and and class loading. | ||||
* | * | ||||
* @author costin@dnt.ro | |||||
* @author Costin Manolache | |||||
* @author <a href="stefan.bodewig@epost.de">Stefan Bodewig</a> | * @author <a href="stefan.bodewig@epost.de">Stefan Bodewig</a> | ||||
*/ | */ | ||||
public abstract class Definer extends Task { | public abstract class Definer extends Task { | ||||
private String name; | private String name; | ||||
private String value; | private String value; | ||||
private Path classpath; | private Path classpath; | ||||
private File file; | |||||
private String resource; | |||||
public void setClasspath(Path classpath) { | public void setClasspath(Path classpath) { | ||||
if (this.classpath == null) { | if (this.classpath == null) { | ||||
@@ -89,24 +94,73 @@ public abstract class Definer extends Task { | |||||
} | } | ||||
public void execute() throws BuildException { | 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); | Class c = al.loadClass(value); | ||||
AntClassLoader.initializeClass(c); | AntClassLoader.initializeClass(c); | ||||
addDefinition(name, c); | addDefinition(name, c); | ||||
@@ -120,7 +174,30 @@ public abstract class Definer extends Task { | |||||
throw new BuildException(msg, ncdfe, location); | 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) { | public void setName( String name) { | ||||
this.name = name; | this.name = name; | ||||
} | } | ||||