### Eclipse Workspace Patch 1.0
#P cargo-trunks
Index: core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/JBossPropertySet.java
===================================================================
--- core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/JBossPropertySet.java (revision 1852)
+++ core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/JBossPropertySet.java (working copy)
@@ -35,4 +35,12 @@
* Whether the JBoss Configuration should be clustered.
*/
String CLUSTERED = "cargo.jboss.clustered";
+
+ /**
+ * Port number to serve deployable through. Default is 18080. We need to use
+ * the same port all the time since JBoss relies on the URL to recognise the
+ * deployable.
+ */
+ String DEPLOYABLE_HOST_PORT = "cargo.jboss.port";
+
}
Index: core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/JBossInstalledLocalDeployer.java
===================================================================
--- core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/JBossInstalledLocalDeployer.java (revision 1852)
+++ core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/JBossInstalledLocalDeployer.java (working copy)
@@ -117,7 +117,7 @@
}
/**
- * Checks whether file or dir represented by string exists
+ * Checks whether file or dir represented by string exists.
*
* @param fileName path to check
* @return true if file/dir exists
Index: core/containers/jboss/pom.xml
===================================================================
--- core/containers/jboss/pom.xml (revision 1852)
+++ core/containers/jboss/pom.xml (working copy)
@@ -27,4 +27,18 @@
Cargo Core JBoss Container
jar
Core API implementation for JBoss containers
+
+
+
+ org.mortbay.jetty
+ jetty
+ 6.1.7
+
+
+ org.mortbay.jetty
+ jetty-util
+ 6.1.7
+
+
+
Index: core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/JBossRemoteDeployer.java
===================================================================
--- core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/JBossRemoteDeployer.java (revision 1852)
+++ core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/JBossRemoteDeployer.java (working copy)
@@ -26,14 +26,15 @@
import org.codehaus.cargo.container.ContainerException;
import org.codehaus.cargo.container.RemoteContainer;
+import org.codehaus.cargo.container.configuration.RuntimeConfiguration;
+import org.codehaus.cargo.container.deployable.Deployable;
import org.codehaus.cargo.container.jboss.internal.HttpURLConnection;
import org.codehaus.cargo.container.jboss.internal.JdkHttpURLConnection;
-import org.codehaus.cargo.container.configuration.RuntimeConfiguration;
-import org.codehaus.cargo.container.deployable.Deployable;
import org.codehaus.cargo.container.property.GeneralPropertySet;
+import org.codehaus.cargo.container.property.RemotePropertySet;
import org.codehaus.cargo.container.property.ServletPropertySet;
-import org.codehaus.cargo.container.property.RemotePropertySet;
import org.codehaus.cargo.container.spi.deployer.AbstractRemoteDeployer;
+import org.codehaus.cargo.util.CargoException;
/**
* Remote deployer that uses JMX to deploy to JBoss.
@@ -56,19 +57,22 @@
* The JBoss JMX deployment URL.
*/
private String deployURL = "/jmx-console/HtmlAdaptor?action=invokeOpByName&"
- + "name=jboss.system:service%3DMainDeployer&methodName=deploy&argType=java.net.URL&arg0=";
+ + "name=jboss.system:service%3DMainDeployer&methodName=deploy&"
+ + "argType=java.net.URL&arg0=";
/**
* The JBoss JMX undeployment URL.
*/
private String undeployURL = "/jmx-console/HtmlAdaptor?action=invokeOpByName&"
- + "name=jboss.system:service%3DMainDeployer&methodName=undeploy&argType=java.net.URL&arg0=";
+ + "name=jboss.system:service%3DMainDeployer&methodName=undeploy&"
+ + "argType=java.net.URL&arg0=";
/**
* The JBoss JMX redeployment URL.
*/
private String redeployURL = "/jmx-console/HtmlAdaptor?action=invokeOpByName&"
- + "name=jboss.system:service%3DMainDeployer&methodName=redeploy&argType=java.net.URL&arg0=";
+ + "name=jboss.system:service%3DMainDeployer&methodName=redeploy&"
+ + "argType=java.net.URL&arg0=";
/**
* The configuration object containing the deployer config data.
@@ -133,7 +137,7 @@
*/
public void deploy(Deployable deployable)
{
- invokeURL(createJBossRemoteURL(deployable, this.deployURL));
+ invokeRemotely(deployable, this.deployURL, true);
}
/**
@@ -142,7 +146,7 @@
*/
public void undeploy(Deployable deployable)
{
- invokeURL(createJBossRemoteURL(deployable, this.undeployURL));
+ invokeRemotely(deployable, this.undeployURL, false);
}
/**
@@ -151,11 +155,61 @@
*/
public void redeploy(Deployable deployable)
{
- invokeURL(createJBossRemoteURL(deployable, this.redeployURL));
+ invokeRemotely(deployable, this.redeployURL, true);
}
-
+
/**
- * @param url the JBoss JMX URL to invoke
+ * @param deployable
+ * deployable to deploy
+ * @param jmxConsoleURL
+ * URL to jmx console
+ * @param expectDownload
+ * expect deployable to be downloaded
+ */
+ private void invokeRemotely(Deployable deployable, String jmxConsoleURL,
+ boolean expectDownload)
+ {
+ FileServer fileServer = setupFileServer(deployable);
+ try
+ {
+ String encodedURL = encodeURLLocation(fileServer.getURL());
+ invokeURL(createJBossRemoteURL(deployable, jmxConsoleURL,
+ encodedURL));
+ if (fileServer.getCallCount() == 0 && expectDownload)
+ {
+ throw new CargoException(
+ "Application server didn't request the file");
+ }
+ }
+ finally
+ {
+ fileServer.shutdown();
+ }
+ }
+
+ /**
+ * @param deployable
+ * deployable to deploy
+ * @return file server instance
+ */
+ protected FileServer setupFileServer(Deployable deployable)
+ {
+ String portStr = configuration.getPropertyValue(JBossPropertySet.DEPLOYABLE_HOST_PORT);
+ int port;
+ if (portStr == null)
+ {
+ port = 18080;
+ }
+ else
+ {
+ port = Integer.parseInt(portStr);
+ }
+ return new JettyHTTPFileServer(port, deployable.getFile(), getLogger());
+ }
+
+ /**
+ * @param url
+ * the JBoss JMX URL to invoke
*/
private void invokeURL(String url)
{
@@ -180,21 +234,23 @@
}
/**
- * @param deployable the deployable for which we'll URL-encode the location
+ * @param url
+ * url to encode
* @return the URL-encoded location that can be passed in a URL
*/
- private String encodeDeployableLocation(Deployable deployable)
+ private String encodeURLLocation(String url)
{
String encodedString;
try
{
- encodedString = URLEncoder.encode(deployable.getFile(), "UTF-8");
+ encodedString = URLEncoder.encode(url, "UTF-8");
}
catch (UnsupportedEncodingException e)
{
- throw new ContainerException("Failed to encode Deployable location ["
- + deployable.getFile() + "] using an [UTF-8] encoding", e);
+ throw new ContainerException(
+ "Failed to encode Deployable location [" + url
+ + "] using an [UTF-8] encoding", e);
}
return encodedString;
@@ -202,19 +258,23 @@
/**
* Compute the JBoss deploy/undeploy URL.
- *
- * @param deployable the file to deploy/undeploy
- * @param urlPrefix the JBoss static part of the deploy§undeploy URL
+ *
+ * @param deployable
+ * the file to deploy/undeploy
+ * @param urlPrefix
+ * the JBoss static part of the deploy§undeploy URL
+ * @param httpURL
+ * URL for JBoss to call back on
* @return the full deploy/undeploy URL
*/
- protected String createJBossRemoteURL(Deployable deployable, String urlPrefix)
+ protected String createJBossRemoteURL(Deployable deployable,
+ String urlPrefix, String httpURL)
{
- return this.configuration.getPropertyValue(GeneralPropertySet.PROTOCOL) + "://"
- + this.configuration.getPropertyValue(GeneralPropertySet.HOSTNAME)
- + ":"
- + this.configuration.getPropertyValue(ServletPropertySet.PORT)
- + urlPrefix
- + "file:"
- + encodeDeployableLocation(deployable);
+ return this.configuration.getPropertyValue(GeneralPropertySet.PROTOCOL)
+ + "://"
+ + this.configuration
+ .getPropertyValue(GeneralPropertySet.HOSTNAME) + ":"
+ + this.configuration.getPropertyValue(ServletPropertySet.PORT)
+ + urlPrefix + httpURL;
}
}
Index: core/containers/jboss/src/test/java/org/codehaus/cargo/container/jboss/JettyHTTPFileServerTest.java
===================================================================
--- core/containers/jboss/src/test/java/org/codehaus/cargo/container/jboss/JettyHTTPFileServerTest.java (revision 0)
+++ core/containers/jboss/src/test/java/org/codehaus/cargo/container/jboss/JettyHTTPFileServerTest.java (revision 0)
@@ -0,0 +1,99 @@
+package org.codehaus.cargo.container.jboss;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+import org.codehaus.cargo.util.log.NullLogger;
+
+public class JettyHTTPFileServerTest extends TestCase
+{
+
+ public void test() throws Exception
+ {
+ File file = createBinaryTempFile();
+ JettyHTTPFileServer fileServer = new JettyHTTPFileServer(0, file
+ .getPath(), new NullLogger());
+ try
+ {
+ String urlStr = fileServer.getURL();
+ assertTrue(urlStr.indexOf("0.0.0.0") == -1);
+ assertTrue(urlStr.indexOf("127.0.0.1") == -1);
+ assertTrue(urlStr.indexOf("localhost") == -1);
+ URL okURL = new URL(urlStr);
+ HttpURLConnection okConn = (HttpURLConnection) okURL
+ .openConnection();
+ byte[] bs = readBytes(okConn.getInputStream());
+ assertEquals(256, bs.length);
+ for (int i = 0; i < 256; ++i)
+ {
+ int bsi = bs[i];
+ if (bsi < 0)
+ {
+ bsi += 256;
+ }
+ assertEquals(i, bsi);
+ }
+ assertEquals(1, fileServer.getCallCount());
+
+ // Try another file where we should get "401 Unauthorized"
+ URL failURL = new URL(urlStr + "_NOT");
+ HttpURLConnection failConn = (HttpURLConnection) failURL
+ .openConnection();
+ try
+ {
+ readBytes(failConn.getInputStream());
+ }
+ catch (IOException e)
+ {
+ assertTrue(e.getMessage().indexOf("401") != -1);
+ }
+ }
+ finally
+ {
+ fileServer.shutdown();
+
+ }
+ }
+
+ private File createBinaryTempFile() throws Exception
+ {
+ File tmp = File.createTempFile("test-", "bin");
+ FileOutputStream fos = null;
+ try
+ {
+ fos = new FileOutputStream(tmp);
+ for (int i = 0; i < 256; ++i)
+ {
+ fos.write(i);
+ }
+ }
+ finally
+ {
+ if (fos != null)
+ {
+ fos.close();
+ }
+ }
+ return tmp;
+ }
+
+ private byte[] readBytes(InputStream is) throws Exception
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buf = new byte[100];
+ int len;
+ while ((len = is.read(buf)) != -1)
+ {
+ baos.write(buf, 0, len);
+ }
+ return baos.toByteArray();
+ }
+
+}
Index: core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/JettyHTTPFileServer.java
===================================================================
--- core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/JettyHTTPFileServer.java (revision 0)
+++ core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/JettyHTTPFileServer.java (revision 0)
@@ -0,0 +1,142 @@
+package org.codehaus.cargo.container.jboss;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.codehaus.cargo.util.log.Logger;
+import org.mortbay.jetty.Handler;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.handler.HandlerList;
+import org.mortbay.jetty.handler.ResourceHandler;
+
+/**
+ * File server that serves files over HTTP protocol through a Jetty server.
+ *
+ * @version $Id: $
+ */
+public class JettyHTTPFileServer implements FileServer
+{
+
+ /**
+ * Number of calls served.
+ */
+ protected int callCount;
+
+ /**
+ * Logger instance.
+ */
+ protected Logger logger;
+
+ /**
+ * URL for retrieving file.
+ */
+ protected String url;
+
+ /**
+ * Jetty server instance.
+ */
+ protected Server server;
+
+ /**
+ * @param port
+ * port number to open (use 0 for random)
+ * @param fileName
+ * file to make accessible
+ * @param logger
+ * logger instance
+ */
+ public JettyHTTPFileServer(int port, String fileName, Logger logger)
+ {
+ this.logger = logger;
+ final File file = new File(fileName);
+ if (!file.exists() || !file.isFile())
+ {
+ throw new RuntimeException("File " + fileName
+ + " does not exist or is not a file");
+ }
+ server = new Server(port);
+ ResourceHandler resourceHandler = new ResourceHandler()
+ {
+ public void handle(String target, HttpServletRequest req,
+ HttpServletResponse resp, int dispatch) throws IOException,
+ ServletException
+ {
+ if (target.equals("/" + file.getName()))
+ {
+ ++callCount;
+ super.handle(target, req, resp, dispatch);
+ }
+ else
+ {
+ resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ }
+ };
+ resourceHandler.setResourceBase(file.getParentFile().getPath());
+
+ HandlerList handlerList = new HandlerList();
+ Handler[] handlers = new Handler[] {resourceHandler};
+ handlerList.setHandlers(handlers);
+ server.setHandler(handlerList);
+
+ try
+ {
+ server.start();
+ url = "http://" + InetAddress.getLocalHost().getCanonicalHostName()
+ + ":" + server.getConnectors()[0].getLocalPort() + "/"
+ + file.getName();
+ }
+ catch (UnknownHostException e)
+ {
+ throw new RuntimeException("Error retrieving host name", e);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Error starting jetty server", e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getCallCount()
+ {
+ return callCount;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getURL()
+ {
+ return url;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void shutdown()
+ {
+ try
+ {
+ server.stop();
+ server.join();
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ return;
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Error stopping jetty server", e);
+ }
+ }
+
+}
Index: core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/FileServer.java
===================================================================
--- core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/FileServer.java (revision 0)
+++ core/containers/jboss/src/main/java/org/codehaus/cargo/container/jboss/FileServer.java (revision 0)
@@ -0,0 +1,26 @@
+package org.codehaus.cargo.container.jboss;
+
+/**
+ * Generic file server interface.
+ *
+ * @version $Id: JBossRemoteDeployer.java 1198 2006-11-01 13:39:02Z vmassol $
+ */
+public interface FileServer
+{
+
+ /**
+ * @return URL to fetch file from
+ */
+ String getURL();
+
+ /**
+ * @return number of requests
+ */
+ int getCallCount();
+
+ /**
+ * Shutdown service.
+ */
+ void shutdown();
+
+}
\ No newline at end of file
Index: core/containers/jboss/src/test/java/org/codehaus/cargo/container/jboss/JBossRemoteDeployerTest.java
===================================================================
--- core/containers/jboss/src/test/java/org/codehaus/cargo/container/jboss/JBossRemoteDeployerTest.java (revision 1852)
+++ core/containers/jboss/src/test/java/org/codehaus/cargo/container/jboss/JBossRemoteDeployerTest.java (working copy)
@@ -19,14 +19,12 @@
*/
package org.codehaus.cargo.container.jboss;
-import org.jmock.MockObjectTestCase;
-import org.jmock.Mock;
import org.codehaus.cargo.container.RemoteContainer;
+import org.codehaus.cargo.container.configuration.RuntimeConfiguration;
+import org.codehaus.cargo.container.deployable.Deployable;
import org.codehaus.cargo.container.jboss.internal.HttpURLConnection;
-import org.codehaus.cargo.container.deployable.Deployable;
-import org.codehaus.cargo.container.configuration.RuntimeConfiguration;
-
-import java.io.File;
+import org.jmock.Mock;
+import org.jmock.MockObjectTestCase;
/**
* Unit tests for {@link JBossRemoteDeployer}.
@@ -55,7 +53,7 @@
Mock mockDeployable = mock(Deployable.class);
mockDeployable.stubs().method("getFile").will(
- returnValue("c:/Something With Space/dummy.war"));
+ returnValue("c:/dummy/Something With Space.war"));
Mock mockConnection = mock(HttpURLConnection.class);
String expectedURLPortion1 = "http://localhost:8888/";
@@ -64,8 +62,32 @@
.with(and(stringContains(expectedURLPortion1), stringContains(expectedURLPortion2)),
eq("john"), eq("doe"));
- JBossRemoteDeployer deployer = new JBossRemoteDeployer((RemoteContainer) mockContainer.proxy(),
- (HttpURLConnection) mockConnection.proxy());
+ JBossRemoteDeployer deployer = new JBossRemoteDeployer(
+ (RemoteContainer) mockContainer.proxy(),
+ (HttpURLConnection) mockConnection.proxy())
+ {
+ protected FileServer setupFileServer(Deployable deployable)
+ {
+ return new FileServer()
+ {
+ public int getCallCount()
+ {
+ return 1;
+ }
+
+ public String getURL()
+ {
+ return "http://somewhere/Something With Space.war";
+ }
+
+ public void shutdown()
+ {
+ // OK
+ }
+ };
+ }
+ };
deployer.deploy((Deployable) mockDeployable.proxy());
}
+
}