diff --git a/.gitignore b/.gitignore index e09193e..9fd3478 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ *.ipr *.iws .idea +.DS_Store # Maven target/ diff --git a/jetty-common/src/main/java/org/jboss/arquillian/container/jetty/AbstractJettyEmbeddedConfiguration.java b/jetty-common/src/main/java/org/jboss/arquillian/container/jetty/AbstractJettyEmbeddedConfiguration.java index ea78213..2dc6d5d 100644 --- a/jetty-common/src/main/java/org/jboss/arquillian/container/jetty/AbstractJettyEmbeddedConfiguration.java +++ b/jetty-common/src/main/java/org/jboss/arquillian/container/jetty/AbstractJettyEmbeddedConfiguration.java @@ -19,11 +19,16 @@ import org.jboss.arquillian.container.spi.ConfigurationException; import org.jboss.arquillian.container.spi.client.container.ContainerConfiguration; +import java.io.File; +import java.util.HashMap; +import java.util.Map; + /** * A {@link org.jboss.arquillian.spi.client.container.ContainerConfiguration} common base for the Jetty Embedded containers * * @author Dan Allen * @author Ales Justin + * @author Alex Soto * @version $Revision: $ */ public abstract class AbstractJettyEmbeddedConfiguration implements ContainerConfiguration @@ -32,6 +37,12 @@ public abstract class AbstractJettyEmbeddedConfiguration implements ContainerCon private int bindHttpPort = 9090; + private Map mimeTypes; + + private int headerBufferSize = 0; + + private File realmProperties; + /** * List of server configuration classes that can be used for * establishing the configuration tasks for the WebApp being deployed. @@ -45,6 +56,14 @@ public abstract class AbstractJettyEmbeddedConfiguration implements ContainerCon */ public void validate() throws ConfigurationException { + if(this.realmProperties != null) { + if(!this.realmProperties.exists()) { + throw new ConfigurationException(String.format("Realm properties file %s must exists.", this.realmProperties.getAbsolutePath())); + } + if(this.realmProperties.isDirectory()) { + throw new ConfigurationException("Realm Properties should be a file and not a directory"); + } + } } public int getBindHttpPort() @@ -80,4 +99,54 @@ public void setConfigurationClasses(String configurationClasses) { this.configurationClasses = configurationClasses; } + + public int getHeaderBufferSize() + { + return this.headerBufferSize; + } + + public boolean isHeaderBufferSizeSet() { + return this.headerBufferSize > 0; + } + + public void setHeaderBufferSize(int headerBufferSize) + { + this.headerBufferSize = headerBufferSize; + } + + public void setRealmProperties(String realmProperties) + { + this.realmProperties = new File(realmProperties); + } + + public boolean isRealmPropertiesFileSet() + { + return this.realmProperties != null; + } + + public File getRealmProperties() + { + return realmProperties; + } + + public void setMimeTypes(String mimeTypes) { + this.mimeTypes = new HashMap(); + String[] splittedLines = mimeTypes.split(" "); + for(int i = 0; i < splittedLines.length; i+=2) + { + if(i+1 >= splittedLines.length) + { + throw new ConfigurationException(String.format("Mime Type definition should follow the format [ ]*, for example js application/javascript but %s definition has been found.", mimeTypes)); + } + this.mimeTypes.put(splittedLines[i], splittedLines[i+1]); + } + } + + public boolean areMimeTypesSet() { + return this.mimeTypes != null; + } + + public Map getMimeTypes() { + return mimeTypes; + } } diff --git a/jetty-common/src/test/java/org/jboss/arquillian/container/jetty/DummyJettyEmbeddedConfiguration.java b/jetty-common/src/test/java/org/jboss/arquillian/container/jetty/DummyJettyEmbeddedConfiguration.java new file mode 100644 index 0000000..11d9ed6 --- /dev/null +++ b/jetty-common/src/test/java/org/jboss/arquillian/container/jetty/DummyJettyEmbeddedConfiguration.java @@ -0,0 +1,8 @@ +package org.jboss.arquillian.container.jetty; + +public class DummyJettyEmbeddedConfiguration extends AbstractJettyEmbeddedConfiguration +{ + + + +} diff --git a/jetty-common/src/test/java/org/jboss/arquillian/container/jetty/JettyEmbeddedConfigurationTest.java b/jetty-common/src/test/java/org/jboss/arquillian/container/jetty/JettyEmbeddedConfigurationTest.java new file mode 100644 index 0000000..be030b9 --- /dev/null +++ b/jetty-common/src/test/java/org/jboss/arquillian/container/jetty/JettyEmbeddedConfigurationTest.java @@ -0,0 +1,27 @@ +package org.jboss.arquillian.container.jetty; + + +import org.junit.Test; + +import java.util.Map; + +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertThat; + +public class JettyEmbeddedConfigurationTest { + + private static final String MIME_DEFINITIONS = "js application/javascript " + + "txt text/plain " + + "html text/html"; + + @Test + public void shouldConfigureMimeTypes() { + DummyJettyEmbeddedConfiguration dummyJettyEmbeddedConfiguration = new DummyJettyEmbeddedConfiguration(); + dummyJettyEmbeddedConfiguration.setMimeTypes(MIME_DEFINITIONS); + Map mimeTypes = dummyJettyEmbeddedConfiguration.getMimeTypes(); + assertThat(mimeTypes.get("js"), is("application/javascript")); + assertThat(mimeTypes.get("txt"), is("text/plain")); + assertThat(mimeTypes.get("html"), is("text/html")); + } + +} diff --git a/jetty-embedded-6.1/src/main/java/org/jboss/arquillian/container/jetty/embedded_6_1/JettyEmbeddedContainer.java b/jetty-embedded-6.1/src/main/java/org/jboss/arquillian/container/jetty/embedded_6_1/JettyEmbeddedContainer.java index 1685c62..69e14fc 100644 --- a/jetty-embedded-6.1/src/main/java/org/jboss/arquillian/container/jetty/embedded_6_1/JettyEmbeddedContainer.java +++ b/jetty-embedded-6.1/src/main/java/org/jboss/arquillian/container/jetty/embedded_6_1/JettyEmbeddedContainer.java @@ -16,6 +16,9 @@ */ package org.jboss.arquillian.container.jetty.embedded_6_1; +import java.io.File; +import java.util.Map; +import java.util.Set; import java.util.logging.Logger; import org.jboss.arquillian.container.jetty.EnvUtil; @@ -34,10 +37,12 @@ import org.jboss.shrinkwrap.jetty_6.api.ShrinkWrapWebAppContext; import org.mortbay.jetty.Connector; import org.mortbay.jetty.Handler; +import org.mortbay.jetty.MimeTypes; import org.mortbay.jetty.Server; import org.mortbay.jetty.handler.ContextHandlerCollection; import org.mortbay.jetty.handler.DefaultHandler; import org.mortbay.jetty.nio.SelectChannelConnector; +import org.mortbay.jetty.security.HashUserRealm; import org.mortbay.jetty.servlet.ServletHolder; import org.mortbay.jetty.webapp.WebAppContext; @@ -133,6 +138,10 @@ public void start() throws LifecycleException // Setup connector Connector connector = new SelectChannelConnector(); + if(this.containerConfig.isHeaderBufferSizeSet()) { + connector.setHeaderBufferSize(containerConfig.getHeaderBufferSize()); + } + connector.setHost(containerConfig.getBindAddress()); connector.setPort(containerConfig.getBindHttpPort()); server.setConnectors(new Connector[] { connector }); @@ -144,7 +153,13 @@ public void start() throws LifecycleException new DefaultHandler() }; server.setHandlers(handlers); - + + if(containerConfig.isRealmPropertiesFileSet()) + { + String realmName = getRealmName(); + HashUserRealm hashUserRealm = new HashUserRealm(realmName, containerConfig.getRealmProperties().getAbsolutePath()); + server.addUserRealm(hashUserRealm); + } // Start Server server.start(); @@ -166,6 +181,17 @@ public void start() throws LifecycleException } } + private String getRealmName() { + File realmProperties = containerConfig.getRealmProperties(); + String fileName = realmProperties.getName(); + int index = -1; + if((index = fileName.indexOf('.')) > -1) + { + fileName = fileName.substring(0, index); + } + return fileName; + } + private String[] getWebAppConfigurationClasses() { // If user has specified in Container Configuration, use it. @@ -226,6 +252,11 @@ public ProtocolMetaData deploy(final Archive archive) throws DeploymentExcept { wctx.setConfigurationClasses(webappConfigurationClasses); } + if (containerConfig.areMimeTypesSet()) + { + MimeTypes mimeTypes = getMimeTypes(); + wctx.setMimeTypes(mimeTypes); + } // possible configuration parameters wctx.setExtractWAR(true); wctx.setLogUrlOnStart(true); @@ -254,6 +285,17 @@ public ProtocolMetaData deploy(final Archive archive) throws DeploymentExcept } } + private MimeTypes getMimeTypes() { + Map configuredMimeTypes = containerConfig.getMimeTypes(); + Set> entries = configuredMimeTypes.entrySet(); + MimeTypes mimeTypes = new MimeTypes(); + for(Map.Entry entry : entries) + { + mimeTypes.addMimeMapping(entry.getKey(), entry.getValue()); + } + return mimeTypes; + } + public void undeploy(final Archive archive) throws DeploymentException { WebAppContext wctx = webAppContextProducer.get(); diff --git a/jetty-embedded-7/src/main/java/org/jboss/arquillian/container/jetty/embedded_7/JettyEmbeddedContainer.java b/jetty-embedded-7/src/main/java/org/jboss/arquillian/container/jetty/embedded_7/JettyEmbeddedContainer.java index ef11072..a0ea364 100644 --- a/jetty-embedded-7/src/main/java/org/jboss/arquillian/container/jetty/embedded_7/JettyEmbeddedContainer.java +++ b/jetty-embedded-7/src/main/java/org/jboss/arquillian/container/jetty/embedded_7/JettyEmbeddedContainer.java @@ -16,10 +16,8 @@ */ package org.jboss.arquillian.container.jetty.embedded_7; -import java.util.ArrayList; -import java.util.List; -import java.util.logging.Logger; - +import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; @@ -44,6 +42,13 @@ import org.jboss.shrinkwrap.descriptor.api.Descriptor; import org.jboss.shrinkwrap.jetty_7.api.ShrinkWrapWebAppContext; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Logger; + /** *

