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 | |||