You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beehive.apache.org by js...@apache.org on 2005/05/04 00:17:02 UTC

svn commit: r168006 - in /incubator/beehive/trunk/controls/test: ./ common/ infra/ant/ tools/ant/ tools/ant/src/ tools/ant/src/org/ tools/ant/src/org/apache/ tools/ant/src/org/apache/beehive/ tools/ant/src/org/apache/beehive/test/ tools/ant/src/org/apache/beehive/test/tools/ tools/ant/src/org/apache/beehive/test/tools/ant/

Author: jsong
Date: Tue May  3 15:16:59 2005
New Revision: 168006

URL: http://svn.apache.org/viewcvs?rev=168006&view=rev
Log:
Fix for BEEHIVE-448.  If a controls test fails, the ant build will now fail.

Contributed by Joe Pemberton


Added:
    incubator/beehive/trunk/controls/test/infra/ant/
    incubator/beehive/trunk/controls/test/infra/ant/ant-ext.jar   (with props)
    incubator/beehive/trunk/controls/test/tools/ant/
    incubator/beehive/trunk/controls/test/tools/ant/build.xml
    incubator/beehive/trunk/controls/test/tools/ant/src/
    incubator/beehive/trunk/controls/test/tools/ant/src/org/
    incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/
    incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/
    incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/
    incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/
    incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/
    incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/Call.java
    incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/CatchTask.java
    incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/FinallyTask.java
    incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/ForEach.java
    incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/TryTask.java
Modified:
    incubator/beehive/trunk/controls/test/build.xml
    incubator/beehive/trunk/controls/test/common/path.properties

Modified: incubator/beehive/trunk/controls/test/build.xml
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/build.xml?rev=168006&r1=168005&r2=168006&view=diff
==============================================================================
--- incubator/beehive/trunk/controls/test/build.xml (original)
+++ incubator/beehive/trunk/controls/test/build.xml Tue May  3 15:16:59 2005
@@ -19,6 +19,15 @@
     <taskdef name="mantis"
                 classname="org.apache.beehive.test.tools.mantis.MantisTask"
                 classpathref="mantis.classpath"/>
+    <taskdef name="try"
+                classname="org.apache.beehive.test.tools.ant.TryTask"
+                classpath="${ant-ext.jar}"/>
+    <taskdef name="catch"
+                classname="org.apache.beehive.test.tools.ant.CatchTask"
+                classpath="${ant-ext.jar}"/>
+    <taskdef name="finally"
+                classname="org.apache.beehive.test.tools.ant.FinallyTask"
+                classpath="${ant-ext.jar}"/>
 		
     <property name="test.logs" location="${controls.test.root}/logs"/>
 
@@ -375,17 +384,21 @@
 	        <echo message="start a new thread to build controlsWeb"/>
                 <start-server shmem="false" javaOptions=""/>
 		<sequential>
-			<antcall target="build-test-webapp" />
-			<echo message="continue the new thread, wait for app server to start"/>
-			<sleep seconds="20"/>
-			<echo message="continue the new thread, deploy controlsWeb"/>
-			<ant dir ="./webapps" antfile="build.xml" target="ensure.deployed"/>
-			<echo message="continue the new thread, run junit tests"/>
-			<antcall target="run"/>
-			<ant dir ="./webapps" antfile="build.xml" target="undeploy"/>
-			<echo message="continue the new thread, undeploy controlsWeb"/>
-			<echo message="stop app server, finish the new thread"/>
-                <stop-server />
+            <try>
+                <antcall target="build-test-webapp" />
+                <echo message="continue the new thread, wait for app server to start"/>
+                <sleep seconds="20"/>
+                <echo message="continue the new thread, deploy controlsWeb"/>
+                <ant dir ="./webapps" antfile="build.xml" target="ensure.deployed"/>
+                <echo message="continue the new thread, run junit tests"/>
+                <antcall target="run"/>
+                <ant dir ="./webapps" antfile="build.xml" target="undeploy"/>
+                <echo message="continue the new thread, undeploy controlsWeb"/>
+                <echo message="stop app server, finish the new thread"/>
+                <finally>
+                    <stop-server />
+                </finally>
+            </try>
 		</sequential>
         </parallel>
     </target>	 
@@ -418,11 +431,14 @@
         <property name="test-suite" value="${mantis.tch.srcgen.dir}/root.xml"/>
         <property name="tch.base-logfile-name" value="tch"/>
 
+        <property name="tch.fail-build" value="true"/>
+
 	<tch tchHome="${tch.home}"
 	     testfile="${test-suite}"
 	     fork="true"
 	     classpathref="tch.run.classpath"
 	     failureproperty="run.failed"
+         failonerror="${tch.fail-build}"
 	     dir="${controls.test.root}"
          inheritall="true">
 