* Jetty Embedded 7.x container for the Arquillian project. @@ -131,7 +136,11 @@ public void start() throws LifecycleException server = new Server(); // Setup connector - Connector connector = new SelectChannelConnector(); + SelectChannelConnector connector = new SelectChannelConnector(); + if(this.containerConfig.isHeaderBufferSizeSet()) { + connector.setRequestHeaderSize(containerConfig.getHeaderBufferSize()); + connector.setResponseHeaderSize(containerConfig.getHeaderBufferSize()); + } connector.setHost(containerConfig.getBindAddress()); connector.setPort(containerConfig.getBindHttpPort()); server.setConnectors(new Connector[] { connector }); @@ -143,6 +152,13 @@ public void start() throws LifecycleException handlers.addHandler(new DefaultHandler()); server.setHandler(handlers); + if(containerConfig.isRealmPropertiesFileSet()) + { + String realmName = getRealmName(); + HashLoginService hashUserRealm = new HashLoginService(realmName, containerConfig.getRealmProperties().getAbsolutePath()); + server.addBean(hashUserRealm); + } + // Start Server log.info("Starting Jetty Embedded Server " + Server.getVersion() + " [id:" + server.hashCode() + "]"); server.start(); @@ -161,6 +177,17 @@ public void start() throws LifecycleException } } + private String getRealmName() { + File realmProperties = containerConfig.getRealmProperties(); + String fileName = realmProperties.getName(); + int index = -1; + if((index = fileName.indexOf('.')) > -1) + { + fileName = fileName.substring(0, index); + } + return fileName; + } + @Override public ProtocolMetaData deploy(final Archive archive) throws DeploymentException { @@ -172,7 +199,11 @@ public ProtocolMetaData deploy(final Archive archive) throws DeploymentExcept { wctx.setConfigurationClasses(webappConfigurationClasses); } - + if (containerConfig.areMimeTypesSet()) + { + MimeTypes mimeTypes = getMimeTypes(); + wctx.setMimeTypes(mimeTypes); + } // possible configuration parameters wctx.setExtractWAR(true); wctx.setLogUrlOnStart(true); @@ -202,6 +233,17 @@ public ProtocolMetaData deploy(final Archive archive) throws DeploymentExcept } } + private MimeTypes getMimeTypes() { + Map configuredMimeTypes = containerConfig.getMimeTypes(); + Set> entries = configuredMimeTypes.entrySet(); + MimeTypes mimeTypes = new MimeTypes(); + for(Map.Entry entry : entries) + { + mimeTypes.addMimeMapping(entry.getKey(), entry.getValue()); + } + return mimeTypes; + } + private String[] getWebAppConfigurationClasses() { // If user has specified in Container Configuration, use it. diff --git a/jetty-embedded-8/src/main/java/org/jboss/arquillian/container/jetty/embedded_8/JettyEmbeddedContainer.java b/jetty-embedded-8/src/main/java/org/jboss/arquillian/container/jetty/embedded_8/JettyEmbeddedContainer.java index 35cff3e..db66a25 100644 --- a/jetty-embedded-8/src/main/java/org/jboss/arquillian/container/jetty/embedded_8/JettyEmbeddedContainer.java +++ b/jetty-embedded-8/src/main/java/org/jboss/arquillian/container/jetty/embedded_8/JettyEmbeddedContainer.java @@ -16,10 +16,15 @@ */ package org.jboss.arquillian.container.jetty.embedded_8; +import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.logging.Logger; +import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; @@ -131,7 +136,12 @@ public void start() throws LifecycleException server = new Server(); // Setup connector - Connector connector = new SelectChannelConnector(); + SelectChannelConnector connector = new SelectChannelConnector(); + if(this.containerConfig.isHeaderBufferSizeSet()) { + connector.setRequestHeaderSize(containerConfig.getHeaderBufferSize()); + connector.setResponseHeaderSize(containerConfig.getHeaderBufferSize()); + } + connector.setHost(containerConfig.getBindAddress()); connector.setPort(containerConfig.getBindHttpPort()); server.setConnectors(new Connector[] { connector }); @@ -143,6 +153,13 @@ public void start() throws LifecycleException handlers.addHandler(new DefaultHandler()); server.setHandler(handlers); + if(containerConfig.isRealmPropertiesFileSet()) + { + String realmName = getRealmName(); + HashLoginService hashUserRealm = new HashLoginService(realmName, containerConfig.getRealmProperties().getAbsolutePath()); + server.addBean(hashUserRealm); + } + // Start Server log.info("Starting Jetty Embedded Server " + Server.getVersion() + " [id:" + server.hashCode() + "]"); server.start(); @@ -161,6 +178,17 @@ public void start() throws LifecycleException } } + private String getRealmName() { + File realmProperties = containerConfig.getRealmProperties(); + String fileName = realmProperties.getName(); + int index = -1; + if((index = fileName.indexOf('.')) > -1) + { + fileName = fileName.substring(0, index); + } + return fileName; + } + private String[] getWebAppConfigurationClasses() { // If user has specified in Container Configuration, use it. @@ -257,6 +285,11 @@ public ProtocolMetaData deploy(final Archive archive) throws DeploymentExcept { wctx.setConfigurationClasses(configurationClasses); } + if (containerConfig.areMimeTypesSet()) + { + MimeTypes mimeTypes = getMimeTypes(); + wctx.setMimeTypes(mimeTypes); + } // possible configuration parameters wctx.setExtractWAR(true); @@ -287,6 +320,17 @@ public ProtocolMetaData deploy(final Archive archive) throws DeploymentExcept } } + private MimeTypes getMimeTypes() { + Map configuredMimeTypes = containerConfig.getMimeTypes(); + Set> entries = configuredMimeTypes.entrySet(); + MimeTypes mimeTypes = new MimeTypes(); + for(Map.Entry entry : entries) + { + mimeTypes.addMimeMapping(entry.getKey(), entry.getValue()); + } + return mimeTypes; + } + @Override public void undeploy(Archive archive) throws DeploymentException { diff --git a/jetty-embedded-9/src/main/java/org/jboss/arquillian/container/jetty/embedded_9/JettyEmbeddedContainer.java b/jetty-embedded-9/src/main/java/org/jboss/arquillian/container/jetty/embedded_9/JettyEmbeddedContainer.java index 515d355..ec74e53 100644 --- a/jetty-embedded-9/src/main/java/org/jboss/arquillian/container/jetty/embedded_9/JettyEmbeddedContainer.java +++ b/jetty-embedded-9/src/main/java/org/jboss/arquillian/container/jetty/embedded_9/JettyEmbeddedContainer.java @@ -16,14 +16,19 @@ */ package org.jboss.arquillian.container.jetty.embedded_9; +import java.io.File; +import java.util.Map; +import java.util.Set; import java.util.logging.Logger; import org.eclipse.jetty.annotations.AnnotationConfiguration; import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.AppLifeCycle; import org.eclipse.jetty.deploy.DeploymentManager; +import org.eclipse.jetty.http.MimeTypes; import org.eclipse.jetty.plus.webapp.EnvConfiguration; import org.eclipse.jetty.plus.webapp.PlusConfiguration; +import org.eclipse.jetty.security.HashLoginService; import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpConfiguration; @@ -59,17 +64,17 @@ *

