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