Modified: incubator/beehive/trunk/controls/test/common/path.properties
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/common/path.properties?rev=168006&r1=168005&r2=168006&view=diff
==============================================================================
--- incubator/beehive/trunk/controls/test/common/path.properties (original)
+++ incubator/beehive/trunk/controls/test/common/path.properties Tue May  3 15:16:59 2005
@@ -40,6 +40,8 @@
 milton.jar=${controls.test.infra.dir}/milton/milton.jar
 milton.templates=${controls.test.root}/webapps/common/milton
 
+ant-ext.jar=${controls.test.infra.dir}/ant/ant-ext.jar
+
 crimson.jar=${external.dir}/crimson/crimson-1.1.jar
 jakarta.jar=${external.dir}/jakarta/jakarta-regexp-1.2.jar
 jaxp.jar=${external.dir}/jaxp/jaxp.jar

Added: incubator/beehive/trunk/controls/test/infra/ant/ant-ext.jar
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/infra/ant/ant-ext.jar?rev=168006&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/beehive/trunk/controls/test/infra/ant/ant-ext.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/beehive/trunk/controls/test/tools/ant/build.xml
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/tools/ant/build.xml?rev=168006&view=auto
==============================================================================
--- incubator/beehive/trunk/controls/test/tools/ant/build.xml (added)
+++ incubator/beehive/trunk/controls/test/tools/ant/build.xml Tue May  3 15:16:59 2005
@@ -0,0 +1,47 @@
+<project name="beehive-tools-ant" default="deploy" basedir=".">
+
+  <import file="../../../../beehive-imports.xml"/>
+  <import file="../../../../ant/axis-import.xml"/>
+  
+  <property name="src.dir" value="${basedir}/src"/>
+  <property name="build.dir" value="${basedir}/build"/>
+
+  <property file="../../common/path.properties"/>
+
+  <target name="usage">
+    <echo>
+deploy			builds ant-ext.jar and copies to testinfra directory
+clean              	deletes ant-ext build artifacts
+redeploy                rebuilds ant-ext.jar
+    </echo>
+  </target>
+
+  <target name="redeploy" depends="clean_all,deploy"/>
+  
+  <!-- ========================= -->
+  <!-- builds milton and packages it into a jar -->
+  <!-- ========================= -->
+  <target name="deploy">
+    <mkdir dir="${build.dir}"/>
+    <javac srcdir="${src.dir}"
+            destdir="${build.dir}"
+            failonerror="true"
+            verbose="false"
+            deprecation="true"
+            debug="true"
+            />
+     <jar basedir="${build.dir}" destfile="${ant-ext.jar}"/>
+   </target>
+   
+   <!-- ========================= -->
+   <!-- Cleans build artifacts -->
+   <!-- ========================= -->
+   <target name="clean">
+     <delete dir="${build.dir}"/>
+   </target>
+
+   <target name="clean_all" depends="clean">
+     <delete file="${ant-ext.jar}"/>
+   </target>
+
+</project>

