webAppContextProcessors) {
+ this.config = config;
+ this.webAppContextProcessors = webAppContextProcessors;
+ }
+
+ protected App createApp(final Archive> archive) {
+ String name = archive.getName();
+ int extOff = name.lastIndexOf('.');
+ if (extOff <= 0) {
+ throw new RuntimeException("Not a valid Web Archive filename: " + name);
+ }
+ String ext = name.substring(extOff).toLowerCase();
+ if (!ext.equals(".war")) {
+ throw new RuntimeException("Not a recognized Web Archive: " + name);
+ }
+ name = name.substring(0, extOff);
+
+ final File exported;
+ try {
+ if (this.config.isUseArchiveNameAsContext()) {
+ exported = Files.createFile(EXPORT_DIR.toPath().resolve(archive.getName())).toFile();
+ exported.deleteOnExit();
+ } else {
+ // If this method returns successfully then it is guaranteed that:
+ // 1. The file denoted by the returned abstract pathname did not exist before this method was invoked, and
+ // 2. Neither this method nor any of its variants will return the same abstract pathname again in the current invocation of the virtual machine.
+ exported = File.createTempFile(EXPORT_FILE_PREFIX, archive.getName(), EXPORT_DIR);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Could not create temporary File in " + EXPORT_DIR + " to write exported archive",
+ e);
+ }
+ // We are overwriting the temporary file placeholder reserved by File#createTemplateFile()
+ archive.as(ZipExporter.class).exportTo(exported, true);
+
+ // Mark to delete when we come down
+ // exported.deleteOnExit();
+
+ // Add the context
+ URI uri = exported.toURI();
+ LOG.info("Webapp archive location: " + uri.toASCIIString());
+
+ return new ArchiveApp(deploymentManager, this, Path.of(uri), archive);
+ }
+
+ private static class ArchiveApp extends App {
+ private final Archive> archive;
+
+ public ArchiveApp(DeploymentManager manager, AppProvider provider, Path originId, Archive> archive) {
+ super(manager, provider, originId);
+ this.archive = archive;
+ }
+ }
+
+ private static boolean isWebArchiveFile(Path path) {
+ if (!path.toFile().isFile()) {
+ return false;
+ } else {
+ String name = path.toFile().getName().toLowerCase(Locale.ENGLISH);
+ return name.endsWith(".war") || name.endsWith(".jar");
+ }
+ }
+
+ @Override
+ public ContextHandler createContextHandler(final App app) throws Exception {
+ Resource resource = ResourceFactory.root().newResource(app.getPath());
+ Path file = resource.getPath();
+ if (!resource.exists())
+ throw new IllegalStateException("App resouce does not exist " + resource);
+
+ String context = file.toFile().getName();
+
+ if (isWebArchiveFile(file)) {
+ // Context Path is the same as the archive.
+ context = context.substring(0, context.length() - 4);
+ } else {
+ throw new IllegalStateException("unable to create ContextHandler for " + app);
+ }
+
+ // Ensure "/" is Not Trailing in context paths.
+ if (context.endsWith("/") && context.length() > 0) {
+ context = context.substring(0, context.length() - 1);
+ }
+
+ // Start building the webapplication
+ WebAppContext webAppContext = new WebAppContext();
+ webAppContext.setDisplayName(context);
+ webAppContext.setLogUrlOnStart(true);
+ webAppContext.setCrossContextDispatchSupported(config.isCrossContextDispatchSupported());
+ String configuredConfigurationClasses = config.getConfigurationClasses();
+ if (configuredConfigurationClasses != null && configuredConfigurationClasses.trim().length() > 0) {
+ // User provided classlist, use it as-is.
+ webAppContext.setConfigurationClasses(configuredConfigurationClasses.split(","));
+
+ } else {
+ // Arquillian assumption is that all features of Servlet 3.1 are available.
+ // This means that annotation scanning is enabled by default.
+ // That means jetty-plus is mandatory.
+
+ // Applying equivalent of etc/jetty-annotations.xml
+ webAppContext.addConfiguration(new JettyWebXmlConfiguration(),
+ new AnnotationConfiguration());
+
+ // Applying equivalent of etc/jetty-plus.xml
+ webAppContext.addConfiguration(new FragmentConfiguration()
+ , new EnvConfiguration(), new PlusConfiguration());
+ }
+
+ // special case of archive (or dir) named "root" is / context
+ if (context.equalsIgnoreCase("root")) {
+ context = SLASH;
+ } else if (context.toLowerCase(Locale.ENGLISH).startsWith("root-")) {
+ int dash = context.toLowerCase(Locale.ENGLISH).indexOf('-');
+ String virtual = context.substring(dash + 1);
+ webAppContext.setVirtualHosts(List.of(virtual));
+ context = SLASH;
+ }
+
+ // Ensure "/" is Prepended to all context paths.
+ if (context.charAt(0) != '/') {
+ context = "/" + context;
+ }
+
+ webAppContext.setContextPath(context);
+ webAppContext.setWar(file.toFile().getAbsolutePath());
+ if (config.hasDefaultsDescriptor()) {
+ webAppContext.setDefaultsDescriptor(config.getDefaultsDescriptor().toASCIIString());
+ }
+ webAppContext.setExtractWAR(true);
+
+ webAppContext.setParentLoaderPriority(config.getClassloaderBehavior() == JettyEmbeddedConfiguration.ClassLoaderBehavior.JAVA_SPEC);
+
+ if (config.getTempDirectory() != null) {
+ /*
+ * Since the Temp Dir is really a context base temp directory, Lets set the Temp Directory in a way similar to how WebInfConfiguration does it,
+ * instead of setting the WebAppContext.setTempDirectory(File). If we used .setTempDirectory(File) all webapps will wind up in the same temp / work
+ * directory, overwriting each others work.
+ */
+ webAppContext.setAttribute(WebAppContext.TEMP_DIR, config.getTempDirectory());
+ }
+
+ webAppContextProcessors.forEach(processor -> processor.process(webAppContext, ((ArchiveApp)app).archive));
+
+ return webAppContext;
+ }
+
+ @Override
+ public String getEnvironmentName() {
+ return "ee11";
+ }
+
+ @Override
+ public void setDeploymentManager(DeploymentManager deploymentManager) {
+ this.deploymentManager = deploymentManager;
+ }
+}
diff --git a/jetty-embedded-12-ee11/src/main/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyEmbeddedConfiguration.java b/jetty-embedded-12-ee11/src/main/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyEmbeddedConfiguration.java
new file mode 100644
index 0000000..ce5beac
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/main/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyEmbeddedConfiguration.java
@@ -0,0 +1,132 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.arquillian.container.jetty.embedded_12_ee11;
+
+import java.io.File;
+import java.net.URI;
+
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.jboss.arquillian.container.jetty.AbstractJettyEmbeddedConfiguration;
+
+/**
+ * A {@link org.jboss.arquillian.container.spi.client.container.ContainerConfiguration} implementation for the Jetty Embedded
+ * containers.
+ *
+ * @author Dan Allen
+ * @author Ales Justin
+ */
+public class JettyEmbeddedConfiguration extends AbstractJettyEmbeddedConfiguration {
+ public enum ClassLoaderBehavior
+
+ {
+ /**
+ * Default behavior for Java Spec (server classloader, then webapp).
+ *
+ * Also the default for Arquillian.
+ */
+ JAVA_SPEC,
+ /** Default behavior for Servlet Spec (webapp classloader, then server) */
+ SERVLET_SPEC
+ }
+
+ /**
+ * Classloader Search Order behavior.
+ *
+ * Default for Arquillian is {@link ClassLoaderBehavior#JAVA_SPEC}.
+ */
+ private ClassLoaderBehavior classloaderBehavior = ClassLoaderBehavior.JAVA_SPEC;
+
+ /**
+ * Optional override for the default servlet spec descriptor
+ */
+ private URI defaultsDescriptor;
+
+ /**
+ * Dump, to System.err, the server state tree after the server has successfully started up.
+ */
+ private boolean dumpServerAfterStart = false;
+
+ /**
+ * Optional HttpConfiguration for the ServerConnector that Arquillian
+ * creates.
+ */
+ private HttpConfiguration httpConfiguration;
+
+ /**
+ * Idle Timeout (in milliseconds) for active connections.
+ *
+ * Default: 30,000ms
+ */
+ private long idleTimeoutMillis = 30000;
+
+ /**
+ * Base directory for all temp files that Jetty will manage.
+ */
+ private File tempDirectory;
+
+ public ClassLoaderBehavior getClassloaderBehavior() {
+ return classloaderBehavior;
+ }
+
+ public URI getDefaultsDescriptor() {
+ return defaultsDescriptor;
+ }
+
+ public HttpConfiguration getHttpConfiguration() {
+ return httpConfiguration;
+ }
+
+ public long getIdleTimeoutMillis() {
+ return idleTimeoutMillis;
+ }
+
+ public File getTempDirectory() {
+ return tempDirectory;
+ }
+
+ public boolean hasDefaultsDescriptor() {
+ return (defaultsDescriptor != null);
+ }
+
+ public boolean isDumpServerAfterStart() {
+ return dumpServerAfterStart;
+ }
+
+ public void setClassloaderBehavior(ClassLoaderBehavior classloaderBehavior) {
+ this.classloaderBehavior = classloaderBehavior;
+ }
+
+ public void setDefaultsDescriptor(URI defaultsDescriptor) {
+ this.defaultsDescriptor = defaultsDescriptor;
+ }
+
+ public void setDumpServerAfterStart(boolean serverDumpAfterStart) {
+ this.dumpServerAfterStart = serverDumpAfterStart;
+ }
+
+ public void setHttpConfiguration(HttpConfiguration httpConfiguration) {
+ this.httpConfiguration = httpConfiguration;
+ }
+
+ public void setIdleTimeoutMillis(long milliseconds) {
+ this.idleTimeoutMillis = milliseconds;
+ }
+
+ public void setTempDirectory(File tempDirectory) {
+ this.tempDirectory = tempDirectory;
+ }
+}
diff --git a/jetty-embedded-12-ee11/src/main/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyEmbeddedContainer.java b/jetty-embedded-12-ee11/src/main/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyEmbeddedContainer.java
new file mode 100644
index 0000000..98db667
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/main/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyEmbeddedContainer.java
@@ -0,0 +1,369 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.arquillian.container.jetty.embedded_12_ee11;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.codehaus.plexus.util.ReflectionUtils;
+import org.eclipse.jetty.deploy.App;
+import org.eclipse.jetty.deploy.AppLifeCycle;
+import org.eclipse.jetty.deploy.DeploymentManager;
+import org.eclipse.jetty.ee11.cdi.CdiDecoratingListener;
+import org.eclipse.jetty.ee11.cdi.CdiServletContainerInitializer;
+import org.eclipse.jetty.http.CookieCompliance;
+import org.eclipse.jetty.http.HttpVersion;
+import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory;
+import org.eclipse.jetty.security.HashLoginService;
+import org.eclipse.jetty.server.ConnectionFactory;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.SecureRequestCustomizer;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.handler.ContextHandlerCollection;
+import org.eclipse.jetty.server.handler.DefaultHandler;
+import org.eclipse.jetty.ee11.servlet.ServletHandler;
+import org.eclipse.jetty.ee11.servlet.ServletHolder;
+import org.eclipse.jetty.util.TypeUtil;
+import org.eclipse.jetty.util.resource.ResourceFactory;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.ee11.webapp.WebAppContext;
+import org.jboss.arquillian.container.jetty.EnvUtil;
+import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
+import org.jboss.arquillian.container.spi.client.container.DeploymentException;
+import org.jboss.arquillian.container.spi.client.container.LifecycleException;
+import org.jboss.arquillian.container.spi.client.protocol.ProtocolDescription;
+import org.jboss.arquillian.container.spi.client.protocol.metadata.HTTPContext;
+import org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData;
+import org.jboss.arquillian.container.spi.client.protocol.metadata.Servlet;
+import org.jboss.arquillian.container.spi.context.annotation.DeploymentScoped;
+import org.jboss.arquillian.core.api.Instance;
+import org.jboss.arquillian.core.api.InstanceProducer;
+import org.jboss.arquillian.core.api.annotation.ApplicationScoped;
+import org.jboss.arquillian.core.api.annotation.Inject;
+import org.jboss.arquillian.core.spi.ServiceLoader;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.descriptor.api.Descriptor;
+
+import jakarta.servlet.ServletContext;
+
+/**
+ *
+ * Jetty Embedded 11.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
+ */
+public class JettyEmbeddedContainer implements DeployableContainer {
+ private static final Logger log = Logger.getLogger(JettyEmbeddedContainer.class.getName());
+
+ private Server server;
+ private String listeningHost;
+ private int listeningPort;
+ private DeploymentManager deployer;
+ private ArquillianAppProvider appProvider;
+
+ private JettyEmbeddedConfiguration containerConfig;
+
+ @Inject
+ @DeploymentScoped
+ private InstanceProducer webAppContextProducer;
+
+ @Inject
+ @ApplicationScoped
+ private InstanceProducer servletContextInstanceProducer;
+
+ @Inject
+ private Instance serviceLoader;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jboss.arquillian.spi.client.container.DeployableContainer#getConfigurationClass()
+ */
+ public Class getConfigurationClass() {
+ return JettyEmbeddedConfiguration.class;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jboss.arquillian.spi.client.container.DeployableContainer#getDefaultProtocol()
+ */
+ public ProtocolDescription getDefaultProtocol() {
+ // Jetty 9 is a Servlet 3.1 container.
+ // However, Arquillian "Protocol" actual means "Packaging"
+ return new ProtocolDescription("Servlet 5.0");
+ }
+
+ public void setup(JettyEmbeddedConfiguration containerConfig) {
+ this.containerConfig = containerConfig;
+ }
+
+ public void start() throws LifecycleException {
+ EnvUtil.assertMinimumJettyVersion(Server.getVersion(), "12.0");
+
+ try {
+ server = new Server();
+
+ HttpConfiguration httpConfig = getHttpConfiguration();
+
+ ConnectionFactory connectionFactory = new HttpConnectionFactory(httpConfig);
+ // Setup Connector
+ ServerConnector connector;
+ if (containerConfig.isSsl()) {
+ SslContextFactory.Server sslContextFactory = getSslContextFactory();
+ server.addBean(sslContextFactory);
+ SslConnectionFactory sslConnectionFactory = new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString());
+ sslConnectionFactory.setEnsureSecureRequestCustomizer(containerConfig.isSniRequired());
+ connector = new ServerConnector(server, sslConnectionFactory, connectionFactory);
+ } else {
+ connector = new ServerConnector(server, connectionFactory);
+ }
+
+ if (containerConfig.isH2cEnabled()) {
+ HTTP2CServerConnectionFactory http2CServerConnectionFactory = new HTTP2CServerConnectionFactory(httpConfig);
+ connector.addConnectionFactory(http2CServerConnectionFactory);
+ }
+
+ connector.setHost(containerConfig.getBindAddress());
+ connector.setPort(containerConfig.getBindHttpPort());
+ connector.setIdleTimeout(containerConfig.getIdleTimeoutMillis());
+ server.setConnectors(new Connector[] {connector});
+
+ // Handler Tree location for all webapps
+ ContextHandlerCollection contexts = new ContextHandlerCollection();
+
+ // Deployment Management
+ deployer = new DeploymentManager();
+ deployer.setContexts(contexts);
+ Collection webAppContextProcessors = serviceLoader.get().all(WebAppContextProcessor.class);
+ appProvider = new ArquillianAppProvider(containerConfig, webAppContextProcessors);
+ deployer.addAppProvider(appProvider);
+ server.addBean(deployer);
+
+ // Handler Collection
+ Handler.Collection collection = new Handler.Sequence(contexts, new DefaultHandler());
+ server.setHandler(collection);
+
+ if (containerConfig.isRealmPropertiesFileSet()) {
+ String realmName = getRealmName();
+ HashLoginService hashUserRealm =
+ new HashLoginService(realmName,
+ ResourceFactory.of(server)
+ .newResource(Path.of(containerConfig.getRealmProperties().getAbsolutePath())));
+ server.addBean(hashUserRealm);
+ }
+
+ if (containerConfig.areInferredEncodings()) {
+ containerConfig.getInferredEncodings().forEach((s, s2) -> server.getMimeTypes().addInferred(s, s2));
+ }
+
+ server.setDumpAfterStart(containerConfig.isDumpServerAfterStart());
+ log.info("Starting Jetty Embedded Server " + Server.getVersion() + " [id:" + server.hashCode() + "]");
+ server.start();
+
+ listeningHost = connector.getHost();
+ if (listeningHost == null) {
+ listeningHost = containerConfig.getBindAddress();
+ }
+ listeningPort = connector.getLocalPort();
+ } catch (Exception e) {
+ throw new LifecycleException("Could not start container", e);
+ }
+ }
+
+ private String getRealmName() {
+ File realmProperties = containerConfig.getRealmProperties();
+ String fileName = realmProperties.getName();
+ int index;
+ if ((index = fileName.indexOf('.')) > -1) {
+ fileName = fileName.substring(0, index);
+ }
+ return fileName;
+ }
+
+ public void stop() throws LifecycleException {
+ try {
+ log.info("Stopping Jetty Embedded Server [id:" + server.hashCode() + "]");
+ server.stop();
+ } catch (Exception e) {
+ throw new LifecycleException("Could not stop container", e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jboss.arquillian.spi.client.container.DeployableContainer#deploy(org.jboss.shrinkwrap.descriptor.api.Descriptor)
+ */
+ public void deploy(Descriptor descriptor) throws DeploymentException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jboss.arquillian.spi.client.container.DeployableContainer#undeploy(org.jboss.shrinkwrap.descriptor.api.Descriptor)
+ */
+ public void undeploy(Descriptor descriptor) throws DeploymentException {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+
+ public ProtocolMetaData deploy(final Archive> archive) throws DeploymentException {
+ try {
+ App app = appProvider.createApp(archive);
+ deployer.removeApp(app);
+ WebAppContext webAppContext = getWebAppContext(app);
+
+ // Jetty setup telling Jetty's CdiDecoratingListener how to operate.
+ webAppContext.setInitParameter(CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, CdiDecoratingListener.MODE);
+ // jetty setup for layer between Weld and Jetty.
+ webAppContext.addServletContainerInitializer(new CdiServletContainerInitializer());
+ // Weld's org.jboss.weld.environment.servlet.EnhancedListener can be discovered automatically
+ // However, it won't happen if jetty-ee11-annotations JAR isn't present in runtime, hence we add it explicitly
+ // The listener will start up Weld container so long as there is an archive with any beans in it
+ webAppContext.addServletContainerInitializer(new org.jboss.weld.environment.servlet.EnhancedListener());
+
+ if (containerConfig.areMimeTypesSet()) {
+ containerConfig.getMimeTypes().forEach((s, s2) -> webAppContext.getMimeTypes().addMimeMapping(s, s2));
+ }
+
+ deployer.addApp(app);
+ deployer.requestAppGoal(app, AppLifeCycle.STARTED);
+
+ webAppContextProducer.set(app);
+ servletContextInstanceProducer.set(webAppContext.getServletContext());
+
+ HTTPContext httpContext = new HTTPContext(listeningHost, listeningPort);
+ ServletHandler servletHandler = webAppContext.getServletHandler();
+ for (ServletHolder servlet : servletHandler.getServlets()) {
+ httpContext.add(new Servlet(servlet.getName(), servlet.getServletContext().getContextPath()));
+ }
+ return new ProtocolMetaData().addContext(httpContext);
+ } catch (Exception e) {
+ throw new DeploymentException("Could not deploy " + archive.getName(), e);
+ }
+ }
+
+ private WebAppContext getWebAppContext(App app) throws Exception {
+ ContextHandler handler = app.getContextHandler();
+ WebAppContext webAppContext;
+ if (handler instanceof WebAppContext) {
+ webAppContext = (WebAppContext) handler;
+ } else {
+ throw new DeploymentException("Deployment of raw ContextHandler's not supported by Arquillian");
+ }
+ return webAppContext;
+ }
+
+ public void undeploy(Archive> archive) throws DeploymentException {
+ App app = webAppContextProducer.get();
+ if (app != null) {
+ deployer.requestAppGoal(app, AppLifeCycle.UNDEPLOYED);
+ }
+ }
+
+ /**
+ * Setup HTTP Configuration
+ * @return HttpConfiguration
+ */
+ private HttpConfiguration getHttpConfiguration() {
+ HttpConfiguration httpConfig = containerConfig.getHttpConfiguration();
+ if (httpConfig == null) {
+ httpConfig = new HttpConfiguration();
+ if (this.containerConfig.isHeaderBufferSizeSet()) {
+ httpConfig.setRequestHeaderSize(containerConfig.getHeaderBufferSize());
+ httpConfig.setResponseHeaderSize(containerConfig.getHeaderBufferSize());
+ }
+ if(this.containerConfig.getRequestCookieCompliance()!=null) {
+ httpConfig.setRequestCookieCompliance(CookieCompliance.from(containerConfig.getRequestCookieCompliance()));
+ }
+ if(this.containerConfig.getResponseCookieCompliance()!=null) {
+ httpConfig.setResponseCookieCompliance(CookieCompliance.from(containerConfig.getResponseCookieCompliance()));
+ }
+
+ if(containerConfig.getHttpConfigurationProperties()!=null){
+ for(Map.Entry propertyEntry:containerConfig.getHttpConfigurationProperties().entrySet()){
+ Method setter = ReflectionUtils.getSetter(propertyEntry.getKey(), httpConfig.getClass());
+ Class> setterClass = ReflectionUtils.getSetterType(setter);
+ Object value = TypeUtil.valueOf(setterClass, propertyEntry.getValue());
+ try {
+ setter.invoke(httpConfig, value);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ log.log(Level.WARNING, "Ignore error setting field with name " + propertyEntry.getKey() + " with value " + propertyEntry.getValue(), e);
+ }
+ }
+ }
+
+ }
+
+ SecureRequestCustomizer secureRequestCustomizer = httpConfig.getCustomizer(SecureRequestCustomizer.class);
+ if (secureRequestCustomizer == null) {
+ secureRequestCustomizer = new SecureRequestCustomizer();
+ httpConfig.addCustomizer(secureRequestCustomizer);
+ }
+ secureRequestCustomizer.setSniHostCheck(containerConfig.isSniHostCheck());
+ secureRequestCustomizer.setSniRequired(containerConfig.isSniRequired());
+ return httpConfig;
+ }
+
+ private SslContextFactory.Server getSslContextFactory() {
+ SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
+ if (containerConfig.getKeystorePath() != null) {
+ sslContextFactory.setKeyStorePath(new File(containerConfig.getKeystorePath()).getAbsolutePath());
+ }
+ if (containerConfig.getKeystorePassword() != null) {
+ sslContextFactory.setKeyStorePassword(containerConfig.getKeystorePassword());
+ }
+ if(containerConfig.getTrustStorePath() != null) {
+ sslContextFactory.setTrustStorePath(new File(containerConfig.getTrustStorePath()).getAbsolutePath());
+ }
+ if(containerConfig.getTrustStorePassword() != null) {
+ sslContextFactory.setTrustStorePassword(containerConfig.getTrustStorePassword());
+ }
+ sslContextFactory.setNeedClientAuth(containerConfig.isNeedClientAuth());
+ sslContextFactory.setSniRequired(containerConfig.isSniRequired());
+
+ return sslContextFactory;
+ }
+}
diff --git a/jetty-embedded-12-ee11/src/main/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyExtension.java b/jetty-embedded-12-ee11/src/main/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyExtension.java
new file mode 100644
index 0000000..602c2ef
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/main/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyExtension.java
@@ -0,0 +1,33 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @authors tag. All rights reserved.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.arquillian.container.jetty.embedded_12_ee11;
+
+import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
+import org.jboss.arquillian.core.spi.LoadableExtension;
+
+/**
+ * Jetty Embedded 12.x extension.
+ *
+ * @author Aslak Knutsen
+ */
+public class JettyExtension implements LoadableExtension {
+ @Override
+ public void register(ExtensionBuilder builder) {
+ builder.service(DeployableContainer.class, JettyEmbeddedContainer.class);
+ }
+}
diff --git a/jetty-embedded-12-ee11/src/main/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/WebAppContextProcessor.java b/jetty-embedded-12-ee11/src/main/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/WebAppContextProcessor.java
new file mode 100644
index 0000000..0d430d3
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/main/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/WebAppContextProcessor.java
@@ -0,0 +1,19 @@
+package org.jboss.arquillian.container.jetty.embedded_12_ee11;
+
+import org.eclipse.jetty.ee11.webapp.WebAppContext;
+import org.jboss.shrinkwrap.api.Archive;
+
+/**
+ * used to customise the {@link WebAppContext} created for a given {@link Archive}
+ * You need to register your implementations using the {@link org.jboss.arquillian.core.spi.LoadableExtension} mechanism
+ */
+public interface WebAppContextProcessor {
+
+ /**
+ *
+ * @param webAppContext the created {@link WebAppContext} for the {@link Archive}
+ * @param archive The user defined deployment archive
+ */
+ void process(WebAppContext webAppContext, Archive> archive);
+
+}
diff --git a/jetty-embedded-12-ee11/src/main/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension b/jetty-embedded-12-ee11/src/main/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
new file mode 100644
index 0000000..be80211
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/main/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
@@ -0,0 +1 @@
+org.jboss.arquillian.container.jetty.embedded_12_ee11.JettyExtension
diff --git a/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyEmbeddedClientTestCase.java b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyEmbeddedClientTestCase.java
new file mode 100644
index 0000000..9adf7a0
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyEmbeddedClientTestCase.java
@@ -0,0 +1,158 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.arquillian.container.jetty.embedded_12_ee11;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.transport.HttpClientTransportOverHTTP;
+import org.eclipse.jetty.io.ClientConnector;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.hamcrest.Matchers;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.OperateOnDeployment;
+import org.jboss.arquillian.container.test.api.TargetsContainer;
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.descriptor.api.Descriptors;
+import org.jboss.shrinkwrap.descriptor.api.webapp30.WebAppDescriptor;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import jakarta.servlet.ServletContext;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
+
+/**
+ * Client test case for the Jetty Embedded 12 container
+ *
+ * @author Aslak Knutsen
+ * @author Dan Allen
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JettyEmbeddedClientTestCase {
+ /**
+ * Deployment for the test
+ */
+ @Deployment(testable = false)
+ public static WebArchive getTestArchive() {
+ return ShrinkWrap.create(WebArchive.class, "client-http.war")
+ .addClass(MyOtherServlet.class)
+ .addClass(MyOtherBean.class)
+ .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
+ .setWebXML(new StringAsset(Descriptors.create(WebAppDescriptor.class)
+ .version("4.0")
+ .createServlet()
+ .servletClass(MyOtherServlet.class.getName())
+ .servletName("MyOtherServlet").up()
+ .createServletMapping()
+ .servletName("MyOtherServlet")
+ .urlPattern(MyOtherServlet.URL_PATTERN).up()
+ .exportAsString()));
+ }
+
+ /**
+ * Deployment for the test
+ */
+ @Deployment(testable = false, name = "webapp-https") @TargetsContainer("https")
+ public static WebArchive getTestArchiveHttps() {
+ return ShrinkWrap.create(WebArchive.class, "client-https.war")
+ .addClass(MyServlet.class)
+ .setWebXML(new StringAsset(Descriptors.create(WebAppDescriptor.class)
+ .version("4.0")
+ .createServlet()
+ .servletClass(MyServlet.class.getName())
+ .servletName("MyServlet").up()
+ .createServletMapping()
+ .servletName("MyServlet")
+ .urlPattern(MyServlet.URL_PATTERN).up()
+ .exportAsString()));
+ }
+
+ @ArquillianResource
+ ServletContext servletContext;
+
+ @ArquillianResource URL url;
+
+ @ArquillianResource @OperateOnDeployment("webapp-https") URL urlHttps;
+
+ private HttpClient httpClient;
+ private final SslContextFactory.Client clientSslContextFactory = new SslContextFactory.Client();
+
+ @BeforeEach
+ public void setup() throws Exception {
+ clientSslContextFactory.setTrustAll(true);
+ ClientConnector clientConnector = new ClientConnector();
+ clientConnector.setSelectors(1);
+ clientConnector.setSslContextFactory(clientSslContextFactory);
+ httpClient = new HttpClient(new HttpClientTransportOverHTTP(clientConnector));
+ httpClient.start();
+ }
+
+ @AfterEach
+ public void shutdown() throws Exception {
+ if(httpClient.isRunning()) {
+ httpClient.stop();
+ }
+ }
+
+ @Test
+ public void shouldBeAbleToInvokeServletInDeployedWebApp() throws Exception {
+
+ String body = httpClient.GET(new URL(url, MyOtherServlet.URL_PATTERN).toURI()).getContentAsString();
+
+ assertThat(
+ "Verify that the servlet was deployed and returns expected result",
+ body,
+ Matchers.is(MyOtherServlet.MESSAGE));
+ }
+
+ @Test
+ public void shouldBeAbleToInvokeServletInDeployedWebAppHttps() throws Exception {
+ URL url = new URL("https", urlHttps.getHost(), urlHttps.getPort(), urlHttps.getPath() + MyServlet.URL_PATTERN);
+ String body = httpClient.GET(url.toURI()).getContentAsString();
+
+ assertThat(
+ "Verify that the servlet was deployed and returns expected result",
+ body,
+ Matchers.is(MyServlet.MESSAGE));
+ }
+
+ @Test
+ public void shouldEnrichTestWithServletContext() {
+ assertThat(servletContext, notNullValue());
+ }
+
+ public static String readAllAndClose(InputStream is) throws Exception {
+ try (is;ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+ int read;
+ while ((read = is.read()) != -1) {
+ out.write(read);
+ }
+ return out.toString();
+ }
+ }
+}
diff --git a/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyEmbeddedInContainerTestCase.java b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyEmbeddedInContainerTestCase.java
new file mode 100644
index 0000000..78ea3d8
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/JettyEmbeddedInContainerTestCase.java
@@ -0,0 +1,131 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.arquillian.container.jetty.embedded_12_ee11;
+
+import java.net.URL;
+import java.sql.Connection;
+
+import jakarta.annotation.Resource;
+import jakarta.inject.Inject;
+import javax.sql.DataSource;
+
+import org.hamcrest.core.StringContains;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.OperateOnDeployment;
+import org.jboss.arquillian.junit5.ArquillianExtension;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.GenericArchive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.descriptor.api.Descriptors;
+import org.jboss.shrinkwrap.descriptor.api.webapp30.WebAppDescriptor;
+import org.jboss.shrinkwrap.resolver.api.maven.Maven;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+/**
+ * In-container test case for the Jetty Embedded 12 container
+ *
+ * @author Dan Allen
+ *
+ */
+@ExtendWith(ArquillianExtension.class)
+public class JettyEmbeddedInContainerTestCase {
+ /**
+ * Deployment for the test
+ */
+ @Deployment
+ public static WebArchive getTestArchive() {
+ return ShrinkWrap.create(WebArchive.class)
+ .addClass(MyBean.class)
+ // adding the configuration class silences the logged exception when building the configuration on the server-side, but shouldn't be necessary
+ //.addClass(JettyEmbeddedConfiguration.class)
+ .addAsLibraries(
+ Maven.configureResolver()
+ .workOffline()
+ .loadPomFromFile("pom.xml")
+ .resolve("org.jboss.weld.servlet:weld-servlet-core")
+ .withTransitivity()
+ .as(GenericArchive.class))
+ .addAsWebInfResource("jetty-env.xml")
+ .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
+ .setWebXML("in-container-web.xml");
+ }
+
+ @Deployment(name="encoding")
+ public static WebArchive getEncodingTestArchive() {
+ return ShrinkWrap.create(WebArchive.class)
+ .addClass(MyEncodingServlet.class)
+ .setWebXML(new StringAsset(Descriptors.create(WebAppDescriptor.class)
+ .version("4.0")
+ .createServlet()
+ .servletClass(MyEncodingServlet.class.getName())
+ .servletName("encoding").up()
+ .createServletMapping()
+ .servletName("encoding")
+ .urlPattern(MyEncodingServlet.URL_PATTERN).up()
+ .exportAsString()));
+ }
+
+ @ArquillianResource @OperateOnDeployment("encoding")
+ private URL encodingUrl;
+
+ // defined in jetty-env.xml, scoped to global
+ @Resource(mappedName = "version") Integer version;
+
+ // defined in web.xml, scoped to webapp (relative to java:comp/env)
+ @Resource(name = "name") String name;
+
+ // defined in jetty-env.xml, scoped to webapp (relative to java:comp/env)
+ @Resource(name = "type") String containerType;
+
+ @Resource(name = "jdbc/test") DataSource ds;
+
+ @Inject MyBean testBean;
+
+ @Test
+ public void shouldBeAbleToInjectMembersIntoTestClass() throws Exception {
+ assertThat(version, notNullValue());
+ assertThat(version, is(6));
+ assertThat(name, notNullValue());
+ assertThat(name, is("Jetty"));
+ assertThat(containerType, notNullValue());
+ assertThat(containerType, is("Embedded"));
+ assertThat(ds, notNullValue());
+ try (Connection c = ds.getConnection()) {
+ assertThat(c.getMetaData().getDatabaseProductName(), is("H2"));
+ }
+ assertThat(testBean, notNullValue());
+ assertThat(testBean.getName(), is("Jetty"));
+ }
+
+ @Test
+ public void shouldBeEncodingDefined() throws Exception {
+ String body = JettyEmbeddedClientTestCase.readAllAndClose(new URL(encodingUrl, MyEncodingServlet.URL_PATTERN).openStream());
+
+ assertThat(
+ "Should contains ISO-8859-1",
+ body,
+ StringContains.containsStringIgnoringCase("ISO-8859-1"));
+ }
+}
diff --git a/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyBean.java b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyBean.java
new file mode 100644
index 0000000..6a759ac
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyBean.java
@@ -0,0 +1,30 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.arquillian.container.jetty.embedded_12_ee11;
+
+import jakarta.annotation.Resource;
+import jakarta.enterprise.context.Dependent;
+
+@Dependent
+public class MyBean {
+ @Resource(name = "name")
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyEncodingServlet.java b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyEncodingServlet.java
new file mode 100644
index 0000000..9348009
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyEncodingServlet.java
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.arquillian.container.jetty.embedded_12_ee11;
+
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.io.IOException;
+
+/**
+ * MyEncodingServlet
+ *
+ */
+public class MyEncodingServlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ public static final String URL_PATTERN = "encoding";
+
+
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ response.setContentType("text/html");
+ String encoding = response.getCharacterEncoding();
+ response.getWriter().append(encoding);
+ }
+}
diff --git a/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyOtherBean.java b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyOtherBean.java
new file mode 100644
index 0000000..613cd4e
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyOtherBean.java
@@ -0,0 +1,11 @@
+package org.jboss.arquillian.container.jetty.embedded_12_ee11;
+
+import jakarta.enterprise.context.Dependent;
+
+@Dependent
+public class MyOtherBean {
+
+ public String ping() {
+ return MyOtherBean.class.getSimpleName();
+ }
+}
diff --git a/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyOtherServlet.java b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyOtherServlet.java
new file mode 100644
index 0000000..8e794ab
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyOtherServlet.java
@@ -0,0 +1,30 @@
+package org.jboss.arquillian.container.jetty.embedded_12_ee11;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import jakarta.inject.Inject;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+import java.io.IOException;
+
+public class MyOtherServlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ public static final String URL_PATTERN = "Test2";
+
+ public static final String MESSAGE = "hey there";
+
+ @Inject
+ MyOtherBean bean;
+
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ assertThat(bean.ping(), is(MyOtherBean.class.getSimpleName()));
+ response.getWriter().append(MESSAGE);
+ }
+}
diff --git a/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyServlet.java b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyServlet.java
new file mode 100644
index 0000000..5c63922
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/test/java/org/jboss/arquillian/container/jetty/embedded_12_ee11/MyServlet.java
@@ -0,0 +1,43 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.arquillian.container.jetty.embedded_12_ee11;
+
+import java.io.IOException;
+
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServlet;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+/**
+ * TestServlet
+ *
+ * @author Aslak Knutsen
+ */
+public class MyServlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ public static final String URL_PATTERN = "Test";
+
+ public static final String MESSAGE = "hello";
+
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ response.getWriter().append(MESSAGE);
+ }
+}
diff --git a/jetty-embedded-12-ee11/src/test/resources/arquillian.xml b/jetty-embedded-12-ee11/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..f2ffd74
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/test/resources/arquillian.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+ 0
+
+ js application/js
+ txt text/plain
+
+
+ text/html iso-8859-1
+
+ true
+
+
+ relativeRedirectAllowed false
+
+
+
+
+
+
+ 0
+ true
+ src/test/resources/keystore.p12
+ storepwd
+
+
+
+
+
diff --git a/jetty-embedded-12-ee11/src/test/resources/default.properties b/jetty-embedded-12-ee11/src/test/resources/default.properties
new file mode 100644
index 0000000..cc7136f
--- /dev/null
+++ b/jetty-embedded-12-ee11/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/jetty-embedded-12-ee11/src/test/resources/in-container-web.xml b/jetty-embedded-12-ee11/src/test/resources/in-container-web.xml
new file mode 100644
index 0000000..8486902
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/test/resources/in-container-web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ name
+ java.lang.String
+ Jetty
+
+
+
+
+ type
+ java.lang.String
+ Remote
+
+
+
diff --git a/jetty-embedded-12-ee11/src/test/resources/jetty-env.xml b/jetty-embedded-12-ee11/src/test/resources/jetty-env.xml
new file mode 100644
index 0000000..7986093
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/test/resources/jetty-env.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+ type
+ Embedded
+ true
+
+
+ version
+ 6
+ true
+
+
+
+
+
+ jdbc/test
+
+
+ jdbc:h2:mem:test
+ sa
+ sa
+
+
+ true
+
+
diff --git a/jetty-embedded-12-ee11/src/test/resources/keystore.p12 b/jetty-embedded-12-ee11/src/test/resources/keystore.p12
new file mode 100644
index 0000000..01a1aea
Binary files /dev/null and b/jetty-embedded-12-ee11/src/test/resources/keystore.p12 differ
diff --git a/jetty-embedded-12-ee11/src/test/resources/simplelogger.properties b/jetty-embedded-12-ee11/src/test/resources/simplelogger.properties
new file mode 100644
index 0000000..6f28e9f
--- /dev/null
+++ b/jetty-embedded-12-ee11/src/test/resources/simplelogger.properties
@@ -0,0 +1,6 @@
+org.slf4j.simpleLogger.defaultLogLevel=info
+#org.slf4j.simpleLogger.log.org.eclipse.jetty.server=debug
+#org.slf4j.simpleLogger.log.org.eclipse.jetty.annotations=debug
+#org.slf4j.simpleLogger.log.org.eclipse.jetty=debug
+#org.slf4j.simpleLogger.log.org.eclipse.jetty.ee11=debug
+
diff --git a/jetty-embedded-12-ee9/pom.xml b/jetty-embedded-12-ee9/pom.xml
index fba52a4..c301de9 100644
--- a/jetty-embedded-12-ee9/pom.xml
+++ b/jetty-embedded-12-ee9/pom.xml
@@ -44,6 +44,11 @@
pom
import