found at runtime. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268005 13f79535-47bb-0310-9956-ffa450edef68master
@@ -12,7 +12,7 @@ | |||
<property name="Name" value="Ant"/> | |||
<property name="name" value="ant"/> | |||
<property name="version" value="1.2alpha2"/> | |||
<property name="version" value="1.2alpha3"/> | |||
<property name="ant.home" value="."/> | |||
<property name="src.bin.dir" value="src/bin"/> | |||
@@ -178,6 +178,8 @@ | |||
<copydir src="${docs.dir}" dest="${ant.dist.dir}/docs"/> | |||
<copydir src="${build.javadocs}" dest="${ant.dist.dir}/docs/api"/> | |||
<fixcrlf srcdir="${ant.dist.dir}/bin" includes="ant,antRun" cr="remove"/> | |||
<fixcrlf srcdir="${ant.dist.dir}/bin" includes="*.bat" cr="add"/> | |||
<chmod perm="+x"> | |||
<fileset dir="${ant.dist.dir}/bin"> | |||
<patternset refid="chmod.patterns"/> | |||
@@ -185,6 +187,7 @@ | |||
</chmod> | |||
<copyfile src="README" dest="${ant.dist.dir}/README"/> | |||
<copyfile src="WHATSNEW" dest="${ant.dist.dir}/WHATSNEW"/> | |||
<copyfile src="TODO" dest="${ant.dist.dir}/TODO"/> | |||
<copyfile src="LICENSE" dest="${ant.dist.dir}/LICENSE"/> | |||
</target> | |||
@@ -302,11 +305,6 @@ | |||
<!-- Run testcase --> | |||
<!-- =================================================================== --> | |||
<target name="runtests" depends="compiletests" if="junit.present"> | |||
<!-- | |||
This would make the buildprocess fail if using an Ant version | |||
without the junit task | |||
<junit printsummary="yes" fork="yes" haltonfailure="yes"> | |||
<classpath> | |||
<pathelement location="${lib.dir}/${name}.jar" /> | |||
@@ -324,19 +322,19 @@ | |||
</fileset> | |||
</batchtest> | |||
</junit> | |||
--> | |||
<java fork="yes" | |||
classname="junit.textui.TestRunner" | |||
taskname="junit"> | |||
<arg value="org.apache.tools.ant.AllJUnitTests" /> | |||
<taskdef name="a" classname="A"> | |||
<classpath> | |||
<pathelement location="${lib.dir}/${name}.jar" /> | |||
<pathelement location="${build.tests}" /> | |||
<path refid="classpath" /> | |||
<pathelement path="${java.class.path}" /> | |||
<path location="/tmp" /> | |||
</classpath> | |||
</java> | |||
</taskdef> | |||
<a test="set"> | |||
Bla | |||
<c test="1" /> | |||
</a> | |||
</target> | |||
</project> | |||
@@ -1002,7 +1002,17 @@ execution depending on system parameters.</p> | |||
<td valign="top">file</td> | |||
<td valign="top">the file to look for.</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> | |||
</tr> | |||
</table> | |||
<h3>Parameters specified as nested elements</h3> | |||
<h4>classpath</h4> | |||
<p><code>Available</code>'s <em>classpath</em> attribute is a <a | |||
href="#path">PATH like structure</a> and can also be set via a nested | |||
<em>classpath</em> element.</p> | |||
<h3>Examples</h3> | |||
<pre> <available classname="org.whatever.Myclass" property="Myclass.present" /></pre> | |||
<p>sets the property <code><i>Myclass.present</i></code> to the value "true" | |||
@@ -3650,7 +3660,17 @@ href="#writingowntask">Writing your own task</a>".</p> | |||
<td valign="top">the full class name implementing the task</td> | |||
<td valign="top" align="center">Yes</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> | |||
</tr> | |||
</table> | |||
<h3>Parameters specified as nested elements</h3> | |||
<h4>classpath</h4> | |||
<p><code>Taskdef</code>'s <em>classpath</em> attribute is a <a | |||
href="#path">PATH like structure</a> and can also be set via a nested | |||
<em>classpath</em> element.</p> | |||
<h3>Examples</h3> | |||
<pre> <taskdef name="myjavadoc" classname="com.mydomain.JavadocTask" /></pre> | |||
<p>makes a task called <code>myjavadoc</code> available to Ant. The class <code>com.mydomain.JavadocTask</code> | |||
@@ -429,9 +429,7 @@ public class Project { | |||
Class c = (Class) taskClassDefinitions.get(taskType); | |||
if (c == null) | |||
throw new BuildException("Could not create task of type: "+taskType+ | |||
" because I can't find it in the list of task"+ | |||
" class definitions"); | |||
return null; | |||
try { | |||
Object o = c.newInstance(); | |||
Task task = null; | |||
@@ -363,7 +363,17 @@ public class ProjectHelper { | |||
} | |||
public void init(String tag, AttributeList attrs) throws SAXParseException { | |||
task = project.createTask(tag); | |||
try { | |||
task = project.createTask(tag); | |||
} catch (BuildException e) { | |||
// swallow here, will be thrown again in | |||
// UnknownElement.maybeConfigure if the problem persists. | |||
} | |||
if (task == null) { | |||
task = new UnknownElement(tag); | |||
task.setProject(project); | |||
} | |||
task.setLocation(new Location(buildFile.toString(), locator.getLineNumber(), locator.getColumnNumber())); | |||
configureId(task, attrs); | |||
@@ -422,7 +432,13 @@ public class ProjectHelper { | |||
IntrospectionHelper.getHelper(targetClass); | |||
try { | |||
child = ih.createElement(target, propType.toLowerCase()); | |||
if (target instanceof UnknownElement) { | |||
child = new UnknownElement(propType.toLowerCase()); | |||
((UnknownElement) target).addChild((UnknownElement) child); | |||
} else { | |||
child = ih.createElement(target, propType.toLowerCase()); | |||
} | |||
configureId(child, attrs); | |||
if (parentWrapper != null) { | |||
@@ -80,6 +80,10 @@ public class RuntimeConfigurable { | |||
wrappedObject = proxy; | |||
} | |||
void setProxy(Object proxy) { | |||
wrappedObject = proxy; | |||
} | |||
/** | |||
* Set's the attributes for the wrapped element. | |||
*/ | |||
@@ -87,6 +91,13 @@ public class RuntimeConfigurable { | |||
this.attributes = new AttributeListImpl(attributes); | |||
} | |||
/** | |||
* Returns the AttributeList of the wrapped element. | |||
*/ | |||
public AttributeList getAttributes() { | |||
return attributes; | |||
} | |||
/** | |||
* Adds child elements to the wrapped element. | |||
*/ | |||
@@ -94,6 +105,13 @@ public class RuntimeConfigurable { | |||
children.addElement(child); | |||
} | |||
/** | |||
* Returns the child with index <code>index</code>. | |||
*/ | |||
RuntimeConfigurable getChild(int index) { | |||
return (RuntimeConfigurable) children.elementAt(index); | |||
} | |||
/** | |||
* Add characters from #PCDATA areas to the wrapped element. | |||
*/ | |||
@@ -159,6 +159,13 @@ public class Target { | |||
} | |||
} | |||
void replaceTask(UnknownElement el, Task t) { | |||
int index = -1; | |||
while ((index = tasks.indexOf(el)) >= 0) { | |||
tasks.setElementAt(t, index); | |||
} | |||
} | |||
private boolean testIfCondition() { | |||
return "".equals(ifCondition) | |||
|| project.getProperty(ifCondition) != null; | |||
@@ -205,6 +205,10 @@ public abstract class Task { | |||
return wrapper; | |||
} | |||
protected void setRuntimeConfigurableWrapper(RuntimeConfigurable wrapper) { | |||
this.wrapper = wrapper; | |||
} | |||
/** | |||
* Configure this task - if it hasn't been done already. | |||
*/ | |||
@@ -0,0 +1,145 @@ | |||
/* | |||
* The Apache Software License, Version 1.1 | |||
* | |||
* Copyright (c) 2000 The Apache Software Foundation. All rights | |||
* reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in | |||
* the documentation and/or other materials provided with the | |||
* distribution. | |||
* | |||
* 3. The end-user documentation included with the redistribution, if | |||
* any, must include the following acknowlegement: | |||
* "This product includes software developed by the | |||
* Apache Software Foundation (http://www.apache.org/)." | |||
* Alternately, this acknowlegement may appear in the software itself, | |||
* if and wherever such third-party acknowlegements normally appear. | |||
* | |||
* 4. The names "The Jakarta Project", "Tomcat", 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.util.Vector; | |||
/** | |||
* Wrapper class that holds all information necessary to create a task | |||
* that did not exist when Ant started. | |||
* | |||
* @author <a href="stefan.bodewig@megabit.net">Stefan Bodewig</a> | |||
*/ | |||
public class UnknownElement extends Task { | |||
private String elementName; | |||
private Task realTask; | |||
private Vector children = new Vector(); | |||
public UnknownElement (String elementName) { | |||
this.elementName = elementName; | |||
} | |||
/** | |||
* return the corresponding XML tag. | |||
*/ | |||
public String getTag() { | |||
return elementName; | |||
} | |||
public void maybeConfigure() throws BuildException { | |||
realTask = project.createTask(elementName); | |||
if (realTask == null) { | |||
throw new BuildException("Could not create task of type: "+elementName+ | |||
" because I can\'t find it in the list of task"+ | |||
" class definitions", location); | |||
} | |||
realTask.setLocation(location); | |||
String id = wrapper.getAttributes().getValue("id"); | |||
if (id != null) { | |||
project.addReference(id, realTask); | |||
} | |||
realTask.init(); | |||
// UnknownElement always has an associated target | |||
realTask.setOwningTarget(target); | |||
wrapper.setProxy(realTask); | |||
realTask.setRuntimeConfigurableWrapper(wrapper); | |||
handleChildren(realTask, wrapper); | |||
realTask.maybeConfigure(); | |||
target.replaceTask(this, realTask); | |||
} | |||
/** | |||
* Called when the real task has been configured for the first time. | |||
*/ | |||
public void execute() { | |||
if (realTask == null) { | |||
// plain impossible to get here, maybeConfigure should | |||
// have thrown an exception. | |||
throw new BuildException("Could not create task of type: " | |||
+ elementName, location); | |||
} | |||
realTask.execute(); | |||
} | |||
public void addChild(UnknownElement child) { | |||
children.addElement(child); | |||
} | |||
protected void handleChildren(Object parent, | |||
RuntimeConfigurable parentWrapper) | |||
throws BuildException { | |||
if (parent instanceof TaskAdapter) { | |||
parent = ((TaskAdapter) parent).getProxy(); | |||
} | |||
Class parentClass = parent.getClass(); | |||
IntrospectionHelper ih = IntrospectionHelper.getHelper(parentClass); | |||
for (int i=0; i<children.size(); i++) { | |||
UnknownElement child = (UnknownElement) children.elementAt(i); | |||
Object realChild = ih.createElement(parent, child.getTag()); | |||
RuntimeConfigurable childWrapper = parentWrapper.getChild(i); | |||
childWrapper.setProxy(realChild); | |||
child.handleChildren(realChild, childWrapper); | |||
} | |||
} | |||
}// UnknownElement |
@@ -242,6 +242,8 @@ public class AntStructure extends Task { | |||
enum = ih.getAttributes(); | |||
while (enum.hasMoreElements()) { | |||
String attrName = (String) enum.nextElement(); | |||
if ("id".equals(attrName)) continue; | |||
sb.append(lSep).append(" ").append(attrName).append(" "); | |||
Class type = ih.getAttributeType(attrName); | |||
if (type.equals(java.lang.Boolean.class) || | |||
@@ -55,6 +55,7 @@ | |||
package org.apache.tools.ant.taskdefs; | |||
import org.apache.tools.ant.*; | |||
import org.apache.tools.ant.types.*; | |||
/** | |||
* Define a new task - name and class | |||
@@ -64,6 +65,26 @@ import org.apache.tools.ant.*; | |||
public class Taskdef extends Task { | |||
private String name; | |||
private String value; | |||
private Path classpath; | |||
public void setClasspath(Path classpath) { | |||
if (this.classpath == null) { | |||
this.classpath = classpath; | |||
} else { | |||
this.classpath.append(classpath); | |||
} | |||
} | |||
public Path createClasspath() { | |||
if (this.classpath == null) { | |||
this.classpath = new Path(project); | |||
} | |||
return this.classpath.createPath(); | |||
} | |||
public void setClasspathRef(Reference r) { | |||
createClasspath().setRefid(r); | |||
} | |||
public void execute() throws BuildException { | |||
if (name==null || value==null ) { | |||
@@ -72,8 +93,20 @@ public class Taskdef extends Task { | |||
throw new BuildException(msg); | |||
} | |||
try { | |||
Class taskClass = Class.forName(value); | |||
project.addTaskDefinition(name, taskClass); | |||
ClassLoader loader = null; | |||
if (classpath != null) { | |||
loader = new AntClassLoader(project, classpath, false); | |||
} else { | |||
loader = this.getClass().getClassLoader(); | |||
} | |||
Class taskClass = null; | |||
if (loader != null) { | |||
taskClass = loader.loadClass(value); | |||
} else { | |||
taskClass = Class.forName(value); | |||
} | |||
project.addTaskDefinition(name, taskClass); | |||
} catch (ClassNotFoundException cnfe) { | |||
String msg = "taskdef class " + value + | |||
" cannot be found"; | |||
@@ -67,6 +67,8 @@ import java.util.*; | |||
public class IntrospectionHelperTest extends TestCase { | |||
public static boolean isUnixStyle = File.pathSeparatorChar == ':'; | |||
public IntrospectionHelperTest(String name) { | |||
super(name); | |||
} | |||
@@ -404,7 +406,11 @@ public class IntrospectionHelperTest extends TestCase { | |||
} | |||
public void setTen(File f) { | |||
assertEquals("/tmp/2", f.getAbsolutePath()); | |||
if (isUnixStyle) { | |||
assertEquals("/tmp/2", f.getAbsolutePath()); | |||
} else { | |||
assertEquals("c:\\tmp\\2", f.getAbsolutePath().toLowerCase()); | |||
} | |||
} | |||
public void setEleven(boolean b) { | |||
@@ -129,7 +129,7 @@ public class PathTest extends TestCase { | |||
assertEquals("/test", l[1]); | |||
} else { | |||
assertEquals("drives on DOS", 1, l.length); | |||
assertEquals("c:\\test", l[0]); | |||
assertEquals("c:\\test", l[0].toLowerCase()); | |||
} | |||
p = new Path(project, "c:/test"); | |||
@@ -141,7 +141,7 @@ public class PathTest extends TestCase { | |||
assertEquals("/test", l[1]); | |||
} else { | |||
assertEquals("drives on DOS", 1, l.length); | |||
assertEquals("c:\\test", l[0]); | |||
assertEquals("c:\\test", l[0].toLowerCase()); | |||
} | |||
} | |||