SLING-9785 Provide additional configuration to influence the server
ready checking
diff --git a/README.md b/README.md
index fb4544b..8fc8e59 100644
--- a/README.md
+++ b/README.md
@@ -7,3 +7,38 @@
 This module is part of the [Apache Sling](https://sling.apache.org) project.
 
 Sling Server Setup utilities.
+
+
+### Related System Properties
+
+| Property Name  | Default  | Purpose |
+|---|:---:|---|
+| test.server.url |   | If the server is already running, this is the full address of your target server.  |
+| test.server.hostname | localhost | The hostname for the sling server that will be started  |
+| test.server.username  | admin  | The username to use to login for interacting with the OSGi Web Console  |
+| test.server.password  | admin  | The password of the user to use for interacting with the OSGi Web Console  |
+|  |  |  |
+| server.ready.timeout.seconds | 60 | The maximum amount of time in seconds to wait for the server to become ready  |
+| server.ready.timeout.initial.delay.seconds | 0 | The duration to wait in seconds before checking if the server is ready  |
+| server.ready.timeout.delay.seconds | 1 | The duration of the delay in seconds between attempts to check if the server is ready |
+| server.ready.quiet.period.seconds | 0 | The duration of a quiet period in seconds after the server has become ready and the tests begin running |
+| server.ready.path.* |   | Prefix for properties whose value describe how to check if the server is ready. <br/>The syntax of each value is one of: <table><thead><tr><th>Pattern</th><th>Description</th></tr></thead><tbody><tr><td>[relative_url]:[response_content_contains]</td><td>Load the page and check if the response contains the content string</td></tr><tr><td>[relative_url]:[response_content_pattern]:regexp</td><td>Load the page and check if the response contains the regex pattern</td></tr></tbody></table>   |
+| keepJarRunning | false  | Set to true if you want the server to remain running - you can then run tests against it from another VM. |
+|  |  |  |
+| additional.bundles.path |   | The value is a comma-separated list of additional bundles to install (or uninstall) |
+| additional.bundles.uninstall | false | <table><thead><tr><th>Value</th><th>Description</th></tr></thead><tbody><tr><td>true</td><td>uninstall the additional bundles</td></tr><tr><td>false</td><td>install the additional bundles</td></tr></tbody></table> |
+| sling.additional.bundle.* |   | Prefix for properties whose value describes additional bundles to install |
+| start.bundles.timeout.seconds | 30 | The maximum amount of tiem to wait for the additional bundles to start |
+| bundle.install.timeout.seconds | 10 | The maximum amount of tiem to wait for the additional bundles to install  |
+|  |  |  |
+| jar.executor.server.port | 8765 | The port number for the sling server that will be started |
+| jar.executor.jar.folder |  | The folder that contains the executable jar |
+| jar.executor.jar.name.regexp |  | The name of the executable jar file |
+| jar.executor.vm.options |  | Additional options to pass along to the jvm |
+| jar.executor.work.folder |  | The working directory for the executable jar |
+| jar.executor.jar.options |  | Additional options for the jar execute command line |
+| jar.executor.exit.timeout.seconds | 30 | The maximum time in seconds to wait for for the executor process to exit |
+| jar.executor.wait.on.shutdown | false | True to wait for the executor process to exit normally, false to not wait |
+| jar.executor.java.executable.path |   | The path to the java executable |
+| jar.executor.synchronous.exec |  | True to execute synchronous, false otherwise |
+| jar.executor.synchronous.exec.expected.result | 0 | The exit code expected from the executor |
diff --git a/src/main/java/org/apache/sling/testing/serversetup/instance/SlingTestBase.java b/src/main/java/org/apache/sling/testing/serversetup/instance/SlingTestBase.java
index a57369b..136edfd 100644
--- a/src/main/java/org/apache/sling/testing/serversetup/instance/SlingTestBase.java
+++ b/src/main/java/org/apache/sling/testing/serversetup/instance/SlingTestBase.java
@@ -51,6 +51,9 @@
     public static final String TEST_SERVER_USERNAME = "test.server.username";
     public static final String TEST_SERVER_PASSWORD = "test.server.password";
     public static final String SERVER_READY_TIMEOUT_PROP = "server.ready.timeout.seconds";
+    public static final String SERVER_READY_TIMEOUT_INITIAL_DELAY_PROP = "server.ready.timeout.initial.delay.seconds";
+    public static final String SERVER_READY_TIMEOUT_DELAY_PROP = "server.ready.timeout.delay.seconds";
+    public static final String SERVER_READY_QUIET_PERIOD_PROP = "server.ready.quiet.period.seconds";
     public static final String SERVER_READY_PROP_PREFIX = "server.ready.path";
     public static final String KEEP_JAR_RUNNING_PROP = "keepJarRunning";
     public static final String SERVER_HOSTNAME_PROP = "test.server.hostname";
@@ -172,6 +175,7 @@
             slingTestState.setStartupInfoProvided(true);
             waitForServerReady();
             installAdditionalBundles();
+            waitForQuietPeriod();
             blockIfRequested();
         } catch(Exception e) {
             log.error("Exception in maybeStartServer()", e);
@@ -179,6 +183,20 @@
         }
     }
 