* Jetty Embedded 9.x container for the Arquillian project. *

- * + * *

* This container only supports a WebArchive deployment. The context path of the deployed application is always set to "/test", which is expected by the * Arquillian servlet protocol. *

- * + * *

* Another known issue is that the container configuration process logs an exception when running in-container. However, the container is still configured * properly during setup. *

- * + * * @author Dan Allen * @author Ales Justin * @author Martin Kouba @@ -167,12 +172,16 @@ public void start() throws LifecycleException if (httpConfig == null) { httpConfig = new HttpConfiguration(); + if(this.containerConfig.isHeaderBufferSizeSet()) { + httpConfig.setRequestHeaderSize(containerConfig.getHeaderBufferSize()); + httpConfig.setResponseHeaderSize(containerConfig.getHeaderBufferSize()); + } } ConnectionFactory connectionFactory = new HttpConnectionFactory(httpConfig); - // Setup Connector ServerConnector connector = new ServerConnector(server,connectionFactory); + connector.setHost(containerConfig.getBindAddress()); connector.setPort(containerConfig.getBindHttpPort()); connector.setIdleTimeout(containerConfig.getIdleTimeoutMillis()); @@ -194,6 +203,13 @@ public void start() throws LifecycleException handlers.addHandler(new DefaultHandler()); server.setHandler(handlers); + if(containerConfig.isRealmPropertiesFileSet()) + { + String realmName = getRealmName(); + HashLoginService hashUserRealm = new HashLoginService(realmName, containerConfig.getRealmProperties().getAbsolutePath()); + server.addBean(hashUserRealm); + } + server.setDumpAfterStart(containerConfig.isDumpServerAfterStart()); log.info("Starting Jetty Embedded Server " + Server.getVersion() + " [id:" + server.hashCode() + "]"); server.start(); @@ -211,6 +227,17 @@ public void start() throws LifecycleException } } + private String getRealmName() { + File realmProperties = containerConfig.getRealmProperties(); + String fileName = realmProperties.getName(); + int index = -1; + if((index = fileName.indexOf('.')) > -1) + { + fileName = fileName.substring(0, index); + } + return fileName; + } + public void stop() throws LifecycleException { try @@ -249,26 +276,26 @@ public ProtocolMetaData deploy(final Archive archive) throws DeploymentExcept try { App app = appProvider.createApp(archive); + + WebAppContext webAppContext = getWebAppContext(app); + + if (containerConfig.areMimeTypesSet()) + { + MimeTypes mimeTypes = getMimeTypes(); + webAppContext.setMimeTypes(mimeTypes); + } + deployer.addApp(app); deployer.requestAppGoal(app,AppLifeCycle.STARTED); webAppContextProducer.set(app); HTTPContext httpContext = new HTTPContext(listeningHost,listeningPort); - ContextHandler handler = app.getContextHandler(); - if (handler instanceof WebAppContext) + ServletHandler servletHandler = webAppContext.getServletHandler(); + for (ServletHolder servlet : servletHandler.getServlets()) { - ServletHandler servletHandler = ((WebAppContext)handler).getServletHandler(); - for (ServletHolder servlet : servletHandler.getServlets()) - { - httpContext.add(new Servlet(servlet.getName(),servlet.getContextPath())); - } + httpContext.add(new Servlet(servlet.getName(),servlet.getContextPath())); } - else - { - throw new DeploymentException("Deployment of raw ContextHandler's not supported by Arquillian"); - } - return new ProtocolMetaData().addContext(httpContext); } catch (Exception e) @@ -277,6 +304,31 @@ public ProtocolMetaData deploy(final Archive archive) throws DeploymentExcept } } + private WebAppContext getWebAppContext(App app) throws Exception { + ContextHandler handler = app.getContextHandler(); + WebAppContext webAppContext = null; + if (handler instanceof WebAppContext) + { + webAppContext = (WebAppContext)handler; + } + else + { + throw new DeploymentException("Deployment of raw ContextHandler's not supported by Arquillian"); + } + return webAppContext; + } + + private MimeTypes getMimeTypes() { + Map configuredMimeTypes = containerConfig.getMimeTypes(); + Set> entries = configuredMimeTypes.entrySet(); + MimeTypes mimeTypes = new MimeTypes(); + for(Map.Entry entry : entries) + { + mimeTypes.addMimeMapping(entry.getKey(), entry.getValue()); + } + return mimeTypes; + } + public void undeploy(Archive archive) throws DeploymentException { App app = webAppContextProducer.get(); diff --git a/jetty-embedded-9/src/test/resources/arquillian.xml b/jetty-embedded-9/src/test/resources/arquillian.xml index 304dfc8..7854c1d 100644 --- a/jetty-embedded-9/src/test/resources/arquillian.xml +++ b/jetty-embedded-9/src/test/resources/arquillian.xml @@ -10,6 +10,11 @@ 9595 + src/test/resources/default.properties + + js application/js + txt text/plain + diff --git a/jetty-embedded-9/src/test/resources/default.properties b/jetty-embedded-9/src/test/resources/default.properties new file mode 100644 index 0000000..cc7136f --- /dev/null +++ b/jetty-embedded-9/src/test/resources/default.properties @@ -0,0 +1,3 @@ +admin: admin,server-administrator,content-administrator,admin +other: other +guest: guest,read-only \ No newline at end of file diff --git a/pom.xml b/pom.xml index d5dc2cd..fa78dd4 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ - 1.1.4.Final + 1.1.8.Final 2.1.0 1.1.13.Final @@ -40,8 +40,8 @@ 1.2.138 - 1.5 - 1.5 + 1.7 + 1.7