[java-idp-integration-tests] branch master updated: Add abstract server process in preparation for testing Tomcat.
Tom Zeller
tzeller at dragonacea.biz
Mon Jul 11 13:43:51 EDT 2016
This is an automated email from the git hooks/post-receive script.
tzeller pushed a commit to branch master
in repository java-idp-integration-tests.
View the commit online:
http://git.shibboleth.net/view/?p=java-idp-integration-tests.git;a=commit;h=380d431ab5ef6995144bdc8a6f50c4e1403996a0
The following commit(s) were added to refs/heads/master by this push:
new 380d431 Add abstract server process in preparation for testing Tomcat.
380d431 is described below
commit 380d431ab5ef6995144bdc8a6f50c4e1403996a0
Author: Tom Zeller <tzeller at dragonacea.biz>
AuthorDate: Mon Jul 11 12:43:21 2016 -0500
Add abstract server process in preparation for testing Tomcat.
Move non-Jetty specific code to an abstract class in order to make room
for a TomcatServerProcess.
---
...rverProcess.java => AbstractServerProcess.java} | 368 +++++++---------
.../shibboleth/idp/test/BaseIntegrationTest.java | 16 +-
.../shibboleth/idp/test/JettyServerProcess.java | 474 +--------------------
3 files changed, 172 insertions(+), 686 deletions(-)
diff --git a/src/test/java/net/shibboleth/idp/test/JettyServerProcess.java b/src/test/java/net/shibboleth/idp/test/AbstractServerProcess.java
similarity index 61%
copy from src/test/java/net/shibboleth/idp/test/JettyServerProcess.java
copy to src/test/java/net/shibboleth/idp/test/AbstractServerProcess.java
index 514d933..ce733de 100644
--- a/src/test/java/net/shibboleth/idp/test/JettyServerProcess.java
+++ b/src/test/java/net/shibboleth/idp/test/AbstractServerProcess.java
@@ -17,32 +17,16 @@
package net.shibboleth.idp.test;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FilenameFilter;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
-import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
-import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.httpclient.HttpClientBuilder;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
@@ -60,98 +44,75 @@ import org.springframework.context.Lifecycle;
import com.google.common.base.Stopwatch;
+import net.shibboleth.utilities.java.support.annotation.constraint.Live;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.httpclient.HttpClientBuilder;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
/**
- * Start Jetty server in a new {@link Process} via start.jar.
+ * Start IdP server in a new {@link Process}.
* <p>
* Waits for the IdP status page to be available.
*/
-public class JettyServerProcess extends AbstractInitializableComponent implements Lifecycle {
+public class AbstractServerProcess extends AbstractInitializableComponent implements Lifecycle {
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(JettyServerProcess.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AbstractServerProcess.class);
- /** Path to jetty.base. */
- @Nonnull private Path pathToJettyBase;
+ /** Path to Servlet container base. */
+ @Nonnull private Path pathToContainerBase;
- /** Path to jetty.home. */
- @Nonnull private Path pathToJettyHome;
+ /** Path to Servlet container home. */
+ @Nonnull private Path pathToContainerHome;
/** URL of the IdP status page. */
@NonnullAfterInit private String statusPageURL;
- /** The string indicating that the Jetty server has finished starting. */
- @Nonnull public final String startedRegex = "Server:main: Started \\@";
-
- /** Process builder used to create the Jetty server process. */
+ /** Process builder used to create the server process. */
@NonnullAfterInit private ProcessBuilder processBuilder;
- /** Jetty server process. */
+ /** Server process. */
@Nullable private Process process;
- /** Current jetty log */
- @Nullable private File logFile;
-
- /** Commands used to start the Jetty server process. */
+ /** Commands used to start the server process. */
@NonnullAfterInit private List<String> commands;
- /** Whether the Jetty server process is running. */
- @Nonnull private boolean isRunning = false;
-
- /** Additional commands used to start the Jetty server process. */
+ /** Additional commands used to start the server process. */
@Nullable private List<String> additionalCommands;
- /**
- * Set path to jetty.base.
- *
- * @param jettyBasePath path to jetty.base
- * @return this Jetty server
- */
- @Nonnull
- public JettyServerProcess setJettyBasePath(@Nonnull final Path jettyBasePath) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- pathToJettyBase = Constraint.isNotNull(jettyBasePath, "Path to jetty.base cannot be null");
- return this;
- }
-
- /**
- * Set path to jetty.home.
- *
- * @param jettyHomePath path to jetty.home
- * @return this Jetty server
- */
- @Nonnull
- public JettyServerProcess setJettyHomePath(@Nonnull final Path jettyHomePath) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- pathToJettyHome = Constraint.isNotNull(jettyHomePath, "Path to jetty.home cannot be null");
- return this;
- }
+ /** Whether the server process is running. */
+ @Nonnull private boolean isRunning = false;
/**
- * Set additional commands to start the Jetty server process.
+ * Build the commands used to create the server process. Appends additional commands.
*
- * @param commands additional commands
- * @return this Jetty server
+ * @return commands used to create the server process
*/
- @Nonnull
- public JettyServerProcess setAdditionalCommands(@Nullable final List<String> commands) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- if (commands != null) {
- additionalCommands = commands;
+ public List<String> buildCommands() {
+ final List<String> commands = getCommands();
+ final List<String> additionalCommands = getAdditionalCommands();
+ if (additionalCommands != null && !additionalCommands.isEmpty()) {
+ log.debug("Additional commands '{}'", additionalCommands);
+ commands.addAll(additionalCommands);
}
- return this;
+ return commands;
}
/**
- * Set status page URL.
+ * Build the process builder used to create the server process.
*
- * @param URL status page URL
- * @return this Jetty server
+ * @return the process builder used to create the server process
*/
- @Nonnull
- public JettyServerProcess setStatusPageURL(@Nonnull @NotEmpty final String URL) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- statusPageURL = Constraint.isNotNull(StringSupport.trimOrNull(URL), "Status page URL cannot be null nor empty");
- return this;
+ public ProcessBuilder buildProcessBuilder() {
+ final ProcessBuilder builder = new ProcessBuilder();
+ builder.redirectErrorStream(true);
+ builder.directory(pathToContainerBase.toAbsolutePath().toFile());
+ return builder;
}
/** {@inheritDoc} */
@@ -159,30 +120,18 @@ public class JettyServerProcess extends AbstractInitializableComponent implement
protected void doInitialize() throws ComponentInitializationException {
super.doInitialize();
- if (pathToJettyBase == null) {
- throw new ComponentInitializationException("Path to jetty.base cannot be null");
+ if (pathToContainerBase == null) {
+ throw new ComponentInitializationException("Path to Servlet container base cannot be null");
}
- if (pathToJettyHome == null) {
- throw new ComponentInitializationException("Path to jetty.home cannot be null");
+ if (pathToContainerHome == null) {
+ throw new ComponentInitializationException("Path to Servlet container home cannot be null");
}
if (statusPageURL == null) {
throw new ComponentInitializationException("Status page URL cannot be null");
}
- // Throw exception if jetty.base does not exist.
- if (!pathToJettyBase.toAbsolutePath().toFile().exists()) {
- log.error("Path to jetty.base '{}' not found", pathToJettyBase);
- throw new ComponentInitializationException("Path to jetty.base '" + pathToJettyBase + "' not found.");
- }
-
- // Throw exception if jetty.home does not exist.
- if (!pathToJettyHome.toAbsolutePath().toFile().exists()) {
- log.error("Path to jetty.home '{}' not found", pathToJettyHome);
- throw new ComponentInitializationException("Path to jetty.home '" + pathToJettyHome + "' not found.");
- }
-
// Throw exception if idp.home is not defined.
final String idpHome = System.getProperty("idp.home");
if (idpHome == null) {
@@ -196,89 +145,132 @@ public class JettyServerProcess extends AbstractInitializableComponent implement
throw new ComponentInitializationException("Path to idp.home '" + idpHome + "' not found.");
}
- // Throw exception if path to java does not exist.
- final Path pathToJava = Paths.get(System.getProperty("java.home"), "bin", "java");
-
- // Setup commands to start the Jetty process.
commands = new ArrayList<>();
- commands.add(pathToJava.toAbsolutePath().toString());
- commands.add("-Didp.home=" + idpHome);
- commands.add("-jar");
- commands.add(pathToJettyHome.toAbsolutePath().toString() + "/start.jar");
- if (additionalCommands != null && !additionalCommands.isEmpty()) {
- log.debug("Additional commands '{}'", additionalCommands);
- commands.addAll(additionalCommands);
- }
+ processBuilder = buildProcessBuilder();
+ }
- // Create the process builder.
- processBuilder = new ProcessBuilder(commands);
- processBuilder.redirectErrorStream(true);
- processBuilder.directory(pathToJettyBase.toAbsolutePath().toFile());
+ /**
+ * Get additional commands used to create the server process. These commands are appended to those returned by
+ * {@link #getCommands()},
+ *
+ * @return additional commands used to create the server process
+ */
+ @Nullable
+ @Live
+ public List<String> getAdditionalCommands() {
+ return additionalCommands;
+ }
- log.debug("Will start Jetty using command '{}'", processBuilder.command());
+ /**
+ * Get the commands used to create the server process.
+ *
+ * @return commands used to create the server process
+ */
+ @NonnullAfterInit
+ @Live
+ public List<String> getCommands() {
+ return commands;
}
- /** {@inheritDoc} */
- @Override
- public void start() {
- try {
- final Stopwatch stopwatch = Stopwatch.createStarted();
- log.debug("Starting the Jetty server process");
- process = processBuilder.start();
- // waitForJettyLogFile();
- waitForStatusPage();
- stopwatch.stop();
- log.debug("Jetty server process started in {}ms", stopwatch.elapsed(TimeUnit.MILLISECONDS));
- } catch (Exception e) {
- log.error("Unable to start Jetty server process", e);
- throw new RuntimeException("Unable to start Jetty server process", e);
- }
+ /**
+ * Get the process builder used to create the server process.
+ *
+ * @return the process builder
+ */
+ @NonnullAfterInit
+ public ProcessBuilder getProcessBuilder() {
+ return processBuilder;
}
/**
- * Simple method to wait for the Jetty server process to start.
+ * Get path to Servlet container base.
*
- * Wait until the {@link #startedRegex} is found in the Jetty server process output.
+ * @return path to Servlet container base
+ */
+ public Path getServletContainerBasePath() {
+ return pathToContainerBase;
+ }
+
+ /**
+ * Get path to Servlet container home.
*
- * This method will block indefinitely if the {@link #startedRegex} is not found.
+ * @return path to Servlet container home
+ */
+ public Path getServletContainerHomePath() {
+ return pathToContainerHome;
+ }
+
+ /**
+ * Set additional commands to start the server process.
*
- * @throws IOException if an I/O error occurs reading the Jetty server process output
+ * @param commands additional commands
+ * @return this server
*/
- // TODO timeout ?
- // TODO manually set log level to at least INFO ?
- public void waitForJettyLogFile() throws IOException {
- log.debug("Waiting for Jetty server to start ...");
+ @Nonnull
+ public AbstractServerProcess setAdditionalCommands(@Nullable final List<String> commands) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ if (commands != null) {
+ additionalCommands = commands;
+ }
+ return this;
+ }
- final File logsDir = pathToJettyBase.resolve("logs").toFile();
- File[] files = null;
- int loopCount = 0;
+ /**
+ * Set path to Servlet container base.
+ *
+ * @param containerBasePath path to Servlet container base
+ * @return this server
+ */
+ @Nonnull
+ public AbstractServerProcess setServletContainerBasePath(@Nonnull final Path containerBasePath) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ pathToContainerBase = Constraint.isNotNull(containerBasePath, "Path to Servlet container base cannot be null");
+ return this;
+ }
- while (true) {
- files = logsDir.listFiles(new FilenameFilter() {
+ /**
+ * Set path to Servlet container home.
+ *
+ * @param containerHomePath path to Servlet container home
+ * @return this server
+ */
+ @Nonnull
+ public AbstractServerProcess setServletContainerHomePath(@Nonnull final Path containerHomePath) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ pathToContainerHome = Constraint.isNotNull(containerHomePath, "Path to Servlet container home cannot be null");
+ return this;
+ }
- @Override
- public boolean accept(File arg0, String arg1) {
- return arg1.endsWith("stderrout.log");
- }
- });
+ /**
+ * Set status page URL.
+ *
+ * @param URL status page URL
+ * @return this server
+ */
+ @Nonnull
+ public AbstractServerProcess setStatusPageURL(@Nonnull @NotEmpty final String URL) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ statusPageURL = Constraint.isNotNull(StringSupport.trimOrNull(URL), "Status page URL cannot be null nor empty");
+ return this;
+ }
- if (null != files && files.length > 0 && readFile(files[0])) {
- break;
- }
- if (loopCount++ > 120) {
- throw new RuntimeException("No log after 2 minutes");
- }
- log.trace("Jetty Log not there yet... waiting 500ms");
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
+ /** {@inheritDoc} */
+ @Override
+ public void start() {
+ try {
+ processBuilder.command(buildCommands());
+ log.debug("Will start server using command '{}'", processBuilder.command());
+ final Stopwatch stopwatch = Stopwatch.createStarted();
+ log.debug("Starting the server process");
+ process = processBuilder.start();
+ waitForStatusPage();
+ stopwatch.stop();
+ log.debug("Server process started in {}ms", stopwatch.elapsed(TimeUnit.MILLISECONDS));
+ } catch (Exception e) {
+ log.error("Unable to start server process", e);
+ throw new RuntimeException("Unable to start server process", e);
}
- logFile = files[0];
- isRunning = true;
-
}
/**
@@ -288,13 +280,13 @@ public class JettyServerProcess extends AbstractInitializableComponent implement
* @throws Exception if an error occurs
*/
public void waitForStatusPage() throws Exception {
- log.debug("Waiting for Jetty server to start ...");
+ log.debug("Waiting for server to start ...");
final String statusPageText = getStatusPageText(120, 500);
if (!statusPageText.startsWith(StatusTest.STARTS_WITH)) {
- log.error("Unable to determine if Jetty server has started.");
- throw new RuntimeException("Unable to determine if Jetty server has started.");
+ log.error("Unable to determine if server has started.");
+ throw new RuntimeException("Unable to determine if server has started.");
}
}
@@ -425,50 +417,6 @@ public class JettyServerProcess extends AbstractInitializableComponent implement
}
}
- /**
- * Does the file have data which matches the pattern?
- *
- * @param file The file to open
- * @return whether the pattern has been matched
- * @throws IOException when badness occurrs.
- */
- private boolean readFile(File file) throws IOException {
- BufferedReader reader = null;
- InputStreamReader inputReader = null;
- InputStream inputStream = null;
-
- try {
- inputStream = new FileInputStream(file);
- inputReader = new InputStreamReader(inputStream);
- reader = new BufferedReader(inputReader);
- log.trace("Opened Jetty log {}", file.getAbsolutePath());
-
- final Pattern pattern = Pattern.compile(startedRegex);
- String line = "";
- while ((line = reader.readLine()) != null) {
- log.trace("Jetty log matches '{}' line '{}", pattern.matcher(line).find(), line);
- if (pattern.matcher(line).find()) {
- return true;
- }
- }
- reader.close();
- } catch (IOException ex) {
- log.error("Could not open log", ex);
- throw new RuntimeException("Could not open log", ex);
- } finally {
- if (null != reader) {
- reader.close();
- }
- if (null != inputReader) {
- inputReader.close();
- }
- if (null != inputStream) {
- inputStream.close();
- }
- }
- return false;
- }
-
/** {@inheritDoc} */
@Override
public void stop() {
@@ -480,15 +428,9 @@ public class JettyServerProcess extends AbstractInitializableComponent implement
process.waitFor();
log.trace("Done waiting");
} catch (InterruptedException e) {
- throw new RuntimeException("Unable to wait for Jetty server process", e);
+ throw new RuntimeException("Unable to wait for server process", e);
}
}
- if (null != logFile) {
- log.trace("Deleteing logfile {}", logFile.getAbsolutePath());
- logFile.delete();
- log.trace("Deleted logfile {}", logFile.exists());
- logFile = null;
- }
}
/** {@inheritDoc} */
diff --git a/src/test/java/net/shibboleth/idp/test/BaseIntegrationTest.java b/src/test/java/net/shibboleth/idp/test/BaseIntegrationTest.java
index e474c45..5d2713c 100644
--- a/src/test/java/net/shibboleth/idp/test/BaseIntegrationTest.java
+++ b/src/test/java/net/shibboleth/idp/test/BaseIntegrationTest.java
@@ -203,10 +203,10 @@ public abstract class BaseIntegrationTest
/** IdP XML security manager value before and after this test. */
@NonnullAfterInit protected String defaultIdpXMLSecurityManager;
- /** Jetty server process. */
- @NonnullAfterInit protected JettyServerProcess server;
+ /** Server process. */
+ @NonnullAfterInit protected AbstractServerProcess server;
- /** Additional commands used to start the Jetty server process. */
+ /** Additional commands used to start the server process. */
@NonnullAfterInit protected List<String> serverCommands = new ArrayList<>();
/** Non-secure address that the web server listens on. Defaults to "localhost". */
@@ -527,7 +527,7 @@ public abstract class BaseIntegrationTest
logUnencryptedSAML();
- // Add logging when starting Jetty.
+ // Add logging when starting the server.
serverCommands.add("-Dlogback.configurationFile=" + pathToIdPHome.resolve(pathToLogbackXML).toAbsolutePath());
}
@@ -662,8 +662,8 @@ public abstract class BaseIntegrationTest
*/
public void startJettyServer() throws ComponentInitializationException {
server = new JettyServerProcess();
- server.setJettyBasePath(pathToJettyBase);
- server.setJettyHomePath(pathToJettyHome);
+ server.setServletContainerBasePath(pathToJettyBase);
+ server.setServletContainerHomePath(pathToJettyHome);
server.setAdditionalCommands(serverCommands);
server.setStatusPageURL(getBaseURL() + StatusTest.statusPath);
server.initialize();
@@ -671,10 +671,10 @@ public abstract class BaseIntegrationTest
}
/**
- * Stop the Jetty server.
+ * Stop the server.
*/
@AfterMethod
- public void stopJettyServer() {
+ public void stopServer() {
if (server != null) {
server.stop();
}
diff --git a/src/test/java/net/shibboleth/idp/test/JettyServerProcess.java b/src/test/java/net/shibboleth/idp/test/JettyServerProcess.java
index 514d933..c88a986 100644
--- a/src/test/java/net/shibboleth/idp/test/JettyServerProcess.java
+++ b/src/test/java/net/shibboleth/idp/test/JettyServerProcess.java
@@ -17,484 +17,28 @@
package net.shibboleth.idp.test;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Pattern;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
-import net.shibboleth.utilities.java.support.component.ComponentSupport;
-import net.shibboleth.utilities.java.support.httpclient.HttpClientBuilder;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpStatus;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.HttpRequestRetryHandler;
-import org.apache.http.client.ServiceUnavailableRetryStrategy;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.protocol.HttpContext;
-import org.apache.http.util.EntityUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.context.Lifecycle;
-
-import com.google.common.base.Stopwatch;
-
-/**
- * Start Jetty server in a new {@link Process} via start.jar.
- * <p>
- * Waits for the IdP status page to be available.
- */
-public class JettyServerProcess extends AbstractInitializableComponent implements Lifecycle {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(JettyServerProcess.class);
-
- /** Path to jetty.base. */
- @Nonnull private Path pathToJettyBase;
-
- /** Path to jetty.home. */
- @Nonnull private Path pathToJettyHome;
-
- /** URL of the IdP status page. */
- @NonnullAfterInit private String statusPageURL;
-
- /** The string indicating that the Jetty server has finished starting. */
- @Nonnull public final String startedRegex = "Server:main: Started \\@";
-
- /** Process builder used to create the Jetty server process. */
- @NonnullAfterInit private ProcessBuilder processBuilder;
- /** Jetty server process. */
- @Nullable private Process process;
-
- /** Current jetty log */
- @Nullable private File logFile;
-
- /** Commands used to start the Jetty server process. */
- @NonnullAfterInit private List<String> commands;
-
- /** Whether the Jetty server process is running. */
- @Nonnull private boolean isRunning = false;
-
- /** Additional commands used to start the Jetty server process. */
- @Nullable private List<String> additionalCommands;
-
- /**
- * Set path to jetty.base.
- *
- * @param jettyBasePath path to jetty.base
- * @return this Jetty server
- */
- @Nonnull
- public JettyServerProcess setJettyBasePath(@Nonnull final Path jettyBasePath) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- pathToJettyBase = Constraint.isNotNull(jettyBasePath, "Path to jetty.base cannot be null");
- return this;
- }
-
- /**
- * Set path to jetty.home.
- *
- * @param jettyHomePath path to jetty.home
- * @return this Jetty server
- */
- @Nonnull
- public JettyServerProcess setJettyHomePath(@Nonnull final Path jettyHomePath) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- pathToJettyHome = Constraint.isNotNull(jettyHomePath, "Path to jetty.home cannot be null");
- return this;
- }
-
- /**
- * Set additional commands to start the Jetty server process.
- *
- * @param commands additional commands
- * @return this Jetty server
- */
- @Nonnull
- public JettyServerProcess setAdditionalCommands(@Nullable final List<String> commands) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- if (commands != null) {
- additionalCommands = commands;
- }
- return this;
- }
-
- /**
- * Set status page URL.
- *
- * @param URL status page URL
- * @return this Jetty server
- */
- @Nonnull
- public JettyServerProcess setStatusPageURL(@Nonnull @NotEmpty final String URL) {
- ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
- statusPageURL = Constraint.isNotNull(StringSupport.trimOrNull(URL), "Status page URL cannot be null nor empty");
- return this;
- }
+/** Start Jetty via start.jar. */
+public class JettyServerProcess extends AbstractServerProcess {
/** {@inheritDoc} */
@Override
protected void doInitialize() throws ComponentInitializationException {
super.doInitialize();
- if (pathToJettyBase == null) {
- throw new ComponentInitializationException("Path to jetty.base cannot be null");
- }
-
- if (pathToJettyHome == null) {
- throw new ComponentInitializationException("Path to jetty.home cannot be null");
- }
-
- if (statusPageURL == null) {
- throw new ComponentInitializationException("Status page URL cannot be null");
- }
-
- // Throw exception if jetty.base does not exist.
- if (!pathToJettyBase.toAbsolutePath().toFile().exists()) {
- log.error("Path to jetty.base '{}' not found", pathToJettyBase);
- throw new ComponentInitializationException("Path to jetty.base '" + pathToJettyBase + "' not found.");
- }
+ // Add JETTY_BASE to environment
+ getProcessBuilder().environment().put("JETTY_BASE", getServletContainerBasePath().toAbsolutePath().toString());
- // Throw exception if jetty.home does not exist.
- if (!pathToJettyHome.toAbsolutePath().toFile().exists()) {
- log.error("Path to jetty.home '{}' not found", pathToJettyHome);
- throw new ComponentInitializationException("Path to jetty.home '" + pathToJettyHome + "' not found.");
- }
-
- // Throw exception if idp.home is not defined.
- final String idpHome = System.getProperty("idp.home");
- if (idpHome == null) {
- log.error("System property 'idp.home' is not defined.");
- throw new ComponentInitializationException("System property 'idp.home' is not defined.");
- }
-
- // Throw exception if path to idp.home does not exist.
- if (!Paths.get(idpHome).toAbsolutePath().toFile().exists()) {
- log.error("Path to idp.home '{}' not found", idpHome);
- throw new ComponentInitializationException("Path to idp.home '" + idpHome + "' not found.");
- }
-
- // Throw exception if path to java does not exist.
+ // Start Jetty via start.jar
final Path pathToJava = Paths.get(System.getProperty("java.home"), "bin", "java");
-
- // Setup commands to start the Jetty process.
- commands = new ArrayList<>();
- commands.add(pathToJava.toAbsolutePath().toString());
- commands.add("-Didp.home=" + idpHome);
- commands.add("-jar");
- commands.add(pathToJettyHome.toAbsolutePath().toString() + "/start.jar");
-
- if (additionalCommands != null && !additionalCommands.isEmpty()) {
- log.debug("Additional commands '{}'", additionalCommands);
- commands.addAll(additionalCommands);
- }
-
- // Create the process builder.
- processBuilder = new ProcessBuilder(commands);
- processBuilder.redirectErrorStream(true);
- processBuilder.directory(pathToJettyBase.toAbsolutePath().toFile());
-
- log.debug("Will start Jetty using command '{}'", processBuilder.command());
- }
-
- /** {@inheritDoc} */
- @Override
- public void start() {
- try {
- final Stopwatch stopwatch = Stopwatch.createStarted();
- log.debug("Starting the Jetty server process");
- process = processBuilder.start();
- // waitForJettyLogFile();
- waitForStatusPage();
- stopwatch.stop();
- log.debug("Jetty server process started in {}ms", stopwatch.elapsed(TimeUnit.MILLISECONDS));
- } catch (Exception e) {
- log.error("Unable to start Jetty server process", e);
- throw new RuntimeException("Unable to start Jetty server process", e);
- }
- }
-
- /**
- * Simple method to wait for the Jetty server process to start.
- *
- * Wait until the {@link #startedRegex} is found in the Jetty server process output.
- *
- * This method will block indefinitely if the {@link #startedRegex} is not found.
- *
- * @throws IOException if an I/O error occurs reading the Jetty server process output
- */
- // TODO timeout ?
- // TODO manually set log level to at least INFO ?
- public void waitForJettyLogFile() throws IOException {
- log.debug("Waiting for Jetty server to start ...");
-
- final File logsDir = pathToJettyBase.resolve("logs").toFile();
- File[] files = null;
- int loopCount = 0;
-
- while (true) {
- files = logsDir.listFiles(new FilenameFilter() {
-
- @Override
- public boolean accept(File arg0, String arg1) {
- return arg1.endsWith("stderrout.log");
- }
- });
-
- if (null != files && files.length > 0 && readFile(files[0])) {
- break;
- }
- if (loopCount++ > 120) {
- throw new RuntimeException("No log after 2 minutes");
- }
- log.trace("Jetty Log not there yet... waiting 500ms");
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- logFile = files[0];
- isRunning = true;
-
- }
-
- /**
- * Wait up to 60 seconds for the IdP status page, trying every half-second.
- *
- * @throws RuntimeException if the actual status page text is not expected
- * @throws Exception if an error occurs
- */
- public void waitForStatusPage() throws Exception {
- log.debug("Waiting for Jetty server to start ...");
-
- final String statusPageText = getStatusPageText(120, 500);
-
- if (!statusPageText.startsWith(StatusTest.STARTS_WITH)) {
- log.error("Unable to determine if Jetty server has started.");
- throw new RuntimeException("Unable to determine if Jetty server has started.");
- }
- }
-
- /**
- * Get the text of the IdP status page.
- *
- * @param retries maximum number of times to retry
- * @param millis length of time to sleep in milliseconds between retry attempts
- * @return the text of the IdP status page or <code>null</code>
- * @throws Exception if an error occurs
- */
- @Nullable
- public String getStatusPageText(@Nullable final int retries, @Nonnull final int millis) throws Exception {
-
- final HttpClientBuilder builder = new HttpClientBuilder();
- builder.setHttpRequestRetryHandler(new FiniteWaitHttpRequestRetryHandler(retries / 2, millis));
- builder.setServiceUnavailableRetryHandler(new FiniteWaitServiceUnavailableRetryStrategy(retries / 2, millis));
- builder.setConnectionCloseAfterResponse(false);
- builder.setConnectionDisregardTLSCertificate(true);
- final HttpClient httpClient = builder.buildClient();
-
- final HttpGet httpget = new HttpGet(statusPageURL);
- final HttpResponse response = httpClient.execute(httpget);
- log.trace("Status page response '{}'", response);
-
- try {
- final HttpEntity entity = response.getEntity();
- if (entity != null) {
- long len = entity.getContentLength();
- if (len != -1 && len < 2048) {
- final String statusPageText = EntityUtils.toString(entity);
- log.trace("Status page text '{}'", statusPageText);
- return statusPageText;
- }
- }
- } finally {
- if (response instanceof CloseableHttpResponse) {
- ((CloseableHttpResponse) response).close();
- }
- if (httpClient instanceof CloseableHttpClient) {
- ((CloseableHttpClient) httpClient).close();
- }
- }
-
- return null;
- }
-
- /**
- * A {@link HttpRequestRetryHandler} which retries requests until a maximum number of attempts has been made and
- * which sleeps between retry attempts.
- */
- public class FiniteWaitHttpRequestRetryHandler implements HttpRequestRetryHandler {
-
- /** Maximum number of retry attempts. */
- private final int maxRetries;
-
- /** Length of time to sleep in milliseconds between retry attempts. */
- private final int sleepMillis;
-
- /**
- * Constructor.
- *
- * @param retries maximum number of times to retry
- * @param millis length of time to sleep in milliseconds between retry attempts
- */
- public FiniteWaitHttpRequestRetryHandler(@Nullable final int retries, @Nonnull final int millis) {
- maxRetries = retries;
- sleepMillis = millis;
- }
-
- /** {@inheritDoc} */
- public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
- log.trace("Request retry handler exception msg '{}'", exception.getMessage());
- log.trace("Request retry handler execution count '{}'", executionCount);
-
- if (sleepMillis > 0) {
- try {
- Thread.sleep(sleepMillis);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-
- if (executionCount <= maxRetries) {
- return true;
- }
-
- return false;
- }
- }
-
- /**
- * A {@link ServiceUnavailableRetryStrategy} which retries requests until a maximum number of attempts has been made
- * and which sleeps between retry attempts. This strategy retries response status codes of
- * {@link HttpStatus#SC_SERVICE_UNAVAILABLE} and {@link HttpStatus#SC_NOT_FOUND}.
- */
- public class FiniteWaitServiceUnavailableRetryStrategy implements ServiceUnavailableRetryStrategy {
-
- /** Maximum number of retry attempts. */
- private final int maxRetries;
-
- /** Length of time to sleep in milliseconds between retry attempts. */
- private final int sleepMillis;
-
- /**
- * Constructor.
- *
- * @param retries maximum number of times to retry
- * @param millis length of time to sleep in milliseconds between retry attempts
- */
- public FiniteWaitServiceUnavailableRetryStrategy(int retries, int retryInterval) {
- maxRetries = retries;
- sleepMillis = retryInterval;
- }
-
- @Override
- public boolean retryRequest(final HttpResponse response, final int executionCount, final HttpContext context) {
- log.trace("Service unavailable retry strategy response '{}'", response);
- log.trace("Service unavailable retry strategy execution count '{}'", executionCount);
- return executionCount <= maxRetries
- && (response.getStatusLine().getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE
- || response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_FOUND);
- }
-
- /** {@inheritDoc} */
- public long getRetryInterval() {
- return sleepMillis;
- }
- }
-
- /**
- * Does the file have data which matches the pattern?
- *
- * @param file The file to open
- * @return whether the pattern has been matched
- * @throws IOException when badness occurrs.
- */
- private boolean readFile(File file) throws IOException {
- BufferedReader reader = null;
- InputStreamReader inputReader = null;
- InputStream inputStream = null;
-
- try {
- inputStream = new FileInputStream(file);
- inputReader = new InputStreamReader(inputStream);
- reader = new BufferedReader(inputReader);
- log.trace("Opened Jetty log {}", file.getAbsolutePath());
-
- final Pattern pattern = Pattern.compile(startedRegex);
- String line = "";
- while ((line = reader.readLine()) != null) {
- log.trace("Jetty log matches '{}' line '{}", pattern.matcher(line).find(), line);
- if (pattern.matcher(line).find()) {
- return true;
- }
- }
- reader.close();
- } catch (IOException ex) {
- log.error("Could not open log", ex);
- throw new RuntimeException("Could not open log", ex);
- } finally {
- if (null != reader) {
- reader.close();
- }
- if (null != inputReader) {
- inputReader.close();
- }
- if (null != inputStream) {
- inputStream.close();
- }
- }
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public void stop() {
- if (process != null) {
- log.trace("Stopping process");
- process.destroy();
- try {
- log.trace("Waiting for process to exit");
- process.waitFor();
- log.trace("Done waiting");
- } catch (InterruptedException e) {
- throw new RuntimeException("Unable to wait for Jetty server process", e);
- }
- }
- if (null != logFile) {
- log.trace("Deleteing logfile {}", logFile.getAbsolutePath());
- logFile.delete();
- log.trace("Deleted logfile {}", logFile.exists());
- logFile = null;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean isRunning() {
- return isRunning;
+ getCommands().add(pathToJava.toAbsolutePath().toString());
+ getCommands().add("-Didp.home=" + System.getProperty("idp.home"));
+ getCommands().add("-jar");
+ getCommands().add(getServletContainerHomePath().toAbsolutePath().toString() + "/start.jar");
}
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list