diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 459d125..ffd3d3d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,7 @@ jobs: ci: runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: os: [ ubuntu-latest, windows-latest, macos-latest ] java: [ 11, 17, 21 ] @@ -32,3 +33,9 @@ jobs: ${{ runner.os }}-maven- - name: Build with Maven run: mvn --batch-mode verify + - name: Archive Surefire Reports + uses: actions/upload-artifact@v4 + if: always() + with: + name: ${{ runner.os }}-${{ matrix.java }}-failsafe-reports + path: '**/target/failsafe-reports/*.xml' diff --git a/pom.xml b/pom.xml index 1942414..e449ee8 100644 --- a/pom.xml +++ b/pom.xml @@ -262,5 +262,8 @@ tomcat-embedded-common tomcat-embedded-parent tomcat-embedded-10 + tomcat-managed-parent + tomcat-managed-common + tomcat-managed-10 diff --git a/tomcat-container-parent/pom.xml b/tomcat-container-parent/pom.xml index 7f6d38e..c2eff30 100644 --- a/tomcat-container-parent/pom.xml +++ b/tomcat-container-parent/pom.xml @@ -59,6 +59,10 @@ maven-failsafe-plugin + + + -Dfile.encoding=${project.build.sourceEncoding} + diff --git a/tomcat-managed-10/pom.xml b/tomcat-managed-10/pom.xml new file mode 100755 index 0000000..6872b61 --- /dev/null +++ b/tomcat-managed-10/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + + org.jboss.arquillian.container + arquillian-tomcat-managed-parent + 1.2.1-SNAPSHOT + ../tomcat-managed-parent/pom.xml + + + arquillian-tomcat-managed-10 + Arquillian Container Tomcat Managed 10.x + + + 10 + ${tomcat.major.version}.1.19 + ${project.build.directory}/cargo/installs/apache-tomcat-${tomcat.version}/apache-tomcat-${tomcat.version} + ${project.build.directory}/cargo/configurations/tomcat${tomcat.major.version}x + + + + + javax.servlet + javax.servlet-api + 3.1.0 + test + + + + + + + org.codehaus.cargo + cargo-maven2-plugin + + + install-container + + + tomcat${tomcat.major.version}x + + https://archive.apache.org/dist/tomcat/tomcat-${tomcat.major.version}/v${tomcat.version}/bin/apache-tomcat-${tomcat.version}.zip + + + + + + + + + diff --git a/tomcat-managed-10/src/main/java/org/jboss/arquillian/container/tomcat/managed/Tomcat10ManagedContainer.java b/tomcat-managed-10/src/main/java/org/jboss/arquillian/container/tomcat/managed/Tomcat10ManagedContainer.java new file mode 100755 index 0000000..7d15392 --- /dev/null +++ b/tomcat-managed-10/src/main/java/org/jboss/arquillian/container/tomcat/managed/Tomcat10ManagedContainer.java @@ -0,0 +1,40 @@ +/* + * 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.tomcat.managed; + +import org.jboss.arquillian.container.spi.client.container.DeployableContainer; +import org.jboss.arquillian.container.spi.client.protocol.ProtocolDescription; +import org.jboss.arquillian.container.tomcat.Tomcat7ManagerCommandSpec; + +/** + *

+ * Arquillian {@link DeployableContainer} implementation for an Managed Tomcat server; responsible for both lifecycle and + * deployment operations. + *

