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 String defaultTarget; | ||||
private Hashtable dataClassDefinitions = new Hashtable(); | private Hashtable dataClassDefinitions = new Hashtable(); | ||||
private Hashtable taskClassDefinitions = new Hashtable(); | private Hashtable taskClassDefinitions = new Hashtable(); | ||||
private Hashtable createdTasks = new Hashtable(); | |||||
private Hashtable targets = new Hashtable(); | private Hashtable targets = new Hashtable(); | ||||
private FilterSet globalFilterSet = new FilterSet(); | private FilterSet globalFilterSet = new FilterSet(); | ||||
private FilterSetCollection globalFilters = new FilterSetCollection(globalFilterSet); | private FilterSetCollection globalFilters = new FilterSetCollection(globalFilterSet); | ||||
@@ -589,9 +590,18 @@ public class Project { | |||||
* conditions, that will cause the task execution to fail. | * conditions, that will cause the task execution to fail. | ||||
*/ | */ | ||||
public void addTaskDefinition(String taskName, Class taskClass) throws BuildException { | 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(); | String msg = " +User task: " + taskName + " " + taskClass.getName(); | ||||
@@ -751,6 +761,7 @@ public class Project { | |||||
String msg = " +Task: " + taskType; | String msg = " +Task: " + taskType; | ||||
log (msg, MSG_DEBUG); | log (msg, MSG_DEBUG); | ||||
addCreatedTask(taskType, task); | |||||
return task; | return task; | ||||
} catch (Throwable t) { | } catch (Throwable t) { | ||||
String msg = "Could not create task of type: " | 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 | * create a new DataType instance | ||||
* @param typeName name of the datatype | * @param typeName name of the datatype | ||||
@@ -138,7 +138,7 @@ public class RuntimeConfigurable { | |||||
* Configure the wrapped element and all children. | * Configure the wrapped element and all children. | ||||
*/ | */ | ||||
public void maybeConfigure(Project p) throws BuildException { | public void maybeConfigure(Project p) throws BuildException { | ||||
String id = null; | |||||
String id = null; | |||||
if (attributes != null) { | if (attributes != null) { | ||||
ProjectHelper.configure(wrappedObject, attributes, p); | ProjectHelper.configure(wrappedObject, attributes, p); | ||||
@@ -152,7 +152,13 @@ public class RuntimeConfigurable { | |||||
Enumeration enum = children.elements(); | Enumeration enum = children.elements(); | ||||
while (enum.hasMoreElements()) { | while (enum.hasMoreElements()) { | ||||
RuntimeConfigurable child = (RuntimeConfigurable) enum.nextElement(); | 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)); | 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; | int index = -1; | ||||
while ((index = children.indexOf(el)) >= 0) { | while ((index = children.indexOf(el)) >= 0) { | ||||
children.setElementAt(o, index); | children.setElementAt(o, index); | ||||
@@ -68,6 +68,7 @@ public abstract class Task extends ProjectComponent { | |||||
protected String taskName = null; | protected String taskName = null; | ||||
protected String taskType = null; | protected String taskType = null; | ||||
protected RuntimeConfigurable wrapper; | protected RuntimeConfigurable wrapper; | ||||
private boolean invalid = false; | |||||
/** | /** | ||||
* Sets the target object of this task. | * 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. | * Configure this task - if it hasn't been done already. | ||||
*/ | */ | ||||
public void maybeConfigure() throws BuildException { | 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 | * Perform this task | ||||
*/ | */ | ||||
public final void perform() { | 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(); | 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 | }// UnknownElement |