diff --git a/WHATSNEW b/WHATSNEW index 70b9d2951..cea2a1a64 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -28,6 +28,10 @@ Fixed bugs: contain at least a manifest file, therefore it will now print a warning and do nothing. +* hasn't been all that useful as it couldn't be used outside + of targets (it can now) and nested "unknown" elements have always + been considered to be tasks (changed as well). + Other changes: -------------- diff --git a/src/etc/testcases/taskdefs/taskdef.xml b/src/etc/testcases/taskdefs/taskdef.xml index 0c8383806..9473eec36 100644 --- a/src/etc/testcases/taskdefs/taskdef.xml +++ b/src/etc/testcases/taskdefs/taskdef.xml @@ -7,6 +7,11 @@ + + + + @@ -51,4 +56,10 @@ + + + + + + diff --git a/src/etc/testcases/taskdefs/typedef.xml b/src/etc/testcases/taskdefs/typedef.xml new file mode 100644 index 000000000..165d4df93 --- /dev/null +++ b/src/etc/testcases/taskdefs/typedef.xml @@ -0,0 +1,49 @@ + + + + + + This file should only be run via a testcase + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/org/apache/tools/ant/ProjectHelper.java b/src/main/org/apache/tools/ant/ProjectHelper.java index c0e55cc67..742623fd3 100644 --- a/src/main/org/apache/tools/ant/ProjectHelper.java +++ b/src/main/org/apache/tools/ant/ProjectHelper.java @@ -350,6 +350,8 @@ public class ProjectHelper { public void startElement(String name, AttributeList attrs) throws SAXParseException { if (name.equals("taskdef")) { handleTaskdef(name, attrs); + } else if (name.equals("typedef")) { + handleTypedef(name, attrs); } else if (name.equals("property")) { handleProperty(name, attrs); } else if (name.equals("target")) { @@ -365,6 +367,10 @@ public class ProjectHelper { (new TaskHandler(this, null, null, null)).init(name, attrs); } + private void handleTypedef(String name, AttributeList attrs) throws SAXParseException { + (new TaskHandler(this, null, null, null)).init(name, attrs); + } + private void handleProperty(String name, AttributeList attrs) throws SAXParseException { (new TaskHandler(this, null, null, null)).init(name, attrs); } diff --git a/src/main/org/apache/tools/ant/Target.java b/src/main/org/apache/tools/ant/Target.java index 18a80a630..1da28de48 100644 --- a/src/main/org/apache/tools/ant/Target.java +++ b/src/main/org/apache/tools/ant/Target.java @@ -210,10 +210,10 @@ public class Target implements TaskContainer { } } - void replaceTask(UnknownElement el, Task t) { + void replaceChild(UnknownElement el, Object o) { int index = -1; while ((index = children.indexOf(el)) >= 0) { - children.setElementAt(t, index); + children.setElementAt(o, index); } } diff --git a/src/main/org/apache/tools/ant/UnknownElement.java b/src/main/org/apache/tools/ant/UnknownElement.java index c3aa6d726..3f349d3e7 100644 --- a/src/main/org/apache/tools/ant/UnknownElement.java +++ b/src/main/org/apache/tools/ant/UnknownElement.java @@ -58,22 +58,22 @@ import java.util.Vector; /** * Wrapper class that holds all information necessary to create a task - * that did not exist when Ant started. + * or data type that did not exist when Ant started. * * @author Stefan Bodewig */ public class UnknownElement extends Task { /** - * Holds the name of the task or nested child element of a task - * that hasn't been defined at parser time. + * Holds the name of the task/type or nested child element of a + * task/type that hasn't been defined at parser time. */ private String elementName; /** - * The task after it has been loaded. + * The real object after it has been loaded. */ - private Task realTask; + private Object realThing; /** * Childelements, holds UnknownElement instances. @@ -92,33 +92,41 @@ public class UnknownElement extends Task { } /** - * creates the task instance, creates child elements, configures - * the attributes of the task. + * creates the real object instance, creates child elements, configures + * the attributes of the real object. */ public void maybeConfigure() throws BuildException { - realTask = makeTask(this, wrapper); + realThing = makeObject(this, wrapper); - wrapper.setProxy(realTask); - realTask.setRuntimeConfigurableWrapper(wrapper); + wrapper.setProxy(realThing); + if (realThing instanceof Task) { + ((Task) realThing).setRuntimeConfigurableWrapper(wrapper); + } - handleChildren(realTask, wrapper); + handleChildren(realThing, wrapper); - realTask.maybeConfigure(); - target.replaceTask(this, realTask); + wrapper.maybeConfigure(project); + if (realThing instanceof Task) { + target.replaceChild(this, realThing); + } else { + target.replaceChild(this, wrapper); + } } /** * Called when the real task has been configured for the first time. */ public void execute() { - if (realTask == null) { + if (realThing == null) { // plain impossible to get here, maybeConfigure should // have thrown an exception. throw new BuildException("Could not create task of type: " + elementName, location); } - realTask.perform(); + if (realThing instanceof Task) { + ((Task) realThing).perform(); + } } /** @@ -149,7 +157,7 @@ public class UnknownElement extends Task { Object realChild = null; if (parent instanceof TaskContainer) { - realChild = makeTask(child, childWrapper); + realChild = makeTask(child, childWrapper, false); ((TaskContainer) parent).addTask((Task) realChild); } else { realChild = ih.createElement(project, parent, child.getTag()); @@ -168,44 +176,62 @@ public class UnknownElement extends Task { } } + /** + * Creates a named task or data type - if it is a task, configure it up to the init() stage. + */ + protected Object makeObject(UnknownElement ue, RuntimeConfigurable w) { + Object o = makeTask(ue, w, true); + if (o == null) { + o = project.createDataType(ue.getTag()); + } + if (o == null) { + throw getNotFoundException("task or type", ue.getTag()); + } + return o; + } + /** * Create a named task and configure it up to the init() stage. */ - protected Task makeTask(UnknownElement ue, RuntimeConfigurable w) { + protected Task makeTask(UnknownElement ue, RuntimeConfigurable w, + boolean onTopLevel) { Task task = project.createTask(ue.getTag()); - if (task == null) { - String lSep = System.getProperty("line.separator"); - String msg = "Could not create task of type: " + elementName - + "." + lSep - + "Ant could not find the task or a class this" + lSep - + "task relies upon." + lSep - + "Common solutions are to use taskdef to declare" + lSep - + "your task, or, if this is an optional task," + lSep - + "to put the optional.jar and all required libraries of" +lSep - + "this task in the lib directory of" + lSep - + "your ant installation (ANT_HOME)."; - throw new BuildException(msg, location); + if (task == null && !onTopLevel) { + throw getNotFoundException("task", ue.getTag()); } - task.setLocation(getLocation()); - String id = w.getAttributes().getValue("id"); - if (id != null) { - project.addReference(id, task); + if (task != null) { + task.setLocation(getLocation()); + // UnknownElement always has an associated target + task.setOwningTarget(target); + task.init(); } - // UnknownElement always has an associated target - task.setOwningTarget(target); - - task.init(); return task; } + protected BuildException getNotFoundException(String what, + String elementName) { + String lSep = System.getProperty("line.separator"); + String msg = "Could not create " + what + " of type: " + elementName + + "." + lSep + + "Ant could not find the task or a class this" + lSep + + "task relies upon." + lSep + + "Common solutions are to use taskdef to declare" + lSep + + "your task, or, if this is an optional task," + lSep + + "to put the optional.jar and all required libraries of" +lSep + + "this task in the lib directory of" + lSep + + "your ant installation (ANT_HOME)."; + return new BuildException(msg, location); + } + /** * Get the name to use in logging messages. * * @return the name to use in logging messages. */ public String getTaskName() { - return realTask == null ? super.getTaskName() : realTask.getTaskName(); + return realThing == null || !(realThing instanceof Task) ? + super.getTaskName() : ((Task) realThing).getTaskName(); } }// UnknownElement diff --git a/src/testcases/org/apache/tools/ant/taskdefs/TaskdefTest.java b/src/testcases/org/apache/tools/ant/taskdefs/TaskdefTest.java index 27020cad3..f50bf706b 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/TaskdefTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/TaskdefTest.java @@ -100,4 +100,8 @@ public class TaskdefTest extends TaskdefsTest { public void test7() { expectLog("test7", "worked"); } + + public void testGlobal() { + expectLog("testGlobal", "worked"); + } } diff --git a/src/testcases/org/apache/tools/ant/taskdefs/TypedefTest.java b/src/testcases/org/apache/tools/ant/taskdefs/TypedefTest.java new file mode 100644 index 000000000..d0a5dd85b --- /dev/null +++ b/src/testcases/org/apache/tools/ant/taskdefs/TypedefTest.java @@ -0,0 +1,107 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 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", "Ant", 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 + * . + */ + +package org.apache.tools.ant.taskdefs; + +import org.apache.tools.ant.Project; + +/** + * @author Stefan Bodewig + * @version $Revision$ + */ +public class TypedefTest extends TaskdefsTest { + + public TypedefTest(String name) { + super(name); + } + + public void setUp() { + configureProject("src/etc/testcases/taskdefs/typedef.xml"); + } + + public void testEmpty() { + expectBuildException("empty", "required argument not specified"); + } + + public void testNoName() { + expectBuildException("noName", "required argument not specified"); + } + + public void testNoClassname() { + expectBuildException("noClassname", "required argument not specified"); + } + + public void testClassNotFound() { + expectBuildException("classNotFound", + "classname specified doesn't exist"); + } + + public void testGlobal() { + expectLog("testGlobal", ""); + Object ref = project.getReferences().get("global"); + assertNotNull("ref is not null", ref); + assertEquals("org.example.types.TypedefTestType", + ref.getClass().getName()); + } + + public void testLocal() { + expectLog("testLocal", + "Overriding previous definition of reference to local"); + Object ref = project.getReferences().get("local"); + assertNotNull("ref is not null", ref); + assertEquals("org.example.types.TypedefTestType", + ref.getClass().getName()); + } + +} diff --git a/src/testcases/org/example/types/TypedefTestType.java b/src/testcases/org/example/types/TypedefTestType.java new file mode 100644 index 000000000..b736ad03d --- /dev/null +++ b/src/testcases/org/example/types/TypedefTestType.java @@ -0,0 +1,61 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 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", "Ant", 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 + * . + */ + +package org.example.types; + +import org.apache.tools.ant.ProjectComponent; + +public class TypedefTestType extends ProjectComponent { +} +