Browse Source

Make <typedef> something that is useful.

PR: 4143


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269893 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 23 years ago
parent
commit
ba558a362e
9 changed files with 308 additions and 40 deletions
  1. +4
    -0
      WHATSNEW
  2. +11
    -0
      src/etc/testcases/taskdefs/taskdef.xml
  3. +49
    -0
      src/etc/testcases/taskdefs/typedef.xml
  4. +6
    -0
      src/main/org/apache/tools/ant/ProjectHelper.java
  5. +2
    -2
      src/main/org/apache/tools/ant/Target.java
  6. +64
    -38
      src/main/org/apache/tools/ant/UnknownElement.java
  7. +4
    -0
      src/testcases/org/apache/tools/ant/taskdefs/TaskdefTest.java
  8. +107
    -0
      src/testcases/org/apache/tools/ant/taskdefs/TypedefTest.java
  9. +61
    -0
      src/testcases/org/example/types/TypedefTestType.java

+ 4
- 0
WHATSNEW View File

@@ -28,6 +28,10 @@ Fixed bugs:
contain at least a manifest file, therefore it will now print a
warning and do nothing.

* <typedef> 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:
--------------



+ 11
- 0
src/etc/testcases/taskdefs/taskdef.xml View File

@@ -7,6 +7,11 @@
<pathelement path="${java.class.path}" />
</path>

<taskdef name="global"
classname="org.example.tasks.TaskdefTestContainerTask">
<classpath refid="testclasses" />
</taskdef>

<target name="test1">
<taskdef/>
</target>
@@ -51,4 +56,10 @@
</test7>
</target>

<target name="testGlobal">
<global>
<echo message="worked" />
</global>
</target>

</project>

+ 49
- 0
src/etc/testcases/taskdefs/typedef.xml View File

@@ -0,0 +1,49 @@
<?xml version="1.0"?>

<project name="test" basedir="." default="invalid">

<target name="invalid">
<fail>This file should only be run via a testcase</fail>
</target>

<target name="empty">
<typedef />
</target>

<target name="noClassname">
<typedef name="dummy" />
</target>

<target name="noName">
<typedef classname="org.example.types.TypedefTestType">
<classpath refid="testclasses" />
</typedef>
</target>

<target name="classNotFound">
<typedef name="" classname="oops"/>
</target>

<path id="testclasses">
<pathelement location="../../../../build/testcases" />
<pathelement path="${java.class.path}" />
</path>

<typedef name="global"
classname="org.example.types.TypedefTestType">
<classpath refid="testclasses" />
</typedef>

<target name="testGlobal">
<global id="global" />
</target>

<target name="testLocal">
<typedef name="local"
classname="org.example.types.TypedefTestType">
<classpath refid="testclasses" />
</typedef>
<local id="local" />
</target>

</project>

+ 6
- 0
src/main/org/apache/tools/ant/ProjectHelper.java View File

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


+ 2
- 2
src/main/org/apache/tools/ant/Target.java View File

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



+ 64
- 38
src/main/org/apache/tools/ant/UnknownElement.java View File

@@ -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 <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
*/
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

+ 4
- 0
src/testcases/org/apache/tools/ant/taskdefs/TaskdefTest.java View File

@@ -100,4 +100,8 @@ public class TaskdefTest extends TaskdefsTest {
public void test7() {
expectLog("test7", "worked");
}

public void testGlobal() {
expectLog("testGlobal", "worked");
}
}

+ 107
- 0
src/testcases/org/apache/tools/ant/taskdefs/TypedefTest.java View File

@@ -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
* <http://www.apache.org/>.
*/

package org.apache.tools.ant.taskdefs;

import org.apache.tools.ant.Project;

/**
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
* @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());
}

}

+ 61
- 0
src/testcases/org/example/types/TypedefTestType.java View File

@@ -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
* <http://www.apache.org/>.
*/

package org.example.types;

import org.apache.tools.ant.ProjectComponent;

public class TypedefTestType extends ProjectComponent {
}


Loading…
Cancel
Save