diff --git a/proposal/mutant/build.xml b/proposal/mutant/build.xml
index 67a03633e..5e5790b8f 100644
--- a/proposal/mutant/build.xml
+++ b/proposal/mutant/build.xml
@@ -55,6 +55,9 @@
+
+
+
diff --git a/proposal/mutant/src/main/org/apache/ant/component/core/AntAspectHandler.java b/proposal/mutant/src/main/org/apache/ant/component/core/AntAspectHandler.java
new file mode 100644
index 000000000..1b691742a
--- /dev/null
+++ b/proposal/mutant/src/main/org/apache/ant/component/core/AntAspectHandler.java
@@ -0,0 +1,75 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000 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.ant.component.core;
+
+import java.io.File;
+import java.net.*;
+import org.apache.ant.core.execution.*;
+
+/**
+ *
+ * @author Conor MacNeill
+ */
+public class AntAspectHandler extends AbstractAspectHandler {
+ private String id;
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public void afterConfigElement(Object element) throws ExecutionException {
+ getAspectContext().setDataValue(id, element);
+ }
+}
diff --git a/proposal/mutant/src/main/org/apache/ant/component/core/Echo.java b/proposal/mutant/src/main/org/apache/ant/component/core/Echo.java
index 03aa67d6e..a2305c90b 100644
--- a/proposal/mutant/src/main/org/apache/ant/component/core/Echo.java
+++ b/proposal/mutant/src/main/org/apache/ant/component/core/Echo.java
@@ -63,7 +63,7 @@ import java.io.*;
*
* @author costin@dnt.ro
*/
-public class Echo extends ExecutionTask {
+public class Echo extends AbstractTask {
protected String message = ""; // required
protected File file = null;
protected boolean append = false;
diff --git a/proposal/mutant/src/main/org/apache/ant/component/core/FileConverter.java b/proposal/mutant/src/main/org/apache/ant/component/core/FileConverter.java
index c98c2e8a1..58e61de92 100644
--- a/proposal/mutant/src/main/org/apache/ant/component/core/FileConverter.java
+++ b/proposal/mutant/src/main/org/apache/ant/component/core/FileConverter.java
@@ -76,7 +76,6 @@ public class FileConverter implements AntConverter {
try {
URL url = new URL(frame.getBaseURL(), value);
if (url.getProtocol().equals("file")) {
- System.out.println("Converted URL to " + url);
return new File(url.getFile());
}
return new File(value);
diff --git a/proposal/mutant/src/main/org/apache/ant/component/core/Property.java b/proposal/mutant/src/main/org/apache/ant/component/core/Property.java
index 7e1c72a98..80c841d91 100644
--- a/proposal/mutant/src/main/org/apache/ant/component/core/Property.java
+++ b/proposal/mutant/src/main/org/apache/ant/component/core/Property.java
@@ -62,7 +62,7 @@ import java.net.*;
/**
*
*/
-public class Property extends ExecutionTask {
+public class Property extends AbstractTask {
private String name;
private String value;
private URL file;
@@ -144,9 +144,8 @@ public class Property extends ExecutionTask {
//
public void execute() throws ExecutionException {
- ExecutionFrame frame = getExecutionFrame();
if ((name != null) && (value != null)) {
- frame.setDataValue(name, value);
+ getTaskContext().setDataValue(name, value);
}
if (file != null) {
@@ -199,11 +198,11 @@ public class Property extends ExecutionTask {
}
protected void addProperties(Properties properties) throws ExecutionException {
- ExecutionFrame frame = getExecutionFrame();
for (Iterator i = properties.keySet().iterator(); i.hasNext();) {
String propertyName = (String)i.next();
String propertyValue = properties.getProperty(propertyName);
- frame.setDataValue(propertyName, frame.replacePropertyRefs(propertyValue));
+ getTaskContext().setDataValue(propertyName,
+ getTaskContext().replacePropertyRefs(propertyValue));
}
}
diff --git a/proposal/mutant/src/main/org/apache/ant/component/core/antlib.xml b/proposal/mutant/src/main/org/apache/ant/component/core/antlib.xml
index 19d0b960a..2df9b68d1 100644
--- a/proposal/mutant/src/main/org/apache/ant/component/core/antlib.xml
+++ b/proposal/mutant/src/main/org/apache/ant/component/core/antlib.xml
@@ -1,8 +1,17 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/proposal/mutant/src/main/org/apache/ant/component/thread/Parallel.java b/proposal/mutant/src/main/org/apache/ant/component/thread/Parallel.java
new file mode 100644
index 000000000..eb5e2268c
--- /dev/null
+++ b/proposal/mutant/src/main/org/apache/ant/component/thread/Parallel.java
@@ -0,0 +1,78 @@
+/*
+ * 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.ant.component.thread;
+
+import org.apache.ant.core.execution.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * Parallel execution of contained tasks.
+ *
+ */
+public class Parallel extends AbstractTask implements TaskContainer {
+ private List tasks = new ArrayList();
+
+ public void addTask(Task nestedTask) {
+ tasks.add(nestedTask);
+ }
+
+ public void execute() throws ExecutionException {
+ for (Iterator i = tasks.iterator(); i.hasNext(); ) {
+ Task nestedTask = (Task)i.next();
+ nestedTask.execute();
+ }
+ }
+}
diff --git a/proposal/mutant/src/main/org/apache/ant/component/thread/Sequential.java b/proposal/mutant/src/main/org/apache/ant/component/thread/Sequential.java
new file mode 100644
index 000000000..3ae824c5d
--- /dev/null
+++ b/proposal/mutant/src/main/org/apache/ant/component/thread/Sequential.java
@@ -0,0 +1,78 @@
+/*
+ * 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.ant.component.thread;
+
+import org.apache.ant.core.execution.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * Sequential execution of contained tasks.
+ *
+ */
+public class Sequential extends AbstractTask implements TaskContainer {
+ private List tasks = new ArrayList();
+
+ public void addTask(Task nestedTask) {
+ tasks.add(nestedTask);
+ }
+
+ public void execute() throws ExecutionException {
+ for (Iterator i = tasks.iterator(); i.hasNext(); ) {
+ Task nestedTask = (Task)i.next();
+ nestedTask.execute();
+ }
+ }
+}
diff --git a/proposal/mutant/src/main/org/apache/ant/component/thread/antlib.xml b/proposal/mutant/src/main/org/apache/ant/component/thread/antlib.xml
new file mode 100644
index 000000000..1b22f56ab
--- /dev/null
+++ b/proposal/mutant/src/main/org/apache/ant/component/thread/antlib.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/AbstractAspectHandler.java b/proposal/mutant/src/main/org/apache/ant/core/execution/AbstractAspectHandler.java
new file mode 100644
index 000000000..6fcc1e2b0
--- /dev/null
+++ b/proposal/mutant/src/main/org/apache/ant/core/execution/AbstractAspectHandler.java
@@ -0,0 +1,80 @@
+/*
+ * 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.ant.core.execution;
+
+import org.apache.ant.core.model.*;
+import org.apache.ant.core.support.*;
+import java.util.*;
+import java.net.URL;
+
+/**
+ *
+ * @author Conor MacNeill
+ */
+public abstract class AbstractAspectHandler implements AspectHandler {
+ private ExecutionContext aspectContext;
+
+ public void setAspectContext(ExecutionContext context) {
+ this.aspectContext = context;
+ }
+
+ protected ExecutionContext getAspectContext() {
+ return aspectContext;
+ }
+
+ public void afterConfigElement(Object element) throws ExecutionException {
+ }
+}
+
diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/AbstractTask.java b/proposal/mutant/src/main/org/apache/ant/core/execution/AbstractTask.java
new file mode 100644
index 000000000..9fac29aad
--- /dev/null
+++ b/proposal/mutant/src/main/org/apache/ant/core/execution/AbstractTask.java
@@ -0,0 +1,96 @@
+/*
+ * 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.ant.core.execution;
+
+import org.apache.ant.core.model.*;
+import org.apache.ant.core.support.*;
+import java.util.*;
+import java.net.URL;
+
+/**
+ * @author Conor MacNeill
+ */
+public abstract class AbstractTask implements Task {
+ private ExecutionContext taskContext;
+
+ public void setTaskContext(ExecutionContext context) {
+ this.taskContext = context;
+ }
+
+ protected ExecutionContext getTaskContext() {
+ return taskContext;
+ }
+
+ /**
+ * Log a message with the default (INFO) priority.
+ *
+ * @param msg the message to be logged.
+ */
+ public void log(String msg) {
+ log(msg, BuildEvent.MSG_INFO);
+ }
+
+ /**
+ * Log a mesage with the give priority.
+ *
+ * @param the message to be logged.
+ * @param msgLevel the message priority at which this message is to be logged.
+ */
+ public void log(String msg, int msgLevel) {
+ taskContext.log(msg, msgLevel);
+ }
+
+}
+
diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/AntLibrary.java b/proposal/mutant/src/main/org/apache/ant/core/execution/AntLibrary.java
index 194b2403d..6e4873136 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/execution/AntLibrary.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/execution/AntLibrary.java
@@ -54,6 +54,7 @@
package org.apache.ant.core.execution;
+import org.apache.ant.core.support.*;
import java.util.*;
import java.net.URL;
@@ -68,35 +69,51 @@ public class AntLibrary {
/**
* The task definitions contained by this library
*/
- private List taskDefinitions = new ArrayList();
+ private Map taskDefinitions = new HashMap();
/**
* The converter definitions contained by this library
*/
- private List converterDefinitions = new ArrayList();
+ private Map converterDefinitions = new HashMap();
+
+ /**
+ * The aspect handler definitions contained by this library
+ */
+ private Map aspectDefinitions = new HashMap();
/**
* Add a task definition to this library
*/
public void addTaskDefinition(TaskDefinition taskDefinition) {
- taskDefinitions.add(taskDefinition);
+ String taskName = taskDefinition.getName();
+ taskDefinitions.put(taskName, taskDefinition);
}
-
+
+ /**
+ * Add a converter definition to this library
+ */
+ public void addConverterDefinition(ConverterDefinition converterDef) {
+ String targetClassname = converterDef.getTargetClassName();
+ converterDefinitions.put(targetClassname, converterDef);
+ }
+
+ /**
+ * Add an aspect handler definition to this library
+ */
+ public void addAspectDefinition(AspectDefinition aspectDef) {
+ String aspectPrefix = aspectDef.getAspectPrefix();
+ aspectDefinitions.put(aspectPrefix, aspectDef);
+ }
+
/**
* Get the task definitions
*
* @return an iterator which returns TaskDefinition objects.
*/
public Iterator getTaskDefinitions() {
- return taskDefinitions.iterator();
+ return taskDefinitions.values().iterator();
}
- /**
- * Add a converter definition to this library
- */
- public void addConverterDefinition(ConverterDefinition converterDefinition) {
- converterDefinitions.add(converterDefinition);
- }
/**
* Get the converter definitions
@@ -104,7 +121,17 @@ public class AntLibrary {
* @return an iterator which returns ConverterDefinition objects.
*/
public Iterator getConverterDefinitions() {
- return converterDefinitions.iterator();
+ return converterDefinitions.values().iterator();
}
+
+ /**
+ * Get the aspect handler definitions
+ *
+ * @return an iterator which returns AspectDefinition objects.
+ */
+ public Iterator getAspectDefinitions() {
+ return aspectDefinitions.values().iterator();
+ }
+
}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/AspectDefinition.java b/proposal/mutant/src/main/org/apache/ant/core/execution/AspectDefinition.java
new file mode 100644
index 000000000..5a20ec3d9
--- /dev/null
+++ b/proposal/mutant/src/main/org/apache/ant/core/execution/AspectDefinition.java
@@ -0,0 +1,124 @@
+/*
+ * 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.ant.core.execution;
+
+import java.util.*;
+import java.net.URL;
+
+/**
+ * @author Conor MacNeill
+ */
+public class AspectDefinition {
+ /** The URL of the library which defines this aspect handler */
+ private URL aspectLibraryURL;
+
+ /** The aspect's tag */
+ private String aspectPrefix;
+
+ /** The aspect handler's classname */
+ private String aspectClassName;
+
+ /** The aspect handler's class loader. */
+ private ClassLoader aspectClassLoader;
+
+ /** The class to which this converter converts. */
+ private Class aspectHandlerClass = null;
+
+ public AspectDefinition(URL aspectLibraryURL, String aspectPrefix,
+ String aspectClassName, ClassLoader aspectClassLoader) {
+ this.aspectLibraryURL = aspectLibraryURL;
+ this.aspectPrefix = aspectPrefix;
+ this.aspectClassName = aspectClassName;
+ this.aspectClassLoader = aspectClassLoader;
+ }
+
+ /**
+ * Get the URL where this aspect handler was defined.
+ *
+ * @returns a URL of the lib defintion file
+ */
+ public URL getLibraryURL() {
+ return aspectLibraryURL;
+ }
+
+ /**
+ * Get the Aspect's Prefix
+ */
+ public String getAspectPrefix() {
+ return aspectPrefix;
+ }
+
+
+ /**
+ * Get the aspect handler class
+ *
+ * @return a class object for this aspect handler's class
+ */
+ public synchronized Class getAspectHandlerClass() throws ClassNotFoundException {
+ if (aspectHandlerClass == null) {
+ aspectHandlerClass = Class.forName(aspectClassName, true, aspectClassLoader);
+ }
+ return aspectHandlerClass;
+ }
+
+ /**
+ * Get the classname of the aspect handler that is being defined.
+ */
+ public String getAspectHandlerClassName() {
+ return aspectClassName;
+ }
+
+}
+
diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/AspectHandler.java b/proposal/mutant/src/main/org/apache/ant/core/execution/AspectHandler.java
new file mode 100644
index 000000000..4acf85352
--- /dev/null
+++ b/proposal/mutant/src/main/org/apache/ant/core/execution/AspectHandler.java
@@ -0,0 +1,74 @@
+/*
+ * 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.ant.core.execution;
+
+import org.apache.ant.core.model.*;
+import org.apache.ant.core.support.*;
+import java.util.*;
+import java.net.URL;
+
+/**
+ * An AspectHandler is used to handle a set of aspects which may occur in a number
+ * of elements in the build model.
+ *
+ * @author Conor MacNeill
+ */
+public interface AspectHandler {
+
+ void setAspectContext(ExecutionContext context);
+
+ void afterConfigElement(Object element) throws ExecutionException ;
+}
+
diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/ClassIntrospectionException.java b/proposal/mutant/src/main/org/apache/ant/core/execution/ClassIntrospectionException.java
index 3c1aaeaae..088ac34dd 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/execution/ClassIntrospectionException.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/execution/ClassIntrospectionException.java
@@ -90,7 +90,7 @@ public class ClassIntrospectionException extends Exception {
* @param cause Exception that might have caused this one.
*/
public ClassIntrospectionException(Throwable cause) {
- super(cause.toString());
+ super(cause.getMessage());
this.cause = cause;
}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/ConverterDefinition.java b/proposal/mutant/src/main/org/apache/ant/core/execution/ConverterDefinition.java
index 99101bba7..b1a4640cf 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/execution/ConverterDefinition.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/execution/ConverterDefinition.java
@@ -124,7 +124,7 @@ public class ConverterDefinition {
*/
public synchronized Class getConverterClass() throws ClassNotFoundException {
if (converterClass == null) {
- converterClass = converterClassLoader.loadClass(converterClassName);
+ converterClass = Class.forName(converterClassName, true, converterClassLoader);
}
return converterClass;
}
@@ -136,7 +136,7 @@ public class ConverterDefinition {
*/
public synchronized Class getTargetClass() throws ClassNotFoundException {
if (targetClass == null) {
- targetClass = converterClassLoader.loadClass(targetClassName);
+ targetClass = Class.forName(targetClassName, true, converterClassLoader);
}
return targetClass;
}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionTask.java b/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionContext.java
similarity index 64%
rename from proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionTask.java
rename to proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionContext.java
index f3a190d2e..cb4b768b5 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionTask.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionContext.java
@@ -60,60 +60,22 @@ import java.util.*;
import java.net.URL;
/**
- * An ExecutionTask is the execution time equivalent of the Task
- * object in the Ant project model. Subclasses of ExecutionTask are
- * created by Task writers to implement particular, desired
- * functionality
- *
- * An ExecutionTask subclass is created for a particular task type.
- * The data from the task model is introspected into the ExecutionTask
- * which is then executed.
+ * The ExecutionContext interface provides a task or apsect instance with access to the
+ * container-provided services. This is the only way to access the container.
*
* @author Conor MacNeill
*/
-public abstract class ExecutionTask {
+public class ExecutionContext {
private ExecutionFrame frame = null;
- private Location location = Location.UNKNOWN_LOCATION;
private BuildEventSupport eventSupport;
private BuildElement buildElement;
- void setExecutionFrame(ExecutionFrame frame) {
+ public ExecutionContext(ExecutionFrame frame, BuildEventSupport eventSupport,
+ BuildElement buildElement) {
this.frame = frame;
- }
-
- /**
- * Get the ExecutionFrame in which this ExecutionTask is being executed.
- * to which this task belongs
- *
- * @return the execution task's ExecutionFrame.
- */
- public ExecutionFrame getExecutionFrame() {
- return frame;
- }
-
- /**
- * Configure the event support to be used to fire events
- */
- void setBuildEventSupport(BuildEventSupport eventSupport) {
this.eventSupport = eventSupport;
- }
-
- /**
- * Associate this ExecutionTask with a buildElement in the
- * project model
- */
- void setBuildElement(BuildElement buildElement) {
this.buildElement = buildElement;
}
-
- /**
- * Log a message with the default (INFO) priority.
- *
- * @param msg the message to be logged.
- */
- public void log(String msg) {
- log(msg, BuildEvent.MSG_INFO);
- }
/**
* Log a mesage with the give priority.
@@ -125,26 +87,22 @@ public abstract class ExecutionTask {
eventSupport.fireMessageLogged(this, buildElement, msg, msgLevel);
}
- /**
- * Called by the project to let the task initialize properly.
- *
- * @throws ExecutionException if someting goes wrong with the build
- */
- public void init() throws ExecutionException {}
+ public void setDataValue(String name, Object value) throws ExecutionException {
+ frame.setDataValue(name, value);
+ }
- /**
- * Called by the frame to let the task do it's work.
- *
- * @throws ExecutionException if someting goes wrong with the build
- */
- abstract public void execute() throws ExecutionException;
+ public Object getDataValue(String name) throws ExecutionException {
+ return frame.getDataValue(name);
+ }
/**
- * Returns the file location where this task was defined.
+ * Replace ${} style constructions in the given value with the string value of
+ * the corresponding data types.
+ *
+ * @param value the string to be scanned for property references.
*/
- public Location getLocation() {
- return buildElement.getLocation();
+ public String replacePropertyRefs(String value) throws ExecutionException {
+ return frame.replacePropertyRefs(value);
}
-
}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionFrame.java b/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionFrame.java
index 59bb1d062..ffb28aca4 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionFrame.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionFrame.java
@@ -55,6 +55,7 @@ package org.apache.ant.core.execution;
import org.apache.ant.core.model.*;
import org.apache.ant.core.support.*;
+import org.apache.ant.core.types.*;
import java.util.*;
import java.net.*;
@@ -67,6 +68,13 @@ import java.net.*;
* @author Conor MacNeill
*/
public class ExecutionFrame {
+ /** State used in dependency analysis when a target's dependencies are being
+ examined. */
+ private static final String VISITING = "VISITING";
+
+ /** State used in dependency analysis to indicate a target has been examined */
+ private static final String VISITED = "VISITED";
+
/** The Project that this execiton frame is processing */
private Project project = null;
@@ -74,9 +82,6 @@ public class ExecutionFrame {
Project's source URL and it's base attribute. */
private URL baseURL = null;
- /** The task defs that this frame will use to process tasks */
- private Map taskDefs = new HashMap();
-
/** The imported frames of this frame. For each project imported by this frame's
project, a corresponding ExecutionFrame is created. */
private Map importedFrames = new HashMap();
@@ -88,22 +93,79 @@ public class ExecutionFrame {
created by tasks that have been executed */
private Map dataValues = new HashMap();
- /** Introspector objects used to configure ExecutionTasks from the Task models.*/
+ /** Introspector objects used to configure Tasks from the Task models.*/
private Map introspectors = new HashMap();
+ /** The task defs that this frame will use to process tasks */
+ private Map taskDefs = new HashMap();
+
/** Type converters for this executionFrame. Converters are used when configuring
Tasks to handle special type conversions. */
private Map converters = new HashMap();
+ /** The aspect handler active in this frame */
+ private Map aspectHandlers = new HashMap();
+
/** The namespace under which this execution frame lives in the hierarchical
project namespace - null for the root namespace */
private String namespace;
- public ExecutionFrame(Project project, Map taskDefs, Map converterDefs,
- String namespace) throws ConfigException {
- this.project = project;
- this.taskDefs = taskDefs;
+ /**
+ * Construct an execution frame to process the given project model with
+ * the configuration represented by the libraries.
+ *
+ * @param project the model of the project to be built.
+ * @param libraries an Array of AntLibrary objects containing the
+ * configuration of Ant for this build.
+ *
+ * @throws ConfigException when the project cannot be setup with the
+ * given configuration
+ */
+ public ExecutionFrame(Project project, AntLibrary[] libraries)
+ throws ConfigException {
+
+ this.namespace = null;
+ setupFrame(project, libraries);
+ }
+
+ /**
+ * Construct a subframe for managing a project imported into the main project.
+ * @param project the model of the project to be built.
+ * @param libraries an Array of AntLibrary objects containing the
+ * configuration of Ant for this build.
+ * @param namespace the location of this project within the overall import
+ * namespace.
+ *
+ * @throws ConfigException when the project cannot be setup with the
+ * given configuration
+ */
+ private ExecutionFrame(Project project, AntLibrary[] libraries, String namespace)
+ throws ConfigException {
+
this.namespace = namespace;
+ setupFrame(project, libraries);
+ }
+
+
+ /**
+ * Set up the execution frame.
+ *
+ * This method examines the project model and constructs the required
+ * subframes to handle imported projects.
+ * @param project the model of the project to be built.
+ * @param libraries an Array of AntLibrary objects containing the
+ * configuration of Ant for this build.
+ *
+ * @throws ConfigException when the project cannot be setup with the
+ * given configuration
+ */
+ private void setupFrame(Project project, AntLibrary[] libraries)
+ throws ConfigException {
+
+ this.project = project;
+ for (int i = 0; i < libraries.length; ++i) {
+ addLibrary(libraries[i]);
+ }
try {
String base = project.getBase();
@@ -123,74 +185,149 @@ public class ExecutionFrame {
+ "\" is not valid", e, project.getLocation());
}
- // We create a set of converters from the converter definitions we
- // have been given and initialise them. They should be AntConverters
- setupConverters(converterDefs);
-
for (Iterator i = project.getImportedProjectNames(); i.hasNext();) {
String importName = (String)i.next();
Project importedProject = project.getImportedProject(importName);
String importNamespace
= namespace == null ? importName : namespace + ":" + importName;
ExecutionFrame importedFrame
- = new ExecutionFrame(importedProject, taskDefs, converterDefs, importNamespace);
+ = new ExecutionFrame(importedProject, libraries, importNamespace);
importedFrames.put(importName, importedFrame);
}
}
- public URL getBaseURL() {
- return baseURL;
+ /**
+ * Add a configuration library to this execution frame. The library
+ * will contain task definitions, converters, apsect handler definitions,
+ * etc.
+ *
+ * @param library the configuration library to add to this frame.
+ *
+ * @throws ConfigException if the items in the library cannot be configured.
+ */
+ public void addLibrary(AntLibrary library) throws ConfigException {
+ for (Iterator i = library.getTaskDefinitions(); i.hasNext(); ) {
+ TaskDefinition taskDefinition = (TaskDefinition)i.next();
+ addTaskDefinition(taskDefinition);
+ }
+ for (Iterator i = library.getConverterDefinitions(); i.hasNext(); ) {
+ ConverterDefinition converterDef = (ConverterDefinition)i.next();
+ addConverterDefinition(converterDef);
+ }
+ for (Iterator i = library.getAspectDefinitions(); i.hasNext(); ) {
+ AspectDefinition aspectDef = (AspectDefinition)i.next();
+ addAspectHandler(aspectDef);
+ }
}
- private void setupConverters(Map converterDefs) throws ConfigException {
- converters = new HashMap();
- for (Iterator i = converterDefs.values().iterator(); i.hasNext(); ) {
- ConverterDefinition converterDef = (ConverterDefinition)i.next();
- boolean targetLoaded = false;
- try {
- Class targetClass = converterDef.getTargetClass();
- targetLoaded = false;
- Class converterClass = converterDef.getConverterClass();
- Converter converter = (AntConverter)converterClass.newInstance();
- if (converter instanceof AntConverter) {
- ((AntConverter)converter).init(this);
- }
- converters.put(targetClass, converter);
- }
- catch (ClassNotFoundException e) {
- if (targetLoaded) {
- throw new ConfigException("Unable to load converter class for "
- + converterDef.getConverterClassName()
- + " in converter from " + converterDef.getLibraryURL()
- , e);
- }
- else {
- throw new ConfigException("Unable to load target class "
- + converterDef.getTargetClassName()
- + " in converter from " + converterDef.getLibraryURL()
- , e);
- }
+ /**
+ * Add a task definition to this execution frame
+ *
+ * @param taskDefinition the TaskDefinition to be added to the project.
+ */
+ public void addTaskDefinition(TaskDefinition taskDefinition) {
+ String taskName = taskDefinition.getName();
+ taskDefs.put(taskName, taskDefinition);
+ }
+
+ /**
+ * Add a aspect handler definition to this execution frame
+ *
+ * @param taskDefinition the TaskDefinition to be added to the project.
+ *
+ * @throws ConfigException if the aspect handler cannot be created or configured.
+ */
+ public void addAspectHandler(AspectDefinition aspectDefinition)
+ throws ConfigException {
+ String aspectPrefix = aspectDefinition.getAspectPrefix();
+ try {
+ Class aspectHandlerClass = aspectDefinition.getAspectHandlerClass();
+ aspectHandlers.put(aspectPrefix, aspectHandlerClass);
+ }
+ catch (ClassNotFoundException e) {
+ throw new ConfigException("Unable to load aspect handler class for "
+ + aspectDefinition.getAspectHandlerClassName()
+ + " in converter from " + aspectDefinition.getLibraryURL(),
+ e);
+ }
+ }
+
+ /**
+ * Add a converter definition to this library.
+ *
+ * The converter is created immediately to handle conversions
+ * when items are being configured. If the converter is an instance of
+ * an AntConverter, the converter is configured with this execution
+ * frame giving it the context it needs to resolve items relative to the
+ * project's base, etc.
+ *
+ * @param converterDef the converter definition to load
+ *
+ * @throws ConfigException if the converter cannot be created or configured.
+ */
+ public void addConverterDefinition(ConverterDefinition converterDef) throws ConfigException {
+ boolean targetLoaded = false;
+ try {
+ Class targetClass = converterDef.getTargetClass();
+ targetLoaded = false;
+ Class converterClass = converterDef.getConverterClass();
+ Converter converter = (AntConverter)converterClass.newInstance();
+ if (converter instanceof AntConverter) {
+ ((AntConverter)converter).init(this);
}
- catch (InstantiationException e) {
- throw new ConfigException("Unable to instantiate converter class "
- + converterDef.getTargetClassName()
- + " in converter from " + converterDef.getLibraryURL()
- , e);
+ converters.put(targetClass, converter);
+ }
+ catch (ClassNotFoundException e) {
+ if (targetLoaded) {
+ throw new ConfigException("Unable to load converter class for "
+ + converterDef.getConverterClassName()
+ + " in converter from " + converterDef.getLibraryURL(),
+ e);
}
- catch (IllegalAccessException e) {
- throw new ConfigException("Unable to access converter class "
+ else {
+ throw new ConfigException("Unable to load target class "
+ converterDef.getTargetClassName()
- + " in converter from " + converterDef.getLibraryURL()
- , e);
+ + " in converter from " + converterDef.getLibraryURL(),
+ e);
}
}
+ catch (InstantiationException e) {
+ throw new ConfigException("Unable to instantiate converter class "
+ + converterDef.getTargetClassName()
+ + " in converter from " + converterDef.getLibraryURL(),
+ e);
+ }
+ catch (IllegalAccessException e) {
+ throw new ConfigException("Unable to access converter class "
+ + converterDef.getTargetClassName()
+ + " in converter from " + converterDef.getLibraryURL(),
+ e);
+ }
}
+
+ /**
+ * Get the bae URL of this frame. This will either be specified by the project's
+ * base attribute or be derived implicitly from the project's location.
+ */
+ public URL getBaseURL() {
+ return baseURL;
+ }
+
+
public void addBuildListener(BuildListener listener) {
+ for (Iterator i = getImportedFrames(); i.hasNext(); ) {
+ ExecutionFrame subFrame = (ExecutionFrame)i.next();
+ subFrame.addBuildListener(listener);
+ }
eventSupport.addBuildListener(listener);
}
public void removeBuildListener(BuildListener listener) {
+ for (Iterator i = getImportedFrames(); i.hasNext(); ) {
+ ExecutionFrame subFrame = (ExecutionFrame)i.next();
+ subFrame.removeBuildListener(listener);
+ }
eventSupport.removeBuildListener(listener);
}
@@ -257,26 +394,6 @@ public class ExecutionFrame {
return namespace == null ? name : namespace + ":" + name;
}
- /**
- * Get the relative name of something with respect to this
- * execution frame.
- *
- * @param fullname the fully qualified name.
- *
- * @return the relative version of the given name
- */
- public String getRelativeName(String fullname) {
- if (namespace == null) {
- return fullname;
- }
- int index = fullname.indexOf(namespace);
- if (index != 0) {
- return fullname;
- }
-
- return fullname.substring(namespace.length() + 1);
- }
-
/**
* Execute the given target's tasks
*
@@ -297,32 +414,140 @@ public class ExecutionFrame {
}
/**
- * Initialise the frame by executing the project level tasks if any
+ * Initialize the frame by executing the project level tasks if any
*/
- public void initialise() throws ExecutionException, ConfigException {
+ public void initialize() throws ExecutionException, ConfigException {
+ for (Iterator i = getImportedFrames(); i.hasNext(); ) {
+ ExecutionFrame subFrame = (ExecutionFrame)i.next();
+ subFrame.initialize();
+ }
Iterator taskIterator = project.getTasks();
executeTasks(taskIterator);
}
+ public void fillinDependencyOrder(String targetName, List dependencyOrder,
+ Map state, Stack visiting) throws ConfigException {
+ String fullTargetName = getQualifiedName(targetName);
+ if (state.get(fullTargetName) == VISITED) {
+ return;
+ }
+ Target target = getProject().getTarget(targetName);
+ if (target == null) {
+ StringBuffer sb = new StringBuffer("Target `");
+ sb.append(targetName);
+ sb.append("' does not exist in this project. ");
+ if (!visiting.empty()) {
+ String parent = (String)visiting.peek();
+ sb.append("It is used from target `");
+ sb.append(parent);
+ sb.append("'.");
+ }
+
+ throw new ConfigException(new String(sb), getProject().getLocation());
+ }
+
+ state.put(fullTargetName, VISITING);
+ visiting.push(fullTargetName);
+ for (Iterator i = target.getDependencies(); i.hasNext(); ) {
+ String dependency = (String)i.next();
+ try {
+ ExecutionFrame dependencyFrame = getRelativeFrame(dependency);
+ if (dependencyFrame == null) {
+ StringBuffer sb = new StringBuffer("Target `");
+ sb.append(dependency);
+ sb.append("' does not exist in this project. ");
+ throw new ConfigException(new String(sb), target.getLocation());
+ }
+
+ String fullyQualifiedName = getQualifiedName(dependency);
+ String dependencyState = (String)state.get(fullyQualifiedName);
+ if (dependencyState == null) {
+ dependencyFrame.fillinDependencyOrder(getNameInFrame(dependency), dependencyOrder,
+ state, visiting);
+ }
+ else if (dependencyState == VISITING) {
+ String circleDescription
+ = getCircularDesc(dependency, visiting);
+ throw new ConfigException(circleDescription, target.getLocation());
+ }
+ }
+ catch (ExecutionException e) {
+ throw new ConfigException(e.getMessage(), e, target.getLocation());
+ }
+ }
+
+ state.put(fullTargetName, VISITED);
+ String poppedNode = (String)visiting.pop();
+ if (poppedNode != fullTargetName) {
+ throw new ConfigException("Problem determining dependencies " +
+ " - expecting '" + fullTargetName +
+ "' but got '" + poppedNode + "'");
+ }
+ dependencyOrder.add(fullTargetName);
+ }
+
+ private String getCircularDesc(String end, Stack visitingNodes) {
+ StringBuffer sb = new StringBuffer("Circular dependency: ");
+ sb.append(end);
+ String c;
+ do {
+ c = (String)visitingNodes.pop();
+ sb.append(" <- ");
+ sb.append(c);
+ } while(!c.equals(end));
+ return new String(sb);
+ }
+
+ /**
+ * Check whether the targets in this frame and its subframes are OK
+ */
+ public void checkTargets(List dependencyOrder, Map state, Stack visiting)
+ throws ConfigException {
+ // get the targets and just iterate through them.
+ for (Iterator i = getProject().getTargets(); i.hasNext();) {
+ Target target = (Target)i.next();
+ fillinDependencyOrder(target.getName(),
+ dependencyOrder, state, visiting);
+ }
+
+ // Now do the subframes.
+ for (Iterator i = getImportedFrames(); i.hasNext();) {
+ ExecutionFrame importedFrame = (ExecutionFrame)i.next();
+ importedFrame.checkTargets(dependencyOrder, state, visiting);
+ }
+ }
- private ExecutionTask getConfiguredExecutionTask(TaskElement model)
+
+ /**
+ * Create a Task and configure it according to the given model.
+ */
+ private Task configureTask(TaskElement model)
throws ConfigException, ExecutionException {
String taskType = model.getType();
TaskDefinition taskDefinition = (TaskDefinition)taskDefs.get(taskType);
if (taskDefinition == null) {
- throw new ConfigException("There is no task defintion for tasks of type <"
+ throw new ConfigException("There is no defintion for tasks of type <"
+ taskType + ">", model.getLocation());
}
try {
- Class executionTaskClass = taskDefinition.getExecutionTaskClass();
- ExecutionTask executionTask = (ExecutionTask)executionTaskClass.newInstance();
- executionTask.setExecutionFrame(this);
- executionTask.setBuildEventSupport(eventSupport);
- executionTask.setBuildElement(model);
- configureElement(executionTask, model);
- return executionTask;
+ Class elementClass = taskDefinition.getExecutionTaskClass();
+ Object element = elementClass.newInstance();
+ Task task = null;
+ if (element instanceof Task) {
+ // create a Task context for the Task
+ task = (Task)element;
+ }
+ else {
+ task = new TaskAdapter(taskType, element);
+ }
+
+ ExecutionContext context = new ExecutionContext(this, eventSupport, model);
+ task.setTaskContext(context);
+ configureElement(element, model);
+
+ return task;
}
catch (ClassNotFoundException e) {
throw new ConfigException("Execution class " + taskDefinition.getTaskClassName()
@@ -339,43 +564,51 @@ public class ExecutionFrame {
e, model.getLocation());
}
}
-
- /**
- * Run the tasks returned by the give iterator
- *
- * @param taskIterator the iterator giving the tasks to execute
- */
- public void executeTasks(Iterator taskIterator) throws ExecutionException, ConfigException {
- Task task = null;
- try {
- while (taskIterator.hasNext()) {
- task = (Task)taskIterator.next();
+
+ private List getActiveAspects(BuildElement model)
+ throws ConfigException, ExecutionException,
+ ClassIntrospectionException, ConversionException {
+ List activeAspects = new ArrayList();
+ for (Iterator i = model.getAspectNames(); i.hasNext();) {
+ String aspectPrefix = (String)i.next();
+ Class aspectHandlerClass = (Class)aspectHandlers.get(aspectPrefix);
+ if (aspectHandlerClass != null) {
try {
- ExecutionTask executionTask = getConfiguredExecutionTask(task);
- eventSupport.fireTaskStarted(this, task);
- executionTask.execute();
- }
- catch (ExecutionException e) {
- if (e.getLocation() == null || e.getLocation() == Location.UNKNOWN_LOCATION) {
- e.setLocation(task.getLocation());
+ AspectHandler aspectHandler
+ = (AspectHandler)aspectHandlerClass.newInstance();
+ ClassIntrospector introspector = getIntrospector(aspectHandlerClass);
+
+ ExecutionContext context = new ExecutionContext(this, eventSupport, model);
+ aspectHandler.setAspectContext(context);
+
+ Map aspectAttributes = model.getAspectAttributes(aspectPrefix);
+ for (Iterator j = aspectAttributes.keySet().iterator(); j.hasNext();) {
+ String attributeName = (String)j.next();
+ String attributeValue = (String)aspectAttributes.get(attributeName);
+ introspector.setAttribute(aspectHandler, attributeName,
+ replacePropertyRefs(attributeValue));
}
- throw e;
+ activeAspects.add(aspectHandler);
}
- catch (ConfigException e) {
- if (e.getLocation() == null || e.getLocation() == Location.UNKNOWN_LOCATION) {
- e.setLocation(task.getLocation());
- }
- throw e;
+ catch (InstantiationException e) {
+ throw new ConfigException("Unable to instantiate aspect handler class "
+ + aspectHandlerClass,
+ e);
+ }
+ catch (IllegalAccessException e) {
+ throw new ConfigException("Unable to access aspect handler class "
+ + aspectHandlerClass,
+ e);
}
- eventSupport.fireTaskFinished(this, task, null);
}
- }
- catch (RuntimeException e) {
- eventSupport.fireTaskFinished(this, task, e);
- throw e;
- }
- }
+ }
+ return activeAspects;
+ }
+
+ /**
+ * Configure an element according to the given model.
+ */
private void configureElement(Object element, TaskElement model)
throws ExecutionException, ConfigException {
@@ -401,11 +634,9 @@ public class ExecutionFrame {
if (element instanceof TaskContainer &&
!introspector.supportsNestedElement(nestedElementModel.getType())) {
- ExecutionTask nestedExecutionTask
- = getConfiguredExecutionTask(nestedElementModel);
-
+ Task nestedTask = configureTask(nestedElementModel);
TaskContainer container = (TaskContainer)element;
- container.addExecutionTask(nestedExecutionTask);
+ container.addTask(nestedTask);
}
else {
Object nestedElement
@@ -413,6 +644,11 @@ public class ExecutionFrame {
configureElement(nestedElement, nestedElementModel);
}
}
+ List aspects = getActiveAspects(model);
+ for (Iterator i = aspects.iterator(); i.hasNext(); ) {
+ AspectHandler aspectHandler = (AspectHandler)i.next();
+ aspectHandler.afterConfigElement(element);
+ }
}
catch (ClassIntrospectionException e) {
throw new ExecutionException(e, model.getLocation());
@@ -422,6 +658,42 @@ public class ExecutionFrame {
}
}
+ /**
+ * Run the tasks returned by the give iterator
+ *
+ * @param taskIterator the iterator giving the tasks to execute
+ */
+ public void executeTasks(Iterator taskIterator) throws ExecutionException, ConfigException {
+ TaskElement task = null;
+ try {
+ while (taskIterator.hasNext()) {
+ task = (TaskElement)taskIterator.next();
+ try {
+ Task configuredTask = configureTask(task);
+ eventSupport.fireTaskStarted(this, task);
+ configuredTask.execute();
+ }
+ catch (ExecutionException e) {
+ if (e.getLocation() == null || e.getLocation() == Location.UNKNOWN_LOCATION) {
+ e.setLocation(task.getLocation());
+ }
+ throw e;
+ }
+ catch (ConfigException e) {
+ if (e.getLocation() == null || e.getLocation() == Location.UNKNOWN_LOCATION) {
+ e.setLocation(task.getLocation());
+ }
+ throw e;
+ }
+ eventSupport.fireTaskFinished(this, task, null);
+ }
+ }
+ catch (RuntimeException e) {
+ eventSupport.fireTaskFinished(this, task, e);
+ throw e;
+ }
+ }
+
private ClassIntrospector getIntrospector(Class c) {
if (introspectors.containsKey(c)) {
return (ClassIntrospector)introspectors.get(c);
@@ -510,7 +782,7 @@ public class ExecutionFrame {
* Given a name of an object, get the frame relative from this frame that
* contains that object.
*/
- private ExecutionFrame getRelativeFrame(String name) throws ExecutionException {
+ public ExecutionFrame getRelativeFrame(String name) throws ExecutionException {
int index = name.lastIndexOf(":");
if (index == -1) {
return this;
@@ -534,7 +806,7 @@ public class ExecutionFrame {
/**
* Get the name of an object in its frame
*/
- private String getNameInFrame(String name) {
+ public String getNameInFrame(String name) {
int index = name.lastIndexOf(":");
if (index == -1) {
return name;
@@ -553,7 +825,7 @@ public class ExecutionFrame {
/**
* Get a value from this frame or any imported frame
*/
- private Object getDataValue(String name) throws ExecutionException {
+ public Object getDataValue(String name) throws ExecutionException {
ExecutionFrame frame = getRelativeFrame(name);
return frame.getDirectDataValue(getNameInFrame(name));
}
@@ -586,5 +858,55 @@ public class ExecutionFrame {
private boolean isDirectDataValueSet(String name) {
return dataValues.containsKey(name);
}
-
+
+ public void runBuild(List targetNames) throws AntException {
+ Throwable buildFailureCause = null;
+ try {
+ eventSupport.fireBuildStarted(this, project);
+ initialize();
+
+ if (targetNames.isEmpty()) {
+ // we just execute the default target if any
+ String defaultTarget = project.getDefaultTarget();
+ if (defaultTarget != null) {
+ executeTarget(defaultTarget);
+ }
+ }
+ else {
+ for (Iterator i = targetNames.iterator(); i.hasNext();) {
+ executeTarget((String)i.next());
+ }
+ }
+ eventSupport.fireBuildFinished(this, project, null);
+ }
+ catch (RuntimeException e) {
+ buildFailureCause = e;
+ throw e;
+ }
+ catch (AntException e) {
+ buildFailureCause = e;
+ throw e;
+ }
+ finally {
+ eventSupport.fireBuildFinished(this, project, buildFailureCause);
+ }
+ }
+
+ public void executeTarget(String targetName) throws ExecutionException, ConfigException {
+ // to execute a target we must determine its dependencies and
+ // execute them in order.
+ Map state = new HashMap();
+ Stack visiting = new Stack();
+ List dependencyOrder = new ArrayList();
+ ExecutionFrame startingFrame = getRelativeFrame(targetName);
+ startingFrame.fillinDependencyOrder(getNameInFrame(targetName),
+ dependencyOrder, state, visiting);
+
+ // Now tell each frame to execute the targets required
+ for (Iterator i = dependencyOrder.iterator(); i.hasNext();) {
+ String fullTargetName = (String)i.next();
+ ExecutionFrame frame = getRelativeFrame(fullTargetName);
+ frame.executeTargetTasks(getNameInFrame(fullTargetName));
+ }
+ }
}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionManager.java b/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionManager.java
deleted file mode 100644
index dacca0edd..000000000
--- a/proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionManager.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * 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.ant.core.execution;
-
-
-import org.apache.ant.core.model.*;
-import org.apache.ant.core.support.*;
-import java.util.*;
-
-/**
- * The ExecutionManager manages the execution of Ant. It will create
- * ExecutionFrames to handle the various imported projects, the
- * data values associated with those projects. Before the ExecutionManager
- * can be used, it must be initialised with a set of Ant libraries. These
- * will contain task definitions, aspect definitions, etc.
- *
- * @author Conor MacNeill
- */
-public class ExecutionManager implements BuildListener {
- private static final String VISITING = "VISITING";
- private static final String VISITED = "VISITED";
-
- private HashMap taskDefs = new HashMap();
- private HashMap converterDefs = new HashMap();
- private Project project;
- private ExecutionFrame mainFrame;
- private Map namespaceMap = null;
- private List frameInitOrder = null;
-
- private BuildEventSupport eventSupport = new BuildEventSupport();
-
- public void addBuildListener(BuildListener listener) {
- eventSupport.addBuildListener(listener);
- }
-
- public void removeBuildListener(BuildListener listener) {
- eventSupport.removeBuildListener(listener);
- }
-
- /**
- * Forward any events to our listeners.
- */
- public void processBuildEvent(BuildEvent event) {
- eventSupport.forwardEvent(event);
- }
-
- public void addLibraries(AntLibrary[] libraries) throws ConfigException {
- for (int i = 0; i < libraries.length; ++i) {
- addLibrary(libraries[i]);
- }
- }
-
- public void addLibrary(AntLibrary library) throws ConfigException {
- for (Iterator i = library.getTaskDefinitions(); i.hasNext(); ) {
- TaskDefinition taskDefinition = (TaskDefinition)i.next();
- addTaskDefinition(taskDefinition);
- }
- for (Iterator i = library.getConverterDefinitions(); i.hasNext(); ) {
- ConverterDefinition converterDef = (ConverterDefinition)i.next();
- addConverterDefinition(converterDef);
- }
- }
-
- public void addTaskDefinition(TaskDefinition taskDefinition) throws ConfigException {
- String taskName = taskDefinition.getName();
- if (taskDefs.containsKey(taskName)) {
- String message = "Task " + taskName + " is defined twice" +
- ", in " + ((TaskDefinition)taskDefs.get(taskName)).getLibraryURL() +
- " and " + taskDefinition.getLibraryURL();
- throw new ConfigException(message, new Location(taskDefinition.getLibraryURL().toString()));
- }
- taskDefs.put(taskName, taskDefinition);
- }
-
- public void addConverterDefinition(ConverterDefinition converterDef) throws ConfigException {
- String targetClassname = converterDef.getTargetClassName();
- if (converterDefs.containsKey(targetClassname)) {
- String message = "Converter for " + targetClassname + " is defined twice" +
- ", in " + ((ConverterDefinition)converterDefs.get(targetClassname)).getLibraryURL() +
- " and " + converterDef.getLibraryURL();
- throw new ConfigException(message, new Location(converterDef.getLibraryURL().toString()));
- }
- converterDefs.put(targetClassname, converterDef);
- }
-
- public void setProject(Project project) throws ConfigException {
- this.project = project;
- mainFrame = new ExecutionFrame(project, (Map)taskDefs.clone(),
- (Map)converterDefs.clone(), null);
- namespaceMap = new HashMap();
- frameInitOrder = new ArrayList();
- setupFrame(mainFrame);
-
- // We iterate through all nodes of all projects and make sure every node is OK
- Map state = new HashMap();
- Stack visiting = new Stack();
- List dependencyOrder = new ArrayList();
-
- checkFrameTargets(mainFrame, dependencyOrder, state, visiting);
- }
-
- /**
- * Check whether the targets in the given execution frame and its subframes are OK
- */
- private void checkFrameTargets(ExecutionFrame frame, List dependencyOrder,
- Map state, Stack visiting)
- throws ConfigException {
- // get the targets and just iterate through them.
- for (Iterator i = frame.getProject().getTargets(); i.hasNext();) {
- Target target = (Target)i.next();
- fillinDependencyOrder(frame, target.getName(),
- dependencyOrder, state, visiting);
- }
-
- // Now do the subframes.
- for (Iterator i = frame.getImportedFrames(); i.hasNext();) {
- ExecutionFrame importedFrame = (ExecutionFrame)i.next();
- checkFrameTargets(importedFrame, dependencyOrder, state, visiting);
- }
- }
-
- private void setupFrame(ExecutionFrame frame) {
- frame.addBuildListener(this);
-
- String namespace = frame.getNamespace();
- if (namespace != null) {
- namespaceMap.put(namespace, frame);
- }
- for (Iterator i = frame.getImportedFrameNames(); i.hasNext();) {
- String importName = (String)i.next();
- setupFrame(frame.getImportedFrame(importName));
- }
- frameInitOrder.add(frame);
- }
-
- public void runBuild(List targetNames) throws AntException {
- Throwable buildFailureCause = null;
- try {
- eventSupport.fireBuildStarted(this, project);
- // we initialise each execution frame
- for (Iterator i = frameInitOrder.iterator(); i.hasNext();) {
- ExecutionFrame frame = (ExecutionFrame)i.next();
- frame.initialise();
- }
- if (targetNames.isEmpty()) {
- // we just execute the default target if any
- String defaultTarget = project.getDefaultTarget();
- if (defaultTarget != null) {
- executeTarget(defaultTarget);
- }
- }
- else {
- for (Iterator i = targetNames.iterator(); i.hasNext();) {
- executeTarget((String)i.next());
- }
- }
- eventSupport.fireBuildFinished(this, project, null);
- }
- catch (RuntimeException e) {
- buildFailureCause = e;
- throw e;
- }
- catch (AntException e) {
- buildFailureCause = e;
- throw e;
- }
- finally {
- eventSupport.fireBuildFinished(this, project, buildFailureCause);
- }
- }
-
- private ExecutionFrame getFrame(String name) {
- int namespaceIndex = name.lastIndexOf(":");
- if (namespaceIndex == -1) {
- return mainFrame;
- }
- return (ExecutionFrame)namespaceMap.get(name.substring(0, namespaceIndex));
- }
-
- public void executeTarget(String targetName) throws ExecutionException, ConfigException {
- // to execute a target we must determine its dependencies and
- // execute them in order.
- Map state = new HashMap();
- Stack visiting = new Stack();
- List dependencyOrder = new ArrayList();
- ExecutionFrame startingFrame = getFrame(targetName);
- fillinDependencyOrder(startingFrame, startingFrame.getRelativeName(targetName),
- dependencyOrder, state, visiting);
-
- // Now tell each frame to execute the target
- for (Iterator i = dependencyOrder.iterator(); i.hasNext();) {
- String fullTargetName = (String)i.next();
- ExecutionFrame frame = getFrame(fullTargetName);
- frame.executeTargetTasks(frame.getRelativeName(fullTargetName));
- }
- }
-
- private void fillinDependencyOrder(ExecutionFrame frame, String targetName,
- List dependencyOrder, Map state,
- Stack visiting) throws ConfigException {
- String fullTargetName = frame.getQualifiedName(targetName);
- if (state.get(fullTargetName) == VISITED) {
- return;
- }
- Target target = frame.getProject().getTarget(targetName);
- if (target == null) {
- StringBuffer sb = new StringBuffer("Target `");
- sb.append(targetName);
- sb.append("' does not exist in this project. ");
- if (!visiting.empty()) {
- String parent = (String)visiting.peek();
- sb.append("It is used from target `");
- sb.append(parent);
- sb.append("'.");
- }
-
- throw new ConfigException(new String(sb), frame.getProject().getLocation());
- }
-
- state.put(fullTargetName, VISITING);
- visiting.push(fullTargetName);
- for (Iterator i = target.getDependencies(); i.hasNext(); ) {
- String dependency = (String)i.next();
- String fullyQualifiedName = frame.getQualifiedName(dependency);
- ExecutionFrame dependencyFrame = getFrame(fullyQualifiedName);
- if (dependencyFrame == null) {
- StringBuffer sb = new StringBuffer("Target `");
- sb.append(dependency);
- sb.append("' does not exist in this project. ");
- throw new ConfigException(new String(sb), target.getLocation());
- }
-
- String dependencyState = (String)state.get(fullyQualifiedName);
- if (dependencyState == null) {
- fillinDependencyOrder(dependencyFrame, dependencyFrame.getRelativeName(fullyQualifiedName),
- dependencyOrder, state, visiting);
- }
- else if (dependencyState == VISITING) {
- String circleDescription
- = getCircularDesc(dependency, visiting);
- throw new ConfigException(circleDescription, target.getLocation());
- }
- }
-
- state.put(fullTargetName, VISITED);
- String poppedNode = (String)visiting.pop();
- if (poppedNode != fullTargetName) {
- throw new ConfigException("Problem determining dependencies " +
- " - expecting '" + fullTargetName +
- "' but got '" + poppedNode + "'");
- }
- dependencyOrder.add(fullTargetName);
- }
-
- private String getCircularDesc(String end, Stack visitingNodes) {
- StringBuffer sb = new StringBuffer("Circular dependency: ");
- sb.append(end);
- String c;
- do {
- c = (String)visitingNodes.pop();
- sb.append(" <- ");
- sb.append(c);
- } while(!c.equals(end));
- return new String(sb);
- }
-}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/model/Task.java b/proposal/mutant/src/main/org/apache/ant/core/execution/Task.java
similarity index 87%
rename from proposal/mutant/src/main/org/apache/ant/core/model/Task.java
rename to proposal/mutant/src/main/org/apache/ant/core/execution/Task.java
index d9148a11b..ba98152ea 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/model/Task.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/execution/Task.java
@@ -51,25 +51,23 @@
* information on the Apache Software Foundation, please see
* .
*/
-package org.apache.ant.core.model;
+package org.apache.ant.core.execution;
+
+import org.apache.ant.core.model.*;
import org.apache.ant.core.support.*;
import java.util.*;
+import java.net.URL;
/**
- * A Task is a holder for Task information (attributes and elements)
+ * A task is a top level element in the buidl which will be processed. Ant
+ * currently handles two types of tasks - DataType tasks and execution tasks.
*
* @author Conor MacNeill
*/
-public class Task extends TaskElement {
- /**
- * Create a Task of the given type
- *
- * @param location the location of the element
- * @param type the task's type
- */
- public Task(Location location, String type) {
- super(location, type);
- }
+public interface Task {
+ void setTaskContext(ExecutionContext context);
+ void execute() throws ExecutionException;
}
+
diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/TaskAdapter.java b/proposal/mutant/src/main/org/apache/ant/core/execution/TaskAdapter.java
new file mode 100644
index 000000000..ab871102f
--- /dev/null
+++ b/proposal/mutant/src/main/org/apache/ant/core/execution/TaskAdapter.java
@@ -0,0 +1,100 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999 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.ant.core.execution;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ * Use introspection to "adapt" an arbitrary Bean ( not extending Task, but with similar
+ * patterns).
+ *
+ * @author Conor MacNeill
+ */
+public class TaskAdapter extends AbstractTask {
+
+ /**
+ * The real object that is performing the work
+ */
+ private Object worker;
+
+ private Method executeMethod = null;
+
+ public TaskAdapter(String taskType, Object worker)
+ throws ExecutionException {
+ this.worker = worker;
+ try {
+ Class workerClass = worker.getClass();
+ executeMethod = workerClass.getMethod("execute", new Class[0]);
+ if (executeMethod == null) {
+ throw new ExecutionException("No execute method in the class for the <"
+ + taskType + "> task.");
+ }
+ }
+ catch (NoSuchMethodException e) {
+ throw new ExecutionException(e);
+ }
+ }
+
+
+ public void execute() throws ExecutionException {
+ try {
+ executeMethod.invoke(worker, null);
+ }
+ catch( Exception ex ) {
+ throw new ExecutionException(ex);
+ }
+ }
+}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/TaskContainer.java b/proposal/mutant/src/main/org/apache/ant/core/execution/TaskContainer.java
index 947004ebf..edd6fbf50 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/execution/TaskContainer.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/execution/TaskContainer.java
@@ -67,6 +67,6 @@ public interface TaskContainer {
/**
* Add a task to the container.
*/
- void addExecutionTask(ExecutionTask executionTask) throws ExecutionException;
+ void addTask(Task task) throws ExecutionException;
}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/execution/TaskDefinition.java b/proposal/mutant/src/main/org/apache/ant/core/execution/TaskDefinition.java
index a7b349ec9..840218108 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/execution/TaskDefinition.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/execution/TaskDefinition.java
@@ -117,7 +117,7 @@ public class TaskDefinition {
*/
public synchronized Class getExecutionTaskClass() throws ClassNotFoundException {
if (taskClass == null) {
- taskClass = taskClassLoader.loadClass(taskClassName);
+ taskClass = Class.forName(taskClassName, true, taskClassLoader);
}
return taskClass;
}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/model/BuildElement.java b/proposal/mutant/src/main/org/apache/ant/core/model/BuildElement.java
index 62f463e09..b24f77f09 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/model/BuildElement.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/model/BuildElement.java
@@ -63,20 +63,13 @@ import org.apache.ant.core.support.*;
* @author Conor MacNeill
*/
public class BuildElement {
- /**
- * The aspects defined for this element.
- */
- private Map aspects;
+ /** The aspects defined for this element. */
+ private Map aspectMaps;
- /**
- * The location of this element
- */
+ /** The location of this element */
private Location location;
- /**
- * A comment associated with this element, if any
- *
- */
+ /** A comment associated with this element, if any */
private String comment;
/**
@@ -121,7 +114,44 @@ public class BuildElement {
* @param aspects a Map of apects that relate to this build element.
*/
public void setAspects(Map aspects) {
- this.aspects = aspects;
+ aspectMaps = new HashMap();
+ for (Iterator i = aspects.keySet().iterator(); i.hasNext(); ) {
+ String aspectName = (String)i.next();
+ int separator = aspectName.indexOf(":");
+ if (separator != -1) {
+ String prefix = aspectName.substring(0, separator);
+ String name = aspectName.substring(separator + 1);
+ if (prefix.length() != 0 && name.length() != 0) {
+ Map prefixMap = (Map)aspectMaps.get(prefix);
+ if (prefixMap == null) {
+ prefixMap = new HashMap();
+ aspectMaps.put(prefix, prefixMap);
+ }
+ prefixMap.put(name, aspects.get(aspectName));
+ }
+ }
+ }
+ }
+
+ /**
+ * Get an iterator on the aspects which have been given values on this element
+ *
+ * @return an iterator of Strings , being the aspects which have been given values on
+ * this element.
+ */
+ public Iterator getAspectNames() {
+ return aspectMaps.keySet().iterator();
+ }
+
+ /**
+ * Get the set of attribute values related to the given aspect
+ *
+ * @param apsectPrefix the prefix used to identify the prefix.
+ *
+ * @return a map of the attribute values for the given aspect.
+ */
+ public Map getAspectAttributes(String aspectPrefix) {
+ return (Map)aspectMaps.get(aspectPrefix);
}
}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/model/Project.java b/proposal/mutant/src/main/org/apache/ant/core/model/Project.java
index d9b37f0ae..1bb746f99 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/model/Project.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/model/Project.java
@@ -191,7 +191,7 @@ public class Project extends BuildElement {
* @param task a task to be executed when an execution context
* is associated with the Project (a non-target task)
*/
- public void addTask(Task task) {
+ public void addTask(TaskElement task) {
tasks.add(task);
}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/model/Target.java b/proposal/mutant/src/main/org/apache/ant/core/model/Target.java
index 7590ff7cc..e86582fc3 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/model/Target.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/model/Target.java
@@ -100,7 +100,7 @@ public class Target extends BuildElement {
*
* @param task the task to be added to the target.
*/
- public void addTask(Task task) {
+ public void addTask(TaskElement task) {
tasks.add(task);
}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/support/AntClassLoader.java b/proposal/mutant/src/main/org/apache/ant/core/support/AntClassLoader.java
index b8bf13acb..4b0b0f8f4 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/support/AntClassLoader.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/support/AntClassLoader.java
@@ -59,14 +59,17 @@ import java.net.*;
import java.io.*;
/**
- * A ReverseURLclassLoader is a type of URL classloader which reverse the standard
+ * The AntClassLoader is a type of URL classloader which reverse the standard
* lookup order to load things from the URLs first and then to use the parent class
* loader only if the class does not exist in the URLs.
*
* @author Conor MacNeill
*/
public class AntClassLoader extends URLClassLoader {
+ /** A Debug label to print when the Classloader finds or fails to find a class. */
private String debugLabel = null;
+
+ /** A flag whihc controls whether messages are logged by the loader */
private boolean debug = false;
private void dumpURLs() {
diff --git a/proposal/mutant/src/main/org/apache/ant/core/support/AntException.java b/proposal/mutant/src/main/org/apache/ant/core/support/AntException.java
index 89ba0a900..152045299 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/support/AntException.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/support/AntException.java
@@ -110,7 +110,7 @@ public abstract class AntException extends Exception {
* @param cause Exception that might have caused this one.
*/
public AntException(Throwable cause) {
- super(cause.toString());
+ super(cause.getMessage());
this.cause = cause;
}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/types/DataType.java b/proposal/mutant/src/main/org/apache/ant/core/types/DataType.java
new file mode 100644
index 000000000..10409f83e
--- /dev/null
+++ b/proposal/mutant/src/main/org/apache/ant/core/types/DataType.java
@@ -0,0 +1,131 @@
+/*
+ * 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.ant.core.types;
+
+import org.apache.ant.core.execution.*;
+import java.io.*;
+
+/**
+ * A DataType is an element which can register a named value in the
+ * ExecutionFrame's context.
+ *
+ * @author Conor MacNeill
+ */
+public abstract class DataType extends AbstractTask {
+ private String reference = null;
+
+ final public void execute() throws ExecutionException {
+ }
+
+
+ /**
+ * Creates an exception that indicates that refid has to be the
+ * only attribute if it is set.
+ */
+ protected ExecutionException tooManyAttributes() {
+ return new ExecutionException("You must not specify more than one attribute" +
+ " when using refid" );
+ }
+
+ /**
+ * Creates an exception that indicates that this XML element must
+ * not have child elements if the refid attribute is set.
+ */
+ protected ExecutionException noChildrenAllowed() {
+ return new ExecutionException("You must not specify nested elements when using refid");
+ }
+
+ /**
+ * Creates an exception that indicates the user has generated a
+ * loop of data types referencing each other.
+ */
+ protected ExecutionException circularReference() {
+ return new ExecutionException("This data type contains a circular reference.");
+ }
+
+ /**
+ * Makes this instance in effect a reference to another DataType
+ * instance.
+ */
+ public void setRefid(String reference) throws ExecutionException {
+ this.reference = reference;
+ // check the reference now
+ getReferencedObject();
+ }
+
+ /**
+ * Has the refid attribute of this element been set?
+ */
+ public boolean isReference() {
+ return reference != null;
+ }
+
+ protected Object getReferencedObject() throws ExecutionException {
+ if (!isReference()) {
+ throw new ExecutionException("You cannot get a referenced value from a data type " +
+ "which does not have the refid attribute");
+ }
+
+ Object referencedObject = getTaskContext().getDataValue(reference);
+ if (referencedObject == null) {
+ throw new ExecutionException("Unable to locate the reference specified by refid '" +
+ getReference() + "'");
+ }
+ return referencedObject;
+ }
+
+ protected String getReference() {
+ return reference;
+ }
+}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/types/PatternSet.java b/proposal/mutant/src/main/org/apache/ant/core/types/PatternSet.java
new file mode 100644
index 000000000..8ad633acc
--- /dev/null
+++ b/proposal/mutant/src/main/org/apache/ant/core/types/PatternSet.java
@@ -0,0 +1,369 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2000 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.ant.core.types;
+
+import java.io.*;
+import java.util.*;
+import org.apache.ant.core.execution.*;
+
+/**
+ * Named collection of include/exclude tags.
+ *
+ *
Moved out of MatchingTask to make it a standalone object that
+ * could be referenced (by scripts for example).
+ *
+ * @author Arnout J. Kuiper ajkuiper@wxs.nl
+ * @author Stefano Mazzocchi stefano@apache.org
+ * @author Sam Ruby rubys@us.ibm.com
+ * @author Jon S. Stevens jon@clearink.com
+ * @author Stefan Bodewig
+ */
+public class PatternSet extends DataType {
+ private List includeList = new ArrayList();
+ private List excludeList = new ArrayList();
+
+// private File incl = null;
+// private File excl = null;
+//
+ /**
+ * inner class to hold a name on list. "If" and "Unless" attributes
+ * may be used to invalidate the entry based on the existence of a
+ * property (typically set thru the use of the Available task).
+ */
+ public class NameEntry {
+ private String name;
+// private String ifCond;
+// private String unlessCond;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+// public void setIf(String cond) {
+// ifCond = cond;
+// }
+//
+// public void setUnless(String cond) {
+// unlessCond = cond;
+// }
+//
+ public String getName() {
+ return name;
+ }
+
+// public String evalName(Project p) {
+// return valid(p) ? name : null;
+// }
+
+// private boolean valid(Project p) {
+// if (ifCond != null && p.getProperty(ifCond) == null) {
+// return false;
+// } else if (unlessCond != null && p.getProperty(unlessCond) != null) {
+// return false;
+// }
+// return true;
+// }
+ }
+
+
+ public PatternSet() {
+ }
+
+ /**
+ * Makes this instance in effect a reference to another PatternSet
+ * instance.
+ *
+ *
You must not set another attribute or nest elements inside
+ * this element if you make it a reference.
+ */
+ public void setRefid(String reference) throws ExecutionException {
+ if (!includeList.isEmpty() || !excludeList.isEmpty()) {
+ throw tooManyAttributes();
+ }
+ super.setRefid(reference);
+ }
+
+ /**
+ * add a name entry on the include list
+ */
+ public NameEntry createInclude() throws ExecutionException {
+ if (isReference()) {
+ throw noChildrenAllowed();
+ }
+ return addPatternToList(includeList);
+ }
+
+ /**
+ * add a name entry on the exclude list
+ */
+ public NameEntry createExclude() throws ExecutionException {
+ if (isReference()) {
+ throw noChildrenAllowed();
+ }
+ return addPatternToList(excludeList);
+ }
+
+ /**
+ * Sets the set of include patterns. Patterns may be separated by a comma
+ * or a space.
+ *
+ * @param includes the string containing the include patterns
+ */
+ public void setIncludes(String includes) throws ExecutionException {
+ if (isReference()) {
+ throw tooManyAttributes();
+ }
+ if (includes != null && includes.length() > 0) {
+ StringTokenizer tok = new StringTokenizer(includes, ", ", false);
+ while (tok.hasMoreTokens()) {
+ createInclude().setName(tok.nextToken());
+ }
+ }
+ }
+
+ /**
+ * Sets the set of exclude patterns. Patterns may be separated by a comma
+ * or a space.
+ *
+ * @param excludes the string containing the exclude patterns
+ */
+ public void setExcludes(String excludes) throws ExecutionException {
+ if (isReference()) {
+ throw tooManyAttributes();
+ }
+ if (excludes != null && excludes.length() > 0) {
+ StringTokenizer tok = new StringTokenizer(excludes, ", ", false);
+ while (tok.hasMoreTokens()) {
+ createExclude().setName(tok.nextToken());
+ }
+ }
+ }
+
+ /**
+ * add a name entry to the given list
+ */
+ private NameEntry addPatternToList(List list) {
+ NameEntry result = new NameEntry();
+ list.add(result);
+ return result;
+ }
+
+// /**
+// * Sets the name of the file containing the includes patterns.
+// *
+// * @param incl The file to fetch the include patterns from.
+// */
+// public void setIncludesfile(File incl) throws BuildException {
+// if (isReference()) {
+// throw tooManyAttributes();
+// }
+// if (!incl.exists()) {
+// throw new BuildException("Includesfile "+incl.getAbsolutePath()
+// +" not found.");
+// }
+// this.incl = incl;
+// }
+//
+// /**
+// * Sets the name of the file containing the excludes patterns.
+// *
+// * @param excl The file to fetch the exclude patterns from.
+// */
+// public void setExcludesfile(File excl) throws BuildException {
+// if (isReference()) {
+// throw tooManyAttributes();
+// }
+// if (!excl.exists()) {
+// throw new BuildException("Excludesfile "+excl.getAbsolutePath()
+// +" not found.");
+// }
+// this.excl = excl;
+// }
+//
+// /**
+// * Reads path matching patterns from a file and adds them to the
+// * includes or excludes list (as appropriate).
+// */
+// private void readPatterns(File patternfile, Vector patternlist, Project p)
+// throws BuildException {
+//
+// try {
+// // Get a FileReader
+// BufferedReader patternReader =
+// new BufferedReader(new FileReader(patternfile));
+//
+// // Create one NameEntry in the appropriate pattern list for each
+// // line in the file.
+// String line = patternReader.readLine();
+// while (line != null) {
+// if (line.length() > 0) {
+// line = ProjectHelper.replaceProperties(p, line,
+// p.getProperties());
+// addPatternToList(patternlist).setName(line);
+// }
+// line = patternReader.readLine();
+// }
+// } catch(IOException ioe) {
+// String msg = "An error occured while reading from pattern file: "
+// + patternfile;
+// throw new BuildException(msg, ioe);
+// }
+// }
+//
+ /**
+ * Adds the patterns of the other instance to this set.
+ */
+ public void append(PatternSet other) throws ExecutionException {
+ if (isReference()) {
+ throw new ExecutionException("Cannot append to a reference");
+ }
+
+ String[] incl = other.getIncludePatterns();
+ if (incl != null) {
+ for (int i=0; i 0 || excludeList.size() > 0;
+// }
+//
+ /**
+ * Performs the check for circular references and returns the
+ * referenced PatternSet.
+ */
+ private PatternSet getReferencedPatternSet() throws ExecutionException {
+ Object o = getReferencedObject();
+ if (!(o instanceof PatternSet)) {
+ throw new ExecutionException(getReference() + " doesn\'t denote a patternset");;
+ } else {
+ return (PatternSet) o;
+ }
+ }
+
+
+ /**
+ * Convert a list of NameEntry elements into an array of Strings.
+ */
+ private String[] makeArray(List list) {
+ if (list.size() == 0) {
+ return null;
+ }
+
+ List tmpNames = new Vector();
+ for (Iterator i = list.iterator() ; i.hasNext() ;) {
+ NameEntry ne = (NameEntry)i.next();
+ String pattern = ne.getName();
+ if (pattern != null && pattern.length() > 0) {
+ tmpNames.add(pattern);
+ }
+ }
+
+ String[] result = (String[])tmpNames.toArray(new String[0]);
+ return result;
+ }
+
+// /**
+// * Read includefile ot excludefile if not already done so.
+// */
+// private void readFiles(Project p) {
+// if (incl != null) {
+// readPatterns(incl, includeList, p);
+// incl = null;
+// }
+// if (excl != null) {
+// readPatterns(excl, excludeList, p);
+// excl = null;
+// }
+// }
+//
+}
diff --git a/proposal/mutant/src/main/org/apache/ant/core/xml/AntLibParser.java b/proposal/mutant/src/main/org/apache/ant/core/xml/AntLibParser.java
index 43c2f9bb3..aabc271f9 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/xml/AntLibParser.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/xml/AntLibParser.java
@@ -72,6 +72,7 @@ import org.xml.sax.helpers.DefaultHandler;
public class AntLibParser {
public static final String TASK_ELEMENT = "taskdef";
public static final String CONVERTER_ELEMENT = "converter";
+ public static final String ASPECT_ELEMENT = "aspect";
/**
* The factory used to create SAX parsers.
@@ -191,6 +192,9 @@ public class AntLibParser {
else if (qualifiedName.equals(CONVERTER_ELEMENT)) {
createConverterDef(attributes);
}
+ else if (qualifiedName.equals(ASPECT_ELEMENT)) {
+ createAspectHandler(attributes);
+ }
else {
throw new SAXParseException("Unrecognized element <" +
qualifiedName + "> in Ant library definition", getLocator());
@@ -219,7 +223,6 @@ public class AntLibParser {
"<" + TASK_ELEMENT + "> element", getLocator());
}
- System.out.println("Adding taskdef for " + taskName);
TaskDefinition taskdef = new TaskDefinition(getSourceURL(), taskName, className, componentLoader);
library.addTaskDefinition(taskdef);
}
@@ -229,7 +232,7 @@ public class AntLibParser {
validAttributes.add("target");
validAttributes.add("classname");
Map attributeValues
- = AttributeValidator.validateAttributes("convert", attributes,
+ = AttributeValidator.validateAttributes(CONVERTER_ELEMENT, attributes,
validAttributes, getLocator());
String targetClassName = (String)attributeValues.get("target");
String className = (String)attributeValues.get("classname");
@@ -248,6 +251,30 @@ public class AntLibParser {
library.addConverterDefinition(converterDef);
}
+ public void createAspectHandler(Attributes attributes) throws SAXParseException {
+ Set validAttributes = new HashSet();
+ validAttributes.add("prefix");
+ validAttributes.add("classname");
+ Map attributeValues
+ = AttributeValidator.validateAttributes(ASPECT_ELEMENT, attributes,
+ validAttributes, getLocator());
+ String aspectPrefix = (String)attributeValues.get("prefix");
+ String aspectClassname = (String)attributeValues.get("classname");
+ if (aspectPrefix == null) {
+ throw new SAXParseException("'prefix' attribute is required in a <"
+ + ASPECT_ELEMENT + "> element",
+ getLocator());
+ }
+ if (aspectClassname == null) {
+ throw new SAXParseException("'classname' attribute is required in a " +
+ "<" + ASPECT_ELEMENT + "> element", getLocator());
+ }
+
+ AspectDefinition aspectDef
+ = new AspectDefinition(getSourceURL(), aspectPrefix, aspectClassname, componentLoader);
+ library.addAspectDefinition(aspectDef);
+ }
+
public void endElement(String namespaceURI, String localName, String qName) {
if (state == STATE_ROOT_SEEN && qName.equals("antlib")) {
state = STATE_FINISHED;
diff --git a/proposal/mutant/src/main/org/apache/ant/core/xml/XMLProjectParser.java b/proposal/mutant/src/main/org/apache/ant/core/xml/XMLProjectParser.java
index 454a16aed..461726815 100644
--- a/proposal/mutant/src/main/org/apache/ant/core/xml/XMLProjectParser.java
+++ b/proposal/mutant/src/main/org/apache/ant/core/xml/XMLProjectParser.java
@@ -373,10 +373,10 @@ public class XMLProjectParser {
}
else {
// everything else is a task
- TaskHandler taskHandler
- = new TaskHandler(getXMLReader(), this, getLocator(),
+ TaskElementHandler taskElementHandler
+ = new TaskElementHandler(getXMLReader(), this, getLocator(),
attributes, qualifiedName);
- project.addTask(taskHandler.getTask());
+ project.addTask(taskElementHandler.getTaskElement());
}
}
@@ -730,10 +730,10 @@ public class XMLProjectParser {
public void startElement(String uri, String localName, String qualifiedName,
Attributes attributes) throws SAXParseException {
// everything is a task
- TaskHandler taskHandler
- = new TaskHandler(getXMLReader(), this, getLocator(),
- attributes, qualifiedName);
- target.addTask(taskHandler.getTask());
+ TaskElementHandler taskHandler
+ = new TaskElementHandler(getXMLReader(), this, getLocator(),
+ attributes, qualifiedName);
+ target.addTask(taskHandler.getTaskElement());
}
/**
@@ -747,80 +747,7 @@ public class XMLProjectParser {
}
/**
- * A Task Handler is used to parse tasks.
- */
- private class TaskHandler extends ElementHandler {
- /**
- * The task being parsed by this handler.
- */
- private Task task;
-
- /**
- * Create a task handler to parse the Task element
- *
- * @param xmlReader the XML parser being used to parse the task element.
- * @param parent the parent element handler.
- * @param locator the SAX locator object used to associate elements with source
- * locations.
- * @param attributes attributes of the task
- * @param taskTagName the name of the task.
- */
- public TaskHandler(XMLReader xmlReader, ContentHandler parent, Locator locator,
- Attributes attributes, String taskTagName) {
- super(xmlReader, parent, locator);
- task = new Task(getLocation(locator), taskTagName);
-
- Map aspects = new HashMap();
- for (int i = 0; i < attributes.getLength(); ++i) {
- String attributeName = attributes.getQName(i);
- String attributeValue = attributes.getValue(i);
- if (attributeName.indexOf(":") != -1) {
- // potential aspect attribute
- aspects.put(attributeName, attributeValue);
- }
- else {
- task.addAttribute(attributeName, attributeValue);
- }
- }
- task.setAspects(aspects);
- }
-
- /*
- * Process a nested element within this task. All nested elements within
- * the task are treated as taskelements.
- *
- * @param uri The Namespace URI.
- * @param localName The local name (without prefix).
- * @param qualifiedName The qualified name (with prefix)
- * @param attributes The attributes attached to the element.
- *
- * @throws SAXParseException if there is a parsing problem.
- */
- public void startElement(String uri, String localName, String qualifiedName,
- Attributes attributes) throws SAXParseException {
- // everything within a task is a task element
- TaskElementHandler taskElementHandler
- = new TaskElementHandler(getXMLReader(), this, getLocator(),
- attributes, qualifiedName);
- task.addTaskElement(taskElementHandler.getTaskElement());
- }
-
- public void characters(char[] buf, int start, int end) throws SAXParseException {
- task.addText(new String(buf, start, end));
- }
-
- /**
- * Get the task that is being parsed
- *
- * @return the task being parsed by this task handler.
- */
- public Task getTask() {
- return task;
- }
- }
-
- /**
- * A Task Element Handler parses the nested elements of tasks.
+ * A TaskElementHandler parses the task elements of a build
*/
private class TaskElementHandler extends ElementHandler {
/**
@@ -839,7 +766,7 @@ public class XMLProjectParser {
* @param elementTagName the name of the task element.
*/
public TaskElementHandler(XMLReader xmlReader, ContentHandler parent, Locator locator,
- Attributes attributes, String elementTagName) {
+ Attributes attributes, String elementTagName) {
super(xmlReader, parent, locator);
taskElement
= new TaskElement(getLocation(locator), elementTagName);
@@ -873,10 +800,10 @@ public class XMLProjectParser {
public void startElement(String uri, String localName, String qualifiedName,
Attributes attributes) throws SAXParseException {
// everything within a task element is also a task element
- TaskElementHandler taskElementHandler
+ TaskElementHandler nestedHandler
= new TaskElementHandler(getXMLReader(), this, getLocator(),
- attributes, qualifiedName);
- taskElement.addTaskElement(taskElementHandler.getTaskElement());
+ attributes, qualifiedName);
+ taskElement.addTaskElement(nestedHandler.getTaskElement());
}
public void characters(char[] buf, int start, int end) throws SAXParseException {
diff --git a/proposal/mutant/src/main/org/apache/ant/frontend/Commandline.java b/proposal/mutant/src/main/org/apache/ant/frontend/Commandline.java
index 461080d57..809e8a807 100644
--- a/proposal/mutant/src/main/org/apache/ant/frontend/Commandline.java
+++ b/proposal/mutant/src/main/org/apache/ant/frontend/Commandline.java
@@ -111,7 +111,7 @@ public class Commandline {
}
public void runAnt(String[] args) {
- ExecutionManager executionManager = null;
+ ExecutionFrame mainFrame = null;
try {
parseArguments(args);
Project project = getProject();
@@ -121,10 +121,16 @@ public class Commandline {
// Get the list of library components
AntLibrary[] libraries = ComponentManager.getComponents();
- executionManager = new ExecutionManager();
- executionManager.addLibraries(libraries);
- executionManager.setProject(project);
- addBuildListeners(executionManager);
+
+ mainFrame = new ExecutionFrame(project, libraries);
+
+ // We iterate through all nodes of all projects and make sure every node is OK
+ Map state = new HashMap();
+ Stack visiting = new Stack();
+ List dependencyOrder = new ArrayList();
+
+ mainFrame.checkTargets(dependencyOrder, state, visiting);
+ addBuildListeners(mainFrame);
}
catch (AntException e) {
Location location = e.getLocation();
@@ -132,19 +138,17 @@ public class Commandline {
if (location != null && location != Location.UNKNOWN_LOCATION) {
System.out.print(location);
}
- System.out.print(e.getMessage());
+ System.out.println(e.getMessage());
if (cause != null) {
- System.out.println();
- System.out.print("Root cause: " + cause.getClass().getName() + ": " + cause.getMessage());
+ System.out.println("Root cause: " + cause.getClass().getName() + ": " + cause.getMessage());
}
- System.out.println();
System.exit(1);
}
try {
- executionManager.runBuild(targets);
+ mainFrame.runBuild(targets);
System.exit(0);
}
catch (Exception e) {
@@ -152,18 +156,18 @@ public class Commandline {
}
}
- protected void addBuildListeners(ExecutionManager executionManager)
+ protected void addBuildListeners(ExecutionFrame frame)
throws ConfigException {
// Add the default listener
- executionManager.addBuildListener(createLogger());
+ frame.addBuildListener(createLogger());
for (Iterator i = listeners.iterator(); i.hasNext(); ) {
String className = (String) i.next();
try {
BuildListener listener =
(BuildListener) Class.forName(className).newInstance();
- executionManager.addBuildListener(listener);
+ frame.addBuildListener(listener);
}
catch(Exception exc) {
throw new ConfigException("Unable to instantiate listener " + className, exc);
diff --git a/proposal/mutant/src/main/org/apache/ant/frontend/DefaultLogger.java b/proposal/mutant/src/main/org/apache/ant/frontend/DefaultLogger.java
index 076fff869..211b9ccd5 100644
--- a/proposal/mutant/src/main/org/apache/ant/frontend/DefaultLogger.java
+++ b/proposal/mutant/src/main/org/apache/ant/frontend/DefaultLogger.java
@@ -131,13 +131,11 @@ public class DefaultLogger implements BuildLogger {
if (location != null && location != Location.UNKNOWN_LOCATION) {
out.print(location);
}
- out.print(e.getMessage());
+ out.println(e.getMessage());
if (cause != null) {
- out.println();
- out.print("Root cause: " + cause.getClass().getName() + ": " + cause.getMessage());
+ out.println("Root cause: " + cause.toString());
}
- out.println();
}
else {
t.printStackTrace(err);
@@ -183,9 +181,9 @@ public class DefaultLogger implements BuildLogger {
// Print out the name of the task if we're in one
Object buildElement = event.getBuildElement();
- if (buildElement instanceof Task) {
- Task task = (Task)buildElement;
- String name = task.getType();
+ if (buildElement instanceof TaskElement) {
+ TaskElement taskElement = (TaskElement)buildElement;
+ String name = taskElement.getType();
if (!emacsMode) {
String msg = "[" + name + "] ";