Added: incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/Call.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/Call.java?rev=168006&view=auto
==============================================================================
--- incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/Call.java (added)
+++ incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/Call.java Tue May  3 15:16:59 2005
@@ -0,0 +1,233 @@
+package org.apache.beehive.test.tools.ant;
+
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.StringUtils;
+import org.apache.tools.ant.taskdefs.Ant;
+import org.apache.tools.ant.taskdefs.Property;
+import org.apache.tools.ant.types.FileSet;
+
+import java.io.File;
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.io.IOException;
+import java.util.*;
+import java.util.regex.Pattern;
+import java.lang.reflect.Method;
+
+
+/**
+ * FileSet stuff taken from the org.apache.tools.ant.taskdef.Chmod task.
+ * The 'values' attribute takes precedence over the FileSet.
+ * Doesn't support nested FileSets or PatternSets.
+ */
+public class Call extends Task implements Cloneable {
+    private Boolean shareParentContextStage;
+    private Boolean shareParentContextStageForEach;
+    private boolean shareParentContext;
+
+    private String target;
+
+    private boolean initialized = false;
+    private Ant callee;
+    private Vector params = new Vector();
+
+    public void setShareParentContext(boolean b) {
+        shareParentContextStage = Boolean.valueOf(b);
+//        System.out.println(this + ".setShareParentContext()");
+    }
+    void setShareParentContextStageForEach(boolean b) {
+        shareParentContextStageForEach = Boolean.valueOf(b);
+//        System.out.println(this + ".setShareParentContextStageForEach()");
+    }
+
+    public void setTarget(String target) { this.target = target; }
+
+    public void initialize() {
+        if (shareParentContextStage != null) {
+            shareParentContext = shareParentContextStage.booleanValue();
+        } else if (shareParentContextStageForEach != null) {
+            shareParentContext = shareParentContextStageForEach.booleanValue();
+        }
+//        System.out.println(this + ": " + shareParentContext);
+
+        if (!shareParentContext) {
+            if (initialized) return;
+
+            callee = (Ant) project.createTask("ant");
+
+            Vector newParams = new Vector();
+            for (Iterator i = params.iterator(); i.hasNext(); ) {
+                Property p = (Property)i.next();
+                Property pnew = callee.createProperty();
+                pnew.setName(p.getName());
+                pnew.setValue(p.getValue());
+                newParams.add(pnew);
+            }
+            params = newParams;
+
+            callee.setOwningTarget(getOwningTarget());
+            callee.setTaskName(getTaskName());
+            callee.setLocation(getLocation());
+            callee.setDir(getProject().getBaseDir());
+            callee.setAntfile(getProject().getProperty("ant.file"));
+            initialized = true;
+        }
+    }
+
+    public Property createParam(String name) {
+        if (!shareParentContext) {
+            for (Iterator i = params.iterator(); i.hasNext(); ) {
+                Property p = (Property)i.next();
+                if (p.getName().equals(name)) {
+                    return p;
+                }
+            }
+        }
+        Property param = createParam();
+        param.setName(name);
+        return param;
+    }
+
+    public Property createParam() {
+        initialize();
+        Property param;
+        if (shareParentContext) {
+            param = new Property();
+            param.setTaskName("property");
+            params.add(param);
+        } else {
+            param = callee.createProperty();
+            params.add(param);
+        }
+        return param;
+    }
+
+    public void execute()
+    {
+        initialize();
+        if (target == null) {
+            throw new BuildException(
+                "Attribute target is required.", getLocation());
+        }
+        if (shareParentContext) {
+            Project newProject = new ShareProject(params);
+            newProject.executeTarget(target);
+        } else {
+            callee.init();
+
+            if (target == null) {
+                throw new BuildException(
+                    "Attribute target is required.", getLocation());
+            }
+
+            callee.setTarget(target);
+            callee.execute();
+        }
+    }
+
+    protected Object clone() {
+        try {
+            Call call = (Call)super.clone();
+            call.initialized = false;
+            return call;
+        } catch (CloneNotSupportedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+    class ShareProject extends Project {
+        private HashMap _overrides = new HashMap();
+
+        public ShareProject(List params) {
+            initializeProject();
+            for (Iterator i = params.iterator(); i.hasNext(); ) {
+                Property param = (Property)i.next();
+                _overrides.put(param.getName(), param.getValue());
+            }
+        }
+
+        private void initializeProject() {
+            setInputHandler(getProject().getInputHandler());
+
+            Vector listeners = getProject().getBuildListeners();
+            final int count = listeners.size();
+            for (int i = 0; i < count; i++) {
+                addBuildListener((BuildListener) listeners.elementAt(i));
+            }
+
+            Hashtable taskdefs = getProject().getTaskDefinitions();
+            Enumeration et = taskdefs.keys();
+            while (et.hasMoreElements()) {
+                String taskName = (String) et.nextElement();
+//            if (taskName.equals("property")) {
+//                // we have already added this taskdef in #init
+//                continue;
+//            }
+                Class taskClass = (Class) taskdefs.get(taskName);
+                addTaskDefinition(taskName, taskClass);
+            }
+
+            Hashtable typedefs = getProject().getDataTypeDefinitions();
+            Enumeration e = typedefs.keys();
+            while (e.hasMoreElements()) {
+                String typeName = (String) e.nextElement();
+                Class typeClass = (Class) typedefs.get(typeName);
+                addDataTypeDefinition(typeName, typeClass);
+            }
+
+            String antFile = getLocation().getFileName();
+            if ( antFile == null ) {
+                antFile = "build.xml";
+            }
+            File dir = getProject().getBaseDir();
+
+            File file = FileUtils.newFileUtils().resolveFile(dir, antFile);
+            antFile = file.getAbsolutePath();
+
+            ProjectHelper.configureProject(this, new File(antFile));
+        }
+
+        public synchronized void setUserProperty(String name, String value) {
+            if (!_overrides.containsKey(name)) {
+                getProject().setUserProperty(name, value);
+            }
+        }
+
+        public synchronized void setProperty(String name, String value) {
+            if (!_overrides.containsKey(name)) {
+                getProject().setProperty(name, value);
+            }
+        }
+
+        public synchronized void setNewProperty(String name, String value) {
+            if (!_overrides.containsKey(name)) {
+                getProject().setNewProperty(name, value);
+            }
+        }
+
+        public synchronized void setInheritedProperty(String name, String value) {
+            if (!_overrides.containsKey(name)) {
+                getProject().setInheritedProperty(name, value);
+            }
+        }
+
+        public String getProperty(String name) {
+            if (!_overrides.containsKey(name)) {
+                return getProject().getProperty(name);
+            } else {
+                return (String)_overrides.get(name);
+            }
+        }
+
+        public Hashtable getProperties() {
+            Hashtable h = getProject().getProperties();
+            h.putAll(_overrides);
+            return h;
+        }
+
+        public String replaceProperties(String value)
+                throws BuildException {
+            return ProjectHelper.replaceProperties(this, value, getProperties());
+        }
+    }
+}

Added: incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/CatchTask.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/CatchTask.java?rev=168006&view=auto
==============================================================================
--- incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/CatchTask.java (added)
+++ incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/CatchTask.java Tue May  3 15:16:59 2005
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2001-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS
+ * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+*/
+package org.apache.beehive.test.tools.ant;
+
+import org.apache.tools.ant.taskdefs.Sequential;
+
+
+/**
+ * This is identical to Sequential and can be used on its own as a
+ * Sequential task. Its intended use is as a nested element of the TryTask.
+ *
+ * @author Dale Anson, danson@germane-software.com
+ * @since Ant 1.5
+ */
+public class CatchTask extends Sequential {
+    
+}

Added: incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/FinallyTask.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/FinallyTask.java?rev=168006&view=auto
==============================================================================
--- incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/FinallyTask.java (added)
+++ incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/FinallyTask.java Tue May  3 15:16:59 2005
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2001-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS
+ * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+*/
+package org.apache.beehive.test.tools.ant;
+
+import org.apache.tools.ant.taskdefs.Sequential;
+
+
+/**
+ * This is identical to Sequential and can be used on its own as a
+ * Sequential task. Its intended use is as a nested element of the TryTask.
+ *
+ * @author Dale Anson, danson@germane-software.com
+ * @since Ant 1.5
+ */
+public class FinallyTask extends Sequential {
+}

Added: incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/ForEach.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/ForEach.java?rev=168006&view=auto
==============================================================================
--- incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/ForEach.java (added)
+++ incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/ForEach.java Tue May  3 15:16:59 2005
@@ -0,0 +1,554 @@
+package org.apache.beehive.test.tools.ant;
+
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.util.FileUtils;
+import org.apache.tools.ant.util.StringUtils;
+import org.apache.tools.ant.taskdefs.Ant;
+import org.apache.tools.ant.taskdefs.Property;
+import org.apache.tools.ant.types.FileSet;
+
+import java.io.File;
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.io.IOException;
+import java.util.*;
+import java.util.regex.Pattern;
+import java.lang.reflect.Method;
+
+
+/**
+ * FileSet stuff taken from the org.apache.tools.ant.taskdef.Chmod task.
+ * The 'values' attribute takes precedence over the FileSet.
+ * Doesn't support nested FileSets or PatternSets.
+ */
+public class ForEach extends Task
+{
+    public static final String CURVAL = "curval";
+
+    /** Split on comma or space. */
+    static final private Pattern pat = Pattern.compile("(,\\s*|\\s+)");
+
+    private FileSet fileSet = new FileSet();
+    private boolean fileSetDefined = false;
+    private String values;
+    private Vector calls = new Vector();
+    private boolean parallel;
+    private boolean shareParentContext = false;
+
+    private static Project _topProject;
+
+    public void init() throws BuildException {
+        super.init();
+        if (_topProject == null) _topProject = getProject();
+    }
+
+    public class Call implements Cloneable {
+
+        private String target;
+
+        private boolean initialized = false;
+        private Ant callee;
+        private Vector params = new Vector();
+
+        public void setTarget(String target) { this.target = target; }
+
+        public void init() {
+            if (!shareParentContext) {
+                if (initialized) return;
+
+                callee = (Ant) project.createTask("ant");
+
+                Vector newParams = new Vector();
+                for (Iterator i = params.iterator(); i.hasNext(); ) {
+                    Property p = (Property)i.next();
+                    Property pnew = callee.createProperty();
+                    pnew.setName(p.getName());
+                    pnew.setValue(p.getValue());
+                    newParams.add(pnew);
+                }
+                params = newParams;
+
+                callee.setOwningTarget(getOwningTarget());
+                callee.setTaskName(getTaskName());
+                callee.setLocation(getLocation());
+                callee.setDir(getProject().getBaseDir());
+                callee.setAntfile(getProject().getProperty("ant.file"));
+                initialized = true;
+            }
+        }
+
+        public Property createParam(String name) {
+            if (!shareParentContext) {
+                for (Iterator i = params.iterator(); i.hasNext(); ) {
+                    Property p = (Property)i.next();
+                    if (p.getName().equals(name)) {
+                        return p;
+                    }
+                }
+            }
+            Property param = createParam();
+            param.setName(name);
+            return param;
+        }
+
+        public Property createParam() {
+            init();
+            Property param;
+            if (shareParentContext) {
+                param = new Property();
+                param.setTaskName("property");
+                params.add(param);
+            } else {
+                param = callee.createProperty();
+                params.add(param);
+            }
+            return param;
+        }
+
+        public void execute(String curval)
+        {
+            if (target == null) {
+                throw new BuildException(
+                    "Attribute target is required.", getLocation());
+            }
+            if (shareParentContext) {
+                Project newProject = new MyProject(curval, params);
+                newProject.executeTarget(target);
+            } else {
+                callee.init();
+
+                Property curvalProp = createParam(CURVAL);
+                curvalProp.setValue(curval);
+
+                if (target == null) {
+                    throw new BuildException(
+                        "Attribute target is required.", getLocation());
+                }
+
+                callee.setTarget(target);
+                callee.execute();
+            }
+        }
+
+        protected Object clone() {
+            try {
+                Call call = (Call)super.clone();
+                call.initialized = false;
+                return call;
+            } catch (CloneNotSupportedException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    private void executeCalls(String curval)
+    {
+        for (int i = 0; i < calls.size(); i++)
+        {
+            Call call = (Call) calls.get(i);
+            if (parallel) {
+                call = (Call)call.clone();
+            }
+            call.init();
+            call.execute(curval);
+        }
+    }
+
+    private ThreadLocal _curval = new ClonedInheritableThreadLocal();
+    private ThreadLocal _output = new InheritableThreadLocal();
+    private ForEach _topForEach;
+
+    private static class ClonedInheritableThreadLocal extends InheritableThreadLocal {
+        protected Object childValue(Object parentValue) {
+            try {
+                Method m = parentValue.getClass().getMethod("clone", new Class [] {});
+                Object clonedValue = m.invoke(parentValue, null);
+                return clonedValue;
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public void execute() throws BuildException
+    {
+        if (fileSet.getDir(project) == null)
+            fileSet.setDir(project.getBaseDir());
+
+        final String[] set;
+
+        if (values != null) {
+            String [] splitResult = pat.split(values); //.split(pat);
+            // remove zero-length'd parts...
+            ArrayList tempList = new ArrayList(splitResult.length);
+            for (int i = 0; i < splitResult.length; i++) {
+                if (splitResult[i].trim().length() > 0) {
+                    tempList.add(splitResult[i]);
+                }
+            }
+            set = (String [])tempList.toArray(new String [tempList.size()]);
+        }
+        else {
+            DirectoryScanner ds = fileSet.getDirectoryScanner(getProject());
+            set = ds.getIncludedFiles();
+        }
+
+        if (parallel) {
+
+            // replace the listeners...
+            for (Iterator i = getProject().getBuildListeners().iterator(); i.hasNext(); ) {
+                BuildListener l = (BuildListener)i.next();
+                if (true && (l instanceof DefaultLogger)) {
+                    getProject().addBuildListener(new DelegatingBuildListener(l));
+                    getProject().removeBuildListener(l);
+                    _topForEach = this;
+                } else if (l instanceof DelegatingBuildListener) {
+                    _topForEach = ((DelegatingBuildListener)l).getForEach();
+                }
+            }
+
+            Thread [] threads = new Thread [set.length];
+            final RuntimeException [] exceptions = new RuntimeException [set.length];
+            final StringBuffer [] outputs = new StringBuffer [set.length];
+            // start all the sub-tasks; one in each thread.
+            for (int i = 0; i < set.length; ++i) {
+                final int iSave = i;
+                threads[i] = new Thread(new Runnable() {
+                    private int _index = iSave;
+
+                    public void run() {
+                        ArrayList list = (ArrayList)_topForEach._curval.get();
+                        if (list == null) {
+                            _topForEach._curval.set(list = new ArrayList());
+                        }
+                        try {
+                            list.add(set[_index]);
+
+                            _topProject.registerThreadTask(Thread.currentThread(), ForEach.this);
+
+                            _output.set(outputs[_index] = new StringBuffer());
+                            executeCalls(set[_index]);
+                        } catch (RuntimeException e) {
+                            exceptions[_index] = e;
+                        } finally {
+                            System.out.flush();
+                            System.err.flush();
+                            _topProject.registerThreadTask(Thread.currentThread(), null);
+                            list.remove(list.size() - 1);
+                        }
+                    }
+                });
+                threads[i].start();
+            }
+            // wait for all sub-tasks to complete
+            for (int i = 0; i < set.length; ++i) {
+                try {
+                    threads[i].join();
+                } catch (InterruptedException e) {}
+            }
+            ArrayList exlist = new ArrayList();
+            // report any failures from the sub-tasks.
+            for (int i = 0; i < set.length; ++i) {
+                if (exceptions[i] != null) {
+                    exlist.add(exceptions[i]);
+                    System.out.println("===================================================\n" +
+                            getLocation() + ": curval '" +
+                            set[i] + "' failed.  Output follows:");
+                    System.out.println("Contiguous output of failing thread:\n\n" + outputs[i].toString());
+                    System.out.println(exceptions[i]);
+                    System.out.println("\n===================================================\n");
+                }
+            }
+            // restore the listeners...
+            for (Iterator i = getProject().getBuildListeners().iterator(); i.hasNext(); ) {
+                BuildListener l = (BuildListener)i.next();
+                if (l instanceof DelegatingBuildListener) {
+                    DelegatingBuildListener dbl = (DelegatingBuildListener)l;
+                    getProject().removeBuildListener(l);
+                    getProject().addBuildListener(dbl.getOrig());
+                }
+            }
+
+            if (exlist.size() != 0) {
+                throw new BuildException(exlist.size() + " parallel branches failed: " + exlist.toString(),
+                        getLocation());
+            }
+        } else {
+            for (int i = 0; i < set.length; ++i) {
+                executeCalls(set[i]);
+            }
+        }
+    }
+
+    class DelegatingBuildListener implements BuildListener {
+
+        private BuildListener _orig;
+
+        public DelegatingBuildListener(BuildListener orig) {
+            _orig = orig;
+        }
+
+        public BuildListener getOrig() {
+            return _orig;
+        }
+
+        public void messageLogged(BuildEvent event) {
+            if (_curval.get() == null) {
+                _orig.messageLogged(event);
+                return;
+            }
+            if (event.getPriority() <= Project.MSG_INFO) {
+                StringBuffer buf = (StringBuffer)_output.get();
+                if (buf != null) {
+                    buf.append(event.getMessage() + StringUtils.LINE_SEP);
+                }
+            }
+            BuildEvent newEvent;
+
+            StringBuffer tmp = new StringBuffer("[foreach " + _curval.get().toString().replaceAll(", ", "\\.") + "]: ");
+            if (event.getTask() != null) {
+                StringBuffer message = new StringBuffer();
+
+                // Print out the name of the task if we're in one
+                String name = event.getTask().getTaskName();
+                String label = "[" + name + "] ";
+                int size = 24 - label.length();
+                for (int i = tmp.length(); i < size; i++) {
+                    tmp.append(" ");
+                }
+                tmp.append(label);
+                label = tmp.toString();
+
+                try {
+                    BufferedReader r =
+                        new BufferedReader(
+                            new StringReader(event.getMessage()));
+                    String line = r.readLine();
+                    boolean first = true;
+                    while (line != null) {
+                        if (!first) {
+                            message.append(StringUtils.LINE_SEP);
+                        }
+                        first = false;
+                        message.append(label).append(line);
+                        line = r.readLine();
+                    }
+                } catch (IOException e) {
+                    // shouldn't be possible
+                    message.append(label).append(event.getMessage());
+                }
+                //message.append("\n\n\n");
+                newEvent = new BuildEvent(event.getProject());
+                newEvent.setMessage(message.toString(), event.getPriority());
+            } else {
+                if (event.getTarget() != null) {
+                    newEvent = new BuildEvent(event.getTarget());
+                } else {
+                    newEvent = new BuildEvent(event.getProject());
+                }
+                String newMessage = tmp.toString() +
+                        event.getMessage();
+                newEvent.setMessage(newMessage, event.getPriority());
+            }
+            _orig.messageLogged(newEvent);
+        }
+
+        public void buildFinished(BuildEvent event) {
+            _orig.buildFinished(event);
+        }
+
+        public void buildStarted(BuildEvent event) {
+            _orig.buildStarted(event);
+        }
+
+        public void targetFinished(BuildEvent event) {
+            _orig.targetFinished(event);
+        }
+
+        public void targetStarted(BuildEvent event) {
+            if (_curval.get() == null) {
+                _orig.targetStarted(event);
+                return;
+            }
+            BuildEvent be = new BuildEvent(event.getProject());
+            be.setMessage(event.getTarget().getName() + ":\n", Project.MSG_INFO);
+            messageLogged(be);
+        }
+
+        public void taskFinished(BuildEvent event) {
+            _orig.taskFinished(event);
+        }
+
+        public void taskStarted(BuildEvent event) {
+            _orig.taskStarted(event);
+        }
+
+        public ForEach getForEach() {
+            return ForEach.this;
+        }
+    }
+    public void setValues(String values)
+    {
+        this.values = values;
+    }
+
+    public Object createCall()
+    {
+        Call call = new Call();
+
+        calls.add(call);
+
+        return call;
+    }
+
+    /**
+     * 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)
+    {
+        fileSetDefined = true;
+        fileSet.setIncludes(includes);
+    }
+
+    /**
+     * 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)
+    {
+        fileSetDefined = true;
+        fileSet.setExcludes(excludes);
+    }
+
+    /**
+     * Sets whether default exclusions should be used or not.
+     *
+     * @param useDefaultExcludes "true"|"on"|"yes" when default exclusions
+     *                           should be used, "false"|"off"|"no" when they
+     *                           shouldn't be used.
+     */
+    public void setDefaultexcludes(boolean useDefaultExcludes)
+    {
+        fileSetDefined = true;
+        fileSet.setDefaultexcludes(useDefaultExcludes);
+    }
+
+    /**
+     * The directory which holds the files whose permissions must be changed.
+     * @param dir
+     */
+    public void setDir(File dir)
+    {
+        fileSet.setDir(dir);
+    }
+
+    public void setParallel(boolean parallel) {
+        this.parallel = parallel;
+    }
+
+    public void setShareParentContext(boolean shareParentContext) {
+        this.shareParentContext = shareParentContext;
+    }
+
+    private class MyProject extends Project {
+        private HashMap _overrides = new HashMap();
+
+        public MyProject(String curval, List params) {
+            _overrides.put(CURVAL, curval);
+            initializeProject();
+            for (Iterator i = params.iterator(); i.hasNext(); ) {
+                Property param = (Property)i.next();
+                _overrides.put(param.getName(), param.getValue());
+            }
+        }
+
+        private void initializeProject() {
+            setInputHandler(getProject().getInputHandler());
+
+            Vector listeners = getProject().getBuildListeners();
+            final int count = listeners.size();
+            for (int i = 0; i < count; i++) {
+                addBuildListener((BuildListener) listeners.elementAt(i));
+            }
+
+            Hashtable taskdefs = getProject().getTaskDefinitions();
+            Enumeration et = taskdefs.keys();
+            while (et.hasMoreElements()) {
+                String taskName = (String) et.nextElement();
+//            if (taskName.equals("property")) {
+//                // we have already added this taskdef in #init
+//                continue;
+//            }
+                Class taskClass = (Class) taskdefs.get(taskName);
+                addTaskDefinition(taskName, taskClass);
+            }
+
+            Hashtable typedefs = getProject().getDataTypeDefinitions();
+            Enumeration e = typedefs.keys();
+            while (e.hasMoreElements()) {
+                String typeName = (String) e.nextElement();
+                Class typeClass = (Class) typedefs.get(typeName);
+                addDataTypeDefinition(typeName, typeClass);
+            }
+
+            String antFile = getLocation().getFileName();
+            if ( antFile == null ) {
+                antFile = "build.xml";
+            }
+            File dir = getProject().getBaseDir();
+
+            File file = FileUtils.newFileUtils().resolveFile(dir, antFile);
+            antFile = file.getAbsolutePath();
+
+            ProjectHelper.configureProject(this, new File(antFile));
+        }
+
+        public synchronized void setUserProperty(String name, String value) {
+            if (!_overrides.containsKey(name)) {
+                getProject().setUserProperty(name, value);
+            }
+        }
+
+        public synchronized void setProperty(String name, String value) {
+            if (!_overrides.containsKey(name)) {
+                getProject().setProperty(name, value);
+            }
+        }
+
+        public synchronized void setNewProperty(String name, String value) {
+            if (!_overrides.containsKey(name)) {
+                getProject().setNewProperty(name, value);
+            }
+        }
+
+        public synchronized void setInheritedProperty(String name, String value) {
+            if (!_overrides.containsKey(name)) {
+                getProject().setInheritedProperty(name, value);
+            }
+        }
+
+        public String getProperty(String name) {
+            if (!_overrides.containsKey(name)) {
+                return getProject().getProperty(name);
+            } else {
+                return (String)_overrides.get(name);
+            }
+        }
+
+        public Hashtable getProperties() {
+            Hashtable h = getProject().getProperties();
+            h.putAll(_overrides);
+            return h;
+        }
+
+        public String replaceProperties(String value)
+                throws BuildException {
+            return ProjectHelper.replaceProperties(this, value, getProperties());
+        }
+    }
+}

Added: incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/TryTask.java
URL: http://svn.apache.org/viewcvs/incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/TryTask.java?rev=168006&view=auto
==============================================================================
--- incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/TryTask.java (added)
+++ incubator/beehive/trunk/controls/test/tools/ant/src/org/apache/beehive/test/tools/ant/TryTask.java Tue May  3 15:16:59 2005
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2001-2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS
+ * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+*/
+package org.apache.beehive.test.tools.ant;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Enumeration;
+import java.util.Vector;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.TaskContainer;
+import org.apache.tools.ant.UnknownElement;
+
+/**
+ * Try is a container task - it can contain other Ant tasks. The nested tasks
+ * are simply executed in sequence. Try's primary use is to support the
+ * try/catch-like execution of a set of tasks. If any of the child tasks fail
+ * (that is, they throw a build exception), the exception is caught and the
+ * build can continue. This is sometimes useful for tasks that can fail, but it
+ * isn't necessary to fail the build if they do. For example, the "mail" task
+ * may fail if the server is unavailable, but not sending the message may not be
+ * critical to the build continuing.
+ *
+ * @author     Dale Anson, danson@germane-software.com
+ * @version    $Revision$
+ * @since      Ant 1.5
+ * @ant.task   category="control"
+ */
+public class TryTask extends Task implements TaskContainer {
+
+   /** Vector to hold the nested tasks */
+   private Vector tasks = new Vector();
+
+   /** support for a nested CatchTask */
+   private Task catchTask = null;
+
+   /** support for a nested FinallyTask */
+   private Task finallyTask = null;
+
+   /** should the try block exit on the first failure? Default is true. */
+   private boolean doBreak = true;
+
+   /** should the error message of an exception be logged? Default is true. */
+   private boolean doPrintMessage = true;
+
+   /** should the stack trace of an exception be logged? Default is false. */
+   private boolean doPrintStackTrace = false;
+
+
+   /** Description of the Method */
+   public void init() {
+      getProject().addTaskDefinition( "catch", CatchTask.class );
+      getProject().addTaskDefinition( "finally", FinallyTask.class );
+   }
+
+
+   /**
+    * Override {@link org.apache.tools.ant.Task#maybeConfigure maybeConfigure}
+    * in a way that leaves the nested tasks unconfigured until they get
+    * executed.
+    *
+    * @exception BuildException  Description of Exception
+    * @since                     Ant 1.5
+    */
+   public void maybeConfigure() throws BuildException {
+      if ( isInvalid() ) {
+         super.maybeConfigure();
+      }
+      else {
+         getRuntimeConfigurableWrapper().maybeConfigure( getProject(), false );
+      }
+   }
+
+    boolean taskOfType(Task task, Class type) {
+        if (task instanceof UnknownElement) {
+            task = getProject().createTask(((UnknownElement)task).getTag());
+        }
+        return (task == null) ? false : type.isAssignableFrom(task.getClass());
+    }
+
+   /**
+    * Add a nested task to Try.
+    *
+    * @param task  Nested task to try to execute
+    */
+   public void addTask( Task task ) {
+      if ( taskOfType(task, CatchTask.class) ) {
+         if ( catchTask == null ) {
+            catchTask = task;
+            return;
+         }
+         else {
+            throw new BuildException( "Only one Catch allowed per Try." );
+         }
+      }
+      else if ( taskOfType(task, FinallyTask.class) ) {
+         if ( finallyTask == null ) {
+            finallyTask = task;
+            return;
+         }
+         else {
+            throw new BuildException( "Only one Finally allowed per Try." );
+         }
+      }
+      tasks.addElement( task );
+   }
+
+
+   /**
+    * A try block may contain several tasks. This parameter determines whether
+    * the block should continue executing tasks following a failed task. The
+    * default is true, and the try block will exit on the first failure. Note
+    * that if set to false and more than one task fails, the "catch" target will
+    * execute for each failed task.
+    *
+    * @param b  if set to false, the try block will execute all tasks in the
+    *      block, regardless of failure of an individual task.
+    */
+   public void setBreak( boolean b ) {
+      doBreak = b;
+   }
+
+
+   /**
+    * If printstacktrace is set to true, this is ignored as the error message is
+    * printed as part of the stack trace. Default is to print the message.
+    *
+    * @param b  Should the error message of a failed task be logged?
+    */
+   public void setPrintmessage( boolean b ) {
+      doPrintMessage = b;
+   }
+
+
+   /**
+    * Default is to not print the stack trace.
+    *
+    * @param b  Should the stack trace of a failed task be logged?
+    */
+   public void setPrintstacktrace( boolean b ) {
+      doPrintStackTrace = b;
+   }
+
+    /**
+     * Try to execute all tasks.
+     *
+     * @exception BuildException  Description of Exception
+     */
+    public void execute() throws BuildException {
+        Throwable be = null;
+        try {
+            for ( Enumeration e = tasks.elements(); e.hasMoreElements();  ) {
+                Task task = (Task)e.nextElement();
+                try {
+                    task.perform();
+                }
+                catch ( Throwable throwable ) {
+                    be = throwable;
+                    if ( doPrintStackTrace ) {
+                        try {
+                            // log a message
+                            log( "Task '" + task.getTaskName() + "' in target '" +
+                                 ( task.getOwningTarget() == null ?
+                                 "unknown" :
+                                 task.getOwningTarget().getName() ) +
+                                 "' failed, task stack trace follows:" );
+
+                            // send the stack trace to the log
+                            StringWriter stacktrace = new StringWriter();
+                            PrintWriter writer = new PrintWriter( stacktrace, true );
+                            throwable.printStackTrace( writer );
+                            log( stacktrace.toString() );
+                        }
+                        catch ( Exception ignored ) {
+                           // don't fail on any exception
+                        }
+                    } else if ( doPrintMessage ) {
+                        try {
+                           // log a message
+                           log( "Task '" + task.getTaskName() + "' in target '" +
+                                 ( task.getOwningTarget() == null ?
+                                 "unknown" :
+                                 task.getOwningTarget().getName() ) +
+                                 "' failed, error message is: " + throwable.getMessage() );
+                        }
+                        catch ( Exception ignored ) {
+                           // don't fail on any exception
+                        }
+                    }
+
+                    // check if there is a nested CatchTask to execute.
+                    if ( catchTask != null ) {
+                        try {
+                            catchTask.perform();
+                            // the catch succeeded, clear the exception.
+                            be = null;
+                        } catch (Exception ex) {
+                            log( "Task '" + catchTask.getTaskName() + "' in target '" +
+                                  ( catchTask.getOwningTarget() == null ?
+                                  "unknown" :
+                                  catchTask.getOwningTarget().getName() ) +
+                                  "' failed, error message is: " + ex.getMessage() );
+                            be = ex;
+                        }
+                    }
+
+                    // check if remaining tasks should execute
+                    if ( doBreak ) {
+                        if (be == null) {
+                            break;
+                        } else {
+                            if (be instanceof BuildException)
+                                throw (BuildException)be;
+                            else {
+                                throw new BuildException(be);
+                            }
+                        }
+                    }
+                }
+            }
+        } finally {
+            // do the finally
+            if ( finallyTask != null ) {
+                finallyTask.perform();
+            }
+        }
+    }
+}
+