+    /**
+     * Wait for the configured duration as a quite period to let the server settle down after
+     * doing the startup and install additional bundles work.
+     */
+    protected void waitForQuietPeriod() throws InterruptedException {
+        final String quietPeriodSecProp = systemProperties.getProperty(SERVER_READY_QUIET_PERIOD_PROP, "0");
+        final int quietPeriodSec = TimeoutsProvider.getInstance().getTimeout(Integer.valueOf(quietPeriodSecProp));
+        final int quietPeriodMs = quietPeriodSec * 1000;
+        if (quietPeriodMs > 0) {
+            log.info("Waiting {} seconds as a quiet period", quietPeriodSec);
+            Thread.sleep(quietPeriodMs);
+        }
+    }
+
     protected void installAdditionalBundles() {
         if (slingTestState.isInstallBundlesFailed()) {
             fail("Bundles could not be installed, cannot run tests");
@@ -277,9 +295,20 @@
         }
 
         // Timeout for readiness test
-        final String sec = systemProperties.getProperty(SERVER_READY_TIMEOUT_PROP);
-        final int timeoutSec = TimeoutsProvider.getInstance().getTimeout(sec == null ? 60 : Integer.valueOf(sec));
-        log.info("Will wait up to " + timeoutSec + " seconds for server to become ready");
+        TimeoutsProvider tp = TimeoutsProvider.getInstance();
+        final String sec = systemProperties.getProperty(SERVER_READY_TIMEOUT_PROP, "60");
+        final int timeoutSec = tp.getTimeout(Integer.valueOf(sec));
+
+        final String initialDelaySec = systemProperties.getProperty(SERVER_READY_TIMEOUT_INITIAL_DELAY_PROP, "0");
+        final int timeoutInitialDelaySec = tp.getTimeout(Integer.valueOf(initialDelaySec));
+        final int timeoutInitialDelayMs = timeoutInitialDelaySec * 1000;
+
+        final String delaySec = systemProperties.getProperty(SERVER_READY_TIMEOUT_DELAY_PROP, "1");
+        final int timeoutDelaySec = tp.getTimeout(Integer.valueOf(delaySec));
+        final int timeoutDelayMs = timeoutDelaySec * 1000;
+
+        log.info("Will wait up to {} seconds for server to become ready with a {} second initial delay and {} seconds between each check",
+                new Object[] {timeoutSec, timeoutInitialDelaySec, timeoutDelaySec});
         final long endTime = System.currentTimeMillis() + timeoutSec * 1000L;
 
         // Get the list of paths to test and expected content regexps
@@ -293,6 +322,11 @@
             }
         }
 
+        if (timeoutInitialDelayMs > 0) {
+            // wait for the initial deal duration
+            Thread.sleep(timeoutInitialDelayMs);
+        }
+
         // Consider the server ready if it responds to a GET on each of
         // our configured request paths with a 200 result and content
         // that contains the pattern that's optionally supplied with the
@@ -330,7 +364,7 @@
                 log.info("All {} paths return expected content, server ready", testPaths.size());
                 break;
             }
-            Thread.sleep(TimeoutsProvider.getInstance().getTimeout(1000L));
+            Thread.sleep(timeoutDelayMs);
         }
 
         if (!slingTestState.isServerReady()) {
diff --git a/src/main/java/org/apache/sling/testing/serversetup/instance/package-info.java b/src/main/java/org/apache/sling/testing/serversetup/instance/package-info.java
index 0b34ad5..e7fb459 100644
--- a/src/main/java/org/apache/sling/testing/serversetup/instance/package-info.java
+++ b/src/main/java/org/apache/sling/testing/serversetup/instance/package-info.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-@Version("1.1.0")
+@Version("1.2.0")
 package org.apache.sling.testing.serversetup.instance;
 
 import org.osgi.annotation.versioning.Version;