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