child elements of user defined tasks that override built-in tasks. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@270141 13f79535-47bb-0310-9956-ffa450edef68master
@@ -114,6 +114,7 @@ public class Project { | |||
private String defaultTarget; | |||
private Hashtable dataClassDefinitions = new Hashtable(); | |||
private Hashtable taskClassDefinitions = new Hashtable(); | |||
private Hashtable createdTasks = new Hashtable(); | |||
private Hashtable targets = new Hashtable(); | |||
private FilterSet globalFilterSet = new FilterSet(); | |||
private FilterSetCollection globalFilters = new FilterSetCollection(globalFilterSet); | |||
@@ -589,9 +590,18 @@ public class Project { | |||
* conditions, that will cause the task execution to fail. | |||
*/ | |||
public void addTaskDefinition(String taskName, Class taskClass) throws BuildException { | |||
if (null != taskClassDefinitions.get(taskName)) { | |||
log("Trying to override old definition of task "+taskName, | |||
MSG_WARN); | |||
Class old = (Class)taskClassDefinitions.get(taskName); | |||
if (null != old) { | |||
if (old.equals(taskClass)) { | |||
log("Ignoring override for task " + taskName | |||
+ ", it is already defined by the same class.", | |||
MSG_VERBOSE); | |||
return; | |||
} else { | |||
log("Trying to override old definition of task "+taskName, | |||
MSG_WARN); | |||
invalidateCreatedTasks(taskName); | |||
} | |||
} | |||
String msg = " +User task: " + taskName + " " + taskClass.getName(); | |||
@@ -751,6 +761,7 @@ public class Project { | |||
String msg = " +Task: " + taskType; | |||
log (msg, MSG_DEBUG); | |||
addCreatedTask(taskType, task); | |||
return task; | |||
} catch (Throwable t) { | |||
String msg = "Could not create task of type: " | |||
@@ -759,6 +770,40 @@ public class Project { | |||
} | |||
} | |||
/** | |||
* Keep a record of all tasks that have been created so that they | |||
* can be invalidated if a taskdef overrides the definition. | |||
*/ | |||
private void addCreatedTask(String type, Task task) { | |||
synchronized (createdTasks) { | |||
Vector v = (Vector) createdTasks.get(type); | |||
if (v == null) { | |||
v = new Vector(); | |||
createdTasks.put(type, v); | |||
} | |||
v.addElement(task); | |||
} | |||
} | |||
/** | |||
* Mark tasks as invalid which no longer are of the correct type | |||
* for a given taskname. | |||
*/ | |||
private void invalidateCreatedTasks(String type) { | |||
synchronized (createdTasks) { | |||
Vector v = (Vector) createdTasks.get(type); | |||
if (v != null) { | |||
Enumeration enum = v.elements(); | |||
while (enum.hasMoreElements()) { | |||
Task t = (Task) enum.nextElement(); | |||
t.markInvalid(); | |||
} | |||
v.removeAllElements(); | |||
createdTasks.remove(type); | |||
} | |||
} | |||
} | |||
/** | |||
* create a new DataType instance | |||
* @param typeName name of the datatype | |||
@@ -138,7 +138,7 @@ public class RuntimeConfigurable { | |||
* Configure the wrapped element and all children. | |||
*/ | |||
public void maybeConfigure(Project p) throws BuildException { | |||
String id = null; | |||
String id = null; | |||
if (attributes != null) { | |||
ProjectHelper.configure(wrappedObject, attributes, p); | |||
@@ -152,7 +152,13 @@ public class RuntimeConfigurable { | |||
Enumeration enum = children.elements(); | |||
while (enum.hasMoreElements()) { | |||
RuntimeConfigurable child = (RuntimeConfigurable) enum.nextElement(); | |||
child.maybeConfigure(p); | |||
if (child.wrappedObject instanceof Task) { | |||
Task childTask = (Task) child.wrappedObject; | |||
childTask.setRuntimeConfigurableWrapper(child); | |||
childTask.maybeConfigure(); | |||
} else { | |||
child.maybeConfigure(p); | |||
} | |||
ProjectHelper.storeChild(p, wrappedObject, child.wrappedObject, child.getElementTag().toLowerCase(Locale.US)); | |||
} | |||
@@ -210,7 +210,7 @@ public class Target implements TaskContainer { | |||
} | |||
} | |||
void replaceChild(UnknownElement el, Object o) { | |||
void replaceChild(Task el, Object o) { | |||
int index = -1; | |||
while ((index = children.indexOf(el)) >= 0) { | |||
children.setElementAt(o, index); | |||
@@ -68,6 +68,7 @@ public abstract class Task extends ProjectComponent { | |||
protected String taskName = null; | |||
protected String taskType = null; | |||
protected RuntimeConfigurable wrapper; | |||
private boolean invalid = false; | |||
/** | |||
* Sets the target object of this task. | |||
@@ -174,8 +175,12 @@ public abstract class Task extends ProjectComponent { | |||
* Configure this task - if it hasn't been done already. | |||
*/ | |||
public void maybeConfigure() throws BuildException { | |||
if (wrapper != null) { | |||
wrapper.maybeConfigure(project); | |||
if (!invalid) { | |||
if (wrapper != null) { | |||
wrapper.maybeConfigure(project); | |||
} | |||
} else { | |||
getReplacement(); | |||
} | |||
} | |||
@@ -211,22 +216,56 @@ public abstract class Task extends ProjectComponent { | |||
* Perform this task | |||
*/ | |||
public final void perform() { | |||
try { | |||
project.fireTaskStarted(this); | |||
maybeConfigure(); | |||
execute(); | |||
project.fireTaskFinished(this, null); | |||
} | |||
catch(RuntimeException exc) { | |||
if (exc instanceof BuildException) { | |||
BuildException be = (BuildException) exc; | |||
if (be.getLocation() == Location.UNKNOWN_LOCATION) { | |||
be.setLocation(getLocation()); | |||
if (!invalid) { | |||
try { | |||
project.fireTaskStarted(this); | |||
maybeConfigure(); | |||
execute(); | |||
project.fireTaskFinished(this, null); | |||
} | |||
catch(RuntimeException exc) { | |||
if (exc instanceof BuildException) { | |||
BuildException be = (BuildException) exc; | |||
if (be.getLocation() == Location.UNKNOWN_LOCATION) { | |||
be.setLocation(getLocation()); | |||
} | |||
} | |||
project.fireTaskFinished(this, exc); | |||
throw exc; | |||
} | |||
project.fireTaskFinished(this, exc); | |||
throw exc; | |||
} else { | |||
UnknownElement ue = getReplacement(); | |||
Task task = ue.getTask(); | |||
task.perform(); | |||
} | |||
} | |||
/** | |||
* Mark this task as invalid. | |||
*/ | |||
final void markInvalid() { | |||
invalid = true; | |||
} | |||
private UnknownElement replacement; | |||
/** | |||
* Create an UnknownElement that can be used to replace this task. | |||
*/ | |||
private UnknownElement getReplacement() { | |||
if (replacement == null) { | |||
replacement = new UnknownElement(taskType); | |||
replacement.setProject(project); | |||
replacement.setTaskType(taskType); | |||
replacement.setTaskName(taskName); | |||
replacement.setLocation(location); | |||
replacement.setOwningTarget(target); | |||
replacement.setRuntimeConfigurableWrapper(wrapper); | |||
wrapper.setProxy(replacement); | |||
target.replaceChild(this, replacement); | |||
replacement.maybeConfigure(); | |||
} | |||
return replacement; | |||
} | |||
} | |||
@@ -238,4 +238,14 @@ public class UnknownElement extends Task { | |||
super.getTaskName() : ((Task) realThing).getTaskName(); | |||
} | |||
/** | |||
* Return the task instance after it has been created (and if it is a task. | |||
*/ | |||
public Task getTask() { | |||
if (realThing != null && realThing instanceof Task) { | |||
return (Task) realThing; | |||
} | |||
return null; | |||
} | |||
}// UnknownElement |