diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java
index 462e25639..3433b2441 100644
--- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/BuildEventSupport.java
@@ -54,12 +54,15 @@
package org.apache.ant.antcore.execution;
import java.util.ArrayList;
import java.util.Iterator;
-
+import java.util.Map;
+import java.util.HashMap;
import java.util.List;
-import org.apache.ant.common.model.ModelElement;
-import org.apache.ant.common.event.BuildListener;
-import org.apache.ant.common.event.BuildEvent;
import org.apache.ant.common.antlib.Task;
+import org.apache.ant.common.event.BuildEvent;
+import org.apache.ant.common.event.BuildListener;
+import org.apache.ant.common.model.ModelElement;
+import org.apache.ant.common.util.DemuxOutputReceiver;
+import org.apache.ant.common.event.MessageLevel;
/**
* BuildEventSupport is used by classes which which to send build events to
@@ -68,13 +71,16 @@ import org.apache.ant.common.antlib.Task;
* @author Conor MacNeill
* @created 15 January 2002
*/
-public class BuildEventSupport {
+public class BuildEventSupport implements DemuxOutputReceiver {
/**
* The listeners attached to the object which contains this support
* object
*/
private List listeners = new ArrayList();
+ /** Records the latest task to be executed on a thread (Thread to Task). */
+ private Map threadTasks = new HashMap();
+
/**
* Gets the listeners of the BuildEventSupport
*
@@ -166,6 +172,9 @@ public class BuildEventSupport {
* @param task the task with which the event is associated
*/
public void fireTaskStarted(Task task) {
+ synchronized (this) {
+ threadTasks.put(Thread.currentThread(), task);
+ }
BuildEvent event = new BuildEvent(task, BuildEvent.TASK_STARTED);
for (Iterator i = listeners.iterator(); i.hasNext(); ) {
BuildListener listener = (BuildListener)i.next();
@@ -181,6 +190,11 @@ public class BuildEventSupport {
*/
public void fireTaskFinished(Task task,
Throwable cause) {
+ System.out.flush();
+ System.err.flush();
+ synchronized (this) {
+ threadTasks.remove(Thread.currentThread());
+ }
BuildEvent event = new BuildEvent(task, BuildEvent.TASK_FINISHED,
cause);
for (Iterator i = listeners.iterator(); i.hasNext(); ) {
@@ -204,5 +218,28 @@ public class BuildEventSupport {
listener.messageLogged(event);
}
}
+
+ /**
+ * Demultiplexes output so that each task receives the appropriate
+ * messages. If the current thread is not currently executing a task,
+ * the message is logged directly.
+ *
+ * @param line Message to handle. Should not be null
.
+ * @param isError Whether the text represents an error (true
+ * ) or information (false
).
+ */
+ public void threadOutput(String line, boolean isError) {
+ Task task = (Task)threadTasks.get(Thread.currentThread());
+ if (task == null) {
+ fireMessageLogged(this, line,
+ isError ? MessageLevel.MSG_ERR : MessageLevel.MSG_INFO);
+ } else {
+ if (isError) {
+ task.handleSystemErr(line);
+ } else {
+ task.handleSystemOut(line);
+ }
+ }
+ }
}
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ComponentManager.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ComponentManager.java
index d6612e27a..a14106e95 100644
--- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ComponentManager.java
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ComponentManager.java
@@ -422,7 +422,12 @@ public class ComponentManager implements ComponentService {
throws ExecutionException {
ImportInfo definition = getDefinition(componentName);
+ if (definition == null) {
+ throw new ExecutionException("There is no definition of the <"
+ + componentName + "> component");
+ }
String className = definition.getClassName();
+
ComponentLibrary componentLibrary
= definition.getComponentLibrary();
String localName = definition.getLocalName();
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionManager.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionManager.java
index 71f5c6a23..d7c63176e 100755
--- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionManager.java
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/ExecutionManager.java
@@ -64,6 +64,7 @@ import org.apache.ant.common.event.BuildListener;
import org.apache.ant.common.model.Project;
import org.apache.ant.common.util.AntException;
import org.apache.ant.common.util.ExecutionException;
+import org.apache.ant.common.util.DemuxOutputReceiver;
import org.apache.ant.init.InitConfig;
/**
@@ -75,7 +76,7 @@ import org.apache.ant.init.InitConfig;
* @author Conor MacNeill
* @created 12 January 2002
*/
-public class ExecutionManager {
+public class ExecutionManager implements DemuxOutputReceiver {
/** The AntLibraries built from Ant's Populated Task Libraries. */
private Map antLibraries = new HashMap();
@@ -212,5 +213,17 @@ public class ExecutionManager {
}
}
+ /**
+ * Handle the content from a single thread. This method will be called
+ * by the thread producing the content. The content is broken up into
+ * separate lines
+ *
+ * @param line the content produce by the current thread.
+ * @param isErr true if this content is from the thread's error stream.
+ */
+ public void threadOutput(String line, boolean isErr) {
+ eventSupport.threadOutput(line, isErr);
+ }
+
}
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java
index dd0b7e683..6814f1441 100644
--- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/execution/Frame.java
@@ -74,6 +74,7 @@ import org.apache.ant.common.service.FileService;
import org.apache.ant.common.service.MagicProperties;
import org.apache.ant.common.util.AntException;
import org.apache.ant.common.util.ConfigException;
+import org.apache.ant.common.util.DemuxOutputReceiver;
import org.apache.ant.common.util.ExecutionException;
import org.apache.ant.common.util.FileUtils;
import org.apache.ant.init.InitConfig;
@@ -86,7 +87,7 @@ import org.apache.ant.init.InitConfig;
* @author Conor MacNeill
* @created 14 January 2002
*/
-public class Frame {
+public class Frame implements DemuxOutputReceiver {
/** the base dir of the project */
private File baseDir;
@@ -143,11 +144,9 @@ public class Frame {
*/
private ComponentManager componentManager;
- /**
- * The core's execution Service
- */
+ /** The core's execution Service */
private CoreExecService execService;
-
+
/**
* Create an Execution Frame for the given project
*
@@ -165,6 +164,18 @@ public class Frame {
this.initConfig = initConfig;
}
+ /**
+ * Replace ${} style constructions in the given value with the string
+ * value of the corresponding data values in the frame
+ *
+ * @param value the string to be scanned for property references.
+ * @return the string with all property references replaced
+ * @exception ExecutionException if any of the properties do not exist
+ */
+ public String replacePropertyRefs(String value) throws ExecutionException {
+ return dataService.replacePropertyRefs(value);
+ }
+
/**
* Sets the Project of the Frame
*
@@ -189,18 +200,6 @@ public class Frame {
setMagicProperties();
}
- /**
- * Replace ${} style constructions in the given value with the string
- * value of the corresponding data values in the frame
- *
- * @param value the string to be scanned for property references.
- * @return the string with all property references replaced
- * @exception ExecutionException if any of the properties do not exist
- */
- public String replacePropertyRefs(String value) throws ExecutionException {
- return dataService.replacePropertyRefs(value);
- }
-
/**
* Set a value in this frame or any of its imported frames.
*
@@ -603,7 +602,6 @@ public class Frame {
} catch (ConfigException e) {
throw new ExecutionException(e);
}
-
}
/**
@@ -623,8 +621,8 @@ public class Frame {
if (component instanceof Task) {
execService.executeTask((Task)component);
} else {
- String typeId
- = model.getAspectValue(Constants.ANT_ASPECT, "id");
+ String typeId
+ = model.getAspectValue(Constants.ANT_ASPECT, "id");
if (typeId != null) {
setDataValue(typeId, component, true);
}
@@ -709,6 +707,18 @@ public class Frame {
executeTasks(taskIterator);
}
+ /**
+ * Handle the content from a single thread. This method will be called
+ * by the thread producing the content. The content is broken up into
+ * separate lines
+ *
+ * @param line the content produce by the current thread.
+ * @param isErr true if this content is from the thread's error stream.
+ */
+ public void threadOutput(String line, boolean isErr) {
+ eventSupport.threadOutput(line, isErr);
+ }
+
/**
* Determine the base directory for each frame in the frame hierarchy
*
@@ -755,7 +765,7 @@ public class Frame {
dataService = new CoreDataService(this,
config.isUnsetPropertiesAllowed());
execService = new CoreExecService(this);
-
+
services.put(FileService.class, fileService);
services.put(ComponentService.class, componentManager);
services.put(DataService.class, dataService);
diff --git a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/ProjectHandler.java b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/ProjectHandler.java
index b0c76363d..36ea314f0 100644
--- a/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/ProjectHandler.java
+++ b/proposal/mutant/src/java/antcore/org/apache/ant/antcore/modelparser/ProjectHandler.java
@@ -76,6 +76,15 @@ public class ProjectHandler extends ElementHandler {
/** The default attribute name */
public static final String DEFAULT_ATTR = "default";
+ /** The name of the element used to define references */
+ public static final String REF_ELEMENT = "ant:ref";
+
+ /** The name of the element used to define references */
+ public static final String INCLUDE_ELEMENT = "ant:include";
+
+ /** The name of the element used to define references */
+ public static final String TARGET_ELEMENT = "target";
+
/** The project being parsed. */
private Project project;
@@ -148,8 +157,8 @@ public class ProjectHandler extends ElementHandler {
public void startElement(String uri, String localName, String qualifiedName,
Attributes attributes)
throws SAXParseException {
-
- if (qualifiedName.equals("ref")) {
+
+ if (qualifiedName.equals(REF_ELEMENT)) {
RefHandler refHandler = new RefHandler();
refHandler.start(getParseContext(), getXMLReader(), this,
getLocator(), attributes, getElementSource(),
@@ -160,12 +169,12 @@ public class ProjectHandler extends ElementHandler {
} catch (ModelException e) {
throw new SAXParseException(e.getMessage(), getLocator(), e);
}
- } else if (qualifiedName.equals("include")) {
+ } else if (qualifiedName.equals(INCLUDE_ELEMENT)) {
IncludeHandler includeHandler = new IncludeHandler(project);
includeHandler.start(getParseContext(), getXMLReader(),
this, getLocator(), attributes, getElementSource(),
qualifiedName);
- } else if (qualifiedName.equals("target")) {
+ } else if (qualifiedName.equals(TARGET_ELEMENT)) {
TargetHandler targetHandler = new TargetHandler();
targetHandler.start(getParseContext(), getXMLReader(),
this, getLocator(), attributes,
@@ -175,13 +184,17 @@ public class ProjectHandler extends ElementHandler {
} catch (ModelException e) {
throw new SAXParseException(e.getMessage(), getLocator(), e);
}
- } else {
+ } else if (localName != null) {
// everything else is a task
BuildElementHandler buildElementHandler = new BuildElementHandler();
buildElementHandler.start(getParseContext(), getXMLReader(),
this, getLocator(), attributes, getElementSource(),
qualifiedName);
project.addTask(buildElementHandler.getBuildElement());
+ } else {
+ // ignore namespaced elements
+ throw new SAXParseException("Only the \"ant\" namespace is "
+ + "currently recognized (" + qualifiedName + ")", getLocator());
}
}
diff --git a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java
index 1b036962e..ffba40a70 100644
--- a/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java
+++ b/proposal/mutant/src/java/antlibs/ant1compat/org/apache/tools/ant/Task.java
@@ -164,6 +164,31 @@ public abstract class Task extends ProjectComponent
}
}
+ /**
+ * Handle Output produced by the task. When a task prints to System.out
+ * the container may catch this and redirect the content back to the
+ * task by invoking this method. This method must NOT call System.out,
+ * directly or indirectly.
+ *
+ * @param line The line of content produce by the task
+ */
+ public void handleSystemOut(String line) {
+ handleOutput(line);
+ }
+
+ /**
+ * Handle error information produced by the task. When a task prints to
+ * System.err the container may catch this and redirect the content back
+ * to the task by invoking this method. This method must NOT call
+ * System.err, directly or indirectly.
+ *
+ * @param line The line of error info produce by the task
+ */
+ public void handleSystemErr(String line) {
+ // default behaviout is to log at WARN level
+ handleErrorOutput(line);
+ }
+
/**
* Handle output captured for this task
*
diff --git a/proposal/mutant/src/java/cli/org/apache/ant/cli/Commandline.java b/proposal/mutant/src/java/cli/org/apache/ant/cli/Commandline.java
index f6381e8af..60cba0cef 100755
--- a/proposal/mutant/src/java/cli/org/apache/ant/cli/Commandline.java
+++ b/proposal/mutant/src/java/cli/org/apache/ant/cli/Commandline.java
@@ -57,6 +57,7 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
+import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
@@ -75,6 +76,7 @@ import org.apache.ant.common.event.BuildListener;
import org.apache.ant.common.event.MessageLevel;
import org.apache.ant.common.model.Project;
import org.apache.ant.common.util.ConfigException;
+import org.apache.ant.common.util.DemuxOutputStream;
import org.apache.ant.init.InitConfig;
import org.apache.ant.init.InitUtils;
@@ -298,6 +300,12 @@ public class Commandline {
// create the execution manager to execute the build
executionManager = new ExecutionManager(initConfig, config);
+ OutputStream demuxOut
+ = new DemuxOutputStream(executionManager, false);
+ OutputStream demuxErr
+ = new DemuxOutputStream(executionManager, true);
+ System.setOut(new PrintStream(demuxOut));
+ System.setErr(new PrintStream(demuxErr));
addBuildListeners(executionManager);
} catch (Throwable e) {
if (logger != null) {
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java
index 6cccaa9ba..050861cef 100644
--- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/AbstractTask.java
@@ -52,6 +52,7 @@
* .
*/
package org.apache.ant.common.antlib;
+import org.apache.ant.common.event.MessageLevel;
/**
* Abstract implementation of the Task interface
@@ -81,5 +82,30 @@ public abstract class AbstractTask extends AbstractComponent implements Task {
return taskName;
}
+ /**
+ * Handle Output produced by the task. When a task prints to System.out
+ * the container may catch this and redirect the content back to the
+ * task by invoking this method. This method must NOT call System.out,
+ * directly or indirectly.
+ *
+ * @param line The line of content produce by the task
+ */
+ public void handleSystemOut(String line) {
+ // default behaviout is to log at INFO level
+ log(line, MessageLevel.MSG_INFO);
+ }
+
+ /**
+ * Handle error information produced by the task. When a task prints to
+ * System.err the container may catch this and redirect the content back
+ * to the task by invoking this method. This method must NOT call
+ * System.err, directly or indirectly.
+ *
+ * @param line The line of error info produce by the task
+ */
+ public void handleSystemErr(String line) {
+ // default behaviout is to log at WARN level
+ log(line, MessageLevel.MSG_WARN);
+ }
}
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Task.java b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Task.java
index da16f1dd5..667bbdec1 100644
--- a/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Task.java
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/antlib/Task.java
@@ -81,5 +81,25 @@ public interface Task extends ExecutionComponent {
* @return the taskName value
*/
String getTaskName();
+
+ /**
+ * Handle Output produced by the task. When a task prints to System.out
+ * the container may catch this and redirect the content back to the
+ * task by invoking this method. This method must NOT call System.out,
+ * directly or indirectly.
+ *
+ * @param line The line of content produce by the task
+ */
+ void handleSystemOut(String line);
+
+ /**
+ * Handle error information produced by the task. When a task prints to
+ * System.err the container may catch this and redirect the content back
+ * to the task by invoking this method. This method must NOT call
+ * System.err, directly or indirectly.
+ *
+ * @param line The line of error info produce by the task
+ */
+ void handleSystemErr(String line);
}
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/model/Project.java b/proposal/mutant/src/java/common/org/apache/ant/common/model/Project.java
index b6065f7c2..bc39d5a11 100644
--- a/proposal/mutant/src/java/common/org/apache/ant/common/model/Project.java
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/model/Project.java
@@ -253,9 +253,16 @@ public class Project extends ModelElement {
*
* @param fullTargetName The name of the target relative to this project
* @return the Target object with the given name
+ * @exception ModelException if the given target does not exist in this
+ * project
*/
- public Target getRefTarget(String fullTargetName) {
+ public Target getRefTarget(String fullTargetName) throws ModelException {
Project containingProject = getRefProject(fullTargetName);
+ if (containingProject == null) {
+ throw new ModelException("The target name \"" + fullTargetName
+ + "\" does not exist in this project");
+ }
+
if (containingProject == this) {
return getTarget(fullTargetName);
}
@@ -504,19 +511,23 @@ public class Project extends ModelElement {
if (flattenedList.contains(fullTargetName)) {
return;
}
- String fullProjectName = getFullProjectName(fullTargetName);
- Target target = getRefTarget(fullTargetName);
- if (target == null) {
- throw new ConfigException("Target " + fullTargetName
- + " does not exist");
- }
- for (Iterator i = target.getDependencies(); i.hasNext(); ) {
- String localDependencyName = (String)i.next();
- String fullDependencyName
- = fullProjectName == null ? localDependencyName
- : fullProjectName + REF_DELIMITER + localDependencyName;
- flattenDependency(flattenedList, fullDependencyName);
- flattenedList.add(fullDependencyName);
+ try {
+ String fullProjectName = getFullProjectName(fullTargetName);
+ Target target = getRefTarget(fullTargetName);
+ if (target == null) {
+ throw new ConfigException("Target " + fullTargetName
+ + " does not exist");
+ }
+ for (Iterator i = target.getDependencies(); i.hasNext(); ) {
+ String localDependencyName = (String)i.next();
+ String fullDependencyName
+ = fullProjectName == null ? localDependencyName
+ : fullProjectName + REF_DELIMITER + localDependencyName;
+ flattenDependency(flattenedList, fullDependencyName);
+ flattenedList.add(fullDependencyName);
+ }
+ } catch (ModelException e) {
+ throw new ConfigException(e);
}
}
}
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/util/DemuxOutputReceiver.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/DemuxOutputReceiver.java
new file mode 100644
index 000000000..4057c4be6
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/DemuxOutputReceiver.java
@@ -0,0 +1,74 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001-2002 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.common.util;
+
+/**
+ * A Demux output receiver receives buffered content which has been
+ * demultiplexed from the output potentially generated by multiple threads
+ *
+ * @author Conor MacNeill
+ * @created 22 February 2002
+ */
+public interface DemuxOutputReceiver {
+ /**
+ * Handle the content from a single thread. This method will be called
+ * by the thread producing the content. The content is broken up into
+ * separate lines
+ *
+ * @param line the content produce by the current thread.
+ * @param isErr true if this content is from the thread's error stream.
+ */
+ void threadOutput(String line, boolean isErr);
+}
+
diff --git a/proposal/mutant/src/java/common/org/apache/ant/common/util/DemuxOutputStream.java b/proposal/mutant/src/java/common/org/apache/ant/common/util/DemuxOutputStream.java
new file mode 100644
index 000000000..d3c07e1a3
--- /dev/null
+++ b/proposal/mutant/src/java/common/org/apache/ant/common/util/DemuxOutputStream.java
@@ -0,0 +1,198 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001-2002 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.common.util;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import java.io.OutputStream;
+import java.util.Hashtable;
+
+/**
+ * Buffers content written per thread and forwards the buffers onto the
+ * given receiver
+ *
+ * @author Conor MacNeill
+ * @created 22 February 2002
+ */
+public class DemuxOutputStream extends OutputStream {
+
+ /**
+ * A data class to store information about a buffer. Such informatio is
+ * stored on a per-thread basis.
+ *
+ * @author Conor MacNeill
+ * @created 22 February 2002
+ */
+ private static class BufferInfo {
+ /** The per-thread output stream */
+ private ByteArrayOutputStream buffer;
+
+ /**
+ * Whether the next line-terminator should be skipped in terms of
+ * processing the buffer or not. Used to avoid \r\n invoking
+ * processBuffer twice.
+ */
+ private boolean skip = false;
+ }
+
+ /** Maximum buffer size */
+ private static final int MAX_SIZE = 1024;
+ /** Mapping from thread to buffer (Thread to BufferInfo) */
+ private Hashtable buffers = new Hashtable();
+
+ /** The object which receives the output */
+ private DemuxOutputReceiver receiver;
+
+ /** Whether or not this stream represents an error stream */
+ private boolean isErrorStream;
+
+ /**
+ * Creates a new instance of this class.
+ *
+ * @param isErrorStream true if this is the error string, otherwise a
+ * normal output stream. This is passed to the project so it knows
+ * which stream it is receiving.
+ * @param receiver The receiver to which demux'd content is sent.
+ */
+ public DemuxOutputStream(DemuxOutputReceiver receiver,
+ boolean isErrorStream) {
+ this.receiver = receiver;
+ this.isErrorStream = isErrorStream;
+ }
+
+ /**
+ * Writes the data to the buffer and flushes the buffer if a line
+ * separator is detected or if the buffer has reached its maximum size.
+ *
+ * @param cc data to log (byte).
+ * @exception IOException if the data cannot be written to the stream
+ */
+ public void write(int cc) throws IOException {
+ final byte c = (byte)cc;
+
+ BufferInfo bufferInfo = getBufferInfo();
+ if ((c == '\n') || (c == '\r')) {
+ if (!bufferInfo.skip) {
+ processBuffer(bufferInfo.buffer);
+ }
+ } else {
+ bufferInfo.buffer.write(cc);
+ if (bufferInfo.buffer.size() > MAX_SIZE) {
+ processBuffer(bufferInfo.buffer);
+ }
+ }
+ bufferInfo.skip = (c == '\r');
+ }
+
+ /**
+ * Equivalent to calling {@link #flush flush} on the stream.
+ *
+ * @exception IOException if there is a problem closing the stream.
+ */
+ public void close() throws IOException {
+ flush();
+ }
+
+ /**
+ * Writes all remaining data in the buffer associated with the current
+ * thread to the project.
+ *
+ * @exception IOException if there is a problem flushing the stream.
+ */
+ public void flush() throws IOException {
+ BufferInfo bufferInfo = getBufferInfo();
+ if (bufferInfo.buffer.size() > 0) {
+ processBuffer(bufferInfo.buffer);
+ }
+ }
+
+
+ /**
+ * Converts the buffer to a string and sends it to {@link
+ * Project#demuxOutput(String,boolean) Project.demuxOutput}.
+ *
+ * @param buffer the ByteArrayOutputStream used to collect the output
+ * until a line separator is seen.
+ */
+ protected void processBuffer(ByteArrayOutputStream buffer) {
+ String output = buffer.toString();
+ receiver.threadOutput(output, isErrorStream);
+ resetBufferInfo();
+ }
+
+ /**
+ * Returns the buffer associated with the current thread.
+ *
+ * @return a ByteArrayOutputStream for the current thread to write data
+ * to
+ */
+ private BufferInfo getBufferInfo() {
+ Thread current = Thread.currentThread();
+ BufferInfo bufferInfo = (BufferInfo)buffers.get(current);
+ if (bufferInfo == null) {
+ bufferInfo = new BufferInfo();
+ bufferInfo.buffer = new ByteArrayOutputStream();
+ bufferInfo.skip = false;
+ buffers.put(current, bufferInfo);
+ }
+ return bufferInfo;
+ }
+
+ /** Resets the buffer for the current thread. */
+ private void resetBufferInfo() {
+ Thread current = Thread.currentThread();
+ buffers.remove(current);
+ }
+}
+
diff --git a/proposal/mutant/src/java/start/org/apache/tools/ant/Main.java b/proposal/mutant/src/java/start/org/apache/tools/ant/Main.java
new file mode 100755
index 000000000..5a67d5d7f
--- /dev/null
+++ b/proposal/mutant/src/java/start/org/apache/tools/ant/Main.java
@@ -0,0 +1,71 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 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.tools.ant;
+
+/**
+ * Old Ant1 entry point
+ *
+ * @author Conor MacNeill
+ */
+public class Main {
+ /**
+ * Entry point for starting command line Ant
+ *
+ * @param args commandline arguments
+ */
+ public static void main(String[] args) {
+ org.apache.ant.start.Main.main(args);
+ }
+}
+