+ * + * @author Karel Piwko + * @author Juraj Huska + * @author Ondrej Zizka + * @author Dimitrij Drus + * @version $Revision: #1 $ + */ +public class Tomcat10ManagedContainer extends TomcatManagedContainer { + + public Tomcat10ManagedContainer() { + super(new ProtocolDescription("Servlet 5.0"), new Tomcat7ManagerCommandSpec()); + } +} diff --git a/tomcat-managed-10/src/main/java/org/jboss/arquillian/container/tomcat/managed/Tomcat10ManagedExtension.java b/tomcat-managed-10/src/main/java/org/jboss/arquillian/container/tomcat/managed/Tomcat10ManagedExtension.java new file mode 100755 index 0000000..2cbfc91 --- /dev/null +++ b/tomcat-managed-10/src/main/java/org/jboss/arquillian/container/tomcat/managed/Tomcat10ManagedExtension.java @@ -0,0 +1,12 @@ +package org.jboss.arquillian.container.tomcat.managed; + +import org.jboss.arquillian.container.spi.client.container.DeployableContainer; +import org.jboss.arquillian.core.spi.LoadableExtension; + +public class Tomcat10ManagedExtension implements LoadableExtension { + + @Override + public void register(final ExtensionBuilder builder) { + builder.service(DeployableContainer.class, Tomcat10ManagedContainer.class); + } +} diff --git a/tomcat-managed-10/src/main/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension b/tomcat-managed-10/src/main/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension new file mode 100755 index 0000000..48c77b3 --- /dev/null +++ b/tomcat-managed-10/src/main/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension @@ -0,0 +1 @@ +org.jboss.arquillian.container.tomcat.managed.Tomcat10ManagedExtension diff --git a/tomcat-managed-10/src/test/java/org/jboss/arquillian/container/tomcat/managed/Tomcat10ManagedClientIT.java b/tomcat-managed-10/src/test/java/org/jboss/arquillian/container/tomcat/managed/Tomcat10ManagedClientIT.java new file mode 100755 index 0000000..61c0694 --- /dev/null +++ b/tomcat-managed-10/src/test/java/org/jboss/arquillian/container/tomcat/managed/Tomcat10ManagedClientIT.java @@ -0,0 +1,51 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2014, 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.tomcat.managed; + +import static org.jboss.arquillian.container.tomcat.test.TestDeploymentFactory.ROOT_CONTEXT; +import static org.jboss.arquillian.container.tomcat.test.TestDeploymentFactory.SERVLET_5; +import static org.jboss.arquillian.container.tomcat.test.TestDeploymentFactory.TEST_CONTEXT; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.tomcat.test.TomcatClientITBase; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.runner.RunWith; + +/** + * Tests that Tomcat deployments into the Tomcat 8 server work through the Arquillian lifecycle + * + * @author Jean Deruelle + * @author Dan Allen + * @author Dimitrij Drus + * @version $Revision: $ + */ +@RunWith(Arquillian.class) +public class Tomcat10ManagedClientIT extends TomcatClientITBase { + + @Deployment(name = ROOT_CONTEXT, testable = false) + public static WebArchive createRootDeployment() { + + return TEST_DEPLOYMENT_FACTORY.createWebAppClientDeployment(ROOT_CONTEXT, SERVLET_5); + } + + @Deployment(name = TEST_CONTEXT, testable = false) + public static WebArchive createTestDeployment() { + + return TEST_DEPLOYMENT_FACTORY.createWebAppClientDeployment(TEST_CONTEXT, SERVLET_5); + } +} diff --git a/tomcat-managed-10/src/test/java/org/jboss/arquillian/container/tomcat/managed/Tomcat10ManagedInContainerIT.java b/tomcat-managed-10/src/test/java/org/jboss/arquillian/container/tomcat/managed/Tomcat10ManagedInContainerIT.java new file mode 100755 index 0000000..c500139 --- /dev/null +++ b/tomcat-managed-10/src/test/java/org/jboss/arquillian/container/tomcat/managed/Tomcat10ManagedInContainerIT.java @@ -0,0 +1,49 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2014, 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.tomcat.managed; + +import static org.jboss.arquillian.container.tomcat.test.TestDeploymentFactory.ROOT_CONTEXT; +import static org.jboss.arquillian.container.tomcat.test.TestDeploymentFactory.SERVLET_5; +import static org.jboss.arquillian.container.tomcat.test.TestDeploymentFactory.TEST_CONTEXT; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.tomcat.test.TomcatInContainerITBase; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.runner.RunWith; + +/** + * Tests that Tomcat deployments into the Tomcat 8 server work through the Arquillian lifecycle + * + * @author Dimitrij Drus + * @version $Revision: $ + */ +@RunWith(Arquillian.class) +public class Tomcat10ManagedInContainerIT extends TomcatInContainerITBase { + + @Deployment(name = ROOT_CONTEXT) + public static WebArchive createRootDeployment() { + + return TEST_DEPLOYMENT_FACTORY.createWebAppInContainerDeployment(ROOT_CONTEXT, SERVLET_5); + } + + @Deployment(name = TEST_CONTEXT) + public static WebArchive createTestDeployment() { + + return TEST_DEPLOYMENT_FACTORY.createWebAppInContainerDeployment(TEST_CONTEXT, SERVLET_5); + } +} diff --git a/tomcat-managed-10/src/test/resources/arquillian.xml b/tomcat-managed-10/src/test/resources/arquillian.xml new file mode 100755 index 0000000..5da1d05 --- /dev/null +++ b/tomcat-managed-10/src/test/resources/arquillian.xml @@ -0,0 +1,17 @@ + + + + + + ${test.catalina.home} + ${test.catalina.base} + -Xmx1024m + ${test.jmx.port} + ${test.http.port} + server.xml + ${test.manager.username} + ${test.manager.password} + + + + diff --git a/tomcat-managed-10/src/test/resources/tomcat-users.xml b/tomcat-managed-10/src/test/resources/tomcat-users.xml new file mode 100755 index 0000000..7918383 --- /dev/null +++ b/tomcat-managed-10/src/test/resources/tomcat-users.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tomcat-managed-common/pom.xml b/tomcat-managed-common/pom.xml new file mode 100644 index 0000000..5bdad2b --- /dev/null +++ b/tomcat-managed-common/pom.xml @@ -0,0 +1,53 @@ + + + + 4.0.0 + + + org.jboss.arquillian.container + arquillian-parent-tomcat + 1.2.1-SNAPSHOT + + + arquillian-tomcat-managed-common + Arquillian Tomcat Managed Container Common + + + + + + + org.jboss.arquillian.container + arquillian-tomcat-common + ${project.version} + + + + + + org.jboss.arquillian.container + arquillian-tomcat-common + ${project.version} + test-jar + test + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + test-jar + + + + + + + + diff --git a/tomcat-managed-common/src/main/java/org/jboss/arquillian/container/tomcat/managed/TomcatManagedConfiguration.java b/tomcat-managed-common/src/main/java/org/jboss/arquillian/container/tomcat/managed/TomcatManagedConfiguration.java new file mode 100644 index 0000000..5b8a407 --- /dev/null +++ b/tomcat-managed-common/src/main/java/org/jboss/arquillian/container/tomcat/managed/TomcatManagedConfiguration.java @@ -0,0 +1,225 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2014, 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.tomcat.managed; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +import org.jboss.arquillian.container.spi.ConfigurationException; +import org.jboss.arquillian.container.tomcat.TomcatConfiguration; +import org.jboss.arquillian.container.tomcat.Validate; + +/** + * Arquillian Tomcat Container Configuration + * + * @author Karel Piwko + * @author Juraj Huska + * @author Stephen Coy + * @version $Revision: $ + */ +public class TomcatManagedConfiguration extends TomcatConfiguration { + + static final String JAVA_HOME_ENV_PROPERTY = "JAVA_HOME"; + + static final String JAVA_HOME_SYSTEM_PROPERTY = "java.home"; + + private boolean outputToConsole = true; + + private String catalinaHome = System.getenv("CATALINA_HOME"); + + private String catalinaBase = System.getenv("CATALINA_BASE"); + + private String javaHome = System.getProperty(JAVA_HOME_ENV_PROPERTY); + + private String javaVmArguments = "-Xmx512m"; + + private int startupTimeoutInSeconds = 120; + + private int shutdownTimeoutInSeconds = 45; + + private String workDir = null; + + private String serverConfig = "server.xml"; + + private String loggingProperties = "logging.properties"; + + public TomcatManagedConfiguration() { + // if no javaHome set, reuse this Java JVM + if (javaHome == null || "".equals(javaHome)) { + javaHome = System.getProperty(JAVA_HOME_SYSTEM_PROPERTY); + } + } + + @Override + public void validate() throws ConfigurationException { + + super.validate(); + + Validate.configurationDirectoryExists(catalinaHome, + "Either CATALINA_HOME environment variable or catalinaHome property in Arquillian configuration " + + "must be set and point to a valid directory! " + catalinaHome + " is not valid directory!"); + + Validate.configurationDirectoryExists(javaHome, + "Either \"java.home\" system property, JAVA_HOME environment variable or javaHome property in Arquillian configuration " + + "must be set and point to a valid directory! " + javaHome + " is not valid directory!"); + + //to keep backward compatibility, check catalinaBase only when it's set, otherwise catalinaHome will be used instead + if (catalinaBase != null && catalinaBase.length() != 0) { + Validate.isValidFile(getCatalinaBase() + "/conf/" + serverConfig, + "The server configuration file denoted by serverConfig property has to exist! This file: " + + getCatalinaBase() + + "/conf/" + + serverConfig + + " does not!"); + } + + // set write output to console + this.setOutputToConsole(AccessController.doPrivileged(new PrivilegedAction() { + + @Override + public Boolean run() { + + // By default, redirect to stdout unless disabled by this property + final String val = System.getProperty("org.apache.tomcat.writeconsole"); + return val == null || !"false".equals(val); + } + })); + } + + public String getCatalinaHome() { + + return catalinaHome; + } + + public void setCatalinaHome(final String catalinaHome) { + + this.catalinaHome = catalinaHome; + } + + public String getCatalinaBase() { + return catalinaBase; + } + + public void setCatalinaBase(final String catalinaBase) { + + this.catalinaBase = catalinaBase; + } + + public String getJavaHome() { + + return javaHome; + } + + public void setJavaHome(final String javaHome) { + + this.javaHome = javaHome; + } + + public String getJavaVmArguments() { + + return javaVmArguments; + } + + /** + * This will override the default ("-Xmx512m") startup JVM arguments. + * + * @param javaVmArguments + * use as start up arguments + */ + public void setJavaVmArguments(final String javaVmArguments) { + + this.javaVmArguments = javaVmArguments; + } + + public int getStartupTimeoutInSeconds() { + + return startupTimeoutInSeconds; + } + + public void setStartupTimeoutInSeconds(final int startupTimeoutInSeconds) { + + this.startupTimeoutInSeconds = startupTimeoutInSeconds; + } + + public int getShutdownTimeoutInSeconds() { + + return shutdownTimeoutInSeconds; + } + + public void setShutdownTimeoutInSeconds(final int shutdownTimeoutInSeconds) { + + this.shutdownTimeoutInSeconds = shutdownTimeoutInSeconds; + } + + public String getWorkDir() { + + return workDir; + } + + /** + * @param workDir + * the directory where the compiled JSP files and session serialization data is stored + */ + public void setWorkDir(final String workDir) { + + this.workDir = workDir; + } + + public String getServerConfig() { + + return serverConfig; + } + + public void setServerConfig(final String serverConfig) { + + this.serverConfig = serverConfig; + } + + /** + * @return the loggingProperties + */ + public String getLoggingProperties() { + + return loggingProperties; + } + + /** + * @param loggingProperties + * the loggingProperties to set + */ + public void setLoggingProperties(final String loggingProperties) { + + this.loggingProperties = loggingProperties; + } + + /** + * @param outputToConsole + * the outputToConsole to set + */ + public void setOutputToConsole(final boolean outputToConsole) { + + this.outputToConsole = outputToConsole; + } + + /** + * @return the outputToConsole + */ + public boolean isOutputToConsole() { + + return outputToConsole; + } +} diff --git a/tomcat-managed-common/src/main/java/org/jboss/arquillian/container/tomcat/managed/TomcatManagedContainer.java b/tomcat-managed-common/src/main/java/org/jboss/arquillian/container/tomcat/managed/TomcatManagedContainer.java new file mode 100644 index 0000000..40cc851 --- /dev/null +++ b/tomcat-managed-common/src/main/java/org/jboss/arquillian/container/tomcat/managed/TomcatManagedContainer.java @@ -0,0 +1,326 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2014, 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.tomcat.managed; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeoutException; +import java.util.logging.Logger; + +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.ProtocolMetaData; +import org.jboss.arquillian.container.tomcat.AdditionalJavaOptionsParser; +import org.jboss.arquillian.container.tomcat.ProtocolMetadataParser; +import org.jboss.arquillian.container.tomcat.ShrinkWrapUtil; +import org.jboss.arquillian.container.tomcat.TomcatManager; +import org.jboss.arquillian.container.tomcat.TomcatManagerCommandSpec; +import org.jboss.arquillian.container.tomcat.Validate; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.descriptor.api.Descriptor; + +/** + *

+ * Arquillian {@link org.jboss.arquillian.container.spi.client.container.DeployableContainer} implementation for an + * Managed + * Tomcat server; responsible for both lifecycle and deployment operations. + *

+ * + * @author Karel Piwko + * @author Juraj Huska + * @author Ondrej Zizka + * @author Stephen Coy + * @version $Revision: $ + */ +abstract class TomcatManagedContainer implements DeployableContainer { + + private static final Logger log = Logger.getLogger(TomcatManagedContainer.class.getName()); + + private final TomcatManagerCommandSpec tomcatManagerCommandSpec; + + private final ProtocolDescription protocolDescription; + + /** + * Tomcat container configuration + */ + private TomcatManagedConfiguration configuration; + + private TomcatManager manager; + + private Thread shutdownThread; + + private Process startupProcess; + + TomcatManagedContainer(final ProtocolDescription protocolDescription, + final TomcatManagerCommandSpec tomcatManagerCommandSpec) { + + this.protocolDescription = protocolDescription; + this.tomcatManagerCommandSpec = tomcatManagerCommandSpec; + } + + @Override + public Class getConfigurationClass() { + + return TomcatManagedConfiguration.class; + } + + @Override + public ProtocolDescription getDefaultProtocol() { + + return protocolDescription; + } + + @Override + public void setup(final TomcatManagedConfiguration configuration) { + + this.configuration = configuration; + this.manager = new TomcatManager(configuration, tomcatManagerCommandSpec); + } + + @Override + public void start() throws LifecycleException { + + if (manager.isRunning()) { + throw new LifecycleException("The server is already running! " + + "Managed containers does not support connecting to running server instances due to the " + + "possible harmful effect of connecting to the wrong server. Please stop server before running or " + + "change to another type of container.\n" + + "To disable this check and allow Arquillian to connect to a running server, " + + "set allowConnectingToRunningServer to true in the container configuration"); + } + + try { + final String CATALINA_HOME = configuration.getCatalinaHome(); + String CATALINA_BASE = configuration.getCatalinaBase(); + final String ADDITIONAL_JAVA_OPTS = configuration.getJavaVmArguments(); + + if (CATALINA_BASE == null) { + CATALINA_BASE = CATALINA_HOME; + } + + final String absoluteCatalinaHomePath = new File(CATALINA_HOME).getAbsolutePath(); + final String absoluteCatalinaBasePath = new File(CATALINA_BASE).getAbsolutePath(); + + final String javaCommand = getJavaCommand(); + + // construct a command to execute + final List cmd = new ArrayList(); + + cmd.add(javaCommand); + String seperator = File.separator; + + cmd.add("-Djava.util.logging.config.file=" + absoluteCatalinaBasePath + seperator + "conf" + seperator + + configuration.getLoggingProperties()); + cmd.add("-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"); + + cmd.add("-Dcom.sun.management.jmxremote.port=" + configuration.getJmxPort()); + cmd.add("-Dcom.sun.management.jmxremote.ssl=false"); + cmd.add("-Dcom.sun.management.jmxremote.authenticate=false"); + + cmd.addAll(AdditionalJavaOptionsParser.parse(ADDITIONAL_JAVA_OPTS)); + + String CLASS_PATH = + absoluteCatalinaHomePath + seperator + "bin" + seperator + "bootstrap.jar" + File.pathSeparator; + CLASS_PATH += absoluteCatalinaHomePath + seperator + "bin" + seperator + "tomcat-juli.jar"; + + cmd.add("-classpath"); + cmd.add(CLASS_PATH); + final File endorsed = new File(absoluteCatalinaHomePath + seperator + "endorsed"); + if (endorsed.exists()) { + cmd.add("-Djava.endorsed.dirs=" + endorsed.getAbsolutePath()); + } + cmd.add("-Dcatalina.base=" + absoluteCatalinaBasePath); + cmd.add("-Dcatalina.home=" + absoluteCatalinaHomePath); + cmd.add("-Djava.io.tmpdir=" + absoluteCatalinaBasePath + seperator + "temp"); + cmd.add("org.apache.catalina.startup.Bootstrap"); + cmd.add("-config"); + cmd.add(absoluteCatalinaBasePath + seperator + "conf" + seperator + configuration.getServerConfig()); + cmd.add("start"); + + // execute command + final ProcessBuilder startupProcessBuilder = new ProcessBuilder(cmd); + startupProcessBuilder.redirectErrorStream(true); + startupProcessBuilder.directory(new File(configuration.getCatalinaHome() + "/bin")); + log.info("Starting Tomcat with: " + cmd.toString()); + startupProcess = startupProcessBuilder.start(); + new Thread(new ConsoleConsumer(configuration.isOutputToConsole())).start(); + final Process proc = startupProcess; + + shutdownThread = new Thread(new Runnable() { + + @Override + public void run() { + + if (proc != null) { + proc.destroy(); + try { + proc.waitFor(); + } catch (final InterruptedException e) { + throw new RuntimeException(e); + } + } + } + }); + Runtime.getRuntime().addShutdownHook(shutdownThread); + + final long startupTimeout = configuration.getStartupTimeoutInSeconds(); + long timeout = startupTimeout * 1000; + boolean serverAvailable = false; + while (timeout > 0 && serverAvailable == false) { + serverAvailable = manager.isRunning(); + if (!serverAvailable) { + Thread.sleep(100); + timeout -= 100; + } + } + if (!serverAvailable) { + destroystartupProcess(); + throw new TimeoutException(String.format("Managed server was not started within [%d] s", startupTimeout)); + } + } catch (final Exception ex) { + + throw new LifecycleException("Could not start container", ex); + } + } + + @Override + public void stop() throws LifecycleException { + + if (shutdownThread != null) { + Runtime.getRuntime().removeShutdownHook(shutdownThread); + shutdownThread = null; + } + try { + if (startupProcess != null) { + startupProcess.destroy(); + startupProcess.waitFor(); + startupProcess = null; + } + } catch (final Exception e) { + throw new LifecycleException("Could not stop container", e); + } + } + + /** + * Deploys to remote Tomcat using it's /manager web-app's org.apache.catalina.manager.ManagerServlet. + * + * @throws org.jboss.arquillian.container.spi.client.container.DeploymentException + */ + @Override + public ProtocolMetaData deploy(final Archive archive) throws DeploymentException { + + Validate.notNull(archive, "Archive must not be null"); + + final String archiveName = manager.normalizeArchiveName(archive.getName()); + final URL archiveURL = ShrinkWrapUtil.toURL(archive); + try { + manager.deploy("/" + archiveName, archiveURL); + } catch (final IOException e) { + throw new DeploymentException("Unable to deploy an archive " + archive.getName(), e); + } + + final ProtocolMetadataParser parser = + new ProtocolMetadataParser(configuration); + return parser.retrieveContextServletInfo(archiveName); + } + + @Override + public void undeploy(final Archive archive) throws DeploymentException { + + Validate.notNull(archive, "Archive must not be null"); + + final String archiveName = manager.normalizeArchiveName(archive.getName()); + try { + manager.undeploy("/" + archiveName); + } catch (final IOException e) { + throw new DeploymentException("Unable to undeploy an archive " + archive.getName(), e); + } + } + + @Override + public void deploy(final Descriptor descriptor) throws DeploymentException { + + throw new UnsupportedOperationException("Not implemented"); + } + + @Override + public void undeploy(final Descriptor descriptor) throws DeploymentException { + + throw new UnsupportedOperationException("Not implemented"); + } + + /** + * Runnable that consumes the output of the startupProcess. If nothing consumes the output the AS will hang on some + * platforms + * + * @author Stuart Douglas + */ + private class ConsoleConsumer implements Runnable { + + private final boolean writeOutput; + + ConsoleConsumer(final boolean writeOutput) { + + this.writeOutput = writeOutput; + } + + @Override + public void run() { + + final InputStream stream = startupProcess.getInputStream(); + final BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + String line = null; + try { + while ((line = reader.readLine()) != null) { + if (writeOutput) { + System.out.println(line); + } + } + } catch (final IOException e) { + } + } + } + + private int destroystartupProcess() { + + if (startupProcess == null) + return 0; + startupProcess.destroy(); + try { + return startupProcess.waitFor(); + } catch (final InterruptedException e) { + throw new RuntimeException(e); + } + } + + String getJavaCommand() { + + if (configuration == null) { + throw new IllegalStateException("setup not called"); + } + + return configuration.getJavaHome() + File.separator + "bin" + File.separator + "java"; + } +} diff --git a/tomcat-managed-common/src/test/java/org/jboss/arquillian/container/tomcat/managed/TomcatManagedConfigurationTest.java b/tomcat-managed-common/src/test/java/org/jboss/arquillian/container/tomcat/managed/TomcatManagedConfigurationTest.java new file mode 100644 index 0000000..ade1f7c --- /dev/null +++ b/tomcat-managed-common/src/test/java/org/jboss/arquillian/container/tomcat/managed/TomcatManagedConfigurationTest.java @@ -0,0 +1,34 @@ +package org.jboss.arquillian.container.tomcat.managed; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class TomcatManagedConfigurationTest { + + @Test + public void testGetJavaHomeForDefault() { + + final TomcatManagedConfiguration commonTomcatManagedConfiguration = new TomcatManagedConfiguration(); + + final String expectedJavaHome = System.getProperty(TomcatManagedConfiguration.JAVA_HOME_SYSTEM_PROPERTY); + + final String actualJavaHome = commonTomcatManagedConfiguration.getJavaHome(); + + assertEquals(expectedJavaHome, actualJavaHome); + } + + @Test + public void testGetJavaHomeForNonDefault() { + + final TomcatManagedConfiguration commonTomcatManagedConfiguration = new TomcatManagedConfiguration(); + + final String expectedJavaHome = "EXPECTED_JAVA_HOME"; + + commonTomcatManagedConfiguration.setJavaHome(expectedJavaHome); + + final String actualJavaHome = commonTomcatManagedConfiguration.getJavaHome(); + + assertEquals(expectedJavaHome, actualJavaHome); + } +} diff --git a/tomcat-managed-common/src/test/java/org/jboss/arquillian/container/tomcat/managed/TomcatManagedContainerTest.java b/tomcat-managed-common/src/test/java/org/jboss/arquillian/container/tomcat/managed/TomcatManagedContainerTest.java new file mode 100644 index 0000000..7e962ca --- /dev/null +++ b/tomcat-managed-common/src/test/java/org/jboss/arquillian/container/tomcat/managed/TomcatManagedContainerTest.java @@ -0,0 +1,55 @@ +package org.jboss.arquillian.container.tomcat.managed; + +import static org.junit.Assert.*; + +import java.io.File; + +import org.jboss.arquillian.container.spi.client.protocol.ProtocolDescription; +import org.jboss.arquillian.container.tomcat.Tomcat7ManagerCommandSpec; +import org.junit.Before; +import org.junit.Test; + +public class TomcatManagedContainerTest { + + private TomcatManagedContainer commonTomcatManagedContainer; + + @Before + public void setUp() { + + commonTomcatManagedContainer = + new TomcatManagedContainer(new ProtocolDescription("Servlet 5.0"), new Tomcat7ManagerCommandSpec()) { + + @Override + public ProtocolDescription getDefaultProtocol() { + + return null; + } + }; + } + + @Test + public void testGetJavaCommandForConfiguration() { + + final TomcatManagedConfiguration commonTomcatManagedConfiguration = new TomcatManagedConfiguration(); + + final String testJavaHome = File.separator + "test" + File.separator + "java" + File.separator + "home"; + + commonTomcatManagedConfiguration.setJavaHome(testJavaHome); + + commonTomcatManagedContainer.setup(commonTomcatManagedConfiguration); + + final String actualJavaCommand = commonTomcatManagedContainer.getJavaCommand(); + + final String expectedJavaCommand = testJavaHome + File.separator + "bin" + File.separator + "java"; + + assertEquals(expectedJavaCommand, actualJavaCommand); + } + + @Test(expected = IllegalStateException.class) + public void testGetJavaCommandForNoConfiguration() { + + // No .setup(commonTomcatManagedConfiguration) + + commonTomcatManagedContainer.getJavaCommand(); + } +} diff --git a/tomcat-managed-parent/pom.xml b/tomcat-managed-parent/pom.xml new file mode 100644 index 0000000..8928df8 --- /dev/null +++ b/tomcat-managed-parent/pom.xml @@ -0,0 +1,74 @@ + + + + 4.0.0 + + + org.jboss.arquillian.container + arquillian-tomcat-container-parent + 1.2.1-SNAPSHOT + ../tomcat-container-parent/pom.xml + + + arquillian-tomcat-managed-parent + pom + Arquillian Tomcat Managed Container Parent + + + + + + + org.jboss.arquillian.container + arquillian-tomcat-managed-common + ${project.version} + + + + + + org.jboss.arquillian.container + arquillian-tomcat-managed-common + ${project.version} + test-jar + test + + + + + + + + + org.codehaus.cargo + cargo-maven2-plugin + + + install-container + pre-integration-test + + configure + + + + + ${test.http.port} + ${test.ajp.port} + ${test.rmi.port} + + + + ${project.build.testOutputDirectory}/tomcat-users.xml + conf + + + + + + + + + + + +