Some cleanup and documentation update for the Sling Feature Starter and its Maven Plugin
diff --git a/sling-org-apache-sling-feature-starter/Readme.md b/sling-org-apache-sling-feature-starter/Readme.md
index cf65ebd..2fc61a3 100644
--- a/sling-org-apache-sling-feature-starter/Readme.md
+++ b/sling-org-apache-sling-feature-starter/Readme.md
@@ -2,22 +2,26 @@
 
 This project is the Feature Model based version of the **sling-org-apache-sling-starter**
 module and creates an executable JAR file for now.
-It is also a test case for the Slingstart Feature Maven Plugin.
+It is also a test case for the Slingstart Feature Maven Plugin as it uses it
+to launch a Launchpad Ready Rule and Smoke tests.
 
 ## Build
 
-This plugin depends on the **Sling Start Maven Plugin** (also in the Sling
-Whiteboard) which is for now extracted in its own profile **launch**:
+This plugin depends on the **Sling Start Feature Maven Plugin** (also in the Sling
+Whiteboard) which is then used to run the IT tests:
 
 1. Go to **sling-slingstart-feature-maven-plugin** module in Sling Whiteboard
 2. Build with: `mvn clean install`
 3. Go back to **sling-org-apache-sling-feature-starter**
-4. Build and Launch it with: `mvn clean install -P launch`
-5. Sling will come up and is accessible on the temporary port but the build
-will not end
+4. Build and Launch it with: `mvn clean install`
+5. Sling will come up and run the IT tests and then shut down. Sling can be
+   kept running after the end of the IT tests by providing the property
+   **block.sling.at.the.end** with the value **true**
 
-## Issues
+## Usage
 
-This module must be able to launch Sling in a demon (background) thread
-so that the starter can exit. The question is if that is added here or to
-the Feature Launcher module.
+After the resulting jar file **org.apache.sling.feature.starter-<version>.jar**
+can be executed with:
+```
+java -jar org.apache.sling.feature.starter-<version>.jar ...
+```
diff --git a/sling-org-apache-sling-feature-starter/pom.xml b/sling-org-apache-sling-feature-starter/pom.xml
index 7968c93..1119bad 100644
--- a/sling-org-apache-sling-feature-starter/pom.xml
+++ b/sling-org-apache-sling-feature-starter/pom.xml
@@ -28,6 +28,13 @@
         An Executable JAR file launcher a Feature Launcher System
     </description>
 
+    <!--    <scm>-->
+    <!--        <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-starter.git</connection>-->
+    <!--        <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-starter.git</developerConnection>-->
+    <!--        <url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-feature-starter.git</url>-->
+    <!--        <tag>HEAD</tag>-->
+    <!--    </scm>-->
+
     <properties>
         <sling.java.version>8</sling.java.version>
         <picocli.version>3.6.0</picocli.version>
@@ -36,14 +43,12 @@
         <org.apache.sling.feature.launcher.version>1.1.0</org.apache.sling.feature.launcher.version>
         <org.apache.sling.feature.io.version>1.1.0</org.apache.sling.feature.io.version>
         <org.apache.felix.converter.version>1.0.8</org.apache.felix.converter.version>
-    </properties>
 
-<!--    <scm>-->
-<!--        <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-starter.git</connection>-->
-<!--        <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-starter.git</developerConnection>-->
-<!--        <url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-feature-starter.git</url>-->
-<!--        <tag>HEAD</tag>-->
-<!--    </scm>-->
+        <sling.java.version>8</sling.java.version>
+        <IT.expected.bundles.count>126</IT.expected.bundles.count>
+
+        <block.sling.at.the.end>false</block.sling.at.the.end>
+    </properties>
 
     <build>
         <plugins>
@@ -59,6 +64,20 @@
                 </executions>
             </plugin>
             <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <configuration>
+                    <filesets>
+                        <fileset>
+                            <directory>${basedir}</directory>
+                            <includes>
+                                <include>sling/**</include>
+                                <include>coverage.ec</include>
+                            </includes>
+                        </fileset>
+                    </filesets>
+                </configuration>
+            </plugin>
+            <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-dependency-plugin</artifactId>
                 <executions>
@@ -112,7 +131,95 @@
                     </excludes>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>reserve-network-port</id>
+                        <goals>
+                            <!-- pre-integration-test is too late -->
+                            <goal>reserve-network-port</goal>
+                        </goals>
+                        <phase>process-resources</phase>
+                        <configuration>
+                            <portNames>
+                                <portName>http.port</portName>
+                                <portName>sling.control.port</portName>
+                            </portNames>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.sling</groupId>
+                <artifactId>slingstart-feature-maven-plugin</artifactId>
+                <version>0.0.1-SNAPSHOT</version>
+                <extensions>true</extensions>
+                <executions>
+                    <execution>
+                        <id>start-container-before-IT</id>
+                        <goals>
+                            <goal>start</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>stop-container-after-IT</id>
+                        <goals>
+                            <goal>stop</goal>
+                        </goals>
+                        <configuration>
+                            <!-- Let the Test Server run to manually verify the setup. TODO: remove later -->
+                            <shouldBlockUntilKeyIsPressed>${block.sling.at.the.end}</shouldBlockUntilKeyIsPressed>
+                        </configuration>
+                    </execution>
+                </executions>
+                <configuration>
+                    <launchpadJar>${project.build.directory}/${project.artifactId}-${project.version}.jar</launchpadJar>
+                    <parallelExecution>false</parallelExecution>
+                    <servers>
+                        <server>
+                            <port>${http.port}</port>
+                            <controlPort>${sling.control.port}</controlPort>
+                            <debug>true</debug>
+                        </server>
+                    </servers>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <systemPropertyVariables>
+                        <launchpad.http.port>${http.port}</launchpad.http.port>
+                        <IT.expected.bundles.count>${IT.expected.bundles.count}</IT.expected.bundles.count>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
         </plugins>
+
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <!-- Extend RAT configuration from parent pom -->
+                    <groupId>org.apache.rat</groupId>
+                    <artifactId>apache-rat-plugin</artifactId>
+                    <configuration>
+                        <excludes combine.children="append">
+                            <!-- Exclude sling instance -->
+                            <exclude>sling/**</exclude>
+                        </excludes>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
     </build>
 
     <dependencies>
@@ -185,68 +292,22 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <version>2.8.9</version>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.10</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.utils</artifactId>
+            <version>1.11.2</version>
+            <scope>test</scope>
+        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>org.mockito</groupId>-->
+<!--            <artifactId>mockito-core</artifactId>-->
+<!--            <version>2.8.9</version>-->
+<!--            <scope>test</scope>-->
+<!--        </dependency>-->
     </dependencies>
-    <profiles>
-        <profile>
-            <id>launch</id>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.codehaus.mojo</groupId>
-                        <artifactId>build-helper-maven-plugin</artifactId>
-                        <executions>
-                            <execution>
-                                <id>reserve-network-port</id>
-                                <goals>
-                                    <!-- pre-integration-test is too late -->
-                                    <goal>reserve-network-port</goal>
-                                </goals>
-                                <phase>process-resources</phase>
-                                <configuration>
-                                    <portNames>
-                                        <portName>http.port</portName>
-                                        <portName>sling.control.port</portName>
-                                    </portNames>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.sling</groupId>
-                        <artifactId>slingstart-feature-maven-plugin</artifactId>
-                        <version>0.0.1-SNAPSHOT</version>
-                        <extensions>true</extensions>
-                        <executions>
-                            <execution>
-                                <id>start-container</id>
-                                <goals>
-                                    <goal>start</goal>
-                                    <goal>stop</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                        <configuration>
-                            <launchpadJar>${project.build.directory}/${project.artifactId}-${project.version}.jar</launchpadJar>
-                            <parallelExecution>false</parallelExecution>
-<!--                            <createWebapp>false</createWebapp>-->
-                                <keepLaunchpadRunning>true</keepLaunchpadRunning>
-                            <servers>
-                                <server>
-                                    <port>${http.port}</port>
-                                    <controlPort>${sling.control.port}</controlPort>
-                                    <debug>true</debug>
-                                    <stdOutFile>launchpad.out</stdOutFile>
-                                </server>
-                            </servers>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
 </project>
diff --git a/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/app/SlingStarter.java b/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/app/SlingStarter.java
index 6959c05..16c3edc 100644
--- a/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/app/SlingStarter.java
+++ b/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/app/SlingStarter.java
@@ -27,6 +27,9 @@
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.sling.feature.launcher.impl.Main;
+import org.apache.sling.feature.starter.control.ControlAction;
+import org.apache.sling.feature.starter.control.ControlListener;
+import org.apache.sling.feature.starter.control.ControlTarget;
 import picocli.CommandLine;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Option;
@@ -91,13 +94,6 @@
     // about sling.home
     private static final String ENV_SLING_HOME = "SLING_HOME";
 
-//    /**
-//     * The name of the configuration property indicating the
-//     * {@link ControlAction} to be taken in the {@link #doControlAction()}
-//     * method.
-//     */
-//    protected static final String PROP_CONTROL_ACTION = "sling.control.action";
-
     /**
      * The name of the configuration property indicating the socket to use for
      * the control connection. The value of this property is either just a port
@@ -162,10 +158,6 @@
                     }
                 }
             }
-            //TODO: Remove because this is handled here so we do not need to pass it to the Feature Launcher
-//            if(StringUtils.isNotEmpty(controlAddress)) {
-//                addArgument(argumentList, PROP_CONTROL_SOCKET, controlAddress);
-//            }
             if(StringUtils.isNotEmpty(logLevel)) {
                 addArgument(argumentList, PROP_LOG_LEVEL, logLevel);
             }
@@ -238,31 +230,29 @@
     }
 
     private int doControlAction(ControlAction controlAction, String controlAddress) {
-//        if(controlAction != ControlAction.FOREGROUND) {
-            final ControlListener sl = new ControlListener(
-                this,
-                controlAddress
-            );
-            switch (controlAction) {
-                case FOREGROUND:
-                    if (!sl.listen()) {
-                        return -1;
-                    }
-                    break;
-                case START:
-                    if (!sl.listen()) {
-                        // assume service already running
-                        return 0;
-                    }
-                    break;
-                case STOP:
-                    return sl.shutdownServer();
-                case STATUS:
-                    return sl.statusServer();
-                case THREADS:
-                    return sl.dumpThreads();
-            }
-//        }
+        final ControlListener sl = new ControlListener(
+            this,
+            controlAddress
+        );
+        switch (controlAction) {
+            case FOREGROUND:
+                if (!sl.listen()) {
+                    return -1;
+                }
+                break;
+            case START:
+                if (!sl.listen()) {
+                    // assume service already running
+                    return 0;
+                }
+                break;
+            case STOP:
+                return sl.shutdownServer();
+            case STATUS:
+                return sl.statusServer();
+            case THREADS:
+                return sl.dumpThreads();
+        }
         return -1;
     }
 
diff --git a/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/app/ControlAction.java b/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/control/ControlAction.java
similarity index 96%
rename from sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/app/ControlAction.java
rename to sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/control/ControlAction.java
index 7213d86..6d89bd2 100644
--- a/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/app/ControlAction.java
+++ b/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/control/ControlAction.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sling.feature.starter.app;
+package org.apache.sling.feature.starter.control;
 
 /**
  * The <code>ControlAction</code> defines values to used as the action for the
diff --git a/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/app/ControlListener.java b/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/control/ControlListener.java
similarity index 99%
rename from sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/app/ControlListener.java
rename to sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/control/ControlListener.java
index a996984..4ad21c0 100644
--- a/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/app/ControlListener.java
+++ b/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/control/ControlListener.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sling.feature.starter.app;
+package org.apache.sling.feature.starter.control;
 
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
diff --git a/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/app/ControlTarget.java b/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/control/ControlTarget.java
similarity index 95%
rename from sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/app/ControlTarget.java
rename to sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/control/ControlTarget.java
index 7611889..8e58f49 100644
--- a/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/app/ControlTarget.java
+++ b/sling-org-apache-sling-feature-starter/src/main/java/org/apache/sling/feature/starter/control/ControlTarget.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.sling.feature.starter.app;
+package org.apache.sling.feature.starter.control;
 
 public interface ControlTarget {
 
diff --git a/sling-org-apache-sling-feature-starter/src/test/java/org/apache/sling/feature/starter/it/LaunchpadReadyRule.java b/sling-org-apache-sling-feature-starter/src/test/java/org/apache/sling/feature/starter/it/LaunchpadReadyRule.java
new file mode 100644
index 0000000..f82bc3a
--- /dev/null
+++ b/sling-org-apache-sling-feature-starter/src/test/java/org/apache/sling/feature/starter/it/LaunchpadReadyRule.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.sling.feature.starter.it;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.http.HttpResponse;
+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.impl.client.HttpClients;
+import org.junit.rules.ExternalResource;
+
+public class LaunchpadReadyRule extends ExternalResource {
+
+    private static final int TRIES = 60;
+    private static final int WAIT_BETWEEN_TRIES_MILLIS = 1000;
+
+    private final List<Check> checks = new ArrayList<>();
+
+    public LaunchpadReadyRule(int launchpadPort) {
+
+        checks.add(new Check("http://localhost:" + launchpadPort + "/server/default/jcr:root/content"));
+        checks.add(new Check("http://localhost:" + launchpadPort + "/starter/index.html") {
+            @Override
+            public String runCheck(HttpResponse response) throws Exception {
+                try (InputStreamReader isr = new InputStreamReader(response.getEntity().getContent());
+                        BufferedReader reader = new BufferedReader(isr)) {
+
+                    String line;
+                    while ((line = reader.readLine()) != null) {
+                        if (line.contains("Do not remove this comment, used for Starter integration tests")) {
+                            return null;
+                        }
+                    }
+                }
+
+                return "Did not find 'ready' marker in the response body";
+            }
+        });
+    }
+
+    @Override
+    protected void before() throws Throwable {
+
+        try (CloseableHttpClient client = HttpClients.createDefault()) {
+            for (Check check : checks) {
+                runCheck(client, check);
+            }
+        }
+    }
+
+    private void runCheck(CloseableHttpClient client, Check check) throws Exception {
+
+        String lastFailure = null;
+        HttpGet get = new HttpGet(check.getUrl());
+        
+        for (int i = 0; i < TRIES; i++) {
+            try (CloseableHttpResponse response = client.execute(get)) {
+
+                if (response.getStatusLine().getStatusCode() != 200) {
+                    lastFailure = "Status code is " + response.getStatusLine();
+                    Thread.sleep(WAIT_BETWEEN_TRIES_MILLIS);
+                    continue;
+                }
+
+                lastFailure = check.runCheck(response);
+                if (lastFailure == null) {
+                    return;
+                }
+            } catch ( ConnectException e ) {
+                lastFailure = e.getClass().getName() + " : " + e.getMessage();
+            }
+
+            Thread.sleep(WAIT_BETWEEN_TRIES_MILLIS);
+        }
+        
+        throw new RuntimeException(String.format("Launchpad not ready. Failed check for URL %s with message '%s'",
+                check.getUrl(), lastFailure));
+    }
+
+    static class Check {
+        private String url;
+
+        public Check(String url) {
+            this.url = url;
+        }
+
+        public String getUrl() {
+            return url;
+        }
+
+        /**
+         * @param response the HttpResponse
+         * @return null if check check was successful, an error description otherwise
+         * @throws Exception
+         */
+        public String runCheck(HttpResponse response) throws Exception {
+            return null;
+        }
+    }
+
+}
diff --git a/sling-org-apache-sling-feature-starter/src/test/java/org/apache/sling/feature/starter/it/SmokeIT.java b/sling-org-apache-sling-feature-starter/src/test/java/org/apache/sling/feature/starter/it/SmokeIT.java
new file mode 100644
index 0000000..785e29e
--- /dev/null
+++ b/sling-org-apache-sling-feature-starter/src/test/java/org/apache/sling/feature/starter/it/SmokeIT.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.sling.feature.starter.it;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.felix.utils.json.JSONParser;
+import org.apache.http.Header;
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.impl.client.BasicAuthCache;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+public class SmokeIT {
+
+    private static final int LAUNCHPAD_PORT = Integer.getInteger("launchpad.http.port", 8080);
+    private static final int EXPECTED_BUNDLES_COUNT = Integer.getInteger("IT.expected.bundles.count", Integer.MAX_VALUE);
+
+    @ClassRule
+    public static LaunchpadReadyRule LAUNCHPAD = new LaunchpadReadyRule(LAUNCHPAD_PORT);
+    private HttpClientContext httpClientContext;
+
+    @Before
+    public void prepareHttpContext() {
+
+        CredentialsProvider credsProvider = new BasicCredentialsProvider();
+        UsernamePasswordCredentials creds = new UsernamePasswordCredentials("admin", "admin");
+        credsProvider.setCredentials(new AuthScope("localhost", LAUNCHPAD_PORT), creds);
+
+        BasicAuthCache authCache = new BasicAuthCache();
+        BasicScheme basicAuth = new BasicScheme();
+        authCache.put(new HttpHost("localhost", LAUNCHPAD_PORT, "http"), basicAuth);
+
+        httpClientContext = HttpClientContext.create();
+        httpClientContext.setCredentialsProvider(credsProvider);
+        httpClientContext.setAuthCache(authCache);
+    }
+
+    private CloseableHttpClient newClient() {
+
+        return HttpClientBuilder.create()
+                .setDefaultCredentialsProvider(httpClientContext.getCredentialsProvider())
+                .build();
+    }
+
+    @Test
+    public void verifyAllBundlesStarted() throws Exception {
+
+        try ( CloseableHttpClient client = newClient() ) {
+
+            HttpGet get = new HttpGet("http://localhost:" + LAUNCHPAD_PORT + "/system/console/bundles.json");
+
+            // pass the context to ensure preemptive basic auth is used
+            // https://hc.apache.org/httpcomponents-client-ga/tutorial/html/authentication.html
+            try ( CloseableHttpResponse response = client.execute(get, httpClientContext) ) {
+
+                if ( response.getStatusLine().getStatusCode() != 200 ) {
+                    fail("Unexpected status line " + response.getStatusLine());
+                }
+
+                Header contentType = response.getFirstHeader("Content-Type");
+                assertThat("Content-Type header", contentType.getValue(), CoreMatchers.startsWith("application/json"));
+
+                Map<String, Object> obj = new JSONParser(response.getEntity().getContent()).getParsed();
+
+                @SuppressWarnings("unchecked")
+                List<Object> status = (List<Object>) obj.get("s");
+
+                @SuppressWarnings("unchecked")
+                List<Object> bundles = (List<Object>) obj.get("data");
+                if(bundles.size() < EXPECTED_BUNDLES_COUNT) {
+                    fail("Expected at least " + EXPECTED_BUNDLES_COUNT + " bundles, got " + bundles.size());
+                }
+
+                BundleStatus bs = new BundleStatus(status);
+
+                if ( bs.resolvedBundles != 0 || bs.installedBundles != 0 ) {
+
+                    StringBuilder out = new StringBuilder();
+                    out.append("Expected all bundles to be active, but instead got ")
+                        .append(bs.resolvedBundles).append(" resolved bundles, ")
+                        .append(bs.installedBundles).append(" installed bundlles: ");
+
+                    for ( int i = 0 ; i < bundles.size(); i++ ) {
+                        @SuppressWarnings("unchecked")
+                        Map<String, Object> bundle = (Map<String, Object>) bundles.get(i);
+
+                        String bundleState = (String) bundle.get("state");
+                        String bundleSymbolicName = (String) bundle.get("symbolicName");
+                        String bundleVersion = (String) bundle.get("version");
+
+                        switch ( bundleState ) {
+                            case "Active":
+                            case "Fragment":
+                                continue;
+
+                            default:
+                                out.append("\n- ").append(bundleSymbolicName).append(" ").append(bundleVersion).append(" is in state " ).append(bundleState);
+                        }
+                    }
+
+                    fail(out.toString());
+                }
+            }
+        }
+    }
+
+    @Test
+    public void ensureRepositoryIsStarted() throws Exception {
+        try ( CloseableHttpClient client = newClient() ) {
+
+            HttpGet get = new HttpGet("http://localhost:" + LAUNCHPAD_PORT + "/server/default/jcr:root/content");
+
+            try ( CloseableHttpResponse response = client.execute(get) ) {
+
+                if ( response.getStatusLine().getStatusCode() != 200 ) {
+                    fail("Unexpected status line " + response.getStatusLine());
+                }
+
+                Header contentType = response.getFirstHeader("Content-Type");
+                assertThat("Content-Type header", contentType.getValue(), equalTo("text/xml"));
+
+                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+                dbf.setNamespaceAware(true);
+                DocumentBuilder db = dbf.newDocumentBuilder();
+                Document document = db.parse(response.getEntity().getContent());
+
+                Element docElement = document.getDocumentElement();
+                NamedNodeMap attrs = docElement.getAttributes();
+
+                Node nameAttr = attrs.getNamedItemNS("http://www.jcp.org/jcr/sv/1.0", "name");
+                assertThat("no 'name' attribute found", nameAttr, notNullValue());
+                assertThat("Invalid name attribute value", nameAttr.getNodeValue(), equalTo("content"));
+            }
+        }
+    }
+
+    static class BundleStatus {
+
+        long totalBundles;
+        long activeBundles;
+        long activeFragments;
+        long resolvedBundles;
+        long installedBundles;
+
+        public BundleStatus(List<Object> array) {
+
+            totalBundles = (Long)array.get(0);
+            activeBundles = (Long)array.get(1);
+            activeFragments = (Long)array.get(2);
+            resolvedBundles = (Long)array.get(3);
+            installedBundles = (Long)array.get(4);
+
+        }
+    }
+}
diff --git a/sling-org-apache-sling-feature-starter/src/test/java/org/apache/sling/feature/starter/it/package-info.java b/sling-org-apache-sling-feature-starter/src/test/java/org/apache/sling/feature/starter/it/package-info.java
new file mode 100644
index 0000000..f70e5e8
--- /dev/null
+++ b/sling-org-apache-sling-feature-starter/src/test/java/org/apache/sling/feature/starter/it/package-info.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+/**
+ * <h1>Smoke tests for the Sling Launchpad</h1>
+ * 
+ * <p>This package contains a minimal set of tests for the Sling launchpad. The
+ * tests validate that the launchpad is correctly assembled and that there are
+ * no obvious mistakes such as bundles that can't be wired. More extensive
+ * tests must be placed in specific test projects.</p>
+ * 
+ * <p>The launchpad tests don't depend on other Sling bundles,to prevent circular
+ * dependencies. As such, there is some duplication of code ( at least intent, if 
+ * not implementation ) with some of the testing projects. This is another 
+ * argument for keeping the tests minimal.</p>
+ */
+package org.apache.sling.launchpad;
\ No newline at end of file
diff --git a/sling-slingstart-feature-maven-plugin/Readme.md b/sling-slingstart-feature-maven-plugin/Readme.md
index fea9136..9136029 100644
--- a/sling-slingstart-feature-maven-plugin/Readme.md
+++ b/sling-slingstart-feature-maven-plugin/Readme.md
@@ -45,7 +45,7 @@
 </plugin>
 ```
 
-## Issues
+## Notes
 
-The Feature Launcher does not support to be started in the background and
-so this plugin will be not end the build when Sling is started.
+For now this Plugin only supports the starting and stopping of a Sling
+instance for example to run IT tests.
\ No newline at end of file
diff --git a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/BuildConstants.java b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/BuildConstants.java
index 94161f3..5148958 100644
--- a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/BuildConstants.java
+++ b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/BuildConstants.java
@@ -16,9 +16,6 @@
  */
 package org.apache.sling.maven.slingstart.feature;
 
-//import org.apache.sling.provisioning.model.ModelConstants;
-//import org.apache.sling.provisioning.model.io.ModelArchiveWriter;
-
 import java.util.ArrayList;
 import java.util.List;
 
@@ -26,8 +23,6 @@
 
     // CONTEXTS
     public static final String CONTEXT_GLOBAL = "slingstart:global";
-//    public static final String CONTEXT_STANDALONE = "slingstart" + ModelConstants.RUN_MODE_STANDALONE;
-//    public static final String CONTEXT_WEBAPP = "slingstart" + ModelConstants.RUN_MODE_WEBAPP;
     public static final String CONTEXT_STANDALONE = "slingstart" + ":standalone";
     public static final String CONTEXT_WEBAPP = "slingstart" + ":webapp";
 
@@ -99,7 +94,4 @@
         ATTRS_EXCLUDES.add(ATTR_SPECIFICATION_VENDOR);
         ATTRS_EXCLUDES.add(ATTR_SPECIFICATION_VERSION);
     }
-
-    // build constants
-    public static final String WEBAPP_OUTDIR = "slingstart-webapp";
 }
diff --git a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/launcher/Launcher.java b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/launcher/Launcher.java
deleted file mode 100644
index 0e3538f..0000000
--- a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/launcher/Launcher.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.sling.maven.slingstart.feature.launcher;
-
-import java.io.BufferedReader;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.util.ArrayList;
-import java.util.List;
-
-public class Launcher implements LauncherMBean {
-
-    private final int listenerPort;
-
-    public Launcher(final int listenerPort) {
-        System.out.println("Launcher MBean created on port: " + listenerPort);
-        this.listenerPort = listenerPort;
-    }
-
-    @Override
-    public void startupFinished() {
-        System.out.println("Launcher MBean startup finished called, port: " + listenerPort);
-        final List<String> hosts = new ArrayList<String>();
-        hosts.add("localhost");
-        hosts.add("127.0.0.1");
-
-        boolean done = false;
-        int index = 0;
-        while ( !done && index < hosts.size() ) {
-            final String hostName = hosts.get(index);
-            final int twoMinutes = 2 * 60 * 1000;
-
-            Socket clientSocket = null;
-            DataOutputStream out = null;
-            BufferedReader in = null;
-            try {
-                clientSocket = new Socket();
-                clientSocket.connect(new InetSocketAddress(hostName, listenerPort), twoMinutes);
-                // without that, read() call on the InputStream associated with this Socket is infinite
-                clientSocket.setSoTimeout(twoMinutes);
-
-                out = new DataOutputStream(clientSocket.getOutputStream());
-                in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
-                out.writeBytes("started\n");
-                in.readLine();
-                done = true;
-            } catch (final Throwable ignore) {
-                // catch Throwable because InetSocketAddress and Socket#connect throws unchecked exceptions
-                // we ignore this for now
-            } finally {
-                if ( in != null ) {
-                    try {
-                        in.close();
-                    } catch ( final IOException ioe) {
-                        // ignore
-                    }
-                }
-                if ( out != null ) {
-                    try {
-                        out.close();
-                    } catch ( final IOException ioe) {
-                        // ignore
-                    }
-                }
-                if ( clientSocket != null ) {
-                    try {
-                        clientSocket.close();
-                    } catch (final IOException e) {
-                        // ignore
-                    }
-                }
-            }
-            index++;
-        }
-    }
-
-    @Override
-    public void startupProgress(Float ratio) {
-        // nothing to do
-    }
-}
diff --git a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/launcher/LauncherMBean.java b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/launcher/LauncherMBean.java
deleted file mode 100644
index a221885..0000000
--- a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/launcher/LauncherMBean.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.sling.maven.slingstart.feature.launcher;
-
-/**
- * The launcher MBean interface.
- */
-public interface LauncherMBean {
-
-    /**
-     * Notify the launcher about the finish of the startup.
-     */
-    void startupFinished();
-
-    /**
-     * Notify the launcher about the progress of the startup.
-     * @param ratio Startup progress ratio
-     */
-    void startupProgress(Float ratio);
-}
diff --git a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/launcher/Main.java b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/launcher/Main.java
index f7e4a80..132956b 100644
--- a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/launcher/Main.java
+++ b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/launcher/Main.java
@@ -91,11 +91,6 @@
         final ClassLoader cl = new URLClassLoader(new URL[] {this.appJar.toURI().toURL()});
         Thread.currentThread().setContextClassLoader(cl);
 
-//        // create and register mbean
-//        final MBeanServer jmxServer = ManagementFactory.getPlatformMBeanServer();
-//        jmxServer.registerMBean(new Launcher(this.listenerPort),
-//                new ObjectName("org.apache.sling.feature.launchpad:type=Launcher"));
-
         final Class<?> mainClass = cl.loadClass(MAIN_CLASS_DEF);
         final Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
         mainMethod.invoke(null, (Object)this.startupArgs);
diff --git a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/ControlClient.java b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/ControlClient.java
index e627f38..180658f 100644
--- a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/ControlClient.java
+++ b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/ControlClient.java
@@ -19,59 +19,24 @@
 package org.apache.sling.maven.slingstart.feature.run;
 
 import org.apache.maven.plugin.logging.Log;
-import org.apache.sling.feature.starter.app.ControlTarget;
-import org.slf4j.Logger;
 
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileReader;
-import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.LineNumberReader;
 import java.io.OutputStreamWriter;
-import java.lang.management.LockInfo;
-import java.lang.management.ManagementFactory;
-import java.lang.management.MonitorInfo;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
 import java.math.BigInteger;
 import java.net.ConnectException;
 import java.net.InetSocketAddress;
-import java.net.ServerSocket;
 import java.net.Socket;
 import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
 
 /**
- * The <code>ControlListener</code> class is a helper class for the {@link ControlTarget}
- * class to support in Sling standalone application process communication. This
- * class implements the client and server sides of a TCP/IP based communication
- * channel to control a running Sling application.
- * <p>
- * The server side listens for commands on a configurable host and port &endash;
- * <code>localhost:63000</code> by default &endash; supporting the following
- * commands:
- * <table>
- * <tr>
- * <th>Command</th>
- * <th>Description</th>
- * </tr>
- * <tr>
- * <td><code>status</code></td>
- * <td>Request status information. Currently only <i>OK</i> is sent back. If no
- * connection can be created to the server the client assumes Sling is not
- * running.</td>
- * </tr>
- * <tr>
- * <td><code>stop</code></td>
- * <td>Requests Sling to shutdown.</td>
- * </tr>
- * </table>
+ * The <code>ControlClient</code> class is a helper class to interact with a started
+ * Sling instance through its ControlListener class.
  */
 public class ControlClient {
 
@@ -84,22 +49,15 @@
     // command sent by the client to request a thread dump
     static final String COMMAND_THREADS = "threads";
 
-    // the response sent by the server if the command executed successfully
-    private static final String RESPONSE_OK = "OK";
-
-    // the status response sent by the server when shutting down
-    private static final String RESPONSE_STOPPING = "STOPPING";
-
     // The default interface to listen on
     private static final String DEFAULT_LISTEN_INTERFACE = "127.0.0.1";
 
     // The default port to listen on and to connect to - we select it randomly
     private static final int DEFAULT_LISTEN_PORT = 0;
 
-    private final String listenSpec;
-
     private String secretKey;
     private InetSocketAddress socketAddress;
+
     private File directory;
     private Log logger;
 
@@ -111,12 +69,8 @@
      * <code>[ host ":" ] port</code>. If the parameter is empty or
      * <code>null</code> it defaults to <i>localhost:0</i>. If the host name
      * is missing it defaults to <i>localhost</i>.
-     *
-     * @param listenSpec The specification for the host and port for the socket
-     *            connection. See above for the format of this parameter.
      */
-    public ControlClient(final String listenSpec, final File directory, Log logger) {
-        this.listenSpec = listenSpec; // socketAddress = this.getSocketAddress(listenSpec, selectNewPort);
+    public ControlClient(final File directory, Log logger) {
         this.directory = directory;
         this.logger = logger;
     }
@@ -216,11 +170,6 @@
         return b.toString();
     }
 
-//    private void writeLine(final Socket socket, final String line) throws IOException {
-//        logger.info(socket.getRemoteSocketAddress() + "<" + line);
-//        this.writeLine0(socket, line);
-//    }
-
     private void writeLine0(final Socket socket, final String line) throws IOException {
         final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
         bw.write(line);
@@ -253,29 +202,10 @@
         return new File(configDir, "controlport");
     }
 
-    /**
-     * Read the port from the config file
-     * @return The port or null
-     */
-    private boolean configure(final boolean fromConfigFile) {
-        this.socketAddress = getSocketAddress(this.listenSpec);
-        this.secretKey = generateKey();
-
-        return true;
-    }
-
     private static String generateKey() {
          return new BigInteger(165, new SecureRandom()).toString(32);
     }
 
-    /**
-     * Return the control port file
-     */
-//    private File getConfigFile() {
-//        final File configDir = new File(this.controlTarget.getHome(), "conf");
-//        return new File(configDir, "controlport");
-//    }
-
     private InetSocketAddress getSocketAddress(String listenSpec) {
         try {
 
@@ -339,27 +269,4 @@
             return exception;
         }
     }
-//    private void writePortToConfigFile(final File configFile, final InetSocketAddress socketAddress,
-//            final String secretKey) {
-//        configFile.getParentFile().mkdirs();
-//        FileWriter fw = null;
-//        try {
-//            fw = new FileWriter(configFile);
-//            fw.write(socketAddress.getAddress().getHostAddress());
-//            fw.write(':');
-//            fw.write(String.valueOf(socketAddress.getPort()));
-//            fw.write('\n');
-//            fw.write(secretKey);
-//            fw.write('\n');
-//        } catch (final IOException ignore) {
-//            // ignore
-//        } finally {
-//            if (fw != null) {
-//                try {
-//                    fw.close();
-//                } catch (final IOException ignore) {
-//                }
-//            }
-//        }
-//    }
 }
diff --git a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/ControlListener.java b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/ControlListener.java
deleted file mode 100644
index 0202a91..0000000
--- a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/ControlListener.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.apache.sling.maven.slingstart.feature.run;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-
-/**
- * Control listener.
- * This class listens for the startup of a launchpad instance.
- */
-public class ControlListener implements Runnable {
-
-    // command sent by the client to notify startup
-    private static final String COMMAND_STARTED = "started";
-
-    private static final String RESPONSE_OK = "ok";
-
-    // The default interface to listen on
-    private static final String DEFAULT_LISTEN_INTERFACE = "127.0.0.1";
-
-    // The port to listen on
-    private final int port;
-
-    private volatile boolean started = false;
-
-    private volatile boolean stopped = false;
-
-    private volatile ServerSocket server;
-
-    public ControlListener(final int p) {
-        this.port = p;
-        final Thread listener = new Thread(this);
-        listener.setDaemon(true);
-        listener.setName("Launchapd startup listener");
-        listener.start();
-    }
-
-    public int getPort() {
-        return this.port;
-    }
-
-    public boolean isStarted() {
-        return this.started;
-    }
-
-    public void stop() {
-        stopped = true;
-        if ( server != null ) {
-            try {
-                server.close();
-            } catch (IOException e) {
-                // ignore
-            }
-        }
-    }
-
-    /**
-     * Implements the server thread receiving commands from clients and acting
-     * upon them.
-     */
-    @Override
-    public void run() {
-        final InetSocketAddress socketAddress = getSocketAddress(this.port);
-        try {
-            server = new ServerSocket();
-            server.bind(socketAddress);
-        } catch (final IOException ioe) {
-            return;
-        }
-
-        try {
-            while (!stopped) {
-
-                final Socket s = server.accept();
-
-                try {
-                    final String commandLine = readLine(s);
-                    if (commandLine == null) {
-                        final String msg = "ERR: missing command";
-                        writeLine(s, msg);
-                        continue;
-                    }
-
-                    final String command = commandLine;
-
-                    if (COMMAND_STARTED.equals(command)) {
-                        writeLine(s, RESPONSE_OK);
-                        this.started = true;
-                        this.stopped = true;
-                        break;
-
-                    } else {
-                        final String msg = "ERR:" + command;
-                        writeLine(s, msg);
-
-                    }
-                } finally {
-                    try {
-                        s.close();
-                    } catch (IOException ignore) {
-                    }
-                }
-            }
-        } catch (final IOException ioe) {
-            // ignore
-        } finally {
-            try {
-                server.close();
-            } catch (final IOException ignore) {
-                // ignore
-            }
-        }
-    }
-
-    private String readLine(final Socket socket) throws IOException {
-        final BufferedReader br = new BufferedReader(new InputStreamReader(
-            socket.getInputStream(), "UTF-8"));
-        return br.readLine();
-    }
-
-    private void writeLine(final Socket socket, final String line) throws IOException {
-        final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
-            socket.getOutputStream(), "UTF-8"));
-        bw.write(line);
-        bw.write("\r\n");
-        bw.flush();
-    }
-
-    private static InetSocketAddress getSocketAddress(final int port) {
-        final String address = DEFAULT_LISTEN_INTERFACE;
-
-        final InetSocketAddress addr = new InetSocketAddress(address, port);
-        if (!addr.isUnresolved()) {
-            return addr;
-        }
-
-        return null;
-    }
-}
diff --git a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/LauncherCallable.java b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/LauncherCallable.java
index 89228e5..9eb616d 100644
--- a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/LauncherCallable.java
+++ b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/LauncherCallable.java
@@ -124,8 +124,8 @@
             this.logger.info("Started Launchpad '" + configuration.getId() +
                     "' at port " + configuration.getPort()+ " [run modes: " + configuration.getRunmode()+ "]");
         } finally {
-            // stop control port
-            cfg.getControlClient().shutdownServer();
+//            // stop control port
+//            cfg.getControlClient().shutdownServer();
 
             // call launchpad stop routine if not properly started
             if (!started) {
@@ -372,8 +372,6 @@
     }
 
     private static File getControlPortFile(final File directory) {
-//        final File launchpadDir = new File(directory, LaunchpadEnvironment.WORK_DIR_NAME);
-//        final File confDir = new File(launchpadDir, "conf");
         final File confDir = new File(directory, "conf");
         final File controlPortFile = new File(confDir, "controlport");
         return controlPortFile;
diff --git a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/LaunchpadEnvironment.java b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/LaunchpadEnvironment.java
index 150679c..21def49 100644
--- a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/LaunchpadEnvironment.java
+++ b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/LaunchpadEnvironment.java
@@ -84,8 +84,6 @@
 
     private void installLauncher(final File folder) throws IOException {
         final File binDir = new File(folder, "bin");
-        copyResource("org/apache/sling/maven/slingstart/feature/launcher/Launcher.class", binDir);
-        copyResource("org/apache/sling/maven/slingstart/feature/launcher/LauncherMBean.class", binDir);
         copyResource("org/apache/sling/maven/slingstart/feature/launcher/Main.class", binDir);
     }
 
diff --git a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/ProcessDescription.java b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/ProcessDescription.java
index ccda0be..8cd1a20 100644
--- a/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/ProcessDescription.java
+++ b/sling-slingstart-feature-maven-plugin/src/main/java/org/apache/sling/maven/slingstart/feature/run/ProcessDescription.java
@@ -35,7 +35,6 @@
         this.id = id;
         this.directory = directory;
         this.controlClient = new ControlClient(
-            listenerSpec,
             directory,
             logger
         );