From c2e518039b65dc5b8c9c31f9f78b2d72ea8db2d1 Mon Sep 17 00:00:00 2001 From: Conor MacNeill Date: Fri, 18 May 2001 13:38:25 +0000 Subject: [PATCH] Mutant update. Reorganization of classes to a fair extent Introduction of a non-functional parallel task Converted some data types over Initial experiments with apsects used to store data type values git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269031 13f79535-47bb-0310-9956-ffa450edef68 --- proposal/mutant/build.xml | 3 + .../ant/component/core/AntAspectHandler.java | 75 +++ .../org/apache/ant/component/core/Echo.java | 2 +- .../ant/component/core/FileConverter.java | 1 - .../apache/ant/component/core/Property.java | 9 +- .../org/apache/ant/component/core/antlib.xml | 9 + .../apache/ant/component/thread/Parallel.java | 78 +++ .../ant/component/thread/Sequential.java | 78 +++ .../apache/ant/component/thread/antlib.xml | 4 + .../core/execution/AbstractAspectHandler.java | 80 +++ .../ant/core/execution/AbstractTask.java | 96 +++ .../apache/ant/core/execution/AntLibrary.java | 51 +- .../ant/core/execution/AspectDefinition.java | 124 ++++ .../ant/core/execution/AspectHandler.java | 74 +++ .../ClassIntrospectionException.java | 2 +- .../core/execution/ConverterDefinition.java | 4 +- ...ecutionTask.java => ExecutionContext.java} | 76 +-- .../ant/core/execution/ExecutionFrame.java | 566 ++++++++++++++---- .../ant/core/execution/ExecutionManager.java | 317 ---------- .../ant/core/{model => execution}/Task.java | 22 +- .../ant/core/execution/TaskAdapter.java | 100 ++++ .../ant/core/execution/TaskContainer.java | 2 +- .../ant/core/execution/TaskDefinition.java | 2 +- .../apache/ant/core/model/BuildElement.java | 54 +- .../org/apache/ant/core/model/Project.java | 2 +- .../org/apache/ant/core/model/Target.java | 2 +- .../ant/core/support/AntClassLoader.java | 5 +- .../apache/ant/core/support/AntException.java | 2 +- .../org/apache/ant/core/types/DataType.java | 131 ++++ .../org/apache/ant/core/types/PatternSet.java | 369 ++++++++++++ .../org/apache/ant/core/xml/AntLibParser.java | 31 +- .../apache/ant/core/xml/XMLProjectParser.java | 97 +-- .../org/apache/ant/frontend/Commandline.java | 30 +- .../apache/ant/frontend/DefaultLogger.java | 12 +- 34 files changed, 1853 insertions(+), 657 deletions(-) create mode 100644 proposal/mutant/src/main/org/apache/ant/component/core/AntAspectHandler.java create mode 100644 proposal/mutant/src/main/org/apache/ant/component/thread/Parallel.java create mode 100644 proposal/mutant/src/main/org/apache/ant/component/thread/Sequential.java create mode 100644 proposal/mutant/src/main/org/apache/ant/component/thread/antlib.xml create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/AbstractAspectHandler.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/AbstractTask.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/AspectDefinition.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/AspectHandler.java rename proposal/mutant/src/main/org/apache/ant/core/execution/{ExecutionTask.java => ExecutionContext.java} (64%) delete mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/ExecutionManager.java rename proposal/mutant/src/main/org/apache/ant/core/{model => execution}/Task.java (87%) create mode 100644 proposal/mutant/src/main/org/apache/ant/core/execution/TaskAdapter.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/types/DataType.java create mode 100644 proposal/mutant/src/main/org/apache/ant/core/types/PatternSet.java 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 + "] ";