summaryrefslogtreecommitdiffstats
path: root/src/main/java/net/sf/antcontrib/antserver
diff options
context:
space:
mode:
authorcarnold <[email protected]>2007-07-31 03:18:26 +0000
committercarnold <[email protected]>2007-07-31 03:18:26 +0000
commit6e33899d3676c1f470c41703ac0b512341e9324c (patch)
tree7a3ef5e22ad823c78a9940541b9bf44dc3222306 /src/main/java/net/sf/antcontrib/antserver
parent07c6778db4f5ad7e790193801834d48d90cfaad0 (diff)
Bug 1760649: Initial Maven 2 build for ant-contrib
git-svn-id: file:///home/sven/projects/JOGL/temp/ant-contrib/svn/ant-contrib-code/ant-contrib/trunk@130 32d7a393-a5a9-423c-abd3-5d954feb1f2f
Diffstat (limited to 'src/main/java/net/sf/antcontrib/antserver')
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/Command.java82
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/Response.java112
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/Util.java67
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/client/Client.java251
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/client/ClientTask.java203
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/commands/AbstractCommand.java69
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/commands/DisconnectCommand.java57
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/commands/HelloWorldCommand.java51
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/commands/PropertyContainer.java65
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/commands/ReferenceContainer.java65
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/commands/RunAntCommand.java203
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/commands/RunTargetCommand.java176
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/commands/SendFileCommand.java171
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/commands/ShutdownCommand.java51
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/server/ConnectionBuildListener.java198
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/server/ConnectionHandler.java231
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/server/Server.java126
-rw-r--r--src/main/java/net/sf/antcontrib/antserver/server/ServerTask.java68
18 files changed, 2246 insertions, 0 deletions
diff --git a/src/main/java/net/sf/antcontrib/antserver/Command.java b/src/main/java/net/sf/antcontrib/antserver/Command.java
new file mode 100644
index 0000000..e9d84a0
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/Command.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+
+import org.apache.tools.ant.Project;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public interface Command
+ extends Serializable
+{
+ /***
+ * This should throw a build exception if the parameters
+ * are invalid.
+ */
+ public void validate(Project project);
+
+ /***
+ * Is there additional content being sent from the local
+ * machine to the remote server
+ */
+ public long getContentLength();
+
+ /***
+ * Gets the content's input stream. Should be called only on the
+ * client side for sending the content over the connection
+ * @return the content's input stream.
+ */
+ public InputStream getContentStream() throws IOException;
+
+
+ public long getResponseContentLength();
+
+ public InputStream getReponseContentStream() throws IOException;
+
+ /***
+ * Execute the command.
+ * @param project The project which is being executed
+ * @return If true, the connection will be closed
+ * @throws Throwable
+ */
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream contentStream)
+ throws Throwable;
+
+ /***
+ * Process any additional data from a response.
+ */
+ public boolean respond(Project project,
+ long contentLength,
+ InputStream contentStream)
+ throws IOException;
+
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/Response.java b/src/main/java/net/sf/antcontrib/antserver/Response.java
new file mode 100644
index 0000000..b1958d9
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/Response.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.Serializable;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ *
+ ****************************************************************************/
+
+
+public class Response
+ implements Serializable
+{
+ private boolean succeeded;
+ private String errorStackTrace;
+ private String errorMessage;
+ private String resultsXml;
+
+ private long contentLength;
+
+ public Response()
+ {
+ super();
+ this.succeeded = true;
+ }
+
+
+ public boolean isSucceeded()
+ {
+ return succeeded;
+ }
+
+
+ public void setSucceeded(boolean succeeded)
+ {
+ this.succeeded = succeeded;
+ }
+
+ public void setThrowable(Throwable t)
+ {
+ errorMessage = t.getMessage();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ t.printStackTrace(ps);
+ ps.flush();
+ setErrorStackTrace(baos.toString());
+ }
+
+ public String getErrorStackTrace()
+ {
+ return errorStackTrace;
+ }
+
+
+ public void setErrorStackTrace(String errorStackTrace)
+ {
+ this.errorStackTrace = errorStackTrace;
+ }
+
+
+ public String getErrorMessage()
+ {
+ return errorMessage;
+ }
+
+
+ public void setErrorMessage(String errorMessage)
+ {
+ this.errorMessage = errorMessage;
+ }
+
+
+ public String getResultsXml()
+ {
+ return resultsXml;
+ }
+
+
+ public void setResultsXml(String resultsXml)
+ {
+ this.resultsXml = resultsXml;
+ }
+
+ public long getContentLength()
+ {
+ return contentLength;
+ }
+
+ public void setContentLength(long contentLength)
+ {
+ this.contentLength = contentLength;
+ }
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/Util.java b/src/main/java/net/sf/antcontrib/antserver/Util.java
new file mode 100644
index 0000000..124e315
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/Util.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class Util
+{
+ public static final int CHUNK = 10*1024;
+
+ public static final void transferBytes(InputStream input,
+ long length,
+ OutputStream output,
+ boolean closeInput)
+ throws IOException
+ {
+
+ byte b[] = new byte[CHUNK];
+ int read = 0;
+ int totalread = 0;
+
+ while (totalread < length)
+ {
+ int toRead = (int)Math.min(CHUNK, length - totalread);
+ read = input.read(b, 0, toRead);
+ output.write(b, 0, read);
+ totalread += read;
+ }
+
+ try
+ {
+ if (closeInput)
+ input.close();
+ }
+ catch (IOException e)
+ {
+ // ; gulp
+ }
+ }
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/client/Client.java b/src/main/java/net/sf/antcontrib/antserver/client/Client.java
new file mode 100644
index 0000000..061815f
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/client/Client.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.client;
+
+import java.io.*;
+import java.net.Socket;
+import java.net.SocketException;
+
+import org.apache.tools.ant.Project;
+
+import net.sf.antcontrib.antserver.Command;
+import net.sf.antcontrib.antserver.Response;
+import net.sf.antcontrib.antserver.Util;
+import net.sf.antcontrib.antserver.commands.DisconnectCommand;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class Client
+{
+ private String machine;
+ private int port;
+ private Project project;
+
+
+ public Client(Project project, String machine, int port)
+ {
+ super();
+ this.machine = machine;
+ this.port = port;
+ this.project = project;
+ }
+
+
+ private Socket socket;
+ private OutputStream os;
+ private InputStream is;
+ private ObjectOutputStream oos;
+ private ObjectInputStream ois;
+ private boolean connected;
+
+
+ public void connect()
+ throws IOException
+ {
+ project.log("Opening connection to " + machine + ":" + port,
+ Project.MSG_DEBUG);
+
+ try
+ {
+ socket = new Socket(machine, port);
+ socket.setKeepAlive(true);
+ project.log("Got connection to " + machine + ":" + port,
+ Project.MSG_DEBUG);
+
+ os = socket.getOutputStream();
+ is = socket.getInputStream();
+
+ oos = new ObjectOutputStream(os);
+ ois = new ObjectInputStream(is);
+
+ connected = true;
+ try
+ {
+ // Read the initial response object so that the
+ // object stream is initialized
+ ois.readObject();
+ }
+ catch (ClassNotFoundException e)
+ {
+ ; // gulp
+ }
+ }
+ finally
+ {
+ // If we were unable to connect, close everything
+ if (!connected)
+ {
+
+ try
+ {
+ if (os != null)
+ os.close();
+ os = null;
+ oos = null;
+ }
+ catch (IOException e)
+ {
+
+ }
+
+ try
+ {
+ if (is != null)
+ is.close();
+ is = null;
+ ois = null;
+ }
+ catch (IOException e)
+ {
+
+ }
+
+ try
+ {
+ if (socket != null)
+ socket.close();
+ socket = null;
+ }
+ catch (IOException e)
+ {
+
+ }
+ }
+ }
+
+
+ }
+
+ public void shutdown()
+ {
+ try
+ {
+ if (os != null)
+ os.close();
+ }
+ catch (IOException e)
+ {
+ ; // gulp
+
+ }
+ os = null;
+ oos = null;
+
+ try
+ {
+ if (is != null)
+ is.close();
+ }
+ catch (IOException e)
+ {
+ ; // gulp
+
+ }
+ is = null;
+ ois = null;
+
+ try
+ {
+ socket.close();
+ }
+ catch (IOException e)
+ {
+ ; // gulp
+ }
+ socket = null;
+
+ connected = false;
+ }
+
+
+ public void disconnect()
+ throws IOException
+ {
+ if (!connected)
+ return;
+
+ try {
+ oos.writeObject(DisconnectCommand.DISCONNECT_COMMAND);
+ try
+ {
+ // Read disconnect response
+ ois.readObject();
+ }
+ catch (ClassNotFoundException e)
+ {
+ ; // gulp
+ }
+
+ shutdown();
+ }
+ catch (SocketException e) {
+ ; // connection was closed
+ }
+ catch (EOFException e) {
+ ; // connection was closed
+ }
+ }
+
+
+ public Response sendCommand(Command command)
+ throws IOException
+ {
+ project.log("Sending command: " + command,
+ Project.MSG_DEBUG);
+ oos.writeObject(command);
+
+ if (command.getContentLength() > 0)
+ {
+ Util.transferBytes(command.getContentStream(),
+ command.getContentLength(),
+ os,
+ true);
+ }
+
+ Response response = null;
+
+ try
+ {
+ // Read the response object
+ response = (Response) ois.readObject();
+ project.log("Received Response: " + response,
+ Project.MSG_DEBUG);
+ if (response.getContentLength() != 0)
+ {
+ command.respond(project,
+ response.getContentLength(),
+ is);
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ ; // gulp
+ }
+
+ return response;
+ }
+
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/client/ClientTask.java b/src/main/java/net/sf/antcontrib/antserver/client/ClientTask.java
new file mode 100644
index 0000000..34236f0
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/client/ClientTask.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.client;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import net.sf.antcontrib.antserver.Command;
+import net.sf.antcontrib.antserver.Response;
+import net.sf.antcontrib.antserver.commands.RunAntCommand;
+import net.sf.antcontrib.antserver.commands.RunTargetCommand;
+import net.sf.antcontrib.antserver.commands.SendFileCommand;
+import net.sf.antcontrib.antserver.commands.ShutdownCommand;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class ClientTask
+ extends Task
+{
+ private String machine = "localhost";
+ private int port = 17000;
+ private Vector commands;
+ private boolean persistant = false;
+ private boolean failOnError = true;
+
+ public ClientTask()
+ {
+ super();
+ this.commands = new Vector();
+ }
+
+
+ public void setMachine(String machine)
+ {
+ this.machine = machine;
+ }
+
+
+ public void setPort(int port)
+ {
+ this.port = port;
+ }
+
+
+ public void setPersistant(boolean persistant)
+ {
+ this.persistant = persistant;
+ }
+
+
+ public void setFailOnError(boolean failOnError)
+ {
+ this.failOnError = failOnError;
+ }
+
+
+ public void addConfiguredShutdown(ShutdownCommand cmd)
+ {
+ commands.add(cmd);
+ }
+
+ public void addConfiguredRunTarget(RunTargetCommand cmd)
+ {
+ commands.add(cmd);
+ }
+
+ public void addConfiguredRunAnt(RunAntCommand cmd)
+ {
+ commands.add(cmd);
+ }
+
+ public void addConfiguredSendFile(SendFileCommand cmd)
+ {
+ commands.add(cmd);
+ }
+
+
+ public void execute()
+ {
+ Enumeration e = commands.elements();
+ Command c = null;
+ while (e.hasMoreElements())
+ {
+ c = (Command)e.nextElement();
+ c.validate(getProject());
+ }
+
+ Client client = new Client(getProject(), machine, port);
+
+ try
+ {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+
+ try
+ {
+ int failCount = 0;
+
+ client.connect();
+
+ e = commands.elements();
+ c = null;
+ Response r = null;
+ Document d = null;
+ boolean keepGoing = true;
+ while (e.hasMoreElements() && keepGoing)
+ {
+ c = (Command)e.nextElement();
+ r = client.sendCommand(c);
+ if (! r.isSucceeded())
+ {
+ failCount++;
+ log("Command caused a build failure:" + c,
+ Project.MSG_ERR);
+ log(r.getErrorMessage(),
+ Project.MSG_ERR);
+ log(r.getErrorStackTrace(),
+ Project.MSG_DEBUG);
+ if (! persistant)
+ keepGoing = false;
+ }
+
+ try
+ {
+ ByteArrayInputStream bais =
+ new ByteArrayInputStream(r.getResultsXml().getBytes());
+ d = db.parse(bais);
+ NodeList nl = d.getElementsByTagName("target");
+ int len = nl.getLength();
+ Element element = null;
+ for (int i=0;i<len;i++)
+ {
+ element = (Element)nl.item(i);
+ getProject().log("[" + element.getAttribute("name") + "]",
+ Project.MSG_INFO);
+ }
+ }
+ catch (SAXException se)
+ {
+
+ }
+
+ if (c instanceof ShutdownCommand)
+ {
+ keepGoing = false;
+ client.shutdown();
+ }
+ }
+
+ if (failCount > 0 && failOnError)
+ throw new BuildException("One or more commands failed.");
+ }
+ finally
+ {
+ if (client != null)
+ client.disconnect();
+ }
+ }
+ catch (ParserConfigurationException ex)
+ {
+ throw new BuildException(ex);
+ }
+ catch (IOException ex)
+ {
+ throw new BuildException(ex);
+ }
+ }
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/commands/AbstractCommand.java b/src/main/java/net/sf/antcontrib/antserver/commands/AbstractCommand.java
new file mode 100644
index 0000000..9734631
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/commands/AbstractCommand.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.commands;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.tools.ant.Project;
+
+import net.sf.antcontrib.antserver.Command;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ *
+ ****************************************************************************/
+
+
+public abstract class AbstractCommand
+ implements Command
+{
+ public long getContentLength()
+ {
+ return 0;
+ }
+
+
+ public InputStream getContentStream()
+ throws IOException
+ {
+ return null;
+ }
+
+
+ public long getResponseContentLength()
+ {
+ return 0;
+ }
+
+
+ public InputStream getReponseContentStream() throws IOException
+ {
+ return null;
+ }
+
+
+ public boolean respond(Project project,
+ long contentLength,
+ InputStream contentStream)
+ throws IOException
+ {
+ return false;
+ }
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/commands/DisconnectCommand.java b/src/main/java/net/sf/antcontrib/antserver/commands/DisconnectCommand.java
new file mode 100644
index 0000000..a89177b
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/commands/DisconnectCommand.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.commands;
+
+import java.io.InputStream;
+
+import org.apache.tools.ant.Project;
+
+import net.sf.antcontrib.antserver.Command;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class DisconnectCommand
+ extends AbstractCommand
+ implements Command
+{
+ public static Command DISCONNECT_COMMAND =
+ new DisconnectCommand();
+
+ private DisconnectCommand()
+ {
+ }
+
+ public void validate(Project project)
+ {
+ }
+
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream content)
+ throws Throwable
+ {
+ return true;
+ }
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/commands/HelloWorldCommand.java b/src/main/java/net/sf/antcontrib/antserver/commands/HelloWorldCommand.java
new file mode 100644
index 0000000..68f884f
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/commands/HelloWorldCommand.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.commands;
+
+import java.io.InputStream;
+
+import org.apache.tools.ant.Project;
+
+import net.sf.antcontrib.antserver.Command;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class HelloWorldCommand
+ extends AbstractCommand
+ implements Command
+{
+ public void validate(Project project)
+ {
+ }
+
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream content)
+ throws Throwable
+ {
+ project.log("Hello World", Project.MSG_ERR);
+ return false;
+ }
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/commands/PropertyContainer.java b/src/main/java/net/sf/antcontrib/antserver/commands/PropertyContainer.java
new file mode 100644
index 0000000..9c7aaf4
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/commands/PropertyContainer.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.commands;
+
+import java.io.Serializable;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class PropertyContainer
+ implements Serializable
+{
+ private String name;
+ private String value;
+
+ public PropertyContainer()
+ {
+ super();
+ }
+
+
+ public String getName()
+ {
+ return name;
+ }
+
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+
+ public String getValue()
+ {
+ return value;
+ }
+
+
+ public void setValue(String value)
+ {
+ this.value = value;
+ }
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/commands/ReferenceContainer.java b/src/main/java/net/sf/antcontrib/antserver/commands/ReferenceContainer.java
new file mode 100644
index 0000000..e755343
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/commands/ReferenceContainer.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.commands;
+
+import java.io.Serializable;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class ReferenceContainer
+ implements Serializable
+{
+ private String refId;
+ private String toRefId;
+
+ public ReferenceContainer()
+ {
+ super();
+ }
+
+
+ public String getRefId()
+ {
+ return refId;
+ }
+
+
+ public void setRefid(String refId)
+ {
+ this.refId = refId;
+ }
+
+
+ public String getToRefId()
+ {
+ return toRefId;
+ }
+
+
+ public void setToRefId(String toRefId)
+ {
+ this.toRefId = toRefId;
+ }
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/commands/RunAntCommand.java b/src/main/java/net/sf/antcontrib/antserver/commands/RunAntCommand.java
new file mode 100644
index 0000000..51b114c
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/commands/RunAntCommand.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.commands;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.Ant;
+import org.apache.tools.ant.taskdefs.Property;
+
+import net.sf.antcontrib.antserver.Command;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class RunAntCommand
+ extends AbstractCommand
+ implements Command
+{
+
+ private String antFile;
+ private String dir;
+ private String target;
+ private Vector properties;
+ private Vector references;
+ private boolean inheritall = false;
+ private boolean interitrefs = false;
+
+ public RunAntCommand()
+ {
+ super();
+ this.properties = new Vector();
+ this.references = new Vector();
+ }
+
+
+ public String getTarget()
+ {
+ return target;
+ }
+
+
+ public void setTarget(String target)
+ {
+ this.target = target;
+ }
+
+
+ public Vector getProperties()
+ {
+ return properties;
+ }
+
+
+ public void setProperties(Vector properties)
+ {
+ this.properties = properties;
+ }
+
+ public Vector getReferences()
+ {
+ return references;
+ }
+
+
+ public void setReferences(Vector references)
+ {
+ this.references = references;
+ }
+
+ public boolean isInheritall()
+ {
+ return inheritall;
+ }
+
+
+ public void setInheritall(boolean inheritall)
+ {
+ this.inheritall = inheritall;
+ }
+
+
+ public boolean isInteritrefs()
+ {
+ return interitrefs;
+ }
+
+
+ public void setInteritrefs(boolean interitrefs)
+ {
+ this.interitrefs = interitrefs;
+ }
+
+
+ public String getAntFile()
+ {
+ return antFile;
+ }
+
+
+ public void setAntFile(String antFile)
+ {
+ this.antFile = antFile;
+ }
+
+
+ public String getDir()
+ {
+ return dir;
+ }
+
+
+ public void setDir(String dir)
+ {
+ this.dir = dir;
+ }
+
+
+ public void addConfiguredProperty(PropertyContainer property)
+ {
+ properties.addElement(property);
+ }
+
+ public void addConfiguredReference(ReferenceContainer reference)
+ {
+ references.addElement(reference);
+ }
+
+ public void validate(Project project)
+ {
+ }
+
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream content)
+ throws Throwable
+ {
+ Ant ant = (Ant)project.createTask("ant");
+ File baseDir = project.getBaseDir();
+ if (dir != null)
+ baseDir = new File(dir);
+ ant.setDir(baseDir);
+ ant.setInheritAll(inheritall);
+ ant.setInheritRefs(interitrefs);
+
+ if (target != null)
+ ant.setTarget(target);
+
+ if (antFile != null)
+ ant.setAntfile(antFile);
+
+ Enumeration e = properties.elements();
+ PropertyContainer pc = null;
+ Property p = null;
+ while (e.hasMoreElements())
+ {
+ pc = (PropertyContainer)e.nextElement();
+ p = ant.createProperty();
+ p.setName(pc.getName());
+ p.setValue(pc.getValue());
+ }
+
+ e = references.elements();
+ ReferenceContainer rc = null;
+ Ant.Reference ref = null;
+ while (e.hasMoreElements())
+ {
+ rc = (ReferenceContainer)e.nextElement();
+ ref = new Ant.Reference();
+ ref.setRefId(rc.getRefId());
+ ref.setToRefid(rc.getToRefId());
+ ant.addReference(ref);
+ }
+
+ ant.execute();
+
+ return false;
+ }
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/commands/RunTargetCommand.java b/src/main/java/net/sf/antcontrib/antserver/commands/RunTargetCommand.java
new file mode 100644
index 0000000..a22e5db
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/commands/RunTargetCommand.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.commands;
+
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.Ant;
+import org.apache.tools.ant.taskdefs.CallTarget;
+import org.apache.tools.ant.taskdefs.Property;
+
+import net.sf.antcontrib.antserver.Command;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class RunTargetCommand
+ extends AbstractCommand
+ implements Command
+{
+ private String target;
+ private Vector properties;
+ private Vector references;
+ private boolean inheritall = false;
+ private boolean interitrefs = false;
+
+ public RunTargetCommand()
+ {
+ super();
+ this.properties = new Vector();
+ this.references = new Vector();
+ }
+
+
+ public String getTarget()
+ {
+ return target;
+ }
+
+
+ public void setTarget(String target)
+ {
+ this.target = target;
+ }
+
+
+ public Vector getProperties()
+ {
+ return properties;
+ }
+
+
+ public void setProperties(Vector properties)
+ {
+ this.properties = properties;
+ }
+
+
+
+ public Vector getReferences()
+ {
+ return references;
+ }
+
+
+ public void setReferences(Vector references)
+ {
+ this.references = references;
+ }
+
+
+ public boolean isInheritall()
+ {
+ return inheritall;
+ }
+
+
+ public void setInheritall(boolean inheritall)
+ {
+ this.inheritall = inheritall;
+ }
+
+
+ public boolean isInteritrefs()
+ {
+ return interitrefs;
+ }
+
+
+ public void setInteritrefs(boolean interitrefs)
+ {
+ this.interitrefs = interitrefs;
+ }
+
+
+ public void addConfiguredProperty(PropertyContainer property)
+ {
+ properties.addElement(property);
+ }
+
+
+ public void addConfiguredReference(ReferenceContainer reference)
+ {
+ references.addElement(reference);
+ }
+
+ public void validate(Project project)
+ {
+ }
+
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream content)
+ throws Throwable
+ {
+ CallTarget callTarget = (CallTarget)project.createTask("antcall");
+ callTarget.setInheritAll(inheritall);
+ callTarget.setInheritRefs(interitrefs);
+
+ String toExecute = target;
+ if (toExecute == null)
+ toExecute = project.getDefaultTarget();
+ callTarget.setTarget(toExecute);
+
+ Enumeration e = properties.elements();
+ PropertyContainer pc = null;
+ Property p = null;
+ while (e.hasMoreElements())
+ {
+ pc = (PropertyContainer)e.nextElement();
+ p = callTarget.createParam();
+ p.setName(pc.getName());
+ p.setValue(pc.getValue());
+ }
+
+
+ e = references.elements();
+ ReferenceContainer rc = null;
+ Ant.Reference ref = null;
+ while (e.hasMoreElements())
+ {
+ rc = (ReferenceContainer)e.nextElement();
+ ref = new Ant.Reference();
+ ref.setRefId(rc.getRefId());
+ ref.setToRefid(rc.getToRefId());
+ callTarget.addReference(ref);
+ }
+
+ callTarget.execute();
+
+ return false;
+ }
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/commands/SendFileCommand.java b/src/main/java/net/sf/antcontrib/antserver/commands/SendFileCommand.java
new file mode 100644
index 0000000..3aada4d
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/commands/SendFileCommand.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.commands;
+
+import java.io.*;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+
+import net.sf.antcontrib.antserver.Command;
+import net.sf.antcontrib.antserver.Util;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class SendFileCommand
+ extends AbstractCommand
+ implements Command
+{
+ private long contentLength;
+ private String todir;
+ private String tofile;
+ private String fileBaseName;
+ private transient File file;
+
+ public File getFile()
+ {
+ return file;
+ }
+
+ public long getContentLength()
+ {
+ return contentLength;
+ }
+
+ public InputStream getContentStream()
+ throws IOException
+ {
+ return new FileInputStream(file);
+ }
+
+ public void setFile(File file)
+ {
+ this.file = file;
+ this.fileBaseName = file.getName();
+ this.contentLength = file.length();
+ }
+
+
+ public String getTofile()
+ {
+ return tofile;
+ }
+
+
+ public void setTofile(String tofile)
+ {
+ this.tofile = tofile;
+ }
+
+
+ public String getTodir()
+ {
+ return todir;
+ }
+
+
+ public void setTodir(String todir)
+ {
+ this.todir = todir;
+ }
+
+ public void validate(Project project)
+ {
+ if (file == null)
+ throw new BuildException("Missing required attribute 'file'");
+
+ if (tofile == null && todir == null)
+ throw new BuildException("Missing both attributes 'tofile' and 'todir'"
+ + " at least one must be supplied");
+
+ /*
+ try
+ {
+ String realBasePath = project.getBaseDir().getCanonicalPath();
+ String realGetBasePath = file.getCanonicalPath();
+ if (! realGetBasePath.startsWith(realBasePath))
+ throw new SecurityException("Cannot access a file that is not rooted in the project execution directory");
+ }
+ catch (IOException e)
+ {
+ throw new BuildException(e);
+ }
+ */
+
+
+ }
+
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream content)
+ throws Throwable
+ {
+ File dest = null;
+
+ if (tofile != null)
+ {
+ dest = new File(project.getBaseDir(), tofile);
+ if (! new File(tofile).getCanonicalPath().startsWith(project.getBaseDir().getCanonicalPath())) {
+ System.out.println("throwing an exception");
+ throw new SecurityException("The requested filename must be a relative path.");
+ }
+ }
+ else
+ {
+ dest = new File(project.getBaseDir(), todir);
+ dest = new File(dest, fileBaseName);
+
+ if (! new File(todir, tofile).getCanonicalPath().startsWith(project.getBaseDir().getCanonicalPath())) {
+ throw new SecurityException("The requested filename must be a relative path.");
+ }
+
+ }
+
+ FileOutputStream fos = null;
+
+ try
+ {
+ fos = new FileOutputStream(dest);
+
+ Util.transferBytes(content,
+ contentLength,
+ fos,
+ false);
+ }
+ finally
+ {
+ try
+ {
+ if (fos != null)
+ fos.close();
+ }
+ catch (IOException e)
+ {
+ ; // gulp;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/commands/ShutdownCommand.java b/src/main/java/net/sf/antcontrib/antserver/commands/ShutdownCommand.java
new file mode 100644
index 0000000..6dcf226
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/commands/ShutdownCommand.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.commands;
+
+import java.io.InputStream;
+
+import org.apache.tools.ant.Project;
+
+import net.sf.antcontrib.antserver.Command;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class ShutdownCommand
+ extends AbstractCommand
+ implements Command
+{
+ public void validate(Project project)
+ {
+ }
+
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream content)
+ throws Throwable
+ {
+ return false;
+ }
+
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/server/ConnectionBuildListener.java b/src/main/java/net/sf/antcontrib/antserver/server/ConnectionBuildListener.java
new file mode 100644
index 0000000..39cf1e5
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/server/ConnectionBuildListener.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.server;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Stack;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.tools.ant.BuildEvent;
+import org.apache.tools.ant.BuildListener;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class ConnectionBuildListener
+ implements BuildListener
+{
+ private Document results;
+ private Stack elementStack;
+ private ThreadGroup group;
+
+ public ConnectionBuildListener()
+ throws ParserConfigurationException
+ {
+ group = Thread.currentThread().getThreadGroup();
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ results = builder.newDocument();
+ elementStack = new Stack();
+
+ Element rootElement = results.createElement("results");
+ elementStack.push(rootElement);
+ results.appendChild(rootElement);
+ }
+
+ public Document getDocument()
+ {
+ return results;
+ }
+
+ public void buildStarted(BuildEvent event)
+ {
+ }
+
+
+ public void buildFinished(BuildEvent event)
+ {
+ }
+
+
+ public void targetStarted(BuildEvent event)
+ {
+ if (Thread.currentThread().getThreadGroup() != group)
+ return;
+
+ Element parent = (Element)elementStack.peek();
+
+ Element myElement = results.createElement("target");
+ myElement.setAttribute("name", event.getTarget().getName());
+ parent.appendChild(myElement);
+
+ elementStack.push(myElement);
+ }
+
+
+ public void targetFinished(BuildEvent event)
+ {
+ if (Thread.currentThread().getThreadGroup() != group)
+ return;
+
+ Element myElement = (Element)elementStack.peek();
+
+ String message = event.getMessage();
+ if (message != null)
+ myElement.setAttribute("message", message);
+
+ Throwable t = event.getException();
+ if (t != null)
+ {
+ myElement.setAttribute("status", "failure");
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ t.printStackTrace(ps);
+ ps.flush();
+ String errorMessage = t.getMessage();
+ String stackTrace = baos.toString();
+
+ Element error = results.createElement("error");
+ Element errorMsgElement = results.createElement("message");
+ errorMsgElement.appendChild(results.createTextNode(errorMessage));
+ Element stackElement = results.createElement("stack");
+ stackElement.appendChild(results.createCDATASection(stackTrace));
+ error.appendChild(errorMsgElement);
+ error.appendChild(stackElement);
+ myElement.appendChild(error);
+ }
+ else
+ {
+ myElement.setAttribute("status", "success");
+ }
+
+ elementStack.pop();
+ }
+
+
+ public void taskStarted(BuildEvent event)
+ {
+
+ if (Thread.currentThread().getThreadGroup() != group)
+ return;
+
+ Element parent = (Element)elementStack.peek();
+
+ Element myElement = results.createElement("task");
+ myElement.setAttribute("name", event.getTask().getTaskName());
+ parent.appendChild(myElement);
+
+ elementStack.push(myElement);
+ }
+
+
+ public void taskFinished(BuildEvent event)
+ {
+ if (Thread.currentThread().getThreadGroup() != group)
+ return;
+
+ Element myElement = (Element)elementStack.peek();
+
+ Throwable t = event.getException();
+ if (t != null)
+ {
+ myElement.setAttribute("status", "failure");
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ t.printStackTrace(ps);
+ ps.flush();
+ String errorMessage = t.getMessage();
+ String stackTrace = baos.toString();
+
+ Element error = results.createElement("error");
+ Element errorMsgElement = results.createElement("message");
+ errorMsgElement.appendChild(results.createTextNode(errorMessage));
+ Element stackElement = results.createElement("stack");
+ stackElement.appendChild(results.createCDATASection(stackTrace));
+ error.appendChild(errorMsgElement);
+ error.appendChild(stackElement);
+ myElement.appendChild(error);
+ }
+ else
+ {
+ myElement.setAttribute("status", "success");
+ }
+
+ elementStack.pop();
+ }
+
+
+ public void messageLogged(BuildEvent event)
+ {
+ /*
+ if (Thread.currentThread().getThreadGroup() != group)
+ return;
+
+ Element parentElement = (Element)elementStack.peek();
+
+ Element messageElement = results.createElement("message");
+ messageElement.setAttribute("level", String.valueOf(event.getPriority()));
+ messageElement.appendChild(results.createCDATASection(event.getMessage()));
+ parentElement.appendChild(messageElement);
+ */
+ }
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/server/ConnectionHandler.java b/src/main/java/net/sf/antcontrib/antserver/server/ConnectionHandler.java
new file mode 100644
index 0000000..23169e0
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/server/ConnectionHandler.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.server;
+
+import java.io.*;
+import java.net.Socket;
+
+import org.apache.tools.ant.Project;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+
+import net.sf.antcontrib.antserver.Command;
+import net.sf.antcontrib.antserver.Response;
+import net.sf.antcontrib.antserver.Util;
+import net.sf.antcontrib.antserver.commands.DisconnectCommand;
+import net.sf.antcontrib.antserver.commands.ShutdownCommand;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class ConnectionHandler
+ implements Runnable
+{
+ private static long nextGroupId = 0;
+ private ServerTask task;
+ private Socket socket;
+ private Thread thread;
+ private Throwable thrown;
+
+ public ConnectionHandler(ServerTask task, Socket socket)
+ {
+ super();
+ this.socket = socket;
+ this.task = task;
+ }
+
+ public void start()
+ {
+ long gid = nextGroupId;
+ if (nextGroupId == Long.MAX_VALUE)
+ nextGroupId = 0;
+ else
+ nextGroupId++;
+
+ ThreadGroup group = new ThreadGroup("server-tg-" + gid);
+ thread = new Thread(group, this);
+ thread.start();
+ }
+
+ public Throwable getThrown()
+ {
+ return thrown;
+ }
+
+ public void run()
+ {
+ InputStream is = null;
+ OutputStream os = null;
+
+
+ try
+ {
+ ConnectionBuildListener cbl = null;
+
+ is = socket.getInputStream();
+ os = socket.getOutputStream();
+
+ ObjectInputStream ois = new ObjectInputStream(is);
+ ObjectOutputStream oos = new ObjectOutputStream(os);
+
+ // Write the initial response object so that the
+ // object stream is initialized
+ oos.writeObject(new Response());
+
+ boolean disconnect = false;
+ Command inputCommand = null;
+ Response response = null;
+
+ while (! disconnect)
+ {
+ task.getProject().log("Reading command object.",
+ Project.MSG_DEBUG);
+
+ inputCommand = (Command) ois.readObject();
+
+ task.getProject().log("Executing command object: " + inputCommand,
+ Project.MSG_DEBUG);
+
+ response = new Response();
+
+ try
+ {
+ cbl = new ConnectionBuildListener();
+ task.getProject().addBuildListener(cbl);
+
+ inputCommand.execute(task.getProject(),
+ inputCommand.getContentLength(),
+ is);
+
+ response.setSucceeded(true);
+ }
+ catch (Throwable t)
+ {
+ response.setSucceeded(false);
+ response.setThrowable(t);
+ }
+ finally
+ {
+ if (cbl != null)
+ task.getProject().removeBuildListener(cbl);
+ }
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ XMLSerializer serial = new XMLSerializer();
+ OutputFormat fmt = new OutputFormat();
+ fmt.setOmitDocumentType(true);
+ fmt.setOmitXMLDeclaration(false);
+ serial.setOutputFormat(fmt);
+ serial.setOutputByteStream(baos);
+ serial.serialize(cbl.getDocument());
+ response.setResultsXml(baos.toString());
+
+ task.getProject().log("Executed command object: " + inputCommand,
+ Project.MSG_DEBUG);
+
+ task.getProject().log("Sending response: " + response,
+ Project.MSG_DEBUG);
+
+ response.setContentLength(inputCommand.getContentLength());
+
+ oos.writeObject(response);
+
+ if (inputCommand.getResponseContentLength() != 0)
+ {
+ Util.transferBytes(inputCommand.getReponseContentStream(),
+ inputCommand.getResponseContentLength(),
+ os,
+ true);
+ }
+
+ if (inputCommand instanceof DisconnectCommand)
+ {
+ disconnect = true;
+ task.getProject().log("Got disconnect command",
+ Project.MSG_DEBUG);
+ }
+ else if (inputCommand instanceof ShutdownCommand)
+ {
+ disconnect = true;
+ task.getProject().log("Got shutdown command",
+ Project.MSG_DEBUG);
+ task.shutdown();
+ }
+
+ }
+
+ }
+ catch (ClassNotFoundException e)
+ {
+ thrown = e;
+ }
+ catch (IOException e)
+ {
+ thrown = e;
+ }
+ catch (Throwable t)
+ {
+ thrown = t;
+ }
+ finally
+ {
+ if (is != null)
+ {
+ try
+ {
+ is.close();
+ }
+ catch (IOException e)
+ {
+
+ }
+ }
+
+ if (os != null)
+ {
+ try
+ {
+ os.close();
+ }
+ catch (IOException e)
+ {
+
+ }
+ }
+
+ if (socket != null)
+ {
+ try
+ {
+ socket.close();
+ }
+ catch (IOException e)
+ {
+
+ }
+ }
+
+ }
+ }
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/server/Server.java b/src/main/java/net/sf/antcontrib/antserver/server/Server.java
new file mode 100644
index 0000000..b0e8c56
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/server/Server.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.server;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class Server
+ implements Runnable
+{
+ private ServerTask task;
+ private int port = 17000;
+ private boolean running = false;
+ private Thread thread = null;
+
+ public Server(ServerTask task, int port)
+ {
+ super();
+ this.task = task;
+ this.port = port;
+ }
+
+ public void start()
+ throws InterruptedException
+ {
+ thread = new Thread(this);
+ thread.start();
+ thread.join();
+ }
+
+ public void stop()
+ {
+ running = false;
+ }
+
+ public void run()
+ {
+ ServerSocket server = null;
+ running = true;
+ try
+ {
+ task.getProject().log("Starting server on port: " + port,
+ Project.MSG_DEBUG);
+ try
+ {
+ server = new ServerSocket(port);
+ server.setSoTimeout(500);
+ }
+ catch (IOException e)
+ {
+ throw new BuildException(e);
+ }
+
+
+ while (running)
+ {
+ try
+ {
+ Socket clientSocket = server.accept();
+ task.getProject().log("Got a client connection. Starting Handler.",
+ Project.MSG_DEBUG);
+ ConnectionHandler handler = new ConnectionHandler(task,
+ clientSocket);
+ handler.start();
+ }
+ catch (InterruptedIOException e)
+ {
+ ; // gulp, no socket connection
+ }
+ catch (IOException e)
+ {
+ task.getProject().log(e.getMessage(),
+ Project.MSG_ERR);
+ }
+ }
+ }
+ finally
+ {
+ if (server != null)
+ {
+ try
+ {
+ server.close();
+ server = null;
+ }
+ catch (IOException e)
+ {
+ ; // gulp
+ }
+ }
+ }
+ running = false;
+
+
+ }
+
+}
diff --git a/src/main/java/net/sf/antcontrib/antserver/server/ServerTask.java b/src/main/java/net/sf/antcontrib/antserver/server/ServerTask.java
new file mode 100644
index 0000000..74006af
--- /dev/null
+++ b/src/main/java/net/sf/antcontrib/antserver/server/ServerTask.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * 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 net.sf.antcontrib.antserver.server;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class ServerTask
+ extends Task
+{
+ private Server server;
+ private int port = 17000;
+
+ public ServerTask()
+ {
+ super();
+ }
+
+
+ public void setPort(int port)
+ {
+ this.port = port;
+ }
+
+
+ public void shutdown()
+ {
+ server.stop();
+ }
+
+ public void execute()
+ {
+ try
+ {
+ server = new Server(this, port);
+ server.start();
+ }
+ catch (InterruptedException e)
+ {
+ throw new BuildException(e);
+ }
+ }
+}