[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