You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/08/07 03:09:45 UTC

[1/8] incubator-brooklyn git commit: brooklyn-launcher: add org.apache package prefix

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master 7154cc9ec -> cc4ffb9d7


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
new file mode 100644
index 0000000..ab73cbf
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
@@ -0,0 +1,202 @@
+/*
+ * 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.brooklyn.launcher.blueprints;
+
+import static org.testng.Assert.assertNotEquals;
+
+import java.io.File;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.Collection;
+
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherAbstract;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+import brooklyn.entity.Application;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.Lifecycle;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.rebind.RebindOptions;
+import brooklyn.entity.rebind.RebindTestUtils;
+import brooklyn.entity.rebind.persister.FileBasedObjectStore;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.SimpleYamlLauncherForTests;
+import org.apache.brooklyn.launcher.camp.BrooklynCampPlatformLauncher;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.test.Asserts;
+import brooklyn.test.EntityTestUtils;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.os.Os;
+
+public abstract class AbstractBlueprintTest {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractBlueprintTest.class);
+    
+    protected File mementoDir;
+    protected ClassLoader classLoader = AbstractBlueprintTest.class.getClassLoader();
+    
+    protected ManagementContext mgmt;
+    protected SimpleYamlLauncherForTests launcher;
+    protected BrooklynLauncher viewer;
+
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        mementoDir = Os.newTempDir(getClass());
+        mgmt = createOrigManagementContext();
+        LOG.info("Test "+getClass()+" persisting to "+mementoDir);
+
+        launcher = new SimpleYamlLauncherForTests() {
+            @Override
+            protected BrooklynCampPlatformLauncherAbstract newPlatformLauncher() {
+                return new BrooklynCampPlatformLauncher() {
+                    protected ManagementContext newManagementContext() {
+                        return AbstractBlueprintTest.this.mgmt;
+                    }
+                };
+            }
+        };
+        viewer = BrooklynLauncher.newInstance()
+                .managementContext(mgmt)
+                .start();
+    }
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        try {
+            if (mgmt != null) {
+                for (Application app: mgmt.getApplications()) {
+                    LOG.debug("destroying app "+app+" (managed? "+Entities.isManaged(app)+"; mgmt is "+mgmt+")");
+                    try {
+                        Entities.destroy(app);
+                        LOG.debug("destroyed app "+app+"; mgmt now "+mgmt);
+                    } catch (Exception e) {
+                        LOG.error("problems destroying app "+app, e);
+                    }
+                }
+            }
+            if (launcher != null) launcher.destroyAll();
+            if (viewer != null) viewer.terminate();
+            if (mgmt != null) Entities.destroyAll(mgmt);
+            if (mementoDir != null) FileBasedObjectStore.deleteCompletely(mementoDir);
+        } catch (Throwable t) {
+            LOG.error("Caught exception in tearDown method", t);
+        } finally {
+            mgmt = null;
+            launcher = null;
+        }
+    }
+
+    protected void runTest(String yamlFile) throws Exception {
+        final Application app = launcher.launchAppYaml(yamlFile);
+        
+        assertNoFires(app);
+        
+        Application newApp = rebind();
+        assertNoFires(newApp);
+    }
+    
+    protected void runTest(Reader yaml) throws Exception {
+        final Application app = launcher.launchAppYaml(yaml);
+        
+        assertNoFires(app);
+        
+        Application newApp = rebind();
+        assertNoFires(newApp);
+    }
+    
+    protected void assertNoFires(final Entity app) {
+        EntityTestUtils.assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, true);
+        EntityTestUtils.assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+        
+        Asserts.succeedsEventually(new Runnable() {
+            public void run() {
+                for (Entity entity : Entities.descendants(app)) {
+                    assertNotEquals(entity.getAttribute(Attributes.SERVICE_STATE_ACTUAL), Lifecycle.ON_FIRE);
+                    assertNotEquals(entity.getAttribute(Attributes.SERVICE_UP), false);
+                    
+                    if (entity instanceof SoftwareProcess) {
+                        EntityTestUtils.assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
+                        EntityTestUtils.assertAttributeEquals(entity, Attributes.SERVICE_UP, Boolean.TRUE);
+                    }
+                }
+            }});
+    }
+
+    protected Reader loadYaml(String url, String location) {
+        String yaml = 
+                "location: "+location+"\n"+
+                new ResourceUtils(this).getResourceAsString(url);
+        return new StringReader(yaml);
+    }
+    
+    
+    //////////////////////////////////////////////////////////////////
+    // FOR REBIND                                                   //
+    // See brooklyn.entity.rebind.RebindTestFixture in core's tests //
+    //////////////////////////////////////////////////////////////////
+
+    /** rebinds, and sets newApp */
+    protected Application rebind() throws Exception {
+        return rebind(RebindOptions.create());
+    }
+
+    protected Application rebind(RebindOptions options) throws Exception {
+        ManagementContext origMgmt = mgmt;
+        ManagementContext newMgmt = createNewManagementContext();
+        Collection<Application> origApps = origMgmt.getApplications();
+        
+        options = RebindOptions.create(options);
+        if (options.classLoader == null) options.classLoader(classLoader);
+        if (options.mementoDir == null) options.mementoDir(mementoDir);
+        if (options.origManagementContext == null) options.origManagementContext(origMgmt);
+        if (options.newManagementContext == null) options.newManagementContext(newMgmt);
+        
+        for (Application origApp : origApps) {
+            RebindTestUtils.waitForPersisted(origApp);
+        }
+        
+        mgmt = options.newManagementContext;
+        Application newApp = RebindTestUtils.rebind(options);
+        return newApp;
+    }
+    
+    /** @return A started management context */
+    protected LocalManagementContext createOrigManagementContext() {
+        return RebindTestUtils.managementContextBuilder(mementoDir, classLoader)
+                .persistPeriodMillis(1)
+                .forLive(true)
+                .emptyCatalog(true)
+                .buildStarted();
+    }
+
+    /** @return An unstarted management context */
+    protected LocalManagementContext createNewManagementContext() {
+        return RebindTestUtils.managementContextBuilder(mementoDir, classLoader)
+                .persistPeriodMillis(1)
+                .forLive(true)
+                .emptyCatalog(true)
+                .buildUnstarted();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/CouchbaseBlueprintTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/CouchbaseBlueprintTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/CouchbaseBlueprintTest.java
new file mode 100644
index 0000000..fde5b41
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/CouchbaseBlueprintTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.brooklyn.launcher.blueprints;
+
+import org.testng.annotations.Test;
+
+public class CouchbaseBlueprintTest extends AbstractBlueprintTest {
+
+    @Test(groups={"Live"})
+    public void testCouchbaseNode() throws Exception {
+        runTest("couchbase-node.yaml");
+    }
+
+    @Test(groups={"Live"})
+    public void testCouchbaseCluster() throws Exception {
+        runTest("couchbase-cluster.yaml");
+    }
+
+    @Test(groups={"Live"})
+    public void testCouchbaseClusterSingleNode() throws Exception {
+        runTest("couchbase-cluster-singleNode.yaml");
+    }
+    
+    @Test(groups={"Live"})
+    public void testCouchbaseWithPillowfight() throws Exception {
+        runTest("couchbase-w-pillowfight.yaml");
+    }
+
+    /**
+     * FIXME Failed with "Unable to match required VM template constraints" - caused by NPE:
+     *   Caused by: java.lang.NullPointerException: id
+     *     at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:229)
+     *     at org.jclouds.softlayer.domain.OperatingSystem.<init>(OperatingSystem.java:106)
+     *     at org.jclouds.softlayer.domain.OperatingSystem$Builder.build(OperatingSystem.java:87)
+     *     at org.jclouds.softlayer.domain.ContainerVirtualGuestConfiguration$4.apply(ContainerVirtualGuestConfiguration.java:209)
+     *     at org.jclouds.softlayer.domain.ContainerVirtualGuestConfiguration$4.apply(ContainerVirtualGuestConfiguration.java:206)
+     * This blueprint uses {minRam: 16384, minCores: 4}.
+     * Suspect this is already fixed by Andrea Turli in latest jclouds.
+     */
+    @Test(groups={"Live", "WIP"})
+    public void testCouchbaseWithLoadgen() throws Exception {
+        runTest("couchbase-w-loadgen.yaml");
+    }
+
+    /**
+     * FIXME Failed with "Unable to match required VM template constraints" - caused by NPE
+     * (see error described at {@link #testCouchbaseWithLoadgen()}.
+     */
+    @Test(groups={"Live", "WIP"})
+    public void testCouchbaseReplicationWithPillowfight() throws Exception {
+        runTest("couchbase-replication-w-pillowfight.yaml");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/MongoDbBlueprintTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/MongoDbBlueprintTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/MongoDbBlueprintTest.java
new file mode 100644
index 0000000..33c8910
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/blueprints/MongoDbBlueprintTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.brooklyn.launcher.blueprints;
+
+import org.testng.annotations.Test;
+
+public class MongoDbBlueprintTest extends AbstractBlueprintTest {
+
+    // TODO Some tests are failing! Needs investigated.
+
+    @Test(groups={"Integration", "WIP"})
+    public void testMongoSharded() throws Exception {
+        runTest("mongo-sharded.yaml");
+    }
+
+    @Test(groups={"Integration"})
+    public void testMongoReplicaSet() throws Exception {
+        runTest("mongo-blueprint.yaml");
+    }
+
+    @Test(groups={"Integration"})
+    public void testMongoClientAndSingleServer() throws Exception {
+        runTest("mongo-client-single-server.yaml");
+    }
+
+    @Test(groups={"Integration", "WIP"})
+    public void testMongoScripts() throws Exception {
+        runTest("mongo-scripts.yaml");
+    }
+
+    @Test(groups="Integration")
+    public void testMongoSingleServer() throws Exception {
+        runTest("mongo-single-server-blueprint.yaml");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedTheeTierApp.java
----------------------------------------------------------------------
diff --git a/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedTheeTierApp.java b/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedTheeTierApp.java
index 273d130..7a45b62 100644
--- a/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedTheeTierApp.java
+++ b/usage/qa/src/main/java/org/apache/brooklyn/qa/load/SimulatedTheeTierApp.java
@@ -44,7 +44,7 @@ import brooklyn.entity.webapp.JavaWebAppService;
 import brooklyn.entity.webapp.WebAppService;
 import brooklyn.entity.webapp.WebAppServiceConstants;
 import brooklyn.entity.webapp.jboss.JBoss7Server;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.location.basic.PortRanges;
 import brooklyn.policy.autoscaling.AutoScalerPolicy;
 import brooklyn.util.CommandLineUtil;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/qa/src/test/java/org/apache/brooklyn/qa/brooklynnode/SoftlayerObtainPrivateLiveTest.java
----------------------------------------------------------------------
diff --git a/usage/qa/src/test/java/org/apache/brooklyn/qa/brooklynnode/SoftlayerObtainPrivateLiveTest.java b/usage/qa/src/test/java/org/apache/brooklyn/qa/brooklynnode/SoftlayerObtainPrivateLiveTest.java
index 17df429..401a37a 100644
--- a/usage/qa/src/test/java/org/apache/brooklyn/qa/brooklynnode/SoftlayerObtainPrivateLiveTest.java
+++ b/usage/qa/src/test/java/org/apache/brooklyn/qa/brooklynnode/SoftlayerObtainPrivateLiveTest.java
@@ -38,7 +38,7 @@ import brooklyn.entity.brooklynnode.BrooklynEntityMirror;
 import brooklyn.entity.brooklynnode.BrooklynNode;
 import brooklyn.entity.brooklynnode.BrooklynNode.DeployBlueprintEffector;
 import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.location.Location;
 import brooklyn.location.jclouds.JcloudsLocationConfig;
 import brooklyn.management.ManagementContext;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java
----------------------------------------------------------------------
diff --git a/usage/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java b/usage/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java
index d6c479c..2bed408 100644
--- a/usage/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java
+++ b/usage/qa/src/test/java/org/apache/brooklyn/qa/load/LoadTest.java
@@ -40,7 +40,7 @@ import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.rebind.persister.PersistMode;
 import brooklyn.entity.trait.Startable;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.location.Location;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.ha.HighAvailabilityMode;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/qa/src/test/java/org/apache/brooklyn/qa/longevity/webcluster/WebClusterApp.java
----------------------------------------------------------------------
diff --git a/usage/qa/src/test/java/org/apache/brooklyn/qa/longevity/webcluster/WebClusterApp.java b/usage/qa/src/test/java/org/apache/brooklyn/qa/longevity/webcluster/WebClusterApp.java
index 0d3d694..a9809c1 100644
--- a/usage/qa/src/test/java/org/apache/brooklyn/qa/longevity/webcluster/WebClusterApp.java
+++ b/usage/qa/src/test/java/org/apache/brooklyn/qa/longevity/webcluster/WebClusterApp.java
@@ -31,7 +31,7 @@ import brooklyn.entity.webapp.ControlledDynamicWebAppCluster;
 import brooklyn.entity.webapp.jboss.JBoss7Server;
 import brooklyn.event.AttributeSensor;
 import brooklyn.event.basic.Sensors;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.policy.EnricherSpec;
 import brooklyn.policy.autoscaling.AutoScalerPolicy;
 import brooklyn.util.CommandLineUtil;


[2/8] incubator-brooklyn git commit: brooklyn-launcher: add org.apache package prefix

Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java
new file mode 100644
index 0000000..66a9f67
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java
@@ -0,0 +1,258 @@
+/*
+ * 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.brooklyn.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.File;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.entity.Application;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.RebindTestUtils;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.HighAvailabilityMode;
+import brooklyn.management.ha.ManagementPlaneSyncRecordPersister;
+import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.test.Asserts;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.os.Os;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.common.io.Files;
+
+public class BrooklynLauncherHighAvailabilityTest {
+
+    private static final Logger log = LoggerFactory.getLogger(BrooklynLauncherHighAvailabilityTest.class);
+    
+    private static final Duration TIMEOUT = Duration.THIRTY_SECONDS;
+    
+    private BrooklynLauncher primary;
+    private BrooklynLauncher secondary;
+    private BrooklynLauncher tertiary;
+    private File persistenceDir;
+
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        persistenceDir = Files.createTempDir();
+        Os.deleteOnExitRecursively(persistenceDir);
+    }
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (primary != null) primary.terminate();
+        primary = null;
+        if (secondary != null) secondary.terminate();
+        secondary = null;
+        if (tertiary != null) tertiary.terminate();
+        tertiary = null;
+        if (persistenceDir != null) RebindTestUtils.deleteMementoDir(persistenceDir);
+        persistenceDir = null;
+    }
+    
+    @Test
+    public void testStandbyTakesOverWhenPrimaryTerminatedGracefully() throws Exception {
+        doTestStandbyTakesOver(true);
+    }
+
+    @Test(invocationCount=10, groups="Integration")
+    /** test issues with termination and promotion; 
+     * previously we got FileNotFound errors, though these should be fixed with
+     * the various PersistenceObjectStore prepare methods */
+    public void testStandbyTakesOverWhenPrimaryTerminatedGracefullyManyTimes() throws Exception {
+        testStandbyTakesOverWhenPrimaryTerminatedGracefully();
+    }
+
+    @Test(groups="Integration") // because slow waiting for timeouts to promote standbys
+    public void testStandbyTakesOverWhenPrimaryFails() throws Exception {
+        doTestStandbyTakesOver(false);
+    }
+    
+    protected void doTestStandbyTakesOver(boolean stopGracefully) throws Exception {
+        log.info("STARTING standby takeover test");
+        primary = BrooklynLauncher.newInstance();
+        primary.webconsole(false)
+                .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+                .highAvailabilityMode(HighAvailabilityMode.AUTO)
+                .persistMode(PersistMode.AUTO)
+                .persistenceDir(persistenceDir)
+                .persistPeriod(Duration.millis(10))
+                .haHeartbeatPeriod(Duration.millis(10))
+                .haHeartbeatTimeout(Duration.millis(1000))
+                .application(EntitySpec.create(TestApplication.class))
+                .start();
+        ManagementContext primaryManagementContext = primary.getServerDetails().getManagementContext();
+        log.info("started mgmt primary "+primaryManagementContext);
+        
+        assertOnlyApp(primary.getServerDetails().getManagementContext(), TestApplication.class);
+        primaryManagementContext.getRebindManager().getPersister().waitForWritesCompleted(TIMEOUT);
+        
+        // Secondary will come up as standby
+        secondary = BrooklynLauncher.newInstance();
+        secondary.webconsole(false)
+                .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+                .highAvailabilityMode(HighAvailabilityMode.AUTO)
+                .persistMode(PersistMode.AUTO)
+                .persistenceDir(persistenceDir)
+                .persistPeriod(Duration.millis(10))
+                .haHeartbeatPeriod(Duration.millis(10))
+                .haHeartbeatTimeout(Duration.millis(1000))
+                .start();
+        ManagementContext secondaryManagementContext = secondary.getServerDetails().getManagementContext();
+        log.info("started mgmt secondary "+secondaryManagementContext);
+        
+        // TODO can assert it sees the apps read only
+//        assertNoApps(secondary.getServerDetails().getManagementContext());
+
+        // Terminate primary; expect secondary to take over
+        if (stopGracefully) {
+            ((ManagementContextInternal)primaryManagementContext).terminate();
+        } else {
+            ManagementPlaneSyncRecordPersister planePersister = ((ManagementContextInternal)primaryManagementContext).getHighAvailabilityManager().getPersister();
+            planePersister.stop(); // can no longer write heartbeats
+            ((ManagementContextInternal)primaryManagementContext).terminate();
+        }
+        
+        assertOnlyAppEventually(secondaryManagementContext, TestApplication.class);
+        
+        // Start tertiary (force up as standby)
+        tertiary = BrooklynLauncher.newInstance();
+        tertiary.webconsole(false)
+                .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+                .highAvailabilityMode(HighAvailabilityMode.STANDBY)
+                .persistMode(PersistMode.AUTO)
+                .persistenceDir(persistenceDir)
+                .persistPeriod(Duration.millis(10))
+                .haHeartbeatPeriod(Duration.millis(10))
+                .haHeartbeatTimeout(Duration.millis(1000))
+                .start();
+        ManagementContext tertiaryManagementContext = tertiary.getServerDetails().getManagementContext();
+        log.info("started mgmt tertiary "+primaryManagementContext);
+        
+        assertNoApps(tertiary.getServerDetails().getManagementContext());
+
+        // Terminate secondary; expect tertiary to take over
+        if (stopGracefully) {
+            ((ManagementContextInternal)secondaryManagementContext).terminate();
+        } else {
+            ManagementPlaneSyncRecordPersister planePersister = ((ManagementContextInternal)secondaryManagementContext).getHighAvailabilityManager().getPersister();
+            planePersister.stop(); // can no longer write heartbeats
+            ((ManagementContextInternal)secondaryManagementContext).terminate();
+        }
+        
+        assertOnlyAppEventually(tertiaryManagementContext, TestApplication.class);
+    }
+    
+    public void testHighAvailabilityMasterModeFailsIfAlreadyHasMaster() throws Exception {
+        primary = BrooklynLauncher.newInstance();
+        primary.webconsole(false)
+                .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+                .highAvailabilityMode(HighAvailabilityMode.AUTO)
+                .persistMode(PersistMode.AUTO)
+                .persistenceDir(persistenceDir)
+                .persistPeriod(Duration.millis(10))
+                .application(EntitySpec.create(TestApplication.class))
+                .start();
+
+        try {
+            // Secondary will come up as standby
+            secondary = BrooklynLauncher.newInstance();
+            secondary.webconsole(false)
+                    .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+                    .highAvailabilityMode(HighAvailabilityMode.MASTER)
+                    .persistMode(PersistMode.AUTO)
+                    .persistenceDir(persistenceDir)
+                    .persistPeriod(Duration.millis(10))
+                    .start();
+            fail();
+        } catch (IllegalStateException e) {
+            // success
+        }
+    }
+    
+    @Test
+    public void testHighAvailabilityStandbyModeFailsIfNoExistingMaster() throws Exception {
+        try {
+            primary = BrooklynLauncher.newInstance();
+            primary.webconsole(false)
+                    .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+                    .highAvailabilityMode(HighAvailabilityMode.STANDBY)
+                    .persistMode(PersistMode.AUTO)
+                    .persistenceDir(persistenceDir)
+                    .persistPeriod(Duration.millis(10))
+                    .ignorePersistenceErrors(false)
+                    .application(EntitySpec.create(TestApplication.class))
+                    .start();
+            fail();
+        } catch (IllegalStateException e) {
+            // success
+        }
+    }
+    
+    @Test
+    public void testHighAvailabilityHotStandbyModeFailsIfNoExistingMaster() throws Exception {
+        try {
+            primary = BrooklynLauncher.newInstance();
+            primary.webconsole(false)
+                    .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
+                    .highAvailabilityMode(HighAvailabilityMode.HOT_STANDBY)
+                    .persistMode(PersistMode.AUTO)
+                    .persistenceDir(persistenceDir)
+                    .persistPeriod(Duration.millis(10))
+                    .ignorePersistenceErrors(false)
+                    .application(EntitySpec.create(TestApplication.class))
+                    .start();
+            fail();
+        } catch (IllegalStateException e) {
+            // success
+        }
+    }
+    
+    private void assertOnlyApp(ManagementContext managementContext, Class<? extends Application> expectedType) {
+        assertEquals(managementContext.getApplications().size(), 1, "apps="+managementContext.getApplications());
+        assertNotNull(Iterables.find(managementContext.getApplications(), Predicates.instanceOf(TestApplication.class), null), "apps="+managementContext.getApplications());
+    }
+    
+    private void assertNoApps(ManagementContext managementContext) {
+        if (!managementContext.getApplications().isEmpty())
+            log.warn("FAILED assertion (rethrowing), apps="+managementContext.getApplications());
+        assertTrue(managementContext.getApplications().isEmpty(), "apps="+managementContext.getApplications());
+    }
+    
+    private void assertOnlyAppEventually(final ManagementContext managementContext, final Class<? extends Application> expectedType) {
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                assertOnlyApp(managementContext, expectedType);
+            }});
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
new file mode 100644
index 0000000..48fb538
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.brooklyn.launcher;
+
+import java.io.File;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+
+import org.apache.brooklyn.catalog.BrooklynCatalog;
+import org.apache.brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.internal.CatalogInitialization;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.os.Os;
+
+public class BrooklynLauncherRebindCatalogTest {
+
+    private static final String TEST_VERSION = "test-version";
+    private static final String CATALOG_INITIAL = "classpath://rebind-test-catalog.bom";
+    private static final String CATALOG_ADDITIONS = "rebind-test-catalog-additions.bom";
+    private static final Iterable<String> EXPECTED_DEFAULT_IDS = ImmutableSet.of("one:" + TEST_VERSION, "two:" + TEST_VERSION);
+    private static final Iterable<String> EXPECTED_ADDED_IDS = ImmutableSet.of("three:" + TEST_VERSION, "four:" + TEST_VERSION);
+
+    private List<BrooklynLauncher> launchers = Lists.newCopyOnWriteArrayList();
+    
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        for (BrooklynLauncher launcher : launchers) {
+            launcher.terminate();
+        }
+        launchers.clear();
+    }
+    
+    private BrooklynLauncher newLauncherForTests(String persistenceDir) {
+        CatalogInitialization catalogInitialization = new CatalogInitialization(CATALOG_INITIAL, false, null, false);
+        BrooklynLauncher launcher = BrooklynLauncher.newInstance()
+                .brooklynProperties(LocalManagementContextForTests.builder(true).buildProperties())
+                .catalogInitialization(catalogInitialization)
+                .persistMode(PersistMode.AUTO)
+                .persistenceDir(persistenceDir)
+                .webconsole(false);
+        launchers.add(launcher);
+        return launcher;
+    }
+
+    @Test
+    public void testRebindDoesNotEffectCatalog() {
+        String persistenceDir = newTempPersistenceContainerName();
+
+        BrooklynLauncher launcher = newLauncherForTests(persistenceDir);
+        launcher.start();
+        BrooklynCatalog catalog = launcher.getServerDetails().getManagementContext().getCatalog();
+
+        assertCatalogConsistsOfIds(catalog.getCatalogItems(), EXPECTED_DEFAULT_IDS);
+
+        catalog.deleteCatalogItem("one", TEST_VERSION);
+        catalog.deleteCatalogItem("two", TEST_VERSION);
+
+        Assert.assertEquals(Iterables.size(catalog.getCatalogItems()), 0);
+
+        catalog.addItems(new ResourceUtils(this).getResourceAsString(CATALOG_ADDITIONS));
+
+        assertCatalogConsistsOfIds(catalog.getCatalogItems(), EXPECTED_ADDED_IDS);
+
+        launcher.terminate();
+
+        BrooklynLauncher newLauncher = newLauncherForTests(persistenceDir);
+        newLauncher.start();
+        assertCatalogConsistsOfIds(newLauncher.getServerDetails().getManagementContext().getCatalog().getCatalogItems(), EXPECTED_ADDED_IDS);
+    }
+
+    private void assertCatalogConsistsOfIds(Iterable<CatalogItem<Object, Object>> catalogItems, Iterable<String> ids) {
+        Iterable<String> idsFromItems = Iterables.transform(catalogItems, new Function<CatalogItem<?,?>, String>() {
+            @Nullable
+            @Override
+            public String apply(CatalogItem<?, ?> catalogItem) {
+                return catalogItem.getCatalogItemId();
+            }
+        });
+        Assert.assertTrue(Iterables.elementsEqual(ids, idsFromItems), String.format("Expected %s, found %s", ids, idsFromItems));
+    }
+
+    protected String newTempPersistenceContainerName() {
+        File persistenceDirF = Files.createTempDir();
+        Os.deleteOnExitRecursively(persistenceDirF);
+        return persistenceDirF.getAbsolutePath();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java
new file mode 100644
index 0000000..bd804b6
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java
@@ -0,0 +1,257 @@
+/*
+ * 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.brooklyn.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.entity.Application;
+import brooklyn.entity.basic.EntityPredicates;
+import brooklyn.entity.basic.StartableApplication;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.entity.rebind.persister.PersistenceObjectStore;
+import brooklyn.location.Location;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.HighAvailabilityMode;
+import brooklyn.test.Asserts;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.exceptions.FatalConfigurationRuntimeException;
+import brooklyn.util.time.Duration;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+public abstract class BrooklynLauncherRebindTestFixture {
+
+    @SuppressWarnings("unused")
+    private static final Logger log = LoggerFactory.getLogger(BrooklynLauncherRebindTestFixture.class);
+    
+    protected String persistenceDir;
+    protected String persistenceLocationSpec;
+    protected List<BrooklynLauncher> launchers = MutableList.of();
+    
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        persistenceDir = newTempPersistenceContainerName();
+    }
+    
+    protected abstract String newTempPersistenceContainerName();
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        for (BrooklynLauncher l: launchers) {
+            if (l.isStarted()) {
+                l.terminate();
+                PersistenceObjectStore store = getPersistenceStore(l.getServerDetails().getManagementContext());
+                if (store!=null) store.deleteCompletely();
+            }
+        }
+    }
+
+    protected BrooklynLauncher newLauncherBase() {
+        BrooklynLauncher l = BrooklynLauncher.newInstance()
+            .webconsole(false);
+        launchers.add(l);
+        return l;
+    }
+    protected BrooklynLauncher newLauncherDefault(PersistMode mode) {
+        return newLauncherBase()
+                .managementContext(newManagementContextForTests(null))
+                .persistMode(mode)
+                .persistenceDir(persistenceDir)
+                .persistPeriod(Duration.millis(10));
+    }
+    protected LocalManagementContextForTests newManagementContextForTests(BrooklynProperties props) {
+        if (props==null)
+            return new LocalManagementContextForTests();
+        else
+            return new LocalManagementContextForTests(props);
+    }
+
+    protected ManagementContext lastMgmt() {
+        return Iterables.getLast(launchers).getServerDetails().getManagementContext();
+    }
+    
+    @Test
+    public void testRebindsToExistingApp() throws Exception {
+        populatePersistenceDir(persistenceDir, EntitySpec.create(TestApplication.class).displayName("myorig"));
+        
+        // Rebind to the app we just started last time
+        
+        newLauncherDefault(PersistMode.REBIND).start();
+        
+        assertOnlyApp(lastMgmt(), TestApplication.class);
+        assertNotNull(Iterables.find(lastMgmt().getApplications(), EntityPredicates.displayNameEqualTo("myorig"), null), "apps="+lastMgmt().getApplications());
+    }
+
+    @Test
+    public void testRebindCanAddNewApps() throws Exception {
+        populatePersistenceDir(persistenceDir, EntitySpec.create(TestApplication.class).displayName("myorig"));
+        
+        // Rebind to the app we started last time
+        newLauncherDefault(PersistMode.REBIND)
+                .application(EntitySpec.create(TestApplication.class).displayName("mynew"))
+                .start();
+        
+        // New app was added, and orig app was rebound
+        assertEquals(lastMgmt().getApplications().size(), 2, "apps="+lastMgmt().getApplications());
+        assertNotNull(Iterables.find(lastMgmt().getApplications(), EntityPredicates.displayNameEqualTo("mynew"), null), "apps="+lastMgmt().getApplications());
+
+        // And subsequently can create new apps
+        StartableApplication app3 = lastMgmt().getEntityManager().createEntity(
+                EntitySpec.create(TestApplication.class).displayName("mynew2"));
+        app3.start(ImmutableList.<Location>of());
+    }
+
+    @Test
+    public void testAutoRebindsToExistingApp() throws Exception {
+        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
+        populatePersistenceDir(persistenceDir, appSpec);
+        
+        // Auto will rebind if the dir exists
+        newLauncherDefault(PersistMode.AUTO).start();
+        
+        assertOnlyApp(lastMgmt(), TestApplication.class);
+    }
+
+    @Test
+    public void testCleanDoesNotRebindToExistingApp() throws Exception {
+        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
+        populatePersistenceDir(persistenceDir, appSpec);
+        
+        // Auto will rebind if the dir exists
+        newLauncherDefault(PersistMode.CLEAN).start();
+        
+        assertTrue(lastMgmt().getApplications().isEmpty(), "apps="+lastMgmt().getApplications());
+    }
+
+    @Test
+    public void testAutoRebindCreatesNewIfEmptyDir() throws Exception {
+        // Auto will rebind if the dir exists
+        newLauncherDefault(PersistMode.AUTO)
+                .application(EntitySpec.create(TestApplication.class))
+                .start();
+        
+        assertOnlyApp(lastMgmt(), TestApplication.class);
+        assertMementoContainerNonEmptyForTypeEventually("entities");
+    }
+
+    @Test
+    public void testRebindRespectsPersistenceDirSetInProperties() throws Exception {
+        String persistenceDir2 = newTempPersistenceContainerName();
+        
+        BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newDefault();
+        brooklynProperties.put(BrooklynServerConfig.PERSISTENCE_DIR, persistenceDir2);
+        LocalManagementContextForTests mgmt = newManagementContextForTests(brooklynProperties);
+        
+        // Rebind to the app we started last time
+        newLauncherBase()
+                .persistMode(PersistMode.AUTO)
+                .persistPeriod(Duration.millis(10))
+                .managementContext(mgmt)
+                .start();
+        
+        checkPersistenceContainerNameIs(persistenceDir2);
+    }
+
+    // assumes default persistence dir is rebindable
+    @Test(groups="Integration")
+    public void testRebindRespectsDefaultPersistenceDir() throws Exception {
+        newLauncherDefault(PersistMode.AUTO)
+                .persistenceDir((String)null)
+                .start();
+        
+        checkPersistenceContainerNameIsDefault();
+    }
+    
+    protected abstract void checkPersistenceContainerNameIsDefault();
+    protected abstract void checkPersistenceContainerNameIs(String expected);
+
+    @Test
+    public void testPersistenceFailsIfNoDir() throws Exception {
+        runRebindFails(PersistMode.REBIND, badContainerName(), "does not exist");
+    }
+
+    protected abstract String badContainerName();
+
+    @Test
+    public void testExplicitRebindFailsIfEmpty() throws Exception {
+        runRebindFails(PersistMode.REBIND, persistenceDir, "directory is empty");
+    }
+
+    protected void runRebindFails(PersistMode persistMode, String dir, String errmsg) throws Exception {
+        try {
+            newLauncherDefault(persistMode)
+                    .persistenceDir(dir)
+                    .start();
+        } catch (FatalConfigurationRuntimeException e) {
+            if (!e.toString().contains(errmsg)) {
+                throw e;
+            }
+        }
+    }
+
+    protected void populatePersistenceDir(String dir, EntitySpec<? extends StartableApplication> appSpec) throws Exception {
+        BrooklynLauncher launcher = newLauncherDefault(PersistMode.CLEAN)
+                .highAvailabilityMode(HighAvailabilityMode.MASTER)
+                .persistenceDir(dir)
+                .application(appSpec)
+                .start();
+        launcher.terminate();
+        assertMementoContainerNonEmptyForTypeEventually("entities");
+    }
+    
+    protected void assertOnlyApp(ManagementContext managementContext, Class<? extends Application> expectedType) {
+        assertEquals(managementContext.getApplications().size(), 1, "apps="+managementContext.getApplications());
+        assertNotNull(Iterables.find(managementContext.getApplications(), Predicates.instanceOf(TestApplication.class), null), "apps="+managementContext.getApplications());
+    }
+    
+    protected void assertMementoContainerNonEmptyForTypeEventually(final String type) {
+        Asserts.succeedsEventually(ImmutableMap.of("timeout", Duration.TEN_SECONDS), new Runnable() {
+            @Override public void run() {
+                getPersistenceStore(lastMgmt()).listContentsWithSubPath(type);
+            }});
+    }
+
+    static PersistenceObjectStore getPersistenceStore(ManagementContext managementContext) {
+        if (managementContext==null) return null;
+        BrooklynMementoPersisterToObjectStore persister = (BrooklynMementoPersisterToObjectStore)managementContext.getRebindManager().getPersister();
+        if (persister==null) return null;
+        return persister.getObjectStore();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java
new file mode 100644
index 0000000..ee07f67
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java
@@ -0,0 +1,154 @@
+/*
+ * 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.brooklyn.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynServerPaths;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
+import brooklyn.entity.rebind.persister.FileBasedObjectStore;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.HighAvailabilityMode;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.javalang.JavaClassNames;
+import brooklyn.util.os.Os;
+import brooklyn.util.text.Identifiers;
+
+import com.google.common.base.Joiner;
+import com.google.common.io.Files;
+
+public class BrooklynLauncherRebindTestToFiles extends BrooklynLauncherRebindTestFixture {
+
+    protected String newTempPersistenceContainerName() {
+        File persistenceDirF = Files.createTempDir();
+        Os.deleteOnExitRecursively(persistenceDirF);
+        return persistenceDirF.getAbsolutePath();
+    }
+    
+    protected String badContainerName() {
+        return "/path/does/not/exist/"+Identifiers.makeRandomId(4);
+    }
+    
+    protected void checkPersistenceContainerNameIs(String expected) {
+        String expectedFqp = new File(Os.tidyPath(expected)).getAbsolutePath();
+        assertEquals(getPersistenceDir(lastMgmt()).getAbsolutePath(), expectedFqp);
+    }
+
+    static File getPersistenceDir(ManagementContext managementContext) {
+        BrooklynMementoPersisterToObjectStore persister = (BrooklynMementoPersisterToObjectStore)managementContext.getRebindManager().getPersister();
+        FileBasedObjectStore store = (FileBasedObjectStore)persister.getObjectStore();
+        return store.getBaseDir();
+    }
+
+    protected void checkPersistenceContainerNameIsDefault() {
+        String expected = BrooklynServerPaths.newMainPersistencePathResolver(BrooklynProperties.Factory.newEmpty()).location(null).dir(null).resolve();
+        checkPersistenceContainerNameIs(expected);
+    }
+
+    @Test
+    public void testPersistenceFailsIfIsFile() throws Exception {
+        File tempF = File.createTempFile("test-"+JavaClassNames.niceClassAndMethod(), ".not_dir");
+        tempF.deleteOnExit();
+        String tempFileName = tempF.getAbsolutePath();
+        
+        try {
+            runRebindFails(PersistMode.AUTO, tempFileName, "must not be a file");
+            runRebindFails(PersistMode.REBIND, tempFileName, "must not be a file");
+            runRebindFails(PersistMode.CLEAN, tempFileName, "must not be a file");
+        } finally {
+            new File(tempFileName).delete();
+        }
+    }
+    
+    @Test
+    public void testPersistenceFailsIfNotWritable() throws Exception {
+        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
+        populatePersistenceDir(persistenceDir, appSpec);
+        new File(persistenceDir).setWritable(false);
+        try {
+            runRebindFails(PersistMode.AUTO, persistenceDir, "not writable");
+            runRebindFails(PersistMode.REBIND, persistenceDir, "not writable");
+            runRebindFails(PersistMode.CLEAN, persistenceDir, "not writable");
+        } finally {
+            new File(persistenceDir).setWritable(true);
+        }
+    }
+
+    @Test
+    public void testPersistenceFailsIfNotReadable() throws Exception {
+        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
+        populatePersistenceDir(persistenceDir, appSpec);
+        new File(persistenceDir).setReadable(false);
+        try {
+            runRebindFails(PersistMode.AUTO, persistenceDir, "not readable");
+            runRebindFails(PersistMode.REBIND, persistenceDir, "not readable");
+            runRebindFails(PersistMode.CLEAN, persistenceDir, "not readable");
+        } finally {
+            new File(persistenceDir).setReadable(true);
+        }
+    }
+
+    @Test(groups="Integration")
+    public void testCopyPersistedState() throws Exception {
+        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
+        populatePersistenceDir(persistenceDir, appSpec);
+
+        File destinationDir = Files.createTempDir();
+        String destination = destinationDir.getAbsolutePath();
+        String destinationLocation = null; // i.e. file system, rather than object store
+        try {
+            // Auto will rebind if the dir exists
+            BrooklynLauncher launcher = newLauncherDefault(PersistMode.AUTO)
+                    .highAvailabilityMode(HighAvailabilityMode.MASTER)
+                    .webconsole(false);
+            launcher.copyPersistedState(destination, destinationLocation);
+            launcher.terminate();
+            
+            File entities = new File(Os.mergePaths(destination), "entities");
+            assertTrue(entities.isDirectory(), "entities directory should exist");
+            assertEquals(entities.listFiles().length, 1, "entities directory should contain one file (contained: "+
+                    Joiner.on(", ").join(entities.listFiles()) +")");
+
+            File nodes = new File(Os.mergePaths(destination, "nodes"));
+            assertTrue(nodes.isDirectory(), "nodes directory should exist");
+            assertNotEquals(nodes.listFiles().length, 0, "nodes directory should not be empty");
+
+            // Should now have a usable copy in the destinationDir
+            // Auto will rebind if the dir exists
+            newLauncherDefault(PersistMode.AUTO)
+                    .webconsole(false)
+                    .persistenceDir(destinationDir)
+                    .start();
+            assertOnlyApp(lastMgmt(), TestApplication.class);
+            
+        } finally {
+            Os.deleteRecursively(destinationDir);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java
new file mode 100644
index 0000000..b2aeaf9
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.brooklyn.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynServerPaths;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.entity.rebind.persister.jclouds.BlobStoreTest;
+import brooklyn.entity.rebind.persister.jclouds.JcloudsBlobStoreBasedObjectStore;
+import brooklyn.management.ManagementContext;
+import brooklyn.mementos.BrooklynMementoRawData;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.javalang.JavaClassNames;
+import brooklyn.util.os.Os;
+import brooklyn.util.text.Identifiers;
+
+@Test(groups="Live")
+public class BrooklynLauncherRebindToCloudObjectStoreTest extends BrooklynLauncherRebindTestFixture {
+
+    // FIXME BrooklynLauncherRebindToCloudObjectStoreTest.testCleanDoesNotRebindToExistingApp failed:
+    //     apps=[Application[mDNfOA7w]] expected [true] but found [false]
+    // Should it really delete everything in the bucket?! Only if we can back up first!
+
+    // FIXME brooklyn.util.exceptions.FatalRuntimeException: Error rebinding to persisted state: Writes not allowed in brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore@7d2f7563
+    //     at brooklyn.launcher.BrooklynLauncher.persistState(BrooklynLauncher.java:502)
+    //     at brooklyn.launcher.BrooklynLauncherRebindToCloudObjectStoreTest.testCopyPersistedState(BrooklynLauncherRebindToCloudObjectStoreTest.java:144)
+    // Presumably a previous run wasn't tearing down properly, so it joined as a standby rather than being master?! 
+    
+    { persistenceLocationSpec = BlobStoreTest.PERSIST_TO_OBJECT_STORE_FOR_TEST_SPEC; }
+
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        persistenceDir = newTempPersistenceContainerName();
+    }
+
+    @Override
+    protected BrooklynLauncher newLauncherBase() {
+        return super.newLauncherBase().persistenceLocation(persistenceLocationSpec);
+    }
+    
+    protected LocalManagementContextForTests newManagementContextForTests(BrooklynProperties props) {
+        BrooklynProperties p2 = BrooklynProperties.Factory.newDefault();
+        if (props!=null) p2.putAll(props);
+        return new LocalManagementContextForTests(p2);
+    }
+
+    @Override
+    protected String newTempPersistenceContainerName() {
+        return "test-"+JavaClassNames.callerStackElement(0).getClassName()+"-"+Identifiers.makeRandomId(4);
+    }
+    
+    protected String badContainerName() {
+        return "container-does-not-exist-"+Identifiers.makeRandomId(4);
+    }
+    
+    protected void checkPersistenceContainerNameIs(String expected) {
+        assertEquals(getPersistenceContainerName(lastMgmt()), expected);
+    }
+
+    static String getPersistenceContainerName(ManagementContext managementContext) {
+        BrooklynMementoPersisterToObjectStore persister = (BrooklynMementoPersisterToObjectStore)managementContext.getRebindManager().getPersister();
+        JcloudsBlobStoreBasedObjectStore store = (JcloudsBlobStoreBasedObjectStore)persister.getObjectStore();
+        return store.getContainerName();
+    }
+
+    protected void checkPersistenceContainerNameIsDefault() {
+        checkPersistenceContainerNameIs(BrooklynServerPaths.DEFAULT_PERSISTENCE_CONTAINER_NAME);
+    }
+
+    @Override @Test(groups="Live")
+    public void testRebindsToExistingApp() throws Exception {
+        super.testRebindsToExistingApp();
+    }
+
+    @Override @Test(groups="Live")
+    public void testRebindCanAddNewApps() throws Exception {
+        super.testRebindCanAddNewApps();
+    }
+
+    @Override @Test(groups="Live")
+    public void testAutoRebindsToExistingApp() throws Exception {
+        super.testAutoRebindsToExistingApp();
+    }
+
+    // TODO Marked as work-in-progress because "clean" does not backup and then clean out the existing
+    // object store's bucket. Unclear what best behaviour there should be: should we really delete
+    // the data?! We better be confident about our backup!
+    @Override @Test(groups={"Live", "WIP"})
+    public void testCleanDoesNotRebindToExistingApp() throws Exception {
+        super.testCleanDoesNotRebindToExistingApp();
+    }
+
+    @Override @Test(groups="Live")
+    public void testAutoRebindCreatesNewIfEmptyDir() throws Exception {
+        super.testAutoRebindCreatesNewIfEmptyDir();
+    }
+
+    @Override @Test(groups="Live")
+    public void testRebindRespectsPersistenceDirSetInProperties() throws Exception {
+        super.testRebindRespectsPersistenceDirSetInProperties();
+    }
+
+    @Override @Test(groups="Live")
+    public void testRebindRespectsDefaultPersistenceDir() throws Exception {
+        super.testRebindRespectsDefaultPersistenceDir();
+    }
+
+    @Override @Test(groups="Live")
+    public void testPersistenceFailsIfNoDir() throws Exception {
+        super.testPersistenceFailsIfNoDir();
+    }
+
+    @Override @Test(groups="Live")
+    public void testExplicitRebindFailsIfEmpty() throws Exception {
+        super.testExplicitRebindFailsIfEmpty();
+    }
+
+    // TODO Remove duplication from BrooklynLauncherRebindTestToFiles.testCopyPersistedState()
+    @Test(groups="Live")
+    public void testCopyPersistedState() throws Exception {
+        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
+        populatePersistenceDir(persistenceDir, appSpec);
+        
+        String destinationDir = newTempPersistenceContainerName();
+        String destinationLocation = persistenceLocationSpec;
+        try {
+            // Auto will rebind if the dir exists
+            BrooklynLauncher launcher = newLauncherDefault(PersistMode.AUTO)
+                    .webconsole(false)
+                    .persistenceLocation(persistenceLocationSpec);
+            BrooklynMementoRawData memento = launcher.retrieveState();
+            launcher.persistState(memento, destinationDir, destinationLocation);
+            launcher.terminate();
+            
+            assertEquals(memento.getEntities().size(), 1, "entityMementos="+memento.getEntities().keySet());
+            
+            // Should now have a usable copy in the destionationDir
+            // Auto will rebind if the dir exists
+            newLauncherDefault(PersistMode.AUTO)
+                    .webconsole(false)
+                    .persistenceDir(destinationDir)
+                    .persistenceLocation(destinationLocation)
+                    .start();
+            assertOnlyApp(lastMgmt(), TestApplication.class);
+            
+        } finally {
+            Os.deleteRecursively(destinationDir);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
new file mode 100644
index 0000000..df295d8
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherTest.java
@@ -0,0 +1,368 @@
+/*
+ * 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.brooklyn.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.util.Properties;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.catalog.internal.CatalogInitialization;
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.entity.Application;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.RebindTestUtils;
+import brooklyn.location.Location;
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.test.HttpTestUtils;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.test.entity.TestApplicationImpl;
+import brooklyn.test.entity.TestEntity;
+import brooklyn.util.exceptions.FatalRuntimeException;
+import brooklyn.util.io.FileUtil;
+import brooklyn.util.net.Urls;
+import brooklyn.util.os.Os;
+import brooklyn.util.text.StringFunctions;
+import brooklyn.util.text.Strings;
+
+import com.google.api.client.util.Preconditions;
+import com.google.common.base.Charsets;
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.google.common.io.Files;
+
+public class BrooklynLauncherTest {
+    
+    private BrooklynLauncher launcher;
+    private File persistenceDir;
+    
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (launcher != null) launcher.terminate();
+        if (persistenceDir != null) RebindTestUtils.deleteMementoDir(persistenceDir);
+        launcher = null;
+    }
+    
+    // Integration because takes a few seconds to start web-console
+    @Test(groups="Integration")
+    public void testStartsWebServerOnExpectectedPort() throws Exception {
+        launcher = newLauncherForTests(true)
+                .webconsolePort("10000+")
+                .start();
+        
+        String webServerUrlStr = launcher.getServerDetails().getWebServerUrl();
+        URI webServerUri = new URI(webServerUrlStr);
+        
+        assertEquals(launcher.getApplications(), ImmutableList.of());
+        assertTrue(webServerUri.getPort() >= 10000 && webServerUri.getPort() < 10100, "port="+webServerUri.getPort()+"; uri="+webServerUri);
+        HttpTestUtils.assertUrlReachable(webServerUrlStr);
+    }
+    
+    // Integration because takes a few seconds to start web-console
+    @Test(groups="Integration")
+    public void testWebServerTempDirRespectsDataDirConfig() throws Exception {
+        String dataDirName = ".brooklyn-foo"+Strings.makeRandomId(4);
+        String dataDir = "~/"+dataDirName;
+
+        launcher = newLauncherForTests(true)
+                .brooklynProperties(BrooklynServerConfig.MGMT_BASE_DIR, dataDir)
+                .start();
+        
+        ManagementContext managementContext = launcher.getServerDetails().getManagementContext();
+        String expectedTempDir = Os.mergePaths(Os.home(), dataDirName, "planes", managementContext.getManagementPlaneId(), managementContext.getManagementNodeId(), "jetty");
+        
+        File webappTempDir = launcher.getServerDetails().getWebServer().getWebappTempDir();
+        assertEquals(webappTempDir.getAbsolutePath(), expectedTempDir);
+    }
+    
+    @Test
+    public void testCanDisableWebServerStartup() throws Exception {
+        launcher = newLauncherForTests(true)
+                .webconsole(false)
+                .start();
+        
+        assertNull(launcher.getServerDetails().getWebServer());
+        assertNull(launcher.getServerDetails().getWebServerUrl());
+        Assert.assertTrue( ((ManagementContextInternal)launcher.getServerDetails().getManagementContext()).errors().isEmpty() );
+    }
+    
+    @Test
+    public void testStartsAppInstance() throws Exception {
+        launcher = newLauncherForTests(true)
+                .webconsole(false)
+                .application(new TestApplicationImpl())
+                .start();
+        
+        assertOnlyApp(launcher, TestApplication.class);
+    }
+    
+    @Test
+    public void testStartsAppFromSpec() throws Exception {
+        launcher = newLauncherForTests(true)
+                .webconsole(false)
+                .application(EntitySpec.create(TestApplication.class))
+                .start();
+        
+        assertOnlyApp(launcher, TestApplication.class);
+    }
+    
+    @Test
+    public void testStartsAppFromBuilder() throws Exception {
+        launcher = newLauncherForTests(true)
+                .webconsole(false)
+                .application(new ApplicationBuilder(EntitySpec.create(TestApplication.class)) {
+                        @Override protected void doBuild() {
+                        }})
+                .start();
+        
+        assertOnlyApp(launcher, TestApplication.class);
+    }
+
+    @Test
+    public void testStartsAppFromYAML() throws Exception {
+        String yaml = "name: example-app\n" +
+                "services:\n" +
+                "- serviceType: brooklyn.test.entity.TestEntity\n" +
+                "  name: test-app";
+        launcher = newLauncherForTests(true)
+                .webconsole(false)
+                .application(yaml)
+                .start();
+
+        assertEquals(launcher.getApplications().size(), 1, "apps="+launcher.getApplications());
+        Application app = Iterables.getOnlyElement(launcher.getApplications());
+        assertEquals(app.getChildren().size(), 1, "children=" + app.getChildren());
+        assertTrue(Iterables.getOnlyElement(app.getChildren()) instanceof TestEntity);
+    }
+    
+    @Test  // may take 2s initializing location if running this test case alone, but noise if running suite 
+    public void testStartsAppInSuppliedLocations() throws Exception {
+        launcher = newLauncherForTests(true)
+                .webconsole(false)
+                .location("localhost")
+                .application(new ApplicationBuilder(EntitySpec.create(TestApplication.class)) {
+                        @Override protected void doBuild() {
+                        }})
+                .start();
+        
+        Application app = Iterables.find(launcher.getApplications(), Predicates.instanceOf(TestApplication.class));
+        assertOnlyLocation(app, LocalhostMachineProvisioningLocation.class);
+    }
+    
+    @Test
+    public void testUsesSuppliedManagementContext() throws Exception {
+        LocalManagementContext myManagementContext = LocalManagementContextForTests.newInstance();
+        launcher = newLauncherForTests(false)
+                .webconsole(false)
+                .managementContext(myManagementContext)
+                .start();
+        
+        assertSame(launcher.getServerDetails().getManagementContext(), myManagementContext);
+    }
+    
+    @Test
+    public void testUsesSuppliedBrooklynProperties() throws Exception {
+        BrooklynProperties props = LocalManagementContextForTests.builder(true).buildProperties();
+        props.put("mykey", "myval");
+        launcher = newLauncherForTests(false)
+                .webconsole(false)
+                .brooklynProperties(props)
+                .start();
+        
+        assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("mykey"), "myval");
+    }
+
+    @Test
+    public void testUsesSupplementaryBrooklynProperties() throws Exception {
+        launcher = newLauncherForTests(true)
+                .webconsole(false)
+                .brooklynProperties("mykey", "myval")
+                .start();
+        
+        assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("mykey"), "myval");
+    }
+    
+    @Test
+    public void testReloadBrooklynPropertiesRestoresProgrammaticProperties() throws Exception {
+        launcher = newLauncherForTests(true)
+                .webconsole(false)
+                .brooklynProperties("mykey", "myval")
+                .start();
+        LocalManagementContext managementContext = (LocalManagementContext)launcher.getServerDetails().getManagementContext();
+        assertEquals(managementContext.getConfig().getFirst("mykey"), "myval");
+        managementContext.getBrooklynProperties().put("mykey", "newval");
+        assertEquals(managementContext.getConfig().getFirst("mykey"), "newval");
+        managementContext.reloadBrooklynProperties();
+        assertEquals(managementContext.getConfig().getFirst("mykey"), "myval");
+    }
+    
+    @Test
+    public void testReloadBrooklynPropertiesFromFile() throws Exception {
+        File globalPropertiesFile = File.createTempFile("local-brooklyn-properties-test", ".properties");
+        FileUtil.setFilePermissionsTo600(globalPropertiesFile);
+        try {
+            String property = "mykey=myval";
+            Files.append(getMinimalLauncherPropertiesString()+property, globalPropertiesFile, Charsets.UTF_8);
+            launcher = newLauncherForTests(false)
+                    .webconsole(false)
+                    .globalBrooklynPropertiesFile(globalPropertiesFile.getAbsolutePath())
+                    .start();
+            LocalManagementContext managementContext = (LocalManagementContext)launcher.getServerDetails().getManagementContext();
+            assertEquals(managementContext.getConfig().getFirst("mykey"), "myval");
+            property = "mykey=newval";
+            Files.write(getMinimalLauncherPropertiesString()+property, globalPropertiesFile, Charsets.UTF_8);
+            managementContext.reloadBrooklynProperties();
+            assertEquals(managementContext.getConfig().getFirst("mykey"), "newval");
+        } finally {
+            globalPropertiesFile.delete();
+        }
+    }
+
+    @Test(groups="Integration")
+    public void testChecksGlobalBrooklynPropertiesPermissionsX00() throws Exception {
+        File propsFile = File.createTempFile("testChecksGlobalBrooklynPropertiesPermissionsX00", ".properties");
+        propsFile.setReadable(true, false);
+        try {
+            launcher = newLauncherForTests(false)
+                    .webconsole(false)
+                    .globalBrooklynPropertiesFile(propsFile.getAbsolutePath())
+                    .start();
+
+            Assert.fail("Should have thrown");
+        } catch (FatalRuntimeException e) {
+            if (!e.toString().contains("Invalid permissions for file")) throw e;
+        } finally {
+            propsFile.delete();
+        }
+    }
+
+    @Test(groups="Integration")
+    public void testChecksLocalBrooklynPropertiesPermissionsX00() throws Exception {
+        File propsFile = File.createTempFile("testChecksLocalBrooklynPropertiesPermissionsX00", ".properties");
+        propsFile.setReadable(true, false);
+        try {
+            launcher = newLauncherForTests(false)
+                    .webconsole(false)
+                    .localBrooklynPropertiesFile(propsFile.getAbsolutePath())
+                    .start();
+            
+            Assert.fail("Should have thrown");
+        } catch (FatalRuntimeException e) {
+            if (!e.toString().contains("Invalid permissions for file")) throw e;
+        } finally {
+            propsFile.delete();
+        }
+    }
+
+    @Test(groups="Integration")
+    public void testStartsWithBrooklynPropertiesPermissionsX00() throws Exception {
+        File globalPropsFile = File.createTempFile("testChecksLocalBrooklynPropertiesPermissionsX00_global", ".properties");
+        Files.write(getMinimalLauncherPropertiesString()+"key_in_global=1", globalPropsFile, Charset.defaultCharset());
+        File localPropsFile = File.createTempFile("testChecksLocalBrooklynPropertiesPermissionsX00_local", ".properties");
+        Files.write("key_in_local=2", localPropsFile, Charset.defaultCharset());
+        FileUtil.setFilePermissionsTo600(globalPropsFile);
+        FileUtil.setFilePermissionsTo600(localPropsFile);
+        try {
+            launcher = newLauncherForTests(false)
+                    .webconsole(false)
+                    .localBrooklynPropertiesFile(localPropsFile.getAbsolutePath())
+                    .globalBrooklynPropertiesFile(globalPropsFile.getAbsolutePath())
+                    .start();
+            assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("key_in_global"), "1");
+            assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("key_in_local"), "2");
+        } finally {
+            globalPropsFile.delete();
+            localPropsFile.delete();
+        }
+    }
+    
+    @Test  // takes a bit of time because starts webapp, but also tests rest api so useful
+    public void testErrorsCaughtByApiAndRestApiWorks() throws Exception {
+        launcher = newLauncherForTests(true)
+                .catalogInitialization(new CatalogInitialization(null, false, null, false).addPopulationCallback(new Function<CatalogInitialization, Void>() {
+                    @Override
+                    public Void apply(CatalogInitialization input) {
+                        throw new RuntimeException("deliberate-exception-for-testing");
+                    }
+                }))
+                .start();
+        // such an error should be thrown, then caught in this calling thread
+        ManagementContext mgmt = launcher.getServerDetails().getManagementContext();
+        Assert.assertFalse( ((ManagementContextInternal)mgmt).errors().isEmpty() );
+        Assert.assertTrue( ((ManagementContextInternal)mgmt).errors().get(0).toString().contains("deliberate"), ""+((ManagementContextInternal)mgmt).errors() );
+        HttpTestUtils.assertContentMatches(
+            Urls.mergePaths(launcher.getServerDetails().getWebServerUrl(), "v1/server/up"), 
+            "true");
+        HttpTestUtils.assertContentMatches(
+            Urls.mergePaths(launcher.getServerDetails().getWebServerUrl(), "v1/server/healthy"), 
+            "false");
+        // TODO test errors api?
+    }
+
+    private BrooklynLauncher newLauncherForTests(boolean minimal) {
+        Preconditions.checkArgument(launcher==null, "can only be used if no launcher yet");
+        BrooklynLauncher launcher = BrooklynLauncher.newInstance();
+        if (minimal)
+            launcher.brooklynProperties(LocalManagementContextForTests.builder(true).buildProperties());
+        return launcher;
+    }
+
+    private String getMinimalLauncherPropertiesString() throws IOException {
+        BrooklynProperties p1 = LocalManagementContextForTests.builder(true).buildProperties();
+        Properties p = new Properties();
+        p.putAll(Maps.transformValues(p1.asMapWithStringKeys(), StringFunctions.toStringFunction()));
+        Writer w = new StringWriter();
+        p.store(w, "test");
+        w.close();
+        return w.toString()+"\n";
+    }
+
+    private void assertOnlyApp(BrooklynLauncher launcher, Class<? extends Application> expectedType) {
+        assertEquals(launcher.getApplications().size(), 1, "apps="+launcher.getApplications());
+        assertNotNull(Iterables.find(launcher.getApplications(), Predicates.instanceOf(TestApplication.class), null), "apps="+launcher.getApplications());
+    }
+    
+    private void assertOnlyLocation(Application app, Class<? extends Location> expectedType) {
+        assertEquals(app.getLocations().size(), 1, "locs="+app.getLocations());
+        assertNotNull(Iterables.find(app.getLocations(), Predicates.instanceOf(LocalhostMachineProvisioningLocation.class), null), "locs="+app.getLocations());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
new file mode 100644
index 0000000..9510754
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynWebServerTest.java
@@ -0,0 +1,210 @@
+/*
+ * 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.brooklyn.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynWebServer;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.entity.basic.Entities;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.rest.BrooklynWebConfig;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.http.HttpTool;
+import brooklyn.util.http.HttpToolResponse;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+
+public class BrooklynWebServerTest {
+
+    public static final Logger log = LoggerFactory.getLogger(BrooklynWebServer.class);
+
+    private BrooklynProperties brooklynProperties;
+    private BrooklynWebServer webServer;
+    private List<LocalManagementContext> managementContexts = Lists.newCopyOnWriteArrayList();
+    
+    @BeforeMethod(alwaysRun=true)
+    public void setUp(){
+        brooklynProperties = BrooklynProperties.Factory.newEmpty();
+    }
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        for (LocalManagementContext managementContext : managementContexts) {
+            Entities.destroyAll(managementContext);
+        }
+        managementContexts.clear();
+        if (webServer != null) webServer.stop();
+    }
+    
+    private LocalManagementContext newManagementContext(BrooklynProperties brooklynProperties) {
+        LocalManagementContext result = new LocalManagementContextForTests(brooklynProperties);
+        managementContexts.add(result);
+        return result;
+    }
+    
+    @Test
+    public void verifyHttp() throws Exception {
+        webServer = new BrooklynWebServer(newManagementContext(brooklynProperties));
+        try {
+            webServer.start();
+    
+            HttpToolResponse response = HttpTool.execAndConsume(new DefaultHttpClient(), new HttpGet(webServer.getRootUrl()));
+            assertEquals(response.getResponseCode(), 200);
+        } finally {
+            webServer.stop();
+        }
+    }
+
+    @DataProvider(name="keystorePaths")
+    public Object[][] getKeystorePaths() {
+        return new Object[][] {
+                {getFile("server.ks")},
+                {new File(getFile("server.ks")).toURI().toString()},
+                {"classpath://server.ks"}};
+    }
+    
+    @Test(dataProvider="keystorePaths")
+    public void verifyHttps(String keystoreUrl) throws Exception {
+        Map<String,?> flags = ImmutableMap.<String,Object>builder()
+                .put("httpsEnabled", true)
+                .put("keystoreUrl", keystoreUrl)
+                .put("keystorePassword", "password")
+                .build();
+        webServer = new BrooklynWebServer(flags, newManagementContext(brooklynProperties));
+        webServer.start();
+        
+        try {
+            KeyStore keyStore = load("client.ks", "password");
+            KeyStore trustStore = load("client.ts", "password");
+            SSLSocketFactory socketFactory = new SSLSocketFactory(SSLSocketFactory.TLS, keyStore, "password", trustStore, (SecureRandom)null, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+
+            HttpToolResponse response = HttpTool.execAndConsume(
+                    HttpTool.httpClientBuilder()
+                            .port(webServer.getActualPort())
+                            .https(true)
+                            .socketFactory(socketFactory)
+                            .build(),
+                    new HttpGet(webServer.getRootUrl()));
+            assertEquals(response.getResponseCode(), 200);
+        } finally {
+            webServer.stop();
+        }
+    }
+
+    @Test
+    public void verifyHttpsFromConfig() throws Exception {
+        brooklynProperties.put(BrooklynWebConfig.HTTPS_REQUIRED, true);
+        brooklynProperties.put(BrooklynWebConfig.KEYSTORE_URL, getFile("server.ks"));
+        brooklynProperties.put(BrooklynWebConfig.KEYSTORE_PASSWORD, "password");
+        verifyHttpsFromConfig(brooklynProperties);
+    }
+
+    @Test
+    public void verifyHttpsCiphers() throws Exception {
+        brooklynProperties.put(BrooklynWebConfig.HTTPS_REQUIRED, true);
+        brooklynProperties.put(BrooklynWebConfig.TRANSPORT_PROTOCOLS, "XXX");
+        brooklynProperties.put(BrooklynWebConfig.TRANSPORT_CIPHERS, "XXX");
+        try {
+            verifyHttpsFromConfig(brooklynProperties);
+            fail("Expected to fail due to unsupported ciphers during connection negotiation");
+        } catch (Exception e) {
+            assertTrue(Exceptions.getFirstThrowableOfType(e, SSLPeerUnverifiedException.class) != null ||
+                    Exceptions.getFirstThrowableOfType(e, SSLHandshakeException.class) != null,
+                    "Expected to fail due to inability to negotiate");
+        }
+    }
+
+    private void verifyHttpsFromConfig(BrooklynProperties brooklynProperties) throws Exception {
+        webServer = new BrooklynWebServer(MutableMap.of(), newManagementContext(brooklynProperties));
+        webServer.start();
+        
+        try {
+            KeyStore keyStore = load("client.ks", "password");
+            KeyStore trustStore = load("client.ts", "password");
+            SSLSocketFactory socketFactory = new SSLSocketFactory(SSLSocketFactory.TLS, keyStore, "password", trustStore, (SecureRandom)null, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+
+            HttpToolResponse response = HttpTool.execAndConsume(
+                    HttpTool.httpClientBuilder()
+                            .port(webServer.getActualPort())
+                            .https(true)
+                            .socketFactory(socketFactory)
+                            .build(),
+                    new HttpGet(webServer.getRootUrl()));
+            assertEquals(response.getResponseCode(), 200);
+        } finally {
+            webServer.stop();
+        }
+    }
+
+    private KeyStore load(String name, String password) throws Exception {
+        KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+        FileInputStream instream = new FileInputStream(new File(getFile(name)));
+        keystore.load(instream, password.toCharArray());
+        return keystore;
+    }
+    
+    @Test
+    public void testGetFileFromUrl() throws Exception {
+        // On Windows will treat as relative paths
+        String url = "file:///tmp/special%40file%20with%20spaces";
+        String file = "/tmp/special@file with spaces";
+        assertEquals(getFile(new URL(url)), new File(file).getAbsolutePath());
+    }
+
+    private String getFile(String classpathResource) {
+        // this works because both IDE and Maven run tests with classes/resources on the file system
+        return getFile(getClass().getResource("/" + classpathResource));
+    }
+
+    private String getFile(URL url) {
+        try {
+            return new File(url.toURI()).getAbsolutePath();
+        } catch (URISyntaxException e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/SimpleYamlLauncherForTests.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/SimpleYamlLauncherForTests.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/SimpleYamlLauncherForTests.java
new file mode 100644
index 0000000..b2dfc5b
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/SimpleYamlLauncherForTests.java
@@ -0,0 +1,31 @@
+/*
+ * 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.brooklyn.launcher;
+
+import org.apache.brooklyn.launcher.camp.SimpleYamlLauncher;
+import brooklyn.management.ManagementContext;
+import brooklyn.test.entity.LocalManagementContextForTests;
+
+public class SimpleYamlLauncherForTests extends SimpleYamlLauncher {
+
+    protected ManagementContext newManagementContext() {
+        return new LocalManagementContextForTests();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java
new file mode 100644
index 0000000..3aa6334
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/WebAppRunnerTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.brooklyn.launcher;
+
+import org.apache.brooklyn.launcher.BrooklynWebServer;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynServerDetails;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.test.TestResourceUnavailableException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.config.BrooklynProperties;
+import brooklyn.entity.basic.Entities;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.test.HttpTestUtils;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.net.Networking;
+
+import com.google.common.collect.Lists;
+
+
+/**
+ * These tests require the brooklyn.war to work. (Should be placed by maven build.)
+ */
+public class WebAppRunnerTest {
+
+    public static final Logger log = LoggerFactory.getLogger(WebAppRunnerTest.class);
+            
+    List<LocalManagementContext> managementContexts = Lists.newCopyOnWriteArrayList();
+    
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        for (LocalManagementContext managementContext : managementContexts) {
+            Entities.destroyAll(managementContext);
+        }
+        managementContexts.clear();
+    }
+    
+    LocalManagementContext newManagementContext(BrooklynProperties brooklynProperties) {
+        LocalManagementContext result = new LocalManagementContext(brooklynProperties);
+        managementContexts.add(result);
+        return result;
+    }
+    
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    BrooklynWebServer createWebServer(Map properties) {
+        Map bigProps = MutableMap.copyOf(properties);
+        Map attributes = MutableMap.copyOf( (Map) bigProps.get("attributes") );
+        bigProps.put("attributes", attributes);
+
+        BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newEmpty();
+        brooklynProperties.putAll(bigProps);
+        brooklynProperties.put("brooklyn.webconsole.security.provider","brooklyn.rest.security.provider.AnyoneSecurityProvider");
+        brooklynProperties.put("brooklyn.webconsole.security.https.required","false");
+        return new BrooklynWebServer(bigProps, newManagementContext(brooklynProperties));
+    }
+    
+    @Test
+    public void testStartWar1() throws Exception {
+        if (!Networking.isPortAvailable(8090))
+            fail("Another process is using port 8090 which is required for this test.");
+        BrooklynWebServer server = createWebServer(MutableMap.of("port", 8090));
+        assertNotNull(server);
+        
+        try {
+            server.start();
+            assertBrooklynEventuallyAt("http://localhost:8090/");
+        } finally {
+            server.stop();
+        }
+    }
+
+    public static void assertBrooklynEventuallyAt(String url) {
+        HttpTestUtils.assertContentEventuallyContainsText(url, "Brooklyn Web Console");
+    }
+
+    @Test
+    public void testStartSecondaryWar() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
+
+        if (!Networking.isPortAvailable(8090))
+            fail("Another process is using port 8090 which is required for this test.");
+        BrooklynWebServer server = createWebServer(
+            MutableMap.of("port", 8090, "war", "brooklyn.war", "wars", MutableMap.of("hello", "hello-world.war")) );
+        assertNotNull(server);
+        
+        try {
+            server.start();
+
+            assertBrooklynEventuallyAt("http://localhost:8090/");
+            HttpTestUtils.assertContentEventuallyContainsText("http://localhost:8090/hello",
+                "This is the home page for a sample application");
+
+        } finally {
+            server.stop();
+        }
+    }
+
+    @Test
+    public void testStartSecondaryWarAfter() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
+
+        if (!Networking.isPortAvailable(8090))
+            fail("Another process is using port 8090 which is required for this test.");
+        BrooklynWebServer server = createWebServer(MutableMap.of("port", 8090, "war", "brooklyn.war"));
+        assertNotNull(server);
+        
+        try {
+            server.start();
+            server.deploy("/hello", "hello-world.war");
+
+            assertBrooklynEventuallyAt("http://localhost:8090/");
+            HttpTestUtils.assertContentEventuallyContainsText("http://localhost:8090/hello",
+                "This is the home page for a sample application");
+
+        } finally {
+            server.stop();
+        }
+    }
+
+    @Test
+    public void testStartWithLauncher() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
+
+        BrooklynLauncher launcher = BrooklynLauncher.newInstance()
+                .brooklynProperties(BrooklynProperties.Factory.newEmpty())
+                .brooklynProperties("brooklyn.webconsole.security.provider","brooklyn.rest.security.provider.AnyoneSecurityProvider")
+                .webapp("/hello", "hello-world.war")
+                .start();
+        BrooklynServerDetails details = launcher.getServerDetails();
+        
+        try {
+            details.getWebServer().deploy("/hello2", "hello-world.war");
+
+            assertBrooklynEventuallyAt(details.getWebServerUrl());
+            HttpTestUtils.assertContentEventuallyContainsText(details.getWebServerUrl()+"hello", "This is the home page for a sample application");
+            HttpTestUtils.assertContentEventuallyContainsText(details.getWebServerUrl()+"hello2", "This is the home page for a sample application");
+            HttpTestUtils.assertHttpStatusCodeEventuallyEquals(details.getWebServerUrl()+"hello0", 404);
+
+        } finally {
+            details.getWebServer().stop();
+            ((ManagementContextInternal)details.getManagementContext()).terminate();
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/launcher/YamlLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/launcher/YamlLauncher.java b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/YamlLauncher.java
new file mode 100644
index 0000000..f383895
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/launcher/YamlLauncher.java
@@ -0,0 +1,35 @@
+/*
+ * 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.brooklyn.launcher;
+
+import org.apache.brooklyn.launcher.camp.SimpleYamlLauncher;
+
+public class YamlLauncher {
+
+    public static void main(String[] args) {
+        SimpleYamlLauncher l = new SimpleYamlLauncher();
+        l.setShutdownAppsOnExit(true);
+        
+        l.launchAppYaml("java-web-app-and-db-with-function.yaml");
+//        l.launchAppYaml("java-web-app-and-memsql.yaml");
+//        l.launchAppYaml("memsql.yaml");
+//        l.launchAppYaml("classpath://mongo-blueprint.yaml");
+    }
+
+}


[6/8] incubator-brooklyn git commit: brooklyn-launcher: add org.apache package prefix

Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java
deleted file mode 100644
index 9b46624..0000000
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynWebServer.java
+++ /dev/null
@@ -1,652 +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 brooklyn.launcher;
-
-import java.io.File;
-import java.io.InputStream;
-import java.net.InetAddress;
-import java.net.URI;
-import java.security.KeyPair;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.EnumSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.Nullable;
-import javax.servlet.DispatcherType;
-
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.nio.SelectChannelConnector;
-import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
-import org.eclipse.jetty.servlet.FilterHolder;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-import org.eclipse.jetty.util.thread.QueuedThreadPool;
-import org.eclipse.jetty.webapp.WebAppContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Splitter;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Maps;
-import com.sun.jersey.api.container.filter.GZIPContentEncodingFilter;
-import com.sun.jersey.api.core.DefaultResourceConfig;
-import com.sun.jersey.api.core.ResourceConfig;
-import com.sun.jersey.spi.container.servlet.ServletContainer;
-
-import brooklyn.BrooklynVersion;
-import brooklyn.config.BrooklynServerPaths;
-import brooklyn.config.BrooklynServiceAttributes;
-import brooklyn.config.ConfigKey;
-import brooklyn.internal.BrooklynInitialization;
-import brooklyn.launcher.config.CustomResourceLocator;
-import brooklyn.location.PortRange;
-import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.location.basic.PortRanges;
-import brooklyn.management.ManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.rest.BrooklynRestApi;
-import brooklyn.rest.BrooklynWebConfig;
-import brooklyn.rest.filter.BrooklynPropertiesSecurityFilter;
-import brooklyn.rest.filter.HaHotCheckResourceFilter;
-import brooklyn.rest.filter.HaMasterCheckFilter;
-import brooklyn.rest.filter.LoggingFilter;
-import brooklyn.rest.filter.NoCacheFilter;
-import brooklyn.rest.filter.RequestTaggingFilter;
-import brooklyn.rest.util.ManagementContextProvider;
-import brooklyn.rest.util.ShutdownHandler;
-import brooklyn.rest.util.ShutdownHandlerProvider;
-import brooklyn.util.BrooklynNetworkUtils;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.crypto.FluentKeySigner;
-import brooklyn.util.crypto.SecureKeys;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.flags.SetFromFlag;
-import brooklyn.util.flags.TypeCoercions;
-import brooklyn.util.io.FileUtil;
-import brooklyn.util.javalang.Threads;
-import brooklyn.util.logging.LoggingSetup;
-import brooklyn.util.os.Os;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.text.Identifiers;
-import brooklyn.util.text.Strings;
-import brooklyn.util.web.ContextHandlerCollectionHotSwappable;
-
-/**
- * Starts the web-app running, connected to the given management context
- */
-public class BrooklynWebServer {
-    private static final Logger log = LoggerFactory.getLogger(BrooklynWebServer.class);
-
-    public static final String BROOKLYN_WAR_URL = "classpath://brooklyn.war";
-    static {
-        // support loading the WAR in dev mode from an alternate location 
-        CustomResourceLocator.registerAlternateLocator(new CustomResourceLocator.SearchingClassPathInDevMode(
-                BROOKLYN_WAR_URL, "/usage/launcher/target", 
-                "/usage/jsgui/target/brooklyn-jsgui-"+BrooklynVersion.get()+".war"));
-    }
-    
-    static {
-        LoggingSetup.installJavaUtilLoggingBridge();
-    }
-    
-    protected Server server;
-
-    private WebAppContext rootContext;
-    
-    /** base port to use, for http if enabled or else https; if not set, it uses httpPort or httpsPort */
-    @SetFromFlag("port")
-    protected PortRange requestedPort = null;
-    
-    @SetFromFlag
-    protected PortRange httpPort = PortRanges.fromString("8081+");
-    @SetFromFlag
-    protected PortRange httpsPort = PortRanges.fromString("8443+");
-    
-    /** actual port where this gets bound; will be consistent with the "port" passed in
-     * but that might be a range and here it is a single port, or -1 if not yet set */
-    protected volatile int actualPort = -1;
-    /** actual NIC where this is listening; in the case of 0.0.0.0 being passed in as bindAddress,
-     * this will revert to one address (such as localhost) */
-    protected InetAddress actualAddress = null;
-
-    @SetFromFlag
-    protected String war = BROOKLYN_WAR_URL;
-
-    /** IP of NIC where this server should bind, or null to autodetect 
-     * (e.g. 0.0.0.0 if security is configured, or loopback if no security) */
-    @SetFromFlag
-    protected InetAddress bindAddress = null;
-
-    /** The address that this server's management context will be publically available on. */
-    @SetFromFlag
-    protected InetAddress publicAddress = null;
-
-    /**
-     * map of context-prefix to file
-     */
-    @SetFromFlag
-    private Map<String, String> wars = new LinkedHashMap<String, String>();
-
-    @SetFromFlag
-    protected boolean ignoreWebappDeploymentFailures = false;
-
-    @SetFromFlag
-    private Map<String, Object> attributes = new LinkedHashMap<String, Object>();
-
-    private ManagementContext managementContext;
-
-    @SetFromFlag
-    private Boolean httpsEnabled;
-
-    @SetFromFlag
-    private String sslCertificate;
-
-    @SetFromFlag
-    private String keystoreUrl;
-
-    @SetFromFlag @Deprecated /** @deprecated use keystoreUrl */
-    private String keystorePath;
-
-    @SetFromFlag
-    private String keystorePassword;
-
-    @SetFromFlag
-    private String keystoreCertAlias;
-
-    @SetFromFlag
-    private String truststorePath;
-
-    @SetFromFlag
-    private String trustStorePassword;
-    
-    @SetFromFlag
-    private String transportProtocols;
-    
-    @SetFromFlag
-    private String transportCiphers;
-
-    private File webappTempDir;
-    
-    private Class<BrooklynPropertiesSecurityFilter> securityFilterClazz;
-
-    private ShutdownHandler shutdownHandler;
-
-    public BrooklynWebServer(ManagementContext managementContext) {
-        this(Maps.newLinkedHashMap(), managementContext);
-    }
-
-    /**
-     * accepts flags:  port,
-     * war (url of war file which is the root),
-     * wars (map of context-prefix to url),
-     * attrs (map of attribute-name : object pairs passed to the servlet)
-     */
-    public BrooklynWebServer(Map<?,?> flags, ManagementContext managementContext) {
-        this.managementContext = managementContext;
-        Map<?,?> leftovers = FlagUtils.setFieldsFromFlags(flags, this);
-        if (!leftovers.isEmpty())
-            log.warn("Ignoring unknown flags " + leftovers);
-        
-        webappTempDir = BrooklynServerPaths.getBrooklynWebTmpDir(managementContext);
-    }
-
-    public BrooklynWebServer(ManagementContext managementContext, int port) {
-        this(managementContext, port, "brooklyn.war");
-    }
-
-    public BrooklynWebServer(ManagementContext managementContext, int port, String warUrl) {
-        this(MutableMap.of("port", port, "war", warUrl), managementContext);
-    }
-
-    public void setSecurityFilter(Class<BrooklynPropertiesSecurityFilter> filterClazz) {
-        this.securityFilterClazz = filterClazz;
-    }
-
-    public void setShutdownHandler(@Nullable ShutdownHandler shutdownHandler) {
-        this.shutdownHandler = shutdownHandler;
-    }
-
-    public BrooklynWebServer setPort(Object port) {
-        if (getActualPort()>0)
-            throw new IllegalStateException("Can't set port after port has been assigned to server (using "+getActualPort()+")");
-        this.requestedPort = TypeCoercions.coerce(port, PortRange.class);
-        return this;
-    }
-
-    @VisibleForTesting
-    File getWebappTempDir() {
-        return webappTempDir;
-    }
-    
-    public BrooklynWebServer setHttpsEnabled(Boolean httpsEnabled) {
-        this.httpsEnabled = httpsEnabled;
-        return this;
-    }
-    
-    public boolean getHttpsEnabled() {
-        return getConfig(httpsEnabled, BrooklynWebConfig.HTTPS_REQUIRED);
-    }
-    
-    public PortRange getRequestedPort() {
-        return requestedPort;
-    }
-    
-    /** returns port where this is running, or -1 if not yet known */
-    public int getActualPort() {
-        return actualPort;
-    }
-
-    /** interface/address where this server is listening;
-     * if bound to 0.0.0.0 (all NICs, e.g. because security is set) this will return one NIC where this is bound */
-    public InetAddress getAddress() {
-        return actualAddress;
-    }
-    
-    /** URL for accessing this web server (root context) */
-    public String getRootUrl() {
-        String address = (publicAddress != null) ? publicAddress.getHostName() : getAddress().getHostName();
-        if (getActualPort()>0){
-            String protocol = getHttpsEnabled()?"https":"http";
-            return protocol+"://"+address+":"+getActualPort()+"/";
-        } else {
-            return null;
-        }
-    }
-
-      /** sets the WAR to use as the root context (only if server not yet started);
-     * cf deploy("/", url) */
-    public BrooklynWebServer setWar(String url) {
-        this.war = url;
-        return this;
-    }
-
-    /** specifies a WAR to use at a given context path (only if server not yet started);
-     * cf deploy(path, url) */
-    public BrooklynWebServer addWar(String path, String warUrl) {
-        wars.put(path, warUrl);
-        return this;
-    }
-
-    /** InetAddress to which server should bind;
-     * defaults to 0.0.0.0 (although common call path is to set to 127.0.0.1 when security is not set) */
-    public BrooklynWebServer setBindAddress(InetAddress address) {
-        bindAddress = address;
-        return this;
-    }
-
-    /**
-     * Sets the public address that the server's management context's REST API will be available on
-     */
-    public BrooklynWebServer setPublicAddress(InetAddress address) {
-        publicAddress = address;
-        return this;
-    }
-
-    /** @deprecated use setAttribute */
-    public BrooklynWebServer addAttribute(String field, Object value) {
-        return setAttribute(field, value);
-    }
-    /** Specifies an attribute passed to deployed webapps 
-     * (in addition to {@link BrooklynServiceAttributes#BROOKLYN_MANAGEMENT_CONTEXT} */
-    public BrooklynWebServer setAttribute(String field, Object value) {
-        attributes.put(field, value);
-        return this;
-    }
-    
-    public <T> BrooklynWebServer configure(ConfigKey<T> key, T value) {
-        return setAttribute(key.getName(), value);
-    }
-
-    /** Specifies attributes passed to deployed webapps 
-     * (in addition to {@link BrooklynServiceAttributes#BROOKLYN_MANAGEMENT_CONTEXT} */
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public BrooklynWebServer putAttributes(Map newAttrs) {
-        if (newAttrs!=null) attributes.putAll(newAttrs);
-        return this;
-    }
-
-    public void installAsServletFilter(ServletContextHandler context) {
-        ResourceConfig config = new DefaultResourceConfig();
-        // load all our REST API modules, JSON, and Swagger
-        for (Object r: BrooklynRestApi.getAllResources())
-            config.getSingletons().add(r);
-
-        // Accept gzipped requests and responses, disable caching for dynamic content
-        config.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, GZIPContentEncodingFilter.class.getName());
-        config.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, ImmutableList.of(GZIPContentEncodingFilter.class, NoCacheFilter.class));
-        // Checks if appropriate request given HA status
-        config.getProperties().put(ResourceConfig.PROPERTY_RESOURCE_FILTER_FACTORIES, HaHotCheckResourceFilter.class.getName());
-        // configure to match empty path, or any thing which looks like a file path with /assets/ and extension html, css, js, or png
-        // and treat that as static content
-        config.getProperties().put(ServletContainer.PROPERTY_WEB_PAGE_CONTENT_REGEX, "(/?|[^?]*/assets/[^?]+\\.[A-Za-z0-9_]+)");
-        // and anything which is not matched as a servlet also falls through (but more expensive than a regex check?)
-        config.getFeatures().put(ServletContainer.FEATURE_FILTER_FORWARD_ON_404, true);
-        // finally create this as a _filter_ which falls through to a web app or something (optionally)
-        FilterHolder filterHolder = new FilterHolder(new ServletContainer(config));
-
-        context.addFilter(filterHolder, "/*", EnumSet.allOf(DispatcherType.class));
-
-        ManagementContext mgmt = (ManagementContext) context.getAttribute(BrooklynServiceAttributes.BROOKLYN_MANAGEMENT_CONTEXT);
-        config.getSingletons().add(new ManagementContextProvider(mgmt));
-
-        config.getSingletons().add(new ShutdownHandlerProvider(shutdownHandler));
-    }
-
-    ContextHandlerCollectionHotSwappable handlers = new ContextHandlerCollectionHotSwappable();
-    
-    /**
-     * Starts the embedded web application server.
-     */
-    public synchronized void start() throws Exception {
-        if (server != null) throw new IllegalStateException(""+this+" already running");
-
-        if (actualPort == -1){
-            PortRange portRange = getConfig(requestedPort, BrooklynWebConfig.WEB_CONSOLE_PORT);
-            if (portRange==null) {
-                portRange = getHttpsEnabled() ? httpsPort : httpPort;
-            }
-            actualPort = LocalhostMachineProvisioningLocation.obtainPort(getAddress(), portRange);
-            if (actualPort == -1) 
-                throw new IllegalStateException("Unable to provision port for web console (wanted "+portRange+")");
-        }
-
-        server = new Server();
-        final Connector connector;
-        if (getHttpsEnabled()) {
-            connector = new SslSelectChannelConnector(createContextFactory());
-        } else {
-            connector = new SelectChannelConnector();
-        }
-        if (bindAddress != null) {
-            connector.setHost(bindAddress.getHostName());
-        }
-        connector.setPort(actualPort);
-        server.setConnectors(new Connector[]{connector});
-
-        if (bindAddress == null || bindAddress.equals(InetAddress.getByAddress(new byte[] { 0, 0, 0, 0 }))) {
-            actualAddress = BrooklynNetworkUtils.getLocalhostInetAddress();
-        } else {
-            actualAddress = bindAddress;
-        }
-
-        // use a nice name in the thread pool (otherwise this is exactly the same as Server defaults)
-        QueuedThreadPool threadPool = new QueuedThreadPool();
-        threadPool.setName("brooklyn-jetty-server-"+actualPort+"-"+threadPool.getName());
-        server.setThreadPool(threadPool);
-
-        if (log.isDebugEnabled())
-            log.debug("Starting Brooklyn console at "+getRootUrl()+", running " + war + (wars != null ? " and " + wars.values() : ""));
-        
-        addShutdownHook();
-
-        MutableMap<String, String> allWars = MutableMap.copyOf(wars);
-        String rootWar = allWars.remove("/");
-        if (rootWar==null) rootWar = war;
-        
-        for (Map.Entry<String, String> entry : allWars.entrySet()) {
-            String pathSpec = entry.getKey();
-            String warUrl = entry.getValue();
-            WebAppContext webapp = deploy(pathSpec, warUrl);
-            webapp.setTempDirectory(Os.mkdirs(new File(webappTempDir, newTimestampedDirName("war", 8))));
-        }
-        rootContext = deploy("/", rootWar);
-        rootContext.setTempDirectory(Os.mkdirs(new File(webappTempDir, "war-root")));
-
-        rootContext.addFilter(RequestTaggingFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
-        if (securityFilterClazz != null) {
-            rootContext.addFilter(securityFilterClazz, "/*", EnumSet.allOf(DispatcherType.class));
-        }
-        rootContext.addFilter(LoggingFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
-        rootContext.addFilter(HaMasterCheckFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
-        installAsServletFilter(rootContext);
-
-        server.setHandler(handlers);
-        server.start();
-        //reinit required because some webapps (eg grails) might wipe our language extension bindings
-        BrooklynInitialization.reinitAll();
-
-        if (managementContext instanceof ManagementContextInternal) {
-            ((ManagementContextInternal) managementContext).setManagementNodeUri(new URI(getRootUrl()));
-        }
-
-        log.info("Started Brooklyn console at "+getRootUrl()+", running " + rootWar + (allWars!=null && !allWars.isEmpty() ? " and " + wars.values() : ""));
-    }
-
-    private SslContextFactory createContextFactory() throws KeyStoreException {
-        SslContextFactory sslContextFactory = new SslContextFactory();
-
-        // allow webconsole keystore & related properties to be set in brooklyn.properties
-        String ksUrl = getKeystoreUrl();
-        String ksPassword = getConfig(keystorePassword, BrooklynWebConfig.KEYSTORE_PASSWORD);
-        String ksCertAlias = getConfig(keystoreCertAlias, BrooklynWebConfig.KEYSTORE_CERTIFICATE_ALIAS);
-        String trProtos = getConfig(transportProtocols, BrooklynWebConfig.TRANSPORT_PROTOCOLS);
-        String trCiphers = getConfig(transportCiphers, BrooklynWebConfig.TRANSPORT_CIPHERS);
-        
-        if (ksUrl!=null) {
-            sslContextFactory.setKeyStorePath(getLocalKeyStorePath(ksUrl));
-            if (Strings.isEmpty(ksPassword))
-                throw new IllegalArgumentException("Keystore password is required and non-empty if keystore is specified.");
-            sslContextFactory.setKeyStorePassword(ksPassword);
-            if (Strings.isNonEmpty(ksCertAlias))
-                sslContextFactory.setCertAlias(ksCertAlias);
-        } else {
-            log.info("No keystore specified but https enabled; creating a default keystore");
-            
-            if (Strings.isEmpty(ksCertAlias))
-                ksCertAlias = "web-console";
-            
-            // if password is blank the process will block and read from stdin !
-            if (Strings.isEmpty(ksPassword)) {
-                ksPassword = Identifiers.makeRandomId(8);
-                log.debug("created random password "+ksPassword+" for ad hoc internal keystore");
-            }
-            
-            KeyStore ks = SecureKeys.newKeyStore();
-            KeyPair key = SecureKeys.newKeyPair();
-            X509Certificate cert = new FluentKeySigner("brooklyn").newCertificateFor("web-console", key);
-            ks.setKeyEntry(ksCertAlias, key.getPrivate(), ksPassword.toCharArray(),
-                new Certificate[] { cert });
-            
-            sslContextFactory.setKeyStore(ks);
-            sslContextFactory.setKeyStorePassword(ksPassword);
-            sslContextFactory.setCertAlias(ksCertAlias);
-        }
-        if (!Strings.isEmpty(truststorePath)) {
-            sslContextFactory.setTrustStore(checkFileExists(truststorePath, "truststore"));
-            sslContextFactory.setTrustStorePassword(trustStorePassword);
-        }
-
-        if (Strings.isNonBlank(trProtos)) {
-            sslContextFactory.setIncludeProtocols(parseArray(trProtos));
-        }
-        if (Strings.isNonBlank(trCiphers)) {
-            sslContextFactory.setIncludeCipherSuites(parseArray(trCiphers));
-        }
-        return sslContextFactory;
-    }
-
-    private String[] parseArray(String list) {
-        List<String> arr = Splitter.on(",").omitEmptyStrings().trimResults().splitToList(list);
-        return arr.toArray(new String[arr.size()]);
-    }
-
-    private String getKeystoreUrl() {
-        if (keystoreUrl != null) {
-            if (Strings.isNonBlank(keystorePath) && !keystoreUrl.equals(keystorePath)) {
-                log.warn("Deprecated 'keystorePath' supplied with different value than 'keystoreUrl', preferring the latter: "+
-                        keystorePath+" / "+keystoreUrl);
-            }
-            return keystoreUrl;
-        } else if (Strings.isNonBlank(keystorePath)) {
-            log.warn("Deprecated 'keystorePath' used; callers should use 'keystoreUrl'");
-            return keystorePath;
-        } else {
-            return managementContext.getConfig().getConfig(BrooklynWebConfig.KEYSTORE_URL);
-        }
-    }
-
-    private <T> T getConfig(T override, ConfigKey<T> key) {
-        if (override!=null) {
-            return override;
-        } else {
-            return managementContext.getConfig().getConfig(key);
-        }
-    }
-
-    private String getLocalKeyStorePath(String keystoreUrl) {
-        ResourceUtils res = ResourceUtils.create(this);
-        res.checkUrlExists(keystoreUrl, BrooklynWebConfig.KEYSTORE_URL.getName());
-        if (new File(keystoreUrl).exists()) {
-            return keystoreUrl;
-        } else {
-            InputStream keystoreStream;
-            try {
-                keystoreStream = res.getResourceFromUrl(keystoreUrl);
-            } catch (Exception e) {
-                Exceptions.propagateIfFatal(e);
-                throw new IllegalArgumentException("Unable to access URL: "+keystoreUrl, e);
-            }
-            File tmp = Os.newTempFile("brooklyn-keystore", "ks");
-            tmp.deleteOnExit();
-            FileUtil.copyTo(keystoreStream, tmp);
-            Streams.closeQuietly(keystoreStream);
-            return tmp.getAbsolutePath();
-        }
-    }
-
-    private String newTimestampedDirName(String prefix, int randomSuffixLength) {
-        return prefix + "-" + new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date()) + "-" + Identifiers.makeRandomId(randomSuffixLength);
-    }
-    
-    private String checkFileExists(String path, String name) {
-        if(!new File(path).exists()){
-            throw new IllegalArgumentException("Could not find "+name+": "+path);
-        }
-        return path;
-    }
-
-    /**
-     * Asks the app server to stop and waits for it to finish up.
-     */
-    public synchronized void stop() throws Exception {
-        if (server==null) return;
-        String root = getRootUrl();
-        if (shutdownHook != null) Threads.removeShutdownHook(shutdownHook);
-        if (log.isDebugEnabled())
-            log.debug("Stopping Brooklyn web console at "+root+ " (" + war + (wars != null ? " and " + wars.values() : "") + ")");
-
-        server.stop();
-        try {
-            server.join();
-        } catch (Exception e) {
-            /* NPE may be thrown e.g. if threadpool not started */
-        }
-        server = null;
-        LocalhostMachineProvisioningLocation.releasePort(getAddress(), actualPort);
-        actualPort = -1;
-        if (log.isDebugEnabled())
-            log.debug("Stopped Brooklyn web console at "+root);
-    }
-
-    /** serve given WAR at the given pathSpec; if not yet started, it is simply remembered until start;
-     * if server already running, the context for this WAR is started.
-     * @return the context created and added as a handler 
-     * (and possibly already started if server is started,
-     * so be careful with any changes you make to it!)  */
-    public WebAppContext deploy(final String pathSpec, final String warUrl) {
-        String cleanPathSpec = pathSpec;
-        while (cleanPathSpec.startsWith("/"))
-            cleanPathSpec = cleanPathSpec.substring(1);
-        boolean isRoot = cleanPathSpec.isEmpty();
-
-        WebAppContext context = new WebAppContext();
-        context.setAttribute(BrooklynServiceAttributes.BROOKLYN_MANAGEMENT_CONTEXT, managementContext);
-        for (Map.Entry<String, Object> attributeEntry : attributes.entrySet()) {
-            context.setAttribute(attributeEntry.getKey(), attributeEntry.getValue());
-        }
-
-        try {
-            File tmpWarFile = Os.writeToTempFile(new CustomResourceLocator(managementContext.getConfig(), ResourceUtils.create(this)).getResourceFromUrl(warUrl), 
-                    isRoot ? "ROOT" : ("embedded-" + cleanPathSpec), ".war");
-            context.setWar(tmpWarFile.getAbsolutePath());
-        } catch (Exception e) {
-            log.warn("Failed to deploy webapp "+pathSpec+" from "+warUrl
-                + (ignoreWebappDeploymentFailures ? "; launching run without WAR" : " (rethrowing)")
-                + ": "+Exceptions.collapseText(e));
-            if (!ignoreWebappDeploymentFailures) {
-                throw new IllegalStateException("Failed to deploy webapp "+pathSpec+" from "+warUrl+": "+Exceptions.collapseText(e), e);
-            }
-            log.debug("Detail on failure to deploy webapp: "+e, e);
-            context.setWar("/dev/null");
-        }
-
-        context.setContextPath("/" + cleanPathSpec);
-        context.setParentLoaderPriority(true);
-
-        deploy(context);
-        return context;
-    }
-
-    private Thread shutdownHook = null;
-
-    protected synchronized void addShutdownHook() {
-        if (shutdownHook!=null) return;
-        // some webapps can generate a lot of output if we don't shut down the browser first
-        shutdownHook = Threads.addShutdownHook(new Runnable() {
-            @Override
-            public void run() {
-                log.debug("BrooklynWebServer detected shutdown: stopping web-console");
-                try {
-                    stop();
-                } catch (Exception e) {
-                    log.error("Failure shutting down web-console: "+e, e);
-                }
-            }
-        });
-    }
-
-    public void deploy(WebAppContext context) {
-        try {
-            handlers.updateHandler(context);
-        } catch (Exception e) {
-            Throwables.propagate(e);
-        }
-    }
-    
-    public Server getServer() {
-        return server;
-    }
-    
-    public WebAppContext getRootContext() {
-        return rootContext;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/brooklyn/launcher/camp/BrooklynCampPlatformLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/camp/BrooklynCampPlatformLauncher.java b/usage/launcher/src/main/java/brooklyn/launcher/camp/BrooklynCampPlatformLauncher.java
deleted file mode 100644
index 3bd4823..0000000
--- a/usage/launcher/src/main/java/brooklyn/launcher/camp/BrooklynCampPlatformLauncher.java
+++ /dev/null
@@ -1,72 +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 brooklyn.launcher.camp;
-
-import io.brooklyn.camp.CampServer;
-import io.brooklyn.camp.spi.PlatformRootSummary;
-import brooklyn.entity.basic.BrooklynShutdownHooks;
-import brooklyn.launcher.BrooklynLauncher;
-import brooklyn.management.ManagementContext;
-import brooklyn.management.internal.LocalManagementContext;
-
-import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
-import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherAbstract;
-
-import com.google.common.annotations.Beta;
-
-/** variant of super who also starts a CampServer for convenience */
-@Beta
-public class BrooklynCampPlatformLauncher extends BrooklynCampPlatformLauncherAbstract {
-
-    protected BrooklynLauncher brooklynLauncher;
-    protected CampServer campServer;
-
-    @Override
-    public BrooklynCampPlatformLauncher launch() {
-        assert platform == null;
-
-        mgmt = newManagementContext();
-        
-        // We created the management context, so we are responsible for terminating it
-        BrooklynShutdownHooks.invokeTerminateOnShutdown(mgmt);
-
-        brooklynLauncher = BrooklynLauncher.newInstance().managementContext(mgmt).start();
-        platform = new BrooklynCampPlatform(
-                PlatformRootSummary.builder().name("Brooklyn CAMP Platform").build(),
-                mgmt).setConfigKeyAtManagmentContext();
-        
-        campServer = new CampServer(getCampPlatform(), "").start();
-        
-        return this;
-    }
-    
-    protected ManagementContext newManagementContext() {
-        return new LocalManagementContext();
-    }
-
-    public static void main(String[] args) {
-        new BrooklynCampPlatformLauncher().launch();
-    }
-
-    public void stopServers() throws Exception {
-        brooklynLauncher.getServerDetails().getWebServer().stop();
-        campServer.stop();
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/brooklyn/launcher/camp/SimpleYamlLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/camp/SimpleYamlLauncher.java b/usage/launcher/src/main/java/brooklyn/launcher/camp/SimpleYamlLauncher.java
deleted file mode 100644
index 0603ded..0000000
--- a/usage/launcher/src/main/java/brooklyn/launcher/camp/SimpleYamlLauncher.java
+++ /dev/null
@@ -1,35 +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 brooklyn.launcher.camp;
-
-import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherAbstract;
-import org.apache.brooklyn.camp.brooklyn.YamlLauncherAbstract;
-
-import com.google.common.annotations.Beta;
-
-/** convenience for launching YAML files directly */
-@Beta
-public class SimpleYamlLauncher extends YamlLauncherAbstract {
-
-    @Override
-    protected BrooklynCampPlatformLauncherAbstract newPlatformLauncher() {
-        return new BrooklynCampPlatformLauncher();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/brooklyn/launcher/config/BrooklynGlobalConfig.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/config/BrooklynGlobalConfig.java b/usage/launcher/src/main/java/brooklyn/launcher/config/BrooklynGlobalConfig.java
deleted file mode 100644
index 408c08a..0000000
--- a/usage/launcher/src/main/java/brooklyn/launcher/config/BrooklynGlobalConfig.java
+++ /dev/null
@@ -1,66 +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 brooklyn.launcher.config;
-
-import brooklyn.config.BrooklynServiceAttributes;
-import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.BrooklynConfigKeys;
-import brooklyn.location.cloud.CloudLocationConfig;
-import brooklyn.management.internal.BrooklynGarbageCollector;
-import brooklyn.rest.BrooklynWebConfig;
-import brooklyn.util.internal.BrooklynSystemProperties;
-import brooklyn.util.internal.StringSystemProperty;
-import brooklyn.util.time.Duration;
-
-/**
- * Convenience collection of popular global configuration values.
- * (Also a handy way to recall where config keys are set.)
- * <p>
- * These can typically be set in brooklyn.properties for global applicability.
- * In some cases (eg SSH_CONFIG_* keys) they can also be set on entities/locations 
- * for behaviour specific to that entity.
- * <p>
- * Also see:
- * <li> {@link BrooklynSystemProperties}
- * <li> {@link BrooklynServiceAttributes}
- * <li> {@link CloudLocationConfig} and classes in that hierarchy.
- */
-public class BrooklynGlobalConfig {
-
-    public static final ConfigKey<Boolean> REQUIRE_HTTPS = BrooklynWebConfig.HTTPS_REQUIRED;
-    
-    public static final ConfigKey<Duration> GC_PERIOD = BrooklynGarbageCollector.GC_PERIOD;
-    public static final ConfigKey<Boolean> DO_SYSTEM_GC = BrooklynGarbageCollector.DO_SYSTEM_GC;
-    public static final ConfigKey<Integer> MAX_TASKS_PER_TAG = BrooklynGarbageCollector.MAX_TASKS_PER_TAG;
-    public static final ConfigKey<Integer> MAX_TASKS_PER_ENTITY = BrooklynGarbageCollector.MAX_TASKS_PER_ENTITY;
-    public static final ConfigKey<Integer> MAX_TASKS_GLOBAL = BrooklynGarbageCollector.MAX_TASKS_GLOBAL;
-    public static final ConfigKey<Duration> MAX_TASK_AGE = BrooklynGarbageCollector.MAX_TASK_AGE;
-
-    public static final StringSystemProperty LOCALHOST_IP_ADDRESS = BrooklynServiceAttributes.LOCALHOST_IP_ADDRESS;
-    
-    // brooklyn.ssh.config.noDeleteAfterExec = true   will cause scripts to be left in situ for debugging
-    public static final ConfigKey<Boolean> SSH_CONFIG_NO_DELETE_SCRIPT = BrooklynConfigKeys.SSH_CONFIG_NO_DELETE_SCRIPT;
-    
-    public static final ConfigKey<String> SSH_CONFIG_SCRIPT_DIR = BrooklynConfigKeys.SSH_CONFIG_SCRIPT_DIR;
-    public static final ConfigKey<String> SSH_CONFIG_SCRIPT_HEADER = BrooklynConfigKeys.SSH_CONFIG_SCRIPT_HEADER;
-    public static final ConfigKey<String> SSH_CONFIG_DIRECT_HEADER = BrooklynConfigKeys.SSH_CONFIG_DIRECT_HEADER;
-
-    // TODO other constants from elsewhere
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/brooklyn/launcher/config/CustomResourceLocator.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/config/CustomResourceLocator.java b/usage/launcher/src/main/java/brooklyn/launcher/config/CustomResourceLocator.java
deleted file mode 100644
index dfdd643..0000000
--- a/usage/launcher/src/main/java/brooklyn/launcher/config/CustomResourceLocator.java
+++ /dev/null
@@ -1,127 +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 brooklyn.launcher.config;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.BrooklynVersion;
-import brooklyn.config.ConfigMap;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.os.Os;
-
-/** class which allows non-standard locators to be registered for URL's being loaded */
-public class CustomResourceLocator {
-
-    private static final Logger log = LoggerFactory.getLogger(CustomResourceLocator.class);
-    
-    protected final ResourceUtils r;
-    private ConfigMap config;
-
-    public interface ResourceLocator {
-        public boolean isApplicable(String url, ConfigMap config);
-        public InputStream locate(String url, ConfigMap config, ResourceUtils r);
-    }
-    
-    private static List<ResourceLocator> locators = new ArrayList<ResourceLocator>();
-    
-    public CustomResourceLocator(ConfigMap config, ResourceUtils r) {
-        this.config = config;
-        this.r = r;
-    }
-    
-    public static void registerAlternateLocator(ResourceLocator locator) {
-        locators.add(0, locator);
-    }
-    
-    /** returns the first known locator for the given url/config pair */
-    public static ResourceLocator getLocatorFor(String url, ConfigMap config) {
-        for (ResourceLocator l: locators) {
-            if (l.isApplicable(url, config)) return l;
-        }
-        return null;
-    }
-    
-    /** finds the file indicated at the URL, using some rewrites if necessary to work around some known issues.
-     * <p>
-     * in particular, eclipse often does not copy WAR files as instructed by maven, so brooklyn.war might not be found */
-    public InputStream getResourceFromUrl(String url) {
-        // TODO we could allow the source to be overridden from config,
-        // by allowing configuration e.g.
-        // brooklyn.path.override.brooklyn.war=classpath://brooklyn-replacement-webapp.war
-        // (not sure if this is a good idea or not)
-        
-        try {
-            return r.getResourceFromUrl(url);
-        } catch (Exception e) {
-            ResourceLocator locator = getLocatorFor(url, config);
-            if (locator!=null) {
-                log.debug("Unable to load resource from "+url+"; attempting with locator "+locator);
-                try {
-                    InputStream result = locator.locate(url, config, r);
-                    if (result!=null) return result;
-                    if (result==null)
-                        log.warn("Unable to load resource from "+url+", even with custom locator; rethrowing original exception");
-                } catch (Exception e2) {
-                    log.warn("Unable to load resource from "+url+", even with custom locator; rethrowing original exception, new exception is: "+e2);
-                }
-            }
-            throw Exceptions.propagate(e);
-        }
-    }
-
-    public static class SearchingClassPathInDevMode implements ResourceLocator {
-        private final String urlToSearchFor;
-        private final String classpathSuffixToSearchFor;
-        private final String classpathSuffixToUse;
-
-        public SearchingClassPathInDevMode(String urlToSearchFor, String classpathSuffixToSearchFor, String classpathSuffixToUse) {
-            this.urlToSearchFor = urlToSearchFor;
-            this.classpathSuffixToSearchFor = Os.nativePath(classpathSuffixToSearchFor);
-            this.classpathSuffixToUse = classpathSuffixToUse;
-        }
-        
-        @Override
-        public boolean isApplicable(String url, ConfigMap config) {
-            return BrooklynVersion.isDevelopmentEnvironment() && urlToSearchFor.equals(url);
-        }
-
-        @Override
-        public InputStream locate(String url, ConfigMap config, ResourceUtils r) {
-            String cp = System.getProperty("java.class.path");
-            int cpi = cp.indexOf(classpathSuffixToSearchFor);
-            if (cpi==-1) return null;
-            String path = cp.substring(0, cpi);
-            int lps = path.lastIndexOf(File.pathSeparatorChar);
-            if (lps>=0) path = path.substring(lps+1);
-            path = path + classpathSuffixToUse;
-            log.debug("Looking for "+url+" in revised location "+path);
-            InputStream result = r.getResourceFromUrl(path);
-            log.info("Using "+url+" from revised location "+path);
-            return result;
-        }
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/brooklyn/launcher/config/StopWhichAppsOnShutdown.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/config/StopWhichAppsOnShutdown.java b/usage/launcher/src/main/java/brooklyn/launcher/config/StopWhichAppsOnShutdown.java
deleted file mode 100644
index 184278b..0000000
--- a/usage/launcher/src/main/java/brooklyn/launcher/config/StopWhichAppsOnShutdown.java
+++ /dev/null
@@ -1,23 +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 brooklyn.launcher.config;
-
-public enum StopWhichAppsOnShutdown {
-    ALL, ALL_IF_NOT_PERSISTED, NONE, THESE, THESE_IF_NOT_PERSISTED
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/brooklyn/util/web/ContextHandlerCollectionHotSwappable.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/util/web/ContextHandlerCollectionHotSwappable.java b/usage/launcher/src/main/java/brooklyn/util/web/ContextHandlerCollectionHotSwappable.java
deleted file mode 100644
index 1855c7d..0000000
--- a/usage/launcher/src/main/java/brooklyn/util/web/ContextHandlerCollectionHotSwappable.java
+++ /dev/null
@@ -1,62 +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 brooklyn.util.web;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.handler.ContextHandlerCollection;
-import org.eclipse.jetty.webapp.WebAppContext;
-
-public class ContextHandlerCollectionHotSwappable extends ContextHandlerCollection {
-
-    public synchronized void updateHandler(WebAppContext context) throws Exception {
-        Handler[] hl0 = getHandlers();
-        List<Handler> hl = hl0!=null ? new ArrayList<Handler>(Arrays.asList(hl0)) : new ArrayList<Handler>();
-        // remove any previous version
-        removeContextFromList(hl, context.getContextPath());
-        // have to add before the root war (remove root war then add back)
-        Handler oldRoot = removeContextFromList(hl, "/");
-        // now add and add back any root
-        hl.add(context);
-        if (oldRoot!=null) hl.add(oldRoot);
-        setHandlers(hl.toArray(new Handler[0]));
-        
-        // and if we are already running, start the new context
-        if (isRunning()) {
-            context.start();
-        }
-    }
-
-    public static Handler removeContextFromList(List<Handler> hl, String contextPath) {
-        Iterator<Handler> hi = hl.iterator();
-        while (hi.hasNext()) {
-            Handler h = hi.next();
-            if ((h instanceof WebAppContext) && ((WebAppContext)h).getContextPath().equals(contextPath)) {
-                hi.remove();
-                return h;
-            }
-        }
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/org/apache/brooklyn/launcher/Activator.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/Activator.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/Activator.java
new file mode 100644
index 0000000..6215cc7
--- /dev/null
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/Activator.java
@@ -0,0 +1,39 @@
+/*
+ * 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.brooklyn.launcher;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Activator implements BundleActivator {
+
+    public static final Logger log = LoggerFactory.getLogger(Activator.class);
+
+    public void start(BundleContext context) throws Exception {
+        //does nothing on startup, just makes resources available
+        //TODO maybe it wants to register a service that others could use?
+        log.info("Starting brooklyn-launcher OSGi bundle");
+    }
+
+    public void stop(BundleContext context) throws Exception {
+        log.info("Stopping brooklyn-launcher OSGi bundle");
+    }
+}
\ No newline at end of file


[8/8] incubator-brooklyn git commit: This closes #801

Posted by ha...@apache.org.
This closes #801


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/cc4ffb9d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/cc4ffb9d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/cc4ffb9d

Branch: refs/heads/master
Commit: cc4ffb9d7dd13aa2040183212558d82cd1a99725
Parents: 7154cc9 6f58ef3
Author: Hadrian Zbarcea <ha...@apache.org>
Authored: Thu Aug 6 20:54:10 2015 -0400
Committer: Hadrian Zbarcea <ha...@apache.org>
Committed: Thu Aug 6 20:54:10 2015 -0400

----------------------------------------------------------------------
 .../brooklyn/demo/GlobalWebFabricExample.java   |    2 +-
 .../brooklyn/demo/KafkaClusterExample.java      |    2 +-
 .../demo/StandaloneQpidBrokerExample.java       |    2 +-
 .../brooklyn/demo/CumulusRDFApplication.java    |    2 +-
 .../demo/HighAvailabilityCassandraCluster.java  |    2 +-
 .../brooklyn/demo/ResilientMongoDbApp.java      |    2 +-
 .../brooklyn/demo/RiakClusterExample.java       |    2 +-
 .../brooklyn/demo/SimpleCassandraCluster.java   |    2 +-
 .../apache/brooklyn/demo/StormSampleApp.java    |    2 +-
 .../brooklyn/demo/WideAreaCassandraCluster.java |    2 +-
 .../brooklyn/demo/SingleWebServerExample.java   |    2 +-
 .../demo/WebClusterDatabaseExample.java         |    2 +-
 .../demo/WebClusterDatabaseExampleApp.java      |    2 +-
 .../apache/brooklyn/demo/WebClusterExample.java |    2 +-
 .../main/java/org/apache/brooklyn/cli/Main.java |    6 +-
 .../main/java/brooklyn/launcher/Activator.java  |   39 -
 .../brooklyn/launcher/BrooklynLauncher.java     | 1062 ------------------
 .../launcher/BrooklynServerDetails.java         |   47 -
 .../brooklyn/launcher/BrooklynWebServer.java    |  652 -----------
 .../camp/BrooklynCampPlatformLauncher.java      |   72 --
 .../launcher/camp/SimpleYamlLauncher.java       |   35 -
 .../launcher/config/BrooklynGlobalConfig.java   |   66 --
 .../launcher/config/CustomResourceLocator.java  |  127 ---
 .../config/StopWhichAppsOnShutdown.java         |   23 -
 .../ContextHandlerCollectionHotSwappable.java   |   62 -
 .../org/apache/brooklyn/launcher/Activator.java |   39 +
 .../brooklyn/launcher/BrooklynLauncher.java     | 1062 ++++++++++++++++++
 .../launcher/BrooklynServerDetails.java         |   47 +
 .../brooklyn/launcher/BrooklynWebServer.java    |  652 +++++++++++
 .../camp/BrooklynCampPlatformLauncher.java      |   72 ++
 .../launcher/camp/SimpleYamlLauncher.java       |   35 +
 .../config/BrooklynDevelopmentModes.java        |   93 ++
 .../launcher/config/BrooklynGlobalConfig.java   |   66 ++
 .../launcher/config/CustomResourceLocator.java  |  127 +++
 .../config/StopWhichAppsOnShutdown.java         |   23 +
 .../ContextHandlerCollectionHotSwappable.java   |   62 +
 .../entity/basic/VanillaSoftwareYamlTest.java   |   97 --
 .../BrooklynEntityMirrorIntegrationTest.java    |  179 ---
 .../brooklynnode/BrooklynNodeRestTest.java      |  146 ---
 .../database/mssql/MssqlBlueprintLiveTest.java  |   60 -
 .../BrooklynLauncherHighAvailabilityTest.java   |  257 -----
 .../BrooklynLauncherRebindCatalogTest.java      |  116 --
 .../BrooklynLauncherRebindTestFixture.java      |  256 -----
 .../BrooklynLauncherRebindTestToFiles.java      |  153 ---
 ...lynLauncherRebindToCloudObjectStoreTest.java |  174 ---
 .../brooklyn/launcher/BrooklynLauncherTest.java |  367 ------
 .../launcher/BrooklynWebServerTest.java         |  209 ----
 .../launcher/SimpleYamlLauncherForTests.java    |   31 -
 .../brooklyn/launcher/WebAppRunnerTest.java     |  168 ---
 .../java/brooklyn/launcher/YamlLauncher.java    |   35 -
 .../blueprints/AbstractBlueprintTest.java       |  202 ----
 .../blueprints/CouchbaseBlueprintTest.java      |   69 --
 .../blueprints/MongoDbBlueprintTest.java        |   51 -
 .../entity/basic/VanillaSoftwareYamlTest.java   |   98 ++
 .../BrooklynEntityMirrorIntegrationTest.java    |  180 +++
 .../brooklynnode/BrooklynNodeRestTest.java      |  149 +++
 .../database/mssql/MssqlBlueprintLiveTest.java  |   60 +
 .../BrooklynLauncherHighAvailabilityTest.java   |  258 +++++
 .../BrooklynLauncherRebindCatalogTest.java      |  116 ++
 .../BrooklynLauncherRebindTestFixture.java      |  257 +++++
 .../BrooklynLauncherRebindTestToFiles.java      |  154 +++
 ...lynLauncherRebindToCloudObjectStoreTest.java |  175 +++
 .../brooklyn/launcher/BrooklynLauncherTest.java |  368 ++++++
 .../launcher/BrooklynWebServerTest.java         |  210 ++++
 .../launcher/SimpleYamlLauncherForTests.java    |   31 +
 .../brooklyn/launcher/WebAppRunnerTest.java     |  171 +++
 .../apache/brooklyn/launcher/YamlLauncher.java  |   35 +
 .../blueprints/AbstractBlueprintTest.java       |  202 ++++
 .../blueprints/CouchbaseBlueprintTest.java      |   69 ++
 .../blueprints/MongoDbBlueprintTest.java        |   51 +
 .../brooklyn/qa/load/SimulatedTheeTierApp.java  |    2 +-
 .../SoftlayerObtainPrivateLiveTest.java         |    2 +-
 .../org/apache/brooklyn/qa/load/LoadTest.java   |    2 +-
 .../qa/longevity/webcluster/WebClusterApp.java  |    2 +-
 74 files changed, 4883 insertions(+), 4776 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc4ffb9d/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc4ffb9d/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/HighAvailabilityCassandraCluster.java
----------------------------------------------------------------------
diff --cc examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/HighAvailabilityCassandraCluster.java
index 4328269,673b18e..94f824d
--- a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/HighAvailabilityCassandraCluster.java
+++ b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/HighAvailabilityCassandraCluster.java
@@@ -30,8 -27,10 +30,8 @@@ import brooklyn.entity.basic.AbstractAp
  import brooklyn.entity.basic.ConfigKeys;
  import brooklyn.entity.basic.Entities;
  import brooklyn.entity.basic.StartableApplication;
 -import brooklyn.entity.nosql.cassandra.CassandraDatacenter;
 -import brooklyn.entity.nosql.cassandra.CassandraNode;
  import brooklyn.entity.proxying.EntitySpec;
- import brooklyn.launcher.BrooklynLauncher;
+ import org.apache.brooklyn.launcher.BrooklynLauncher;
  import brooklyn.policy.EnricherSpec;
  import brooklyn.policy.PolicySpec;
  import brooklyn.policy.ha.ServiceFailureDetector;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc4ffb9d/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/ResilientMongoDbApp.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc4ffb9d/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/RiakClusterExample.java
----------------------------------------------------------------------
diff --cc examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/RiakClusterExample.java
index fe5edc9,cda67ac..555f13c
--- a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/RiakClusterExample.java
+++ b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/RiakClusterExample.java
@@@ -30,8 -27,10 +30,8 @@@ import brooklyn.entity.basic.AbstractAp
  import brooklyn.entity.basic.ConfigKeys;
  import brooklyn.entity.basic.Entities;
  import brooklyn.entity.basic.StartableApplication;
 -import brooklyn.entity.nosql.riak.RiakCluster;
 -import brooklyn.entity.nosql.riak.RiakNode;
  import brooklyn.entity.proxying.EntitySpec;
- import brooklyn.launcher.BrooklynLauncher;
+ import org.apache.brooklyn.launcher.BrooklynLauncher;
  import brooklyn.policy.EnricherSpec;
  import brooklyn.policy.PolicySpec;
  import brooklyn.policy.ha.ServiceFailureDetector;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc4ffb9d/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/SimpleCassandraCluster.java
----------------------------------------------------------------------
diff --cc examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/SimpleCassandraCluster.java
index fe9059f,7d3aa65..27caccf
--- a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/SimpleCassandraCluster.java
+++ b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/SimpleCassandraCluster.java
@@@ -25,8 -23,9 +25,8 @@@ import org.apache.brooklyn.entity.nosql
  import brooklyn.entity.basic.AbstractApplication;
  import brooklyn.entity.basic.Entities;
  import brooklyn.entity.basic.StartableApplication;
 -import brooklyn.entity.nosql.cassandra.CassandraDatacenter;
  import brooklyn.entity.proxying.EntitySpec;
- import brooklyn.launcher.BrooklynLauncher;
+ import org.apache.brooklyn.launcher.BrooklynLauncher;
  import brooklyn.util.CommandLineUtil;
  
  import com.google.common.collect.Lists;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cc4ffb9d/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/WideAreaCassandraCluster.java
----------------------------------------------------------------------
diff --cc examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/WideAreaCassandraCluster.java
index 6116d13,b528f42..89a1fa3
--- a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/WideAreaCassandraCluster.java
+++ b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/WideAreaCassandraCluster.java
@@@ -32,8 -28,11 +32,8 @@@ import brooklyn.entity.basic.AbstractAp
  import brooklyn.entity.basic.ConfigKeys;
  import brooklyn.entity.basic.Entities;
  import brooklyn.entity.basic.StartableApplication;
 -import brooklyn.entity.nosql.cassandra.CassandraDatacenter;
 -import brooklyn.entity.nosql.cassandra.CassandraFabric;
 -import brooklyn.entity.nosql.cassandra.CassandraNode;
  import brooklyn.entity.proxying.EntitySpec;
- import brooklyn.launcher.BrooklynLauncher;
+ import org.apache.brooklyn.launcher.BrooklynLauncher;
  import brooklyn.policy.EnricherSpec;
  import brooklyn.policy.PolicySpec;
  import brooklyn.policy.ha.ServiceFailureDetector;


[5/8] incubator-brooklyn git commit: brooklyn-launcher: add org.apache package prefix

Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
new file mode 100644
index 0000000..ac17aa1
--- /dev/null
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java
@@ -0,0 +1,1062 @@
+/*
+ * 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.brooklyn.launcher;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.StringReader;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeoutException;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
+import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynAssemblyTemplateInstantiator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+import com.google.common.base.Stopwatch;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import brooklyn.catalog.internal.CatalogInitialization;
+import brooklyn.config.BrooklynProperties;
+import brooklyn.config.BrooklynServerConfig;
+import brooklyn.config.BrooklynServerPaths;
+import brooklyn.config.ConfigKey;
+import brooklyn.config.ConfigPredicates;
+import brooklyn.entity.Application;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.BrooklynShutdownHooks;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.basic.StartableApplication;
+import brooklyn.entity.brooklynnode.BrooklynNode;
+import brooklyn.entity.brooklynnode.LocalBrooklynNode;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.rebind.PersistenceExceptionHandler;
+import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
+import brooklyn.entity.rebind.RebindManager;
+import brooklyn.entity.rebind.RebindManagerImpl;
+import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
+import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils;
+import brooklyn.entity.rebind.persister.PersistMode;
+import brooklyn.entity.rebind.persister.PersistenceObjectStore;
+import brooklyn.entity.rebind.transformer.CompoundTransformer;
+import brooklyn.entity.trait.Startable;
+import org.apache.brooklyn.launcher.config.StopWhichAppsOnShutdown;
+import brooklyn.location.Location;
+import brooklyn.location.LocationSpec;
+import brooklyn.location.PortRange;
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation.LocalhostMachine;
+import brooklyn.location.basic.PortRanges;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.HighAvailabilityManager;
+import brooklyn.management.ha.HighAvailabilityManagerImpl;
+import brooklyn.management.ha.HighAvailabilityMode;
+import brooklyn.management.ha.ManagementNodeState;
+import brooklyn.management.ha.ManagementPlaneSyncRecord;
+import brooklyn.management.ha.ManagementPlaneSyncRecordPersister;
+import brooklyn.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.mementos.BrooklynMementoRawData;
+import brooklyn.rest.BrooklynWebConfig;
+import brooklyn.rest.filter.BrooklynPropertiesSecurityFilter;
+import brooklyn.rest.security.provider.BrooklynUserWithRandomPasswordSecurityProvider;
+import brooklyn.rest.util.ShutdownHandler;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.exceptions.FatalConfigurationRuntimeException;
+import brooklyn.util.exceptions.FatalRuntimeException;
+import brooklyn.util.exceptions.RuntimeInterruptedException;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.io.FileUtil;
+import brooklyn.util.net.Networking;
+import brooklyn.util.os.Os;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Strings;
+import brooklyn.util.time.Duration;
+import brooklyn.util.time.Time;
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+
+/**
+ * Example usage is:
+ *  * <pre>
+ * {@code
+ * BrooklynLauncher launcher = BrooklynLauncher.newInstance()
+ *     .application(new WebClusterDatabaseExample().appDisplayName("Web-cluster example"))
+ *     .location("localhost")
+ *     .start();
+ * 
+ * Entities.dumpInfo(launcher.getApplications());
+ * </pre>
+ */
+public class BrooklynLauncher {
+
+    private static final Logger LOG = LoggerFactory.getLogger(BrooklynLauncher.class);
+
+    /** Creates a configurable (fluent API) launcher for use starting the web console and Brooklyn applications. */
+    public static BrooklynLauncher newInstance() {
+        return new BrooklynLauncher();
+    }
+    
+    private final Map<String,Object> brooklynAdditionalProperties = Maps.newLinkedHashMap();
+    private BrooklynProperties brooklynProperties;
+    private ManagementContext managementContext;
+    
+    private final List<String> locationSpecs = new ArrayList<String>();
+    private final List<Location> locations = new ArrayList<Location>();
+
+    private final List<Application> appsToManage = new ArrayList<Application>();
+    private final List<ApplicationBuilder> appBuildersToManage = new ArrayList<ApplicationBuilder>();
+    private final List<String> yamlAppsToManage = new ArrayList<String>();
+    private final List<Application> apps = new ArrayList<Application>();
+    
+    private boolean startWebApps = true;
+    private boolean startBrooklynNode = false;
+    private PortRange port = null;
+    private Boolean useHttps = null;
+    private InetAddress bindAddress = null;
+    private InetAddress publicAddress = null;
+    private Map<String,String> webApps = new LinkedHashMap<String,String>();
+    private Map<String, ?> webconsoleFlags = Maps.newLinkedHashMap();
+    private Boolean skipSecurityFilter = null;
+    
+    private boolean ignoreWebErrors = false;
+    private boolean ignorePersistenceErrors = true;
+    private boolean ignoreCatalogErrors = true;
+    private boolean ignoreAppErrors = true;
+    
+    private StopWhichAppsOnShutdown stopWhichAppsOnShutdown = StopWhichAppsOnShutdown.THESE_IF_NOT_PERSISTED;
+    private ShutdownHandler shutdownHandler;
+    
+    private Function<ManagementContext,Void> customizeManagement = null;
+    private CatalogInitialization catalogInitialization = null;
+    
+    private PersistMode persistMode = PersistMode.DISABLED;
+    private HighAvailabilityMode highAvailabilityMode = HighAvailabilityMode.DISABLED;
+    private String persistenceDir;
+    private String persistenceLocation;
+    private Duration persistPeriod = Duration.ONE_SECOND;
+    // these default values come from config in HighAvailablilityManagerImpl
+    private Duration haHeartbeatTimeoutOverride = null;
+    private Duration haHeartbeatPeriodOverride = null;
+    
+    private volatile BrooklynWebServer webServer;
+    private CampPlatform campPlatform;
+
+    private boolean started;
+    private String globalBrooklynPropertiesFile = Os.mergePaths(Os.home(), ".brooklyn", "brooklyn.properties");
+    private String localBrooklynPropertiesFile;
+
+    public List<Application> getApplications() {
+        if (!started) throw new IllegalStateException("Cannot retrieve application until started");
+        return ImmutableList.copyOf(apps);
+    }
+    
+    public BrooklynServerDetails getServerDetails() {
+        if (!started) throw new IllegalStateException("Cannot retrieve server details until started");
+        return new BrooklynServerDetails(webServer, managementContext);
+    }
+    
+    /** 
+     * Specifies that the launcher should manage the given Brooklyn application.
+     * The application must not yet be managed. 
+     * The application will not be started as part of this call (callers can
+     * subsequently call {@link #start()} or {@link #getApplications()}.
+     * 
+     * @see #application(ApplicationBuilder)
+     */
+    public BrooklynLauncher application(Application app) {
+        if (Entities.isManaged(app)) throw new IllegalArgumentException("Application must not already be managed");
+        appsToManage.add(checkNotNull(app, "app"));
+        return this;
+    }
+
+    /** 
+     * Specifies that the launcher should build and manage the given Brooklyn application.
+     * The application must not yet be managed. 
+     * The application will not be started as part of this call (callers can
+     * subsequently call {@link #start()} or {@link #getApplications()}.
+     * 
+     * @see #application(Application)
+     */
+    public BrooklynLauncher application(ApplicationBuilder appBuilder) {
+        appBuildersToManage.add(checkNotNull(appBuilder, "appBuilder"));
+        return this;
+    }
+
+    /** 
+     * Specifies that the launcher should build and manage the Brooklyn application
+     * described by the given spec.
+     * The application will not be started as part of this call (callers can
+     * subsequently call {@link #start()} or {@link #getApplications()}.
+     * 
+     * @see #application(Application)
+     */
+    public BrooklynLauncher application(EntitySpec<? extends StartableApplication> appSpec) {
+        appBuildersToManage.add(new ApplicationBuilder(checkNotNull(appSpec, "appSpec")) {
+                @Override protected void doBuild() {
+                }});
+        return this;
+    }
+
+    /**
+     * Specifies that the launcher should build and manage the Brooklyn application
+     * described by the given YAML blueprint.
+     * The application will not be started as part of this call (callers can
+     * subsequently call {@link #start()} or {@link #getApplications()}.
+     *
+     * @see #application(Application)
+     */
+    public BrooklynLauncher application(String yaml) {
+        this.yamlAppsToManage.add(yaml);
+        return this;
+    }
+
+    /**
+     * Adds a location to be passed in on {@link #start()}, when that calls
+     * {@code application.start(locations)}.
+     */
+    public BrooklynLauncher location(Location location) {
+        locations.add(checkNotNull(location, "location"));
+        return this;
+    }
+
+    /**
+     * Give the spec of an application, to be created.
+     * 
+     * @see #location(Location)
+     */
+    public BrooklynLauncher location(String spec) {
+        locationSpecs.add(checkNotNull(spec, "spec"));
+        return this;
+    }
+    
+    public BrooklynLauncher locations(List<String> specs) {
+        locationSpecs.addAll(checkNotNull(specs, "specs"));
+        return this;
+    }
+
+    public BrooklynLauncher persistenceLocation(@Nullable String persistenceLocationSpec) {
+        persistenceLocation = persistenceLocationSpec;
+        return this;
+    }
+
+    public BrooklynLauncher globalBrooklynPropertiesFile(String file) {
+        globalBrooklynPropertiesFile = file;
+        return this;
+    }
+    
+    public BrooklynLauncher localBrooklynPropertiesFile(String file) {
+        localBrooklynPropertiesFile = file;
+        return this;
+    }
+    
+    /** 
+     * Specifies the management context this launcher should use. 
+     * If not specified a new one is created automatically.
+     */
+    public BrooklynLauncher managementContext(ManagementContext context) {
+        if (brooklynProperties != null) throw new IllegalStateException("Cannot set brooklynProperties and managementContext");
+        this.managementContext = context;
+        return this;
+    }
+
+    /**
+     * Specifies the brooklyn properties to be used. 
+     * Must not be set if managementContext is explicitly set.
+     */
+    public BrooklynLauncher brooklynProperties(BrooklynProperties brooklynProperties){
+        if (managementContext != null) throw new IllegalStateException("Cannot set brooklynProperties and managementContext");
+        if (this.brooklynProperties!=null && brooklynProperties!=null && this.brooklynProperties!=brooklynProperties)
+            LOG.warn("Brooklyn properties being reset in "+this+"; set null first if you wish to clear it", new Throwable("Source of brooklyn properties reset"));
+        this.brooklynProperties = brooklynProperties;
+        return this;
+    }
+    
+    /**
+     * Specifies a property to be added to the brooklyn properties
+     */
+    public BrooklynLauncher brooklynProperties(String field, Object value) {
+        brooklynAdditionalProperties.put(checkNotNull(field, "field"), value);
+        return this;
+    }
+    public <T> BrooklynLauncher brooklynProperties(ConfigKey<T> key, T value) {
+        return brooklynProperties(key.getName(), value);
+    }
+
+    /** 
+     * Specifies whether the launcher will start the Brooklyn web console 
+     * (and any additional webapps specified); default true.
+     */
+    public BrooklynLauncher webconsole(boolean startWebApps) {
+        this.startWebApps = startWebApps;
+        return this;
+    }
+
+    public BrooklynLauncher installSecurityFilter(Boolean val) {
+        this.skipSecurityFilter = val == null ? null : !val;
+        return this;
+    }
+
+    /** 
+     * As {@link #webconsolePort(PortRange)} taking a single port
+     */ 
+    public BrooklynLauncher webconsolePort(int port) {
+        return webconsolePort(PortRanges.fromInteger(port));
+    }
+
+    /**
+     * As {@link #webconsolePort(PortRange)} taking a string range
+     */
+    public BrooklynLauncher webconsolePort(String port) {
+        if (port==null) return webconsolePort((PortRange)null);
+        return webconsolePort(PortRanges.fromString(port));
+    }
+
+    /**
+     * Specifies the port where the web console (and any additional webapps specified) will listen;
+     * default (null) means "8081+" being the first available >= 8081 (or "8443+" for https).
+     */ 
+    public BrooklynLauncher webconsolePort(PortRange port) {
+        this.port = port;
+        return this;
+    }
+
+    /**
+     * Specifies whether the webconsole should use https.
+     */ 
+    public BrooklynLauncher webconsoleHttps(Boolean useHttps) {
+        this.useHttps = useHttps;
+        return this;
+    }
+
+    /**
+     * Specifies the NIC where the web console (and any additional webapps specified) will be bound;
+     * default 0.0.0.0, unless no security is specified (e.g. users) in which case it is localhost.
+     */ 
+    public BrooklynLauncher bindAddress(InetAddress bindAddress) {
+        this.bindAddress = bindAddress;
+        return this;
+    }
+
+    /**
+     * Specifies the address that the management context's REST API will be available on. Defaults
+     * to {@link #bindAddress} if it is not 0.0.0.0.
+     * @see #bindAddress(java.net.InetAddress)
+     */
+    public BrooklynLauncher publicAddress(InetAddress publicAddress) {
+        this.publicAddress = publicAddress;
+        return this;
+    }
+
+    /**
+     * Specifies additional flags to be passed to {@link BrooklynWebServer}.
+     */ 
+    public BrooklynLauncher webServerFlags(Map<String,?> webServerFlags) {
+        this.webconsoleFlags  = webServerFlags;
+        return this;
+    }
+
+    /** 
+     * Specifies an additional webapp to host on the webconsole port.
+     * @param contextPath The context path (e.g. "/hello", or equivalently just "hello") where the webapp will be hosted.
+     *      "/" will override the brooklyn console webapp.
+     * @param warUrl The URL from which the WAR should be loaded, supporting classpath:// protocol in addition to file:// and http(s)://.
+     */
+    public BrooklynLauncher webapp(String contextPath, String warUrl) {
+        webApps.put(contextPath, warUrl);
+        return this;
+    }
+
+    public BrooklynLauncher ignorePersistenceErrors(boolean ignorePersistenceErrors) {
+        this.ignorePersistenceErrors = ignorePersistenceErrors;
+        return this;
+    }
+
+    public BrooklynLauncher ignoreCatalogErrors(boolean ignoreCatalogErrors) {
+        this.ignoreCatalogErrors = ignoreCatalogErrors;
+        return this;
+    }
+
+    public BrooklynLauncher ignoreWebErrors(boolean ignoreWebErrors) {
+        this.ignoreWebErrors = ignoreWebErrors;
+        return this;
+    }
+
+    public BrooklynLauncher ignoreAppErrors(boolean ignoreAppErrors) {
+        this.ignoreAppErrors = ignoreAppErrors;
+        return this;
+    }
+
+    public BrooklynLauncher stopWhichAppsOnShutdown(StopWhichAppsOnShutdown stopWhich) {
+        this.stopWhichAppsOnShutdown = stopWhich;
+        return this;
+    }
+
+    public BrooklynLauncher customizeManagement(Function<ManagementContext,Void> customizeManagement) {
+        this.customizeManagement = customizeManagement;
+        return this;
+    }
+
+    @Beta
+    public BrooklynLauncher catalogInitialization(CatalogInitialization catInit) {
+        if (this.catalogInitialization!=null)
+            throw new IllegalStateException("Initial catalog customization already set.");
+        this.catalogInitialization = catInit;
+        return this;
+    }
+
+    public BrooklynLauncher shutdownOnExit(boolean val) {
+        LOG.warn("Call to deprecated `shutdownOnExit`", new Throwable("source of deprecated call"));
+        stopWhichAppsOnShutdown = StopWhichAppsOnShutdown.THESE_IF_NOT_PERSISTED;
+        return this;
+    }
+
+    public BrooklynLauncher persistMode(PersistMode persistMode) {
+        this.persistMode = persistMode;
+        return this;
+    }
+
+    public BrooklynLauncher highAvailabilityMode(HighAvailabilityMode highAvailabilityMode) {
+        this.highAvailabilityMode = highAvailabilityMode;
+        return this;
+    }
+
+    public BrooklynLauncher persistenceDir(@Nullable String persistenceDir) {
+        this.persistenceDir = persistenceDir;
+        return this;
+    }
+
+    public BrooklynLauncher persistenceDir(@Nullable File persistenceDir) {
+        if (persistenceDir==null) return persistenceDir((String)null);
+        return persistenceDir(persistenceDir.getAbsolutePath());
+    }
+
+    public BrooklynLauncher persistPeriod(Duration persistPeriod) {
+        this.persistPeriod = persistPeriod;
+        return this;
+    }
+
+    public BrooklynLauncher haHeartbeatTimeout(Duration val) {
+        this.haHeartbeatTimeoutOverride = val;
+        return this;
+    }
+
+    public BrooklynLauncher startBrooklynNode(boolean val) {
+        this.startBrooklynNode = val;
+        return this;
+    }
+
+    /**
+     * Controls both the frequency of heartbeats, and the frequency of checking the health of other nodes.
+     */
+    public BrooklynLauncher haHeartbeatPeriod(Duration val) {
+        this.haHeartbeatPeriodOverride = val;
+        return this;
+    }
+
+    /**
+     * @param destinationDir Directory for state to be copied to
+     */
+    public void copyPersistedState(String destinationDir) {
+        copyPersistedState(destinationDir, null, null);
+    }
+
+    /**
+     * A listener to call when the user requests a shutdown (i.e. through the REST API)
+     */
+    public BrooklynLauncher shutdownHandler(ShutdownHandler shutdownHandler) {
+        this.shutdownHandler = shutdownHandler;
+        return this;
+    }
+
+    /**
+     * @param destinationDir Directory for state to be copied to
+     * @param destinationLocation Optional location if target for copied state is a blob store.
+     */
+    public void copyPersistedState(String destinationDir, @Nullable String destinationLocation) {
+        copyPersistedState(destinationDir, destinationLocation, null);
+    }
+
+    /**
+     * @param destinationDir Directory for state to be copied to
+     * @param destinationLocationSpec Optional location if target for copied state is a blob store.
+     * @param transformer Optional transformations to apply to retrieved state before it is copied.
+     */
+    public void copyPersistedState(String destinationDir, @Nullable String destinationLocationSpec, @Nullable CompoundTransformer transformer) {
+        initManagementContext();
+        try {
+            highAvailabilityMode = HighAvailabilityMode.HOT_STANDBY;
+            initPersistence();
+        } catch (Exception e) {
+            handleSubsystemStartupError(ignorePersistenceErrors, "persistence", e);
+        }
+        
+        try {
+            BrooklynMementoRawData memento = managementContext.getRebindManager().retrieveMementoRawData();
+            if (transformer != null) memento = transformer.transform(memento);
+            
+            ManagementPlaneSyncRecord planeState = managementContext.getHighAvailabilityManager().loadManagementPlaneSyncRecord(true);
+            
+            LOG.info("Persisting state to "+destinationDir+(destinationLocationSpec!=null ? " @ "+destinationLocationSpec : ""));
+            PersistenceObjectStore destinationObjectStore = BrooklynPersistenceUtils.newPersistenceObjectStore(
+                managementContext, destinationLocationSpec, destinationDir);
+            BrooklynPersistenceUtils.writeMemento(managementContext, memento, destinationObjectStore);
+            BrooklynPersistenceUtils.writeManagerMemento(managementContext, planeState, destinationObjectStore);
+
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            LOG.debug("Error copying persisted state (rethrowing): " + e, e);
+            throw new FatalRuntimeException("Error copying persisted state: " +
+                Exceptions.collapseText(e), e);
+        }
+    }
+
+    /** @deprecated since 0.7.0 use {@link #copyPersistedState} instead */
+    // Make private after deprecation
+    @Deprecated
+    public BrooklynMementoRawData retrieveState() {
+        initManagementContext();
+        initPersistence();
+        return managementContext.getRebindManager().retrieveMementoRawData();
+    }
+
+    /**
+     * @param memento The state to copy
+     * @param destinationDir Directory for state to be copied to
+     * @param destinationLocation Optional location if target for copied state is a blob store.
+     * @deprecated since 0.7.0 use {@link #copyPersistedState} instead
+     */
+    // Make private after deprecation
+    @Deprecated
+    public void persistState(BrooklynMementoRawData memento, String destinationDir, @Nullable String destinationLocationSpec) {
+        initManagementContext();
+        PersistenceObjectStore destinationObjectStore = BrooklynPersistenceUtils.newPersistenceObjectStore(
+            managementContext, destinationLocationSpec, destinationDir);
+        BrooklynPersistenceUtils.writeMemento(managementContext, memento, destinationObjectStore);
+    }
+
+    /**
+     * Starts the web server (with web console) and Brooklyn applications, as per the specifications configured. 
+     * @return An object containing details of the web server and the management context.
+     */
+    public BrooklynLauncher start() {
+        if (started) throw new IllegalStateException("Cannot start() or launch() multiple times");
+        started = true;
+
+        // Create the management context
+        initManagementContext();
+
+        // Inform catalog initialization that it is starting up
+        CatalogInitialization catInit = ((ManagementContextInternal)managementContext).getCatalogInitialization();
+        catInit.setStartingUp(true);
+
+        // Start webapps as soon as mgmt context available -- can use them to detect progress of other processes
+        if (startWebApps) {
+            try {
+                startWebApps();
+            } catch (Exception e) {
+                handleSubsystemStartupError(ignoreWebErrors, "core web apps", e);
+            }
+        }
+        
+        // Add a CAMP platform
+        campPlatform = new BrooklynCampPlatformLauncherNoServer()
+                .useManagementContext(managementContext)
+                .launch()
+                .getCampPlatform();
+        // TODO start CAMP rest _server_ in the below (at /camp) ?
+
+        try {
+            initPersistence();
+            startPersistence();
+        } catch (Exception e) {
+            handleSubsystemStartupError(ignorePersistenceErrors, "persistence", e);
+        }
+
+        try {
+            // run cat init now if it hasn't yet been run; 
+            // will also run if there was an ignored error in catalog above, allowing it to fail startup here if requested
+            if (catInit!=null && !catInit.hasRunOfficialInitialization()) {
+                if (persistMode==PersistMode.DISABLED) {
+                    LOG.debug("Loading catalog as part of launch sequence (it was not loaded as part of any rebind sequence)");
+                    catInit.populateCatalog(ManagementNodeState.MASTER, true, true, null);
+                } else {
+                    // should have loaded during rebind
+                    ManagementNodeState state = managementContext.getHighAvailabilityManager().getNodeState();
+                    LOG.warn("Loading catalog for "+state+" as part of launch sequence (it was not loaded as part of the rebind sequence)");
+                    catInit.populateCatalog(state, true, true, null);
+                }
+            }
+        } catch (Exception e) {
+            handleSubsystemStartupError(ignoreCatalogErrors, "initial catalog", e);
+        }
+        catInit.setStartingUp(false);
+
+        // Create the locations. Must happen after persistence is started in case the
+        // management context's catalog is loaded from persisted state. (Location
+        // resolution uses the catalog's classpath to scan for resolvers.)
+        locations.addAll(managementContext.getLocationRegistry().resolve(locationSpecs));
+
+        // Already rebinded successfully, so previous apps are now available.
+        // Allow the startup to be visible in console for newly created apps.
+        ((LocalManagementContext)managementContext).noteStartupComplete();
+
+        // TODO create apps only after becoming master, analogously to catalog initialization
+        try {
+            createApps();
+            startApps();
+        } catch (Exception e) {
+            handleSubsystemStartupError(ignoreAppErrors, "brooklyn autostart apps", e);
+        }
+
+        if (startBrooklynNode) {
+            try {
+                startBrooklynNode();
+            } catch (Exception e) {
+                handleSubsystemStartupError(ignoreAppErrors, "brooklyn node / self entity", e);
+            }
+        }
+        
+        if (persistMode != PersistMode.DISABLED) {
+            // Make sure the new apps are persisted in case process exits immediately.
+            managementContext.getRebindManager().forcePersistNow(false, null);
+        }
+        return this;
+    }
+
+    private void initManagementContext() {
+        // Create the management context
+        if (managementContext == null) {
+            if (brooklynProperties == null) {
+                BrooklynProperties.Factory.Builder builder = BrooklynProperties.Factory.builderDefault();
+                if (globalBrooklynPropertiesFile != null) {
+                    if (fileExists(globalBrooklynPropertiesFile)) {
+                        LOG.debug("Using global properties file "+globalBrooklynPropertiesFile);
+                        // brooklyn.properties stores passwords (web-console and cloud credentials), 
+                        // so ensure it has sensible permissions
+                        checkFileReadable(globalBrooklynPropertiesFile);
+                        checkFilePermissionsX00(globalBrooklynPropertiesFile);
+                    } else {
+                        LOG.debug("Global properties file "+globalBrooklynPropertiesFile+" does not exist, will ignore");
+                    }
+                    builder.globalPropertiesFile(globalBrooklynPropertiesFile);
+                } else {
+                    LOG.debug("Global properties file disabled");
+                    builder.globalPropertiesFile(null);
+                }
+                
+                if (localBrooklynPropertiesFile != null) {
+                    checkFileReadable(localBrooklynPropertiesFile);
+                    checkFilePermissionsX00(localBrooklynPropertiesFile);
+                    builder.localPropertiesFile(localBrooklynPropertiesFile);
+                }
+                managementContext = new LocalManagementContext(builder, brooklynAdditionalProperties);
+            } else {
+                if (globalBrooklynPropertiesFile != null)
+                    LOG.warn("Ignoring globalBrooklynPropertiesFile "+globalBrooklynPropertiesFile+" because explicit brooklynProperties supplied");
+                if (localBrooklynPropertiesFile != null)
+                    LOG.warn("Ignoring localBrooklynPropertiesFile "+localBrooklynPropertiesFile+" because explicit brooklynProperties supplied");
+                managementContext = new LocalManagementContext(brooklynProperties, brooklynAdditionalProperties);
+            }
+            brooklynProperties = ((ManagementContextInternal)managementContext).getBrooklynProperties();
+            
+            // We created the management context, so we are responsible for terminating it
+            BrooklynShutdownHooks.invokeTerminateOnShutdown(managementContext);
+            
+        } else if (brooklynProperties == null) {
+            brooklynProperties = ((ManagementContextInternal)managementContext).getBrooklynProperties();
+            brooklynProperties.addFromMap(brooklynAdditionalProperties);
+        }
+        
+        if (catalogInitialization!=null) {
+            ((ManagementContextInternal)managementContext).setCatalogInitialization(catalogInitialization);
+        }
+        
+        if (customizeManagement!=null) {
+            customizeManagement.apply(managementContext);
+        }
+    }
+
+    private boolean fileExists(String file) {
+        return new File(Os.tidyPath(file)).exists();
+    }
+
+    private void checkFileReadable(String file) {
+        File f = new File(Os.tidyPath(file));
+        if (!f.exists()) {
+            throw new FatalRuntimeException("File "+file+" does not exist");
+        }
+        if (!f.isFile()) {
+            throw new FatalRuntimeException(file+" is not a file");
+        }
+        if (!f.canRead()) {
+            throw new FatalRuntimeException(file+" is not readable");
+        }
+    }
+    
+    private void checkFilePermissionsX00(String file) {
+        File f = new File(Os.tidyPath(file));
+        
+        Maybe<String> permission = FileUtil.getFilePermissions(f);
+        if (permission.isAbsent()) {
+            LOG.debug("Could not determine permissions of file; assuming ok: "+f);
+        } else {
+            if (!permission.get().subSequence(4, 10).equals("------")) {
+                throw new FatalRuntimeException("Invalid permissions for file "+file+"; expected ?00 but was "+permission.get());
+            }
+        }
+    }
+    
+    private void handleSubsystemStartupError(boolean ignoreSuchErrors, String system, Exception e) {
+        Exceptions.propagateIfFatal(e);
+        if (ignoreSuchErrors) {
+            LOG.error("Subsystem for "+system+" had startup error (continuing with startup): "+e, e);
+            if (managementContext!=null)
+                ((ManagementContextInternal)managementContext).errors().add(e);
+        } else {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    protected void startWebApps() {
+        // No security options in properties and no command line options overriding.
+        if (Boolean.TRUE.equals(skipSecurityFilter) && bindAddress==null) {
+            LOG.info("Starting Brooklyn web-console on loopback because security is explicitly disabled and no bind address specified");
+            bindAddress = Networking.LOOPBACK;
+        } else if (BrooklynWebConfig.hasNoSecurityOptions(brooklynProperties)) {
+            if (bindAddress==null) {
+                LOG.info("Starting Brooklyn web-console with passwordless access on localhost and protected access from any other interfaces (no bind address specified)");
+            } else {
+                if (Arrays.equals(new byte[] { 127, 0, 0, 1 }, bindAddress.getAddress())) { 
+                    LOG.info("Starting Brooklyn web-console with passwordless access on localhost");
+                } else if (Arrays.equals(new byte[] { 0, 0, 0, 0 }, bindAddress.getAddress())) { 
+                    LOG.info("Starting Brooklyn web-console with passwordless access on localhost and random password (logged) required from any other interfaces");
+                } else { 
+                    LOG.info("Starting Brooklyn web-console with passwordless access on localhost (if permitted) and random password (logged) required from any other interfaces");
+                }
+            }
+            brooklynProperties.put(
+                    BrooklynWebConfig.SECURITY_PROVIDER_CLASSNAME,
+                    BrooklynUserWithRandomPasswordSecurityProvider.class.getName());
+        } else {
+            LOG.debug("Starting Brooklyn using security properties: "+brooklynProperties.submap(ConfigPredicates.startingWith(BrooklynWebConfig.BASE_NAME_SECURITY)).asMapWithStringKeys());
+        }
+        if (bindAddress == null) bindAddress = Networking.ANY_NIC;
+
+        LOG.debug("Starting Brooklyn web-console with bindAddress "+bindAddress+" and properties "+brooklynProperties);
+        try {
+            webServer = new BrooklynWebServer(webconsoleFlags, managementContext);
+            webServer.setBindAddress(bindAddress);
+            webServer.setPublicAddress(publicAddress);
+            if (port!=null) webServer.setPort(port);
+            if (useHttps!=null) webServer.setHttpsEnabled(useHttps);
+            webServer.setShutdownHandler(shutdownHandler);
+            webServer.putAttributes(brooklynProperties);
+            if (skipSecurityFilter != Boolean.TRUE) {
+                webServer.setSecurityFilter(BrooklynPropertiesSecurityFilter.class);
+            }
+            for (Map.Entry<String, String> webapp : webApps.entrySet()) {
+                webServer.addWar(webapp.getKey(), webapp.getValue());
+            }
+            webServer.start();
+
+        } catch (Exception e) {
+            LOG.warn("Failed to start Brooklyn web-console (rethrowing): " + Exceptions.collapseText(e));
+            throw new FatalRuntimeException("Failed to start Brooklyn web-console: " + Exceptions.collapseText(e), e);
+        }
+    }
+
+    protected void initPersistence() {
+        // Prepare the rebind directory, and initialise the RebindManager as required
+        final PersistenceObjectStore objectStore;
+        if (persistMode == PersistMode.DISABLED) {
+            LOG.info("Persistence disabled");
+            objectStore = null;
+            
+        } else {
+            try {
+                if (persistenceLocation == null) {
+                    persistenceLocation = brooklynProperties.getConfig(BrooklynServerConfig.PERSISTENCE_LOCATION_SPEC);
+                }
+                persistenceDir = BrooklynServerPaths.newMainPersistencePathResolver(brooklynProperties).location(persistenceLocation).dir(persistenceDir).resolve();
+                objectStore = BrooklynPersistenceUtils.newPersistenceObjectStore(managementContext, persistenceLocation, persistenceDir, 
+                    persistMode, highAvailabilityMode);
+                    
+                RebindManager rebindManager = managementContext.getRebindManager();
+                
+                BrooklynMementoPersisterToObjectStore persister = new BrooklynMementoPersisterToObjectStore(
+                    objectStore,
+                    ((ManagementContextInternal)managementContext).getBrooklynProperties(),
+                    managementContext.getCatalogClassLoader());
+                PersistenceExceptionHandler persistenceExceptionHandler = PersistenceExceptionHandlerImpl.builder().build();
+                ((RebindManagerImpl) rebindManager).setPeriodicPersistPeriod(persistPeriod);
+                rebindManager.setPersister(persister, persistenceExceptionHandler);
+            } catch (FatalConfigurationRuntimeException e) {
+                throw e;
+            } catch (Exception e) {
+                Exceptions.propagateIfFatal(e);
+                LOG.debug("Error initializing persistence subsystem (rethrowing): "+e, e);
+                throw new FatalRuntimeException("Error initializing persistence subsystem: "+
+                    Exceptions.collapseText(e), e);
+            }
+        }
+        
+        // Initialise the HA manager as required
+        if (highAvailabilityMode == HighAvailabilityMode.DISABLED) {
+            LOG.info("High availability disabled");
+        } else {
+            if (objectStore==null)
+                throw new FatalConfigurationRuntimeException("Cannot run in HA mode when no persistence configured.");
+
+            HighAvailabilityManager haManager = managementContext.getHighAvailabilityManager();
+            ManagementPlaneSyncRecordPersister persister =
+                new ManagementPlaneSyncRecordPersisterToObjectStore(managementContext,
+                    objectStore,
+                    managementContext.getCatalogClassLoader());
+            ((HighAvailabilityManagerImpl)haManager).setHeartbeatTimeout(haHeartbeatTimeoutOverride);
+            ((HighAvailabilityManagerImpl)haManager).setPollPeriod(haHeartbeatPeriodOverride);
+            haManager.setPersister(persister);
+        }
+    }
+    
+    protected void startPersistence() {
+        // Now start the HA Manager and the Rebind manager, as required
+        if (highAvailabilityMode == HighAvailabilityMode.DISABLED) {
+            HighAvailabilityManager haManager = managementContext.getHighAvailabilityManager();
+            haManager.disabled();
+
+            if (persistMode != PersistMode.DISABLED) {
+                startPersistenceWithoutHA();
+            }
+            
+        } else {
+            // Let the HA manager decide when objectstore.prepare and rebindmgr.rebind need to be called 
+            // (based on whether other nodes in plane are already running).
+            
+            HighAvailabilityMode startMode=null;
+            switch (highAvailabilityMode) {
+                case AUTO:
+                case MASTER:
+                case STANDBY:
+                case HOT_STANDBY:
+                case HOT_BACKUP:
+                    startMode = highAvailabilityMode;
+                    break;
+                case DISABLED:
+                    throw new IllegalStateException("Unexpected code-branch for high availability mode "+highAvailabilityMode);
+            }
+            if (startMode==null)
+                throw new IllegalStateException("Unexpected high availability mode "+highAvailabilityMode);
+            
+            LOG.debug("Management node (with HA) starting");
+            HighAvailabilityManager haManager = managementContext.getHighAvailabilityManager();
+            // prepare after HA mode is known, to prevent backups happening in standby mode
+            haManager.start(startMode);
+        }
+    }
+
+    private void startPersistenceWithoutHA() {
+        RebindManager rebindManager = managementContext.getRebindManager();
+        if (Strings.isNonBlank(persistenceLocation))
+            LOG.info("Management node (no HA) rebinding to entities at "+persistenceLocation+" in "+persistenceDir);
+        else
+            LOG.info("Management node (no HA) rebinding to entities on file system in "+persistenceDir);
+
+        ClassLoader classLoader = managementContext.getCatalogClassLoader();
+        try {
+            rebindManager.rebind(classLoader, null, ManagementNodeState.MASTER);
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            LOG.debug("Error rebinding to persisted state (rethrowing): "+e, e);
+            throw new FatalRuntimeException("Error rebinding to persisted state: "+
+                Exceptions.collapseText(e), e);
+        }
+        rebindManager.startPersistence();
+    }
+
+    protected void createApps() {
+        for (ApplicationBuilder appBuilder : appBuildersToManage) {
+            StartableApplication app = appBuilder.manage(managementContext);
+            apps.add(app);
+        }
+        for (Application app : appsToManage) {
+            Entities.startManagement(app, managementContext);
+            apps.add(app);
+        }
+        for (String blueprint : yamlAppsToManage) {
+            Application app = getAppFromYaml(blueprint);
+            // Note: BrooklynAssemblyTemplateInstantiator automatically puts applications under management.
+            apps.add(app);
+        }
+    }
+
+    protected void startBrooklynNode() {
+        final String classpath = System.getenv("INITIAL_CLASSPATH");
+        if (Strings.isBlank(classpath)) {
+            LOG.warn("Cannot find INITIAL_CLASSPATH environment variable, skipping BrooklynNode entity creation");
+            return;
+        }
+        if (webServer == null || !startWebApps) {
+            LOG.info("Skipping BrooklynNode entity creation, BrooklynWebServer not running");
+            return;
+        }
+        ApplicationBuilder brooklyn = new ApplicationBuilder() {
+            @SuppressWarnings("deprecation")
+            @Override
+            protected void doBuild() {
+                addChild(EntitySpec.create(LocalBrooklynNode.class)
+                        .configure(SoftwareProcess.ENTITY_STARTED, true)
+                        .configure(SoftwareProcess.RUN_DIR, System.getenv("ROOT"))
+                        .configure(SoftwareProcess.INSTALL_DIR, System.getenv("BROOKLYN_HOME"))
+                        .configure(BrooklynNode.ENABLED_HTTP_PROTOCOLS, ImmutableList.of(webServer.getHttpsEnabled() ? "https" : "http"))
+                        .configure(webServer.getHttpsEnabled() ? BrooklynNode.HTTPS_PORT : BrooklynNode.HTTP_PORT, PortRanges.fromInteger(webServer.getActualPort()))
+                        .configure(BrooklynNode.WEB_CONSOLE_BIND_ADDRESS, bindAddress)
+                        .configure(BrooklynNode.WEB_CONSOLE_PUBLIC_ADDRESS, publicAddress)
+                        .configure(BrooklynNode.CLASSPATH, Splitter.on(":").splitToList(classpath))
+                        .configure(BrooklynNode.NO_WEB_CONSOLE_AUTHENTICATION, Boolean.TRUE.equals(skipSecurityFilter))
+                        .displayName("Brooklyn Console"));
+            }
+        };
+        LocationSpec<?> spec = LocationSpec.create(LocalhostMachine.class).displayName("Local Brooklyn");
+        Location localhost = managementContext.getLocationManager().createLocation(spec);
+        brooklyn.appDisplayName("Brooklyn")
+                .manage(managementContext)
+                .start(ImmutableList.of(localhost));
+    }
+
+    protected Application getAppFromYaml(String input) {
+        AssemblyTemplate at = campPlatform.pdp().registerDeploymentPlan(new StringReader(input));
+        BrooklynAssemblyTemplateInstantiator instantiator;
+        try {
+            AssemblyTemplateInstantiator ati = at.getInstantiator().newInstance();
+            if (ati instanceof BrooklynAssemblyTemplateInstantiator) {
+                instantiator = BrooklynAssemblyTemplateInstantiator.class.cast(ati);
+            } else {
+                throw new IllegalStateException("Cannot create application with instantiator: " + ati);
+            }
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+        Application app = instantiator.create(at, campPlatform);
+        return app;
+    }
+    
+    protected void startApps() {
+        if ((stopWhichAppsOnShutdown==StopWhichAppsOnShutdown.ALL) || 
+            (stopWhichAppsOnShutdown==StopWhichAppsOnShutdown.ALL_IF_NOT_PERSISTED && persistMode==PersistMode.DISABLED)) {
+            BrooklynShutdownHooks.invokeStopAppsOnShutdown(managementContext);
+        }
+
+        List<Throwable> appExceptions = Lists.newArrayList();
+        for (Application app : apps) {
+            if (app instanceof Startable) {
+                
+                if ((stopWhichAppsOnShutdown==StopWhichAppsOnShutdown.THESE) || 
+                    (stopWhichAppsOnShutdown==StopWhichAppsOnShutdown.THESE_IF_NOT_PERSISTED && persistMode==PersistMode.DISABLED)) {
+                    BrooklynShutdownHooks.invokeStopOnShutdown(app);
+                }
+                try {
+                    LOG.info("Starting brooklyn application {} in location{} {}", new Object[] { app, locations.size()!=1?"s":"", locations });
+                    ((Startable)app).start(locations);
+                } catch (Exception e) {
+                    LOG.error("Error starting "+app+": "+Exceptions.collapseText(e), Exceptions.getFirstInteresting(e));
+                    appExceptions.add(Exceptions.collapse(e));
+                    
+                    if (Thread.currentThread().isInterrupted()) {
+                        LOG.error("Interrupted while starting applications; aborting");
+                        break;
+                    }
+                }
+            }
+        }
+        if (!appExceptions.isEmpty()) {
+            Throwable t = Exceptions.create(appExceptions);
+            throw new FatalRuntimeException("Error starting applications: "+Exceptions.collapseText(t), t);
+        }
+    }
+    
+    public boolean isStarted() {
+        return started;
+    }
+    
+    /**
+     * Terminates this launch, but does <em>not</em> stop the applications (i.e. external processes
+     * are left running, etc). However, by terminating the management console the brooklyn applications
+     * become unusable.
+     */
+    public void terminate() {
+        if (!started) return; // no-op
+        
+        if (webServer != null) {
+            try {
+                webServer.stop();
+            } catch (Exception e) {
+                LOG.warn("Error stopping web-server; continuing with termination", e);
+            }
+        }
+
+        // TODO Do we want to do this as part of managementContext.terminate, so after other threads are terminated etc?
+        // Otherwise the app can change between this persist and the terminate.
+        if (persistMode != PersistMode.DISABLED) {
+            try {
+                Stopwatch stopwatch = Stopwatch.createStarted();
+                if (managementContext.getHighAvailabilityManager().getPersister() != null) {
+                    managementContext.getHighAvailabilityManager().getPersister().waitForWritesCompleted(Duration.TEN_SECONDS);
+                }
+                managementContext.getRebindManager().waitForPendingComplete(Duration.TEN_SECONDS, true);
+                LOG.info("Finished waiting for persist; took "+Time.makeTimeStringRounded(stopwatch));
+            } catch (RuntimeInterruptedException e) {
+                Thread.currentThread().interrupt(); // keep going with shutdown
+                LOG.warn("Persistence interrupted during shutdown: "+e, e);
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt(); // keep going with shutdown
+                LOG.warn("Persistence interrupted during shutdown: "+e, e);
+            } catch (TimeoutException e) {
+                LOG.warn("Timeout after 10 seconds waiting for persistence to write all data; continuing");
+            }
+        }
+        
+        if (managementContext instanceof ManagementContextInternal) {
+            ((ManagementContextInternal)managementContext).terminate();
+        }
+        
+        for (Location loc : locations) {
+            if (loc instanceof Closeable) {
+                Streams.closeQuietly((Closeable)loc);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynServerDetails.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynServerDetails.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynServerDetails.java
new file mode 100644
index 0000000..1ffa8cf
--- /dev/null
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynServerDetails.java
@@ -0,0 +1,47 @@
+/*
+ * 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.brooklyn.launcher;
+
+import brooklyn.management.ManagementContext;
+
+public class BrooklynServerDetails {
+
+    protected BrooklynWebServer webServer;
+    protected ManagementContext mgmtContext;
+    
+    public BrooklynServerDetails(BrooklynWebServer webServer, ManagementContext mgmtContext) {
+        super();
+        this.webServer = webServer;
+        this.mgmtContext = mgmtContext;
+    }
+
+    public BrooklynWebServer getWebServer() {
+        return webServer;
+    }
+    
+    public String getWebServerUrl() {
+        if (webServer==null) return null;
+        return webServer.getRootUrl();
+    }
+    
+    public ManagementContext getManagementContext() {
+        return mgmtContext;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
new file mode 100644
index 0000000..1f2bc5d
--- /dev/null
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
@@ -0,0 +1,652 @@
+/*
+ * 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.brooklyn.launcher;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.URI;
+import java.security.KeyPair;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+import javax.servlet.DispatcherType;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Splitter;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+import com.sun.jersey.api.container.filter.GZIPContentEncodingFilter;
+import com.sun.jersey.api.core.DefaultResourceConfig;
+import com.sun.jersey.api.core.ResourceConfig;
+import com.sun.jersey.spi.container.servlet.ServletContainer;
+
+import brooklyn.BrooklynVersion;
+import brooklyn.config.BrooklynServerPaths;
+import brooklyn.config.BrooklynServiceAttributes;
+import brooklyn.config.ConfigKey;
+import brooklyn.internal.BrooklynInitialization;
+import org.apache.brooklyn.launcher.config.CustomResourceLocator;
+import brooklyn.location.PortRange;
+import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
+import brooklyn.location.basic.PortRanges;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.rest.BrooklynRestApi;
+import brooklyn.rest.BrooklynWebConfig;
+import brooklyn.rest.filter.BrooklynPropertiesSecurityFilter;
+import brooklyn.rest.filter.HaHotCheckResourceFilter;
+import brooklyn.rest.filter.HaMasterCheckFilter;
+import brooklyn.rest.filter.LoggingFilter;
+import brooklyn.rest.filter.NoCacheFilter;
+import brooklyn.rest.filter.RequestTaggingFilter;
+import brooklyn.rest.util.ManagementContextProvider;
+import brooklyn.rest.util.ShutdownHandler;
+import brooklyn.rest.util.ShutdownHandlerProvider;
+import brooklyn.util.BrooklynNetworkUtils;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.crypto.FluentKeySigner;
+import brooklyn.util.crypto.SecureKeys;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.flags.FlagUtils;
+import brooklyn.util.flags.SetFromFlag;
+import brooklyn.util.flags.TypeCoercions;
+import brooklyn.util.io.FileUtil;
+import brooklyn.util.javalang.Threads;
+import brooklyn.util.logging.LoggingSetup;
+import brooklyn.util.os.Os;
+import brooklyn.util.stream.Streams;
+import brooklyn.util.text.Identifiers;
+import brooklyn.util.text.Strings;
+import org.apache.brooklyn.util.web.ContextHandlerCollectionHotSwappable;
+
+/**
+ * Starts the web-app running, connected to the given management context
+ */
+public class BrooklynWebServer {
+    private static final Logger log = LoggerFactory.getLogger(BrooklynWebServer.class);
+
+    public static final String BROOKLYN_WAR_URL = "classpath://brooklyn.war";
+    static {
+        // support loading the WAR in dev mode from an alternate location 
+        CustomResourceLocator.registerAlternateLocator(new CustomResourceLocator.SearchingClassPathInDevMode(
+                BROOKLYN_WAR_URL, "/usage/launcher/target", 
+                "/usage/jsgui/target/brooklyn-jsgui-"+BrooklynVersion.get()+".war"));
+    }
+    
+    static {
+        LoggingSetup.installJavaUtilLoggingBridge();
+    }
+    
+    protected Server server;
+
+    private WebAppContext rootContext;
+    
+    /** base port to use, for http if enabled or else https; if not set, it uses httpPort or httpsPort */
+    @SetFromFlag("port")
+    protected PortRange requestedPort = null;
+    
+    @SetFromFlag
+    protected PortRange httpPort = PortRanges.fromString("8081+");
+    @SetFromFlag
+    protected PortRange httpsPort = PortRanges.fromString("8443+");
+    
+    /** actual port where this gets bound; will be consistent with the "port" passed in
+     * but that might be a range and here it is a single port, or -1 if not yet set */
+    protected volatile int actualPort = -1;
+    /** actual NIC where this is listening; in the case of 0.0.0.0 being passed in as bindAddress,
+     * this will revert to one address (such as localhost) */
+    protected InetAddress actualAddress = null;
+
+    @SetFromFlag
+    protected String war = BROOKLYN_WAR_URL;
+
+    /** IP of NIC where this server should bind, or null to autodetect 
+     * (e.g. 0.0.0.0 if security is configured, or loopback if no security) */
+    @SetFromFlag
+    protected InetAddress bindAddress = null;
+
+    /** The address that this server's management context will be publically available on. */
+    @SetFromFlag
+    protected InetAddress publicAddress = null;
+
+    /**
+     * map of context-prefix to file
+     */
+    @SetFromFlag
+    private Map<String, String> wars = new LinkedHashMap<String, String>();
+
+    @SetFromFlag
+    protected boolean ignoreWebappDeploymentFailures = false;
+
+    @SetFromFlag
+    private Map<String, Object> attributes = new LinkedHashMap<String, Object>();
+
+    private ManagementContext managementContext;
+
+    @SetFromFlag
+    private Boolean httpsEnabled;
+
+    @SetFromFlag
+    private String sslCertificate;
+
+    @SetFromFlag
+    private String keystoreUrl;
+
+    @SetFromFlag @Deprecated /** @deprecated use keystoreUrl */
+    private String keystorePath;
+
+    @SetFromFlag
+    private String keystorePassword;
+
+    @SetFromFlag
+    private String keystoreCertAlias;
+
+    @SetFromFlag
+    private String truststorePath;
+
+    @SetFromFlag
+    private String trustStorePassword;
+    
+    @SetFromFlag
+    private String transportProtocols;
+    
+    @SetFromFlag
+    private String transportCiphers;
+
+    private File webappTempDir;
+    
+    private Class<BrooklynPropertiesSecurityFilter> securityFilterClazz;
+
+    private ShutdownHandler shutdownHandler;
+
+    public BrooklynWebServer(ManagementContext managementContext) {
+        this(Maps.newLinkedHashMap(), managementContext);
+    }
+
+    /**
+     * accepts flags:  port,
+     * war (url of war file which is the root),
+     * wars (map of context-prefix to url),
+     * attrs (map of attribute-name : object pairs passed to the servlet)
+     */
+    public BrooklynWebServer(Map<?,?> flags, ManagementContext managementContext) {
+        this.managementContext = managementContext;
+        Map<?,?> leftovers = FlagUtils.setFieldsFromFlags(flags, this);
+        if (!leftovers.isEmpty())
+            log.warn("Ignoring unknown flags " + leftovers);
+        
+        webappTempDir = BrooklynServerPaths.getBrooklynWebTmpDir(managementContext);
+    }
+
+    public BrooklynWebServer(ManagementContext managementContext, int port) {
+        this(managementContext, port, "brooklyn.war");
+    }
+
+    public BrooklynWebServer(ManagementContext managementContext, int port, String warUrl) {
+        this(MutableMap.of("port", port, "war", warUrl), managementContext);
+    }
+
+    public void setSecurityFilter(Class<BrooklynPropertiesSecurityFilter> filterClazz) {
+        this.securityFilterClazz = filterClazz;
+    }
+
+    public void setShutdownHandler(@Nullable ShutdownHandler shutdownHandler) {
+        this.shutdownHandler = shutdownHandler;
+    }
+
+    public BrooklynWebServer setPort(Object port) {
+        if (getActualPort()>0)
+            throw new IllegalStateException("Can't set port after port has been assigned to server (using "+getActualPort()+")");
+        this.requestedPort = TypeCoercions.coerce(port, PortRange.class);
+        return this;
+    }
+
+    @VisibleForTesting
+    File getWebappTempDir() {
+        return webappTempDir;
+    }
+    
+    public BrooklynWebServer setHttpsEnabled(Boolean httpsEnabled) {
+        this.httpsEnabled = httpsEnabled;
+        return this;
+    }
+    
+    public boolean getHttpsEnabled() {
+        return getConfig(httpsEnabled, BrooklynWebConfig.HTTPS_REQUIRED);
+    }
+    
+    public PortRange getRequestedPort() {
+        return requestedPort;
+    }
+    
+    /** returns port where this is running, or -1 if not yet known */
+    public int getActualPort() {
+        return actualPort;
+    }
+
+    /** interface/address where this server is listening;
+     * if bound to 0.0.0.0 (all NICs, e.g. because security is set) this will return one NIC where this is bound */
+    public InetAddress getAddress() {
+        return actualAddress;
+    }
+    
+    /** URL for accessing this web server (root context) */
+    public String getRootUrl() {
+        String address = (publicAddress != null) ? publicAddress.getHostName() : getAddress().getHostName();
+        if (getActualPort()>0){
+            String protocol = getHttpsEnabled()?"https":"http";
+            return protocol+"://"+address+":"+getActualPort()+"/";
+        } else {
+            return null;
+        }
+    }
+
+      /** sets the WAR to use as the root context (only if server not yet started);
+     * cf deploy("/", url) */
+    public BrooklynWebServer setWar(String url) {
+        this.war = url;
+        return this;
+    }
+
+    /** specifies a WAR to use at a given context path (only if server not yet started);
+     * cf deploy(path, url) */
+    public BrooklynWebServer addWar(String path, String warUrl) {
+        wars.put(path, warUrl);
+        return this;
+    }
+
+    /** InetAddress to which server should bind;
+     * defaults to 0.0.0.0 (although common call path is to set to 127.0.0.1 when security is not set) */
+    public BrooklynWebServer setBindAddress(InetAddress address) {
+        bindAddress = address;
+        return this;
+    }
+
+    /**
+     * Sets the public address that the server's management context's REST API will be available on
+     */
+    public BrooklynWebServer setPublicAddress(InetAddress address) {
+        publicAddress = address;
+        return this;
+    }
+
+    /** @deprecated use setAttribute */
+    public BrooklynWebServer addAttribute(String field, Object value) {
+        return setAttribute(field, value);
+    }
+    /** Specifies an attribute passed to deployed webapps 
+     * (in addition to {@link BrooklynServiceAttributes#BROOKLYN_MANAGEMENT_CONTEXT} */
+    public BrooklynWebServer setAttribute(String field, Object value) {
+        attributes.put(field, value);
+        return this;
+    }
+    
+    public <T> BrooklynWebServer configure(ConfigKey<T> key, T value) {
+        return setAttribute(key.getName(), value);
+    }
+
+    /** Specifies attributes passed to deployed webapps 
+     * (in addition to {@link BrooklynServiceAttributes#BROOKLYN_MANAGEMENT_CONTEXT} */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public BrooklynWebServer putAttributes(Map newAttrs) {
+        if (newAttrs!=null) attributes.putAll(newAttrs);
+        return this;
+    }
+
+    public void installAsServletFilter(ServletContextHandler context) {
+        ResourceConfig config = new DefaultResourceConfig();
+        // load all our REST API modules, JSON, and Swagger
+        for (Object r: BrooklynRestApi.getAllResources())
+            config.getSingletons().add(r);
+
+        // Accept gzipped requests and responses, disable caching for dynamic content
+        config.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, GZIPContentEncodingFilter.class.getName());
+        config.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, ImmutableList.of(GZIPContentEncodingFilter.class, NoCacheFilter.class));
+        // Checks if appropriate request given HA status
+        config.getProperties().put(ResourceConfig.PROPERTY_RESOURCE_FILTER_FACTORIES, HaHotCheckResourceFilter.class.getName());
+        // configure to match empty path, or any thing which looks like a file path with /assets/ and extension html, css, js, or png
+        // and treat that as static content
+        config.getProperties().put(ServletContainer.PROPERTY_WEB_PAGE_CONTENT_REGEX, "(/?|[^?]*/assets/[^?]+\\.[A-Za-z0-9_]+)");
+        // and anything which is not matched as a servlet also falls through (but more expensive than a regex check?)
+        config.getFeatures().put(ServletContainer.FEATURE_FILTER_FORWARD_ON_404, true);
+        // finally create this as a _filter_ which falls through to a web app or something (optionally)
+        FilterHolder filterHolder = new FilterHolder(new ServletContainer(config));
+
+        context.addFilter(filterHolder, "/*", EnumSet.allOf(DispatcherType.class));
+
+        ManagementContext mgmt = (ManagementContext) context.getAttribute(BrooklynServiceAttributes.BROOKLYN_MANAGEMENT_CONTEXT);
+        config.getSingletons().add(new ManagementContextProvider(mgmt));
+
+        config.getSingletons().add(new ShutdownHandlerProvider(shutdownHandler));
+    }
+
+    ContextHandlerCollectionHotSwappable handlers = new ContextHandlerCollectionHotSwappable();
+    
+    /**
+     * Starts the embedded web application server.
+     */
+    public synchronized void start() throws Exception {
+        if (server != null) throw new IllegalStateException(""+this+" already running");
+
+        if (actualPort == -1){
+            PortRange portRange = getConfig(requestedPort, BrooklynWebConfig.WEB_CONSOLE_PORT);
+            if (portRange==null) {
+                portRange = getHttpsEnabled() ? httpsPort : httpPort;
+            }
+            actualPort = LocalhostMachineProvisioningLocation.obtainPort(getAddress(), portRange);
+            if (actualPort == -1) 
+                throw new IllegalStateException("Unable to provision port for web console (wanted "+portRange+")");
+        }
+
+        server = new Server();
+        final Connector connector;
+        if (getHttpsEnabled()) {
+            connector = new SslSelectChannelConnector(createContextFactory());
+        } else {
+            connector = new SelectChannelConnector();
+        }
+        if (bindAddress != null) {
+            connector.setHost(bindAddress.getHostName());
+        }
+        connector.setPort(actualPort);
+        server.setConnectors(new Connector[]{connector});
+
+        if (bindAddress == null || bindAddress.equals(InetAddress.getByAddress(new byte[] { 0, 0, 0, 0 }))) {
+            actualAddress = BrooklynNetworkUtils.getLocalhostInetAddress();
+        } else {
+            actualAddress = bindAddress;
+        }
+
+        // use a nice name in the thread pool (otherwise this is exactly the same as Server defaults)
+        QueuedThreadPool threadPool = new QueuedThreadPool();
+        threadPool.setName("brooklyn-jetty-server-"+actualPort+"-"+threadPool.getName());
+        server.setThreadPool(threadPool);
+
+        if (log.isDebugEnabled())
+            log.debug("Starting Brooklyn console at "+getRootUrl()+", running " + war + (wars != null ? " and " + wars.values() : ""));
+        
+        addShutdownHook();
+
+        MutableMap<String, String> allWars = MutableMap.copyOf(wars);
+        String rootWar = allWars.remove("/");
+        if (rootWar==null) rootWar = war;
+        
+        for (Map.Entry<String, String> entry : allWars.entrySet()) {
+            String pathSpec = entry.getKey();
+            String warUrl = entry.getValue();
+            WebAppContext webapp = deploy(pathSpec, warUrl);
+            webapp.setTempDirectory(Os.mkdirs(new File(webappTempDir, newTimestampedDirName("war", 8))));
+        }
+        rootContext = deploy("/", rootWar);
+        rootContext.setTempDirectory(Os.mkdirs(new File(webappTempDir, "war-root")));
+
+        rootContext.addFilter(RequestTaggingFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
+        if (securityFilterClazz != null) {
+            rootContext.addFilter(securityFilterClazz, "/*", EnumSet.allOf(DispatcherType.class));
+        }
+        rootContext.addFilter(LoggingFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
+        rootContext.addFilter(HaMasterCheckFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
+        installAsServletFilter(rootContext);
+
+        server.setHandler(handlers);
+        server.start();
+        //reinit required because some webapps (eg grails) might wipe our language extension bindings
+        BrooklynInitialization.reinitAll();
+
+        if (managementContext instanceof ManagementContextInternal) {
+            ((ManagementContextInternal) managementContext).setManagementNodeUri(new URI(getRootUrl()));
+        }
+
+        log.info("Started Brooklyn console at "+getRootUrl()+", running " + rootWar + (allWars!=null && !allWars.isEmpty() ? " and " + wars.values() : ""));
+    }
+
+    private SslContextFactory createContextFactory() throws KeyStoreException {
+        SslContextFactory sslContextFactory = new SslContextFactory();
+
+        // allow webconsole keystore & related properties to be set in brooklyn.properties
+        String ksUrl = getKeystoreUrl();
+        String ksPassword = getConfig(keystorePassword, BrooklynWebConfig.KEYSTORE_PASSWORD);
+        String ksCertAlias = getConfig(keystoreCertAlias, BrooklynWebConfig.KEYSTORE_CERTIFICATE_ALIAS);
+        String trProtos = getConfig(transportProtocols, BrooklynWebConfig.TRANSPORT_PROTOCOLS);
+        String trCiphers = getConfig(transportCiphers, BrooklynWebConfig.TRANSPORT_CIPHERS);
+        
+        if (ksUrl!=null) {
+            sslContextFactory.setKeyStorePath(getLocalKeyStorePath(ksUrl));
+            if (Strings.isEmpty(ksPassword))
+                throw new IllegalArgumentException("Keystore password is required and non-empty if keystore is specified.");
+            sslContextFactory.setKeyStorePassword(ksPassword);
+            if (Strings.isNonEmpty(ksCertAlias))
+                sslContextFactory.setCertAlias(ksCertAlias);
+        } else {
+            log.info("No keystore specified but https enabled; creating a default keystore");
+            
+            if (Strings.isEmpty(ksCertAlias))
+                ksCertAlias = "web-console";
+            
+            // if password is blank the process will block and read from stdin !
+            if (Strings.isEmpty(ksPassword)) {
+                ksPassword = Identifiers.makeRandomId(8);
+                log.debug("created random password "+ksPassword+" for ad hoc internal keystore");
+            }
+            
+            KeyStore ks = SecureKeys.newKeyStore();
+            KeyPair key = SecureKeys.newKeyPair();
+            X509Certificate cert = new FluentKeySigner("brooklyn").newCertificateFor("web-console", key);
+            ks.setKeyEntry(ksCertAlias, key.getPrivate(), ksPassword.toCharArray(),
+                new Certificate[] { cert });
+            
+            sslContextFactory.setKeyStore(ks);
+            sslContextFactory.setKeyStorePassword(ksPassword);
+            sslContextFactory.setCertAlias(ksCertAlias);
+        }
+        if (!Strings.isEmpty(truststorePath)) {
+            sslContextFactory.setTrustStore(checkFileExists(truststorePath, "truststore"));
+            sslContextFactory.setTrustStorePassword(trustStorePassword);
+        }
+
+        if (Strings.isNonBlank(trProtos)) {
+            sslContextFactory.setIncludeProtocols(parseArray(trProtos));
+        }
+        if (Strings.isNonBlank(trCiphers)) {
+            sslContextFactory.setIncludeCipherSuites(parseArray(trCiphers));
+        }
+        return sslContextFactory;
+    }
+
+    private String[] parseArray(String list) {
+        List<String> arr = Splitter.on(",").omitEmptyStrings().trimResults().splitToList(list);
+        return arr.toArray(new String[arr.size()]);
+    }
+
+    private String getKeystoreUrl() {
+        if (keystoreUrl != null) {
+            if (Strings.isNonBlank(keystorePath) && !keystoreUrl.equals(keystorePath)) {
+                log.warn("Deprecated 'keystorePath' supplied with different value than 'keystoreUrl', preferring the latter: "+
+                        keystorePath+" / "+keystoreUrl);
+            }
+            return keystoreUrl;
+        } else if (Strings.isNonBlank(keystorePath)) {
+            log.warn("Deprecated 'keystorePath' used; callers should use 'keystoreUrl'");
+            return keystorePath;
+        } else {
+            return managementContext.getConfig().getConfig(BrooklynWebConfig.KEYSTORE_URL);
+        }
+    }
+
+    private <T> T getConfig(T override, ConfigKey<T> key) {
+        if (override!=null) {
+            return override;
+        } else {
+            return managementContext.getConfig().getConfig(key);
+        }
+    }
+
+    private String getLocalKeyStorePath(String keystoreUrl) {
+        ResourceUtils res = ResourceUtils.create(this);
+        res.checkUrlExists(keystoreUrl, BrooklynWebConfig.KEYSTORE_URL.getName());
+        if (new File(keystoreUrl).exists()) {
+            return keystoreUrl;
+        } else {
+            InputStream keystoreStream;
+            try {
+                keystoreStream = res.getResourceFromUrl(keystoreUrl);
+            } catch (Exception e) {
+                Exceptions.propagateIfFatal(e);
+                throw new IllegalArgumentException("Unable to access URL: "+keystoreUrl, e);
+            }
+            File tmp = Os.newTempFile("brooklyn-keystore", "ks");
+            tmp.deleteOnExit();
+            FileUtil.copyTo(keystoreStream, tmp);
+            Streams.closeQuietly(keystoreStream);
+            return tmp.getAbsolutePath();
+        }
+    }
+
+    private String newTimestampedDirName(String prefix, int randomSuffixLength) {
+        return prefix + "-" + new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date()) + "-" + Identifiers.makeRandomId(randomSuffixLength);
+    }
+    
+    private String checkFileExists(String path, String name) {
+        if(!new File(path).exists()){
+            throw new IllegalArgumentException("Could not find "+name+": "+path);
+        }
+        return path;
+    }
+
+    /**
+     * Asks the app server to stop and waits for it to finish up.
+     */
+    public synchronized void stop() throws Exception {
+        if (server==null) return;
+        String root = getRootUrl();
+        if (shutdownHook != null) Threads.removeShutdownHook(shutdownHook);
+        if (log.isDebugEnabled())
+            log.debug("Stopping Brooklyn web console at "+root+ " (" + war + (wars != null ? " and " + wars.values() : "") + ")");
+
+        server.stop();
+        try {
+            server.join();
+        } catch (Exception e) {
+            /* NPE may be thrown e.g. if threadpool not started */
+        }
+        server = null;
+        LocalhostMachineProvisioningLocation.releasePort(getAddress(), actualPort);
+        actualPort = -1;
+        if (log.isDebugEnabled())
+            log.debug("Stopped Brooklyn web console at "+root);
+    }
+
+    /** serve given WAR at the given pathSpec; if not yet started, it is simply remembered until start;
+     * if server already running, the context for this WAR is started.
+     * @return the context created and added as a handler 
+     * (and possibly already started if server is started,
+     * so be careful with any changes you make to it!)  */
+    public WebAppContext deploy(final String pathSpec, final String warUrl) {
+        String cleanPathSpec = pathSpec;
+        while (cleanPathSpec.startsWith("/"))
+            cleanPathSpec = cleanPathSpec.substring(1);
+        boolean isRoot = cleanPathSpec.isEmpty();
+
+        WebAppContext context = new WebAppContext();
+        context.setAttribute(BrooklynServiceAttributes.BROOKLYN_MANAGEMENT_CONTEXT, managementContext);
+        for (Map.Entry<String, Object> attributeEntry : attributes.entrySet()) {
+            context.setAttribute(attributeEntry.getKey(), attributeEntry.getValue());
+        }
+
+        try {
+            File tmpWarFile = Os.writeToTempFile(new CustomResourceLocator(managementContext.getConfig(), ResourceUtils.create(this)).getResourceFromUrl(warUrl), 
+                    isRoot ? "ROOT" : ("embedded-" + cleanPathSpec), ".war");
+            context.setWar(tmpWarFile.getAbsolutePath());
+        } catch (Exception e) {
+            log.warn("Failed to deploy webapp "+pathSpec+" from "+warUrl
+                + (ignoreWebappDeploymentFailures ? "; launching run without WAR" : " (rethrowing)")
+                + ": "+Exceptions.collapseText(e));
+            if (!ignoreWebappDeploymentFailures) {
+                throw new IllegalStateException("Failed to deploy webapp "+pathSpec+" from "+warUrl+": "+Exceptions.collapseText(e), e);
+            }
+            log.debug("Detail on failure to deploy webapp: "+e, e);
+            context.setWar("/dev/null");
+        }
+
+        context.setContextPath("/" + cleanPathSpec);
+        context.setParentLoaderPriority(true);
+
+        deploy(context);
+        return context;
+    }
+
+    private Thread shutdownHook = null;
+
+    protected synchronized void addShutdownHook() {
+        if (shutdownHook!=null) return;
+        // some webapps can generate a lot of output if we don't shut down the browser first
+        shutdownHook = Threads.addShutdownHook(new Runnable() {
+            @Override
+            public void run() {
+                log.debug("BrooklynWebServer detected shutdown: stopping web-console");
+                try {
+                    stop();
+                } catch (Exception e) {
+                    log.error("Failure shutting down web-console: "+e, e);
+                }
+            }
+        });
+    }
+
+    public void deploy(WebAppContext context) {
+        try {
+            handlers.updateHandler(context);
+        } catch (Exception e) {
+            Throwables.propagate(e);
+        }
+    }
+    
+    public Server getServer() {
+        return server;
+    }
+    
+    public WebAppContext getRootContext() {
+        return rootContext;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/org/apache/brooklyn/launcher/camp/BrooklynCampPlatformLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/camp/BrooklynCampPlatformLauncher.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/camp/BrooklynCampPlatformLauncher.java
new file mode 100644
index 0000000..72732cd
--- /dev/null
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/camp/BrooklynCampPlatformLauncher.java
@@ -0,0 +1,72 @@
+/*
+ * 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.brooklyn.launcher.camp;
+
+import io.brooklyn.camp.CampServer;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+import brooklyn.entity.basic.BrooklynShutdownHooks;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.internal.LocalManagementContext;
+
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherAbstract;
+
+import com.google.common.annotations.Beta;
+
+/** variant of super who also starts a CampServer for convenience */
+@Beta
+public class BrooklynCampPlatformLauncher extends BrooklynCampPlatformLauncherAbstract {
+
+    protected BrooklynLauncher brooklynLauncher;
+    protected CampServer campServer;
+
+    @Override
+    public BrooklynCampPlatformLauncher launch() {
+        assert platform == null;
+
+        mgmt = newManagementContext();
+        
+        // We created the management context, so we are responsible for terminating it
+        BrooklynShutdownHooks.invokeTerminateOnShutdown(mgmt);
+
+        brooklynLauncher = BrooklynLauncher.newInstance().managementContext(mgmt).start();
+        platform = new BrooklynCampPlatform(
+                PlatformRootSummary.builder().name("Brooklyn CAMP Platform").build(),
+                mgmt).setConfigKeyAtManagmentContext();
+        
+        campServer = new CampServer(getCampPlatform(), "").start();
+        
+        return this;
+    }
+    
+    protected ManagementContext newManagementContext() {
+        return new LocalManagementContext();
+    }
+
+    public static void main(String[] args) {
+        new BrooklynCampPlatformLauncher().launch();
+    }
+
+    public void stopServers() throws Exception {
+        brooklynLauncher.getServerDetails().getWebServer().stop();
+        campServer.stop();
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/org/apache/brooklyn/launcher/camp/SimpleYamlLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/camp/SimpleYamlLauncher.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/camp/SimpleYamlLauncher.java
new file mode 100644
index 0000000..200490a
--- /dev/null
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/camp/SimpleYamlLauncher.java
@@ -0,0 +1,35 @@
+/*
+ * 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.brooklyn.launcher.camp;
+
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherAbstract;
+import org.apache.brooklyn.camp.brooklyn.YamlLauncherAbstract;
+
+import com.google.common.annotations.Beta;
+
+/** convenience for launching YAML files directly */
+@Beta
+public class SimpleYamlLauncher extends YamlLauncherAbstract {
+
+    @Override
+    protected BrooklynCampPlatformLauncherAbstract newPlatformLauncher() {
+        return new BrooklynCampPlatformLauncher();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/BrooklynDevelopmentModes.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/BrooklynDevelopmentModes.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/BrooklynDevelopmentModes.java
new file mode 100644
index 0000000..13d2a3b
--- /dev/null
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/BrooklynDevelopmentModes.java
@@ -0,0 +1,93 @@
+/*
+ * 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.brooklyn.launcher.config;
+
+import java.io.File;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.util.os.Os;
+
+@Deprecated /** @deprecated since 0.7.0; see BrooklynVersion;
+* and anyway this was not really used, and if it were, it would be needed in core; autodetection is pretty good */
+public class BrooklynDevelopmentModes {
+
+    private static final Logger log = LoggerFactory.getLogger(BrooklynDevelopmentModes.class);
+    
+    public static final ConfigKey<BrooklynDevelopmentMode> BROOKLYN_DEV_MODE = new BasicConfigKey<BrooklynDevelopmentMode>(
+            BrooklynDevelopmentMode.class, "brooklyn.developmentMode", "whether to run in development mode " +
+                    "(default is to autodetect based on classpath)", BrooklynDevelopmentMode.AUTO);
+
+    private static AtomicBoolean loggedMode = new AtomicBoolean(false); 
+    
+    public static enum BrooklynDevelopmentMode {
+        TRUE(true), FALSE(false), AUTO(null);
+
+        private final Boolean enabled;
+        
+        BrooklynDevelopmentMode(Boolean enabled) {
+            this.enabled = enabled;
+        }
+        
+        public boolean isEnabled() {
+            boolean enabled = computeEnabled();
+            if (!loggedMode.getAndSet(true)) {
+                // log on first invocation
+                String reason = (this.enabled==null ? "autodetected" : "forced");
+                if (enabled) {
+                    log.info("Brooklyn running in development mode ("+reason+")");
+                } else {
+                    log.debug("Brooklyn not running in development mode ("+reason+")");
+                }
+            }
+            return enabled;
+        }
+        
+        protected boolean computeEnabled() {
+            if (enabled!=null) return enabled;
+            return getAutodectectedDevelopmentMode();
+        }
+    }
+    
+    private static Boolean developmentMode = null;
+    
+    public static boolean getAutodectectedDevelopmentMode() {
+        if (developmentMode!=null) return developmentMode;
+        developmentMode = computeAutodectectedDevelopmentMode();
+        return developmentMode;
+    }
+    
+    private static final String segment = "/core/target/classes";
+    
+    private static boolean computeAutodectectedDevelopmentMode() {
+        String cp = System.getProperty("java.class.path");
+        String platformSegment = Os.nativePath(segment);
+        if (cp==null) return false;
+        if (cp.endsWith(platformSegment) || cp.contains(platformSegment+File.pathSeparator)) {
+            log.debug("Brooklyn developmentMode autodetected (based on presence of '"+segment+"' in classpath)");
+            return true;
+        }
+        return false;
+    }
+    
+}



[7/8] incubator-brooklyn git commit: brooklyn-launcher: add org.apache package prefix

Posted by ha...@apache.org.
brooklyn-launcher: add org.apache package prefix

Also update dependent projects.


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/6f58ef3e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/6f58ef3e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/6f58ef3e

Branch: refs/heads/master
Commit: 6f58ef3e5d3c95c356e4b0cf42689dc848a0e603
Parents: 08662a7
Author: Ciprian Ciubotariu <ch...@gmx.net>
Authored: Thu Jul 16 19:11:03 2015 +0300
Committer: Ciprian Ciubotariu <ch...@gmx.net>
Committed: Thu Aug 6 18:17:11 2015 +0300

----------------------------------------------------------------------
 .../brooklyn/demo/GlobalWebFabricExample.java   |    2 +-
 .../brooklyn/demo/KafkaClusterExample.java      |    2 +-
 .../demo/StandaloneQpidBrokerExample.java       |    2 +-
 .../brooklyn/demo/CumulusRDFApplication.java    |    2 +-
 .../demo/HighAvailabilityCassandraCluster.java  |    2 +-
 .../brooklyn/demo/ResilientMongoDbApp.java      |    2 +-
 .../brooklyn/demo/RiakClusterExample.java       |    2 +-
 .../brooklyn/demo/SimpleCassandraCluster.java   |    2 +-
 .../apache/brooklyn/demo/StormSampleApp.java    |    2 +-
 .../brooklyn/demo/WideAreaCassandraCluster.java |    2 +-
 .../brooklyn/demo/SingleWebServerExample.java   |    2 +-
 .../demo/WebClusterDatabaseExample.java         |    2 +-
 .../demo/WebClusterDatabaseExampleApp.java      |    2 +-
 .../apache/brooklyn/demo/WebClusterExample.java |    2 +-
 .../main/java/org/apache/brooklyn/cli/Main.java |    6 +-
 .../main/java/brooklyn/launcher/Activator.java  |   39 -
 .../brooklyn/launcher/BrooklynLauncher.java     | 1062 ------------------
 .../launcher/BrooklynServerDetails.java         |   47 -
 .../brooklyn/launcher/BrooklynWebServer.java    |  652 -----------
 .../camp/BrooklynCampPlatformLauncher.java      |   72 --
 .../launcher/camp/SimpleYamlLauncher.java       |   35 -
 .../launcher/config/BrooklynGlobalConfig.java   |   66 --
 .../launcher/config/CustomResourceLocator.java  |  127 ---
 .../config/StopWhichAppsOnShutdown.java         |   23 -
 .../ContextHandlerCollectionHotSwappable.java   |   62 -
 .../org/apache/brooklyn/launcher/Activator.java |   39 +
 .../brooklyn/launcher/BrooklynLauncher.java     | 1062 ++++++++++++++++++
 .../launcher/BrooklynServerDetails.java         |   47 +
 .../brooklyn/launcher/BrooklynWebServer.java    |  652 +++++++++++
 .../camp/BrooklynCampPlatformLauncher.java      |   72 ++
 .../launcher/camp/SimpleYamlLauncher.java       |   35 +
 .../config/BrooklynDevelopmentModes.java        |   93 ++
 .../launcher/config/BrooklynGlobalConfig.java   |   66 ++
 .../launcher/config/CustomResourceLocator.java  |  127 +++
 .../config/StopWhichAppsOnShutdown.java         |   23 +
 .../ContextHandlerCollectionHotSwappable.java   |   62 +
 .../entity/basic/VanillaSoftwareYamlTest.java   |   97 --
 .../BrooklynEntityMirrorIntegrationTest.java    |  179 ---
 .../brooklynnode/BrooklynNodeRestTest.java      |  146 ---
 .../database/mssql/MssqlBlueprintLiveTest.java  |   60 -
 .../BrooklynLauncherHighAvailabilityTest.java   |  257 -----
 .../BrooklynLauncherRebindCatalogTest.java      |  116 --
 .../BrooklynLauncherRebindTestFixture.java      |  256 -----
 .../BrooklynLauncherRebindTestToFiles.java      |  153 ---
 ...lynLauncherRebindToCloudObjectStoreTest.java |  174 ---
 .../brooklyn/launcher/BrooklynLauncherTest.java |  367 ------
 .../launcher/BrooklynWebServerTest.java         |  209 ----
 .../launcher/SimpleYamlLauncherForTests.java    |   31 -
 .../brooklyn/launcher/WebAppRunnerTest.java     |  168 ---
 .../java/brooklyn/launcher/YamlLauncher.java    |   35 -
 .../blueprints/AbstractBlueprintTest.java       |  202 ----
 .../blueprints/CouchbaseBlueprintTest.java      |   69 --
 .../blueprints/MongoDbBlueprintTest.java        |   51 -
 .../entity/basic/VanillaSoftwareYamlTest.java   |   98 ++
 .../BrooklynEntityMirrorIntegrationTest.java    |  180 +++
 .../brooklynnode/BrooklynNodeRestTest.java      |  149 +++
 .../database/mssql/MssqlBlueprintLiveTest.java  |   60 +
 .../BrooklynLauncherHighAvailabilityTest.java   |  258 +++++
 .../BrooklynLauncherRebindCatalogTest.java      |  116 ++
 .../BrooklynLauncherRebindTestFixture.java      |  257 +++++
 .../BrooklynLauncherRebindTestToFiles.java      |  154 +++
 ...lynLauncherRebindToCloudObjectStoreTest.java |  175 +++
 .../brooklyn/launcher/BrooklynLauncherTest.java |  368 ++++++
 .../launcher/BrooklynWebServerTest.java         |  210 ++++
 .../launcher/SimpleYamlLauncherForTests.java    |   31 +
 .../brooklyn/launcher/WebAppRunnerTest.java     |  171 +++
 .../apache/brooklyn/launcher/YamlLauncher.java  |   35 +
 .../blueprints/AbstractBlueprintTest.java       |  202 ++++
 .../blueprints/CouchbaseBlueprintTest.java      |   69 ++
 .../blueprints/MongoDbBlueprintTest.java        |   51 +
 .../brooklyn/qa/load/SimulatedTheeTierApp.java  |    2 +-
 .../SoftlayerObtainPrivateLiveTest.java         |    2 +-
 .../org/apache/brooklyn/qa/load/LoadTest.java   |    2 +-
 .../qa/longevity/webcluster/WebClusterApp.java  |    2 +-
 74 files changed, 4883 insertions(+), 4776 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java
----------------------------------------------------------------------
diff --git a/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java b/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java
index d55de16..a3830b8 100644
--- a/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java
+++ b/examples/global-web-fabric/src/main/java/org/apache/brooklyn/demo/GlobalWebFabricExample.java
@@ -41,7 +41,7 @@ import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.webapp.ElasticJavaWebAppService;
 import brooklyn.entity.webapp.JavaWebAppService;
 import brooklyn.event.basic.PortAttributeSensorAndConfigKey;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.location.basic.PortRanges;
 import brooklyn.util.BrooklynMavenArtifacts;
 import brooklyn.util.CommandLineUtil;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/simple-messaging-pubsub/src/main/java/org/apache/brooklyn/demo/KafkaClusterExample.java
----------------------------------------------------------------------
diff --git a/examples/simple-messaging-pubsub/src/main/java/org/apache/brooklyn/demo/KafkaClusterExample.java b/examples/simple-messaging-pubsub/src/main/java/org/apache/brooklyn/demo/KafkaClusterExample.java
index f0d361e..541ff4e 100644
--- a/examples/simple-messaging-pubsub/src/main/java/org/apache/brooklyn/demo/KafkaClusterExample.java
+++ b/examples/simple-messaging-pubsub/src/main/java/org/apache/brooklyn/demo/KafkaClusterExample.java
@@ -24,7 +24,7 @@ import brooklyn.entity.basic.ApplicationBuilder;
 import brooklyn.entity.basic.Entities;
 import brooklyn.entity.messaging.kafka.KafkaCluster;
 import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.util.CommandLineUtil;
 
 import com.google.common.collect.Lists;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/simple-messaging-pubsub/src/main/java/org/apache/brooklyn/demo/StandaloneQpidBrokerExample.java
----------------------------------------------------------------------
diff --git a/examples/simple-messaging-pubsub/src/main/java/org/apache/brooklyn/demo/StandaloneQpidBrokerExample.java b/examples/simple-messaging-pubsub/src/main/java/org/apache/brooklyn/demo/StandaloneQpidBrokerExample.java
index 9df7005..2571c39 100644
--- a/examples/simple-messaging-pubsub/src/main/java/org/apache/brooklyn/demo/StandaloneQpidBrokerExample.java
+++ b/examples/simple-messaging-pubsub/src/main/java/org/apache/brooklyn/demo/StandaloneQpidBrokerExample.java
@@ -26,7 +26,7 @@ import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.messaging.amqp.AmqpServer;
 import brooklyn.entity.messaging.qpid.QpidBroker;
 import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.util.CommandLineUtil;
 
 import com.google.common.collect.ImmutableMap;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
----------------------------------------------------------------------
diff --git a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
index 5b521bd..66d187f 100644
--- a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
+++ b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/CumulusRDFApplication.java
@@ -52,7 +52,7 @@ import brooklyn.entity.webapp.tomcat.TomcatServer;
 import brooklyn.event.SensorEvent;
 import brooklyn.event.SensorEventListener;
 import brooklyn.event.basic.DependentConfiguration;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.location.Location;
 import brooklyn.location.basic.PortRanges;
 import brooklyn.policy.EnricherSpec;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/HighAvailabilityCassandraCluster.java
----------------------------------------------------------------------
diff --git a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/HighAvailabilityCassandraCluster.java b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/HighAvailabilityCassandraCluster.java
index a380798..673b18e 100644
--- a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/HighAvailabilityCassandraCluster.java
+++ b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/HighAvailabilityCassandraCluster.java
@@ -30,7 +30,7 @@ import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.nosql.cassandra.CassandraDatacenter;
 import brooklyn.entity.nosql.cassandra.CassandraNode;
 import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.policy.EnricherSpec;
 import brooklyn.policy.PolicySpec;
 import brooklyn.policy.ha.ServiceFailureDetector;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/ResilientMongoDbApp.java
----------------------------------------------------------------------
diff --git a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/ResilientMongoDbApp.java b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/ResilientMongoDbApp.java
index 3824502..84ca5dd 100644
--- a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/ResilientMongoDbApp.java
+++ b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/ResilientMongoDbApp.java
@@ -36,7 +36,7 @@ import brooklyn.entity.nosql.mongodb.MongoDBServer;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.event.SensorEvent;
 import brooklyn.event.SensorEventListener;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.policy.ha.ServiceFailureDetector;
 import brooklyn.policy.ha.ServiceReplacer;
 import brooklyn.policy.ha.ServiceRestarter;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/RiakClusterExample.java
----------------------------------------------------------------------
diff --git a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/RiakClusterExample.java b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/RiakClusterExample.java
index 1d61a45..cda67ac 100644
--- a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/RiakClusterExample.java
+++ b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/RiakClusterExample.java
@@ -30,7 +30,7 @@ import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.nosql.riak.RiakCluster;
 import brooklyn.entity.nosql.riak.RiakNode;
 import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.policy.EnricherSpec;
 import brooklyn.policy.PolicySpec;
 import brooklyn.policy.ha.ServiceFailureDetector;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/SimpleCassandraCluster.java
----------------------------------------------------------------------
diff --git a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/SimpleCassandraCluster.java b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/SimpleCassandraCluster.java
index 2ba6ba3..7d3aa65 100644
--- a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/SimpleCassandraCluster.java
+++ b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/SimpleCassandraCluster.java
@@ -25,7 +25,7 @@ import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.nosql.cassandra.CassandraDatacenter;
 import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.util.CommandLineUtil;
 
 import com.google.common.collect.Lists;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/StormSampleApp.java
----------------------------------------------------------------------
diff --git a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/StormSampleApp.java b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/StormSampleApp.java
index fcb3102..8b7854a 100644
--- a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/StormSampleApp.java
+++ b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/StormSampleApp.java
@@ -29,7 +29,7 @@ import brooklyn.entity.basic.Entities;
 import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.messaging.storm.StormDeployment;
 import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.util.CommandLineUtil;
 
 import com.google.common.collect.Lists;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/WideAreaCassandraCluster.java
----------------------------------------------------------------------
diff --git a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/WideAreaCassandraCluster.java b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/WideAreaCassandraCluster.java
index 21156e8..b528f42 100644
--- a/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/WideAreaCassandraCluster.java
+++ b/examples/simple-nosql-cluster/src/main/java/org/apache/brooklyn/demo/WideAreaCassandraCluster.java
@@ -32,7 +32,7 @@ import brooklyn.entity.nosql.cassandra.CassandraDatacenter;
 import brooklyn.entity.nosql.cassandra.CassandraFabric;
 import brooklyn.entity.nosql.cassandra.CassandraNode;
 import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.policy.EnricherSpec;
 import brooklyn.policy.PolicySpec;
 import brooklyn.policy.ha.ServiceFailureDetector;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/SingleWebServerExample.java
----------------------------------------------------------------------
diff --git a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/SingleWebServerExample.java b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/SingleWebServerExample.java
index 4561e2c..34eda75 100644
--- a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/SingleWebServerExample.java
+++ b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/SingleWebServerExample.java
@@ -30,7 +30,7 @@ import brooklyn.entity.basic.StartableApplication;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.webapp.JavaWebAppService;
 import brooklyn.entity.webapp.jboss.JBoss7Server;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.location.basic.PortRanges;
 import brooklyn.util.CommandLineUtil;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExample.java
----------------------------------------------------------------------
diff --git a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExample.java b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExample.java
index 4f10eb1..c308b5b 100644
--- a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExample.java
+++ b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExample.java
@@ -42,7 +42,7 @@ import brooklyn.entity.webapp.WebAppService;
 import brooklyn.entity.webapp.WebAppServiceConstants;
 import brooklyn.event.AttributeSensor;
 import brooklyn.event.basic.Sensors;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.location.basic.PortRanges;
 import brooklyn.policy.autoscaling.AutoScalerPolicy;
 import brooklyn.util.CommandLineUtil;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java
----------------------------------------------------------------------
diff --git a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java
index 179fabc..65193ad 100644
--- a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java
+++ b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterDatabaseExampleApp.java
@@ -47,7 +47,7 @@ import brooklyn.entity.webapp.WebAppService;
 import brooklyn.entity.webapp.WebAppServiceConstants;
 import brooklyn.event.AttributeSensor;
 import brooklyn.event.basic.Sensors;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.location.basic.PortRanges;
 import brooklyn.policy.autoscaling.AutoScalerPolicy;
 import brooklyn.util.BrooklynMavenArtifacts;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterExample.java
----------------------------------------------------------------------
diff --git a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterExample.java b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterExample.java
index 51642aa..57215fa 100644
--- a/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterExample.java
+++ b/examples/simple-web-cluster/src/main/java/org/apache/brooklyn/demo/WebClusterExample.java
@@ -31,7 +31,7 @@ import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.webapp.ControlledDynamicWebAppCluster;
 import brooklyn.entity.webapp.DynamicWebAppCluster;
 import brooklyn.entity.webapp.jboss.JBoss7Server;
-import brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
 import brooklyn.policy.autoscaling.AutoScalerPolicy;
 import brooklyn.util.CommandLineUtil;
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
----------------------------------------------------------------------
diff --git a/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java b/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
index 1c60fe7..71a6d4e 100644
--- a/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
+++ b/usage/cli/src/main/java/org/apache/brooklyn/cli/Main.java
@@ -83,9 +83,9 @@ import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils;
 import brooklyn.entity.rebind.persister.PersistMode;
 import brooklyn.entity.rebind.transformer.CompoundTransformer;
 import brooklyn.entity.trait.Startable;
-import brooklyn.launcher.BrooklynLauncher;
-import brooklyn.launcher.BrooklynServerDetails;
-import brooklyn.launcher.config.StopWhichAppsOnShutdown;
+import org.apache.brooklyn.launcher.BrooklynLauncher;
+import org.apache.brooklyn.launcher.BrooklynServerDetails;
+import org.apache.brooklyn.launcher.config.StopWhichAppsOnShutdown;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.Task;
 import brooklyn.management.ha.HighAvailabilityMode;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/brooklyn/launcher/Activator.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/Activator.java b/usage/launcher/src/main/java/brooklyn/launcher/Activator.java
deleted file mode 100644
index bf9bba2..0000000
--- a/usage/launcher/src/main/java/brooklyn/launcher/Activator.java
+++ /dev/null
@@ -1,39 +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 brooklyn.launcher;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class Activator implements BundleActivator {
-
-    public static final Logger log = LoggerFactory.getLogger(Activator.class);
-
-    public void start(BundleContext context) throws Exception {
-        //does nothing on startup, just makes resources available
-        //TODO maybe it wants to register a service that others could use?
-        log.info("Starting brooklyn-launcher OSGi bundle");
-    }
-
-    public void stop(BundleContext context) throws Exception {
-        log.info("Stopping brooklyn-launcher OSGi bundle");
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
deleted file mode 100644
index eb4fb82..0000000
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
+++ /dev/null
@@ -1,1062 +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 brooklyn.launcher;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.Closeable;
-import java.io.File;
-import java.io.StringReader;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeoutException;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer;
-import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynAssemblyTemplateInstantiator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
-import com.google.common.base.Splitter;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
-import brooklyn.catalog.internal.CatalogInitialization;
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.BrooklynServerConfig;
-import brooklyn.config.BrooklynServerPaths;
-import brooklyn.config.ConfigKey;
-import brooklyn.config.ConfigPredicates;
-import brooklyn.entity.Application;
-import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.entity.basic.BrooklynShutdownHooks;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.SoftwareProcess;
-import brooklyn.entity.basic.StartableApplication;
-import brooklyn.entity.brooklynnode.BrooklynNode;
-import brooklyn.entity.brooklynnode.LocalBrooklynNode;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.entity.rebind.PersistenceExceptionHandler;
-import brooklyn.entity.rebind.PersistenceExceptionHandlerImpl;
-import brooklyn.entity.rebind.RebindManager;
-import brooklyn.entity.rebind.RebindManagerImpl;
-import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
-import brooklyn.entity.rebind.persister.BrooklynPersistenceUtils;
-import brooklyn.entity.rebind.persister.PersistMode;
-import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-import brooklyn.entity.rebind.transformer.CompoundTransformer;
-import brooklyn.entity.trait.Startable;
-import brooklyn.launcher.config.StopWhichAppsOnShutdown;
-import brooklyn.location.Location;
-import brooklyn.location.LocationSpec;
-import brooklyn.location.PortRange;
-import brooklyn.location.basic.LocalhostMachineProvisioningLocation.LocalhostMachine;
-import brooklyn.location.basic.PortRanges;
-import brooklyn.management.ManagementContext;
-import brooklyn.management.ha.HighAvailabilityManager;
-import brooklyn.management.ha.HighAvailabilityManagerImpl;
-import brooklyn.management.ha.HighAvailabilityMode;
-import brooklyn.management.ha.ManagementNodeState;
-import brooklyn.management.ha.ManagementPlaneSyncRecord;
-import brooklyn.management.ha.ManagementPlaneSyncRecordPersister;
-import brooklyn.management.ha.ManagementPlaneSyncRecordPersisterToObjectStore;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.mementos.BrooklynMementoRawData;
-import brooklyn.rest.BrooklynWebConfig;
-import brooklyn.rest.filter.BrooklynPropertiesSecurityFilter;
-import brooklyn.rest.security.provider.BrooklynUserWithRandomPasswordSecurityProvider;
-import brooklyn.rest.util.ShutdownHandler;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.exceptions.FatalConfigurationRuntimeException;
-import brooklyn.util.exceptions.FatalRuntimeException;
-import brooklyn.util.exceptions.RuntimeInterruptedException;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.io.FileUtil;
-import brooklyn.util.net.Networking;
-import brooklyn.util.os.Os;
-import brooklyn.util.stream.Streams;
-import brooklyn.util.text.Strings;
-import brooklyn.util.time.Duration;
-import brooklyn.util.time.Time;
-import io.brooklyn.camp.CampPlatform;
-import io.brooklyn.camp.spi.AssemblyTemplate;
-import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
-
-/**
- * Example usage is:
- *  * <pre>
- * {@code
- * BrooklynLauncher launcher = BrooklynLauncher.newInstance()
- *     .application(new WebClusterDatabaseExample().appDisplayName("Web-cluster example"))
- *     .location("localhost")
- *     .start();
- * 
- * Entities.dumpInfo(launcher.getApplications());
- * </pre>
- */
-public class BrooklynLauncher {
-
-    private static final Logger LOG = LoggerFactory.getLogger(BrooklynLauncher.class);
-
-    /** Creates a configurable (fluent API) launcher for use starting the web console and Brooklyn applications. */
-    public static BrooklynLauncher newInstance() {
-        return new BrooklynLauncher();
-    }
-    
-    private final Map<String,Object> brooklynAdditionalProperties = Maps.newLinkedHashMap();
-    private BrooklynProperties brooklynProperties;
-    private ManagementContext managementContext;
-    
-    private final List<String> locationSpecs = new ArrayList<String>();
-    private final List<Location> locations = new ArrayList<Location>();
-
-    private final List<Application> appsToManage = new ArrayList<Application>();
-    private final List<ApplicationBuilder> appBuildersToManage = new ArrayList<ApplicationBuilder>();
-    private final List<String> yamlAppsToManage = new ArrayList<String>();
-    private final List<Application> apps = new ArrayList<Application>();
-    
-    private boolean startWebApps = true;
-    private boolean startBrooklynNode = false;
-    private PortRange port = null;
-    private Boolean useHttps = null;
-    private InetAddress bindAddress = null;
-    private InetAddress publicAddress = null;
-    private Map<String,String> webApps = new LinkedHashMap<String,String>();
-    private Map<String, ?> webconsoleFlags = Maps.newLinkedHashMap();
-    private Boolean skipSecurityFilter = null;
-    
-    private boolean ignoreWebErrors = false;
-    private boolean ignorePersistenceErrors = true;
-    private boolean ignoreCatalogErrors = true;
-    private boolean ignoreAppErrors = true;
-    
-    private StopWhichAppsOnShutdown stopWhichAppsOnShutdown = StopWhichAppsOnShutdown.THESE_IF_NOT_PERSISTED;
-    private ShutdownHandler shutdownHandler;
-    
-    private Function<ManagementContext,Void> customizeManagement = null;
-    private CatalogInitialization catalogInitialization = null;
-    
-    private PersistMode persistMode = PersistMode.DISABLED;
-    private HighAvailabilityMode highAvailabilityMode = HighAvailabilityMode.DISABLED;
-    private String persistenceDir;
-    private String persistenceLocation;
-    private Duration persistPeriod = Duration.ONE_SECOND;
-    // these default values come from config in HighAvailablilityManagerImpl
-    private Duration haHeartbeatTimeoutOverride = null;
-    private Duration haHeartbeatPeriodOverride = null;
-    
-    private volatile BrooklynWebServer webServer;
-    private CampPlatform campPlatform;
-
-    private boolean started;
-    private String globalBrooklynPropertiesFile = Os.mergePaths(Os.home(), ".brooklyn", "brooklyn.properties");
-    private String localBrooklynPropertiesFile;
-
-    public List<Application> getApplications() {
-        if (!started) throw new IllegalStateException("Cannot retrieve application until started");
-        return ImmutableList.copyOf(apps);
-    }
-    
-    public BrooklynServerDetails getServerDetails() {
-        if (!started) throw new IllegalStateException("Cannot retrieve server details until started");
-        return new BrooklynServerDetails(webServer, managementContext);
-    }
-    
-    /** 
-     * Specifies that the launcher should manage the given Brooklyn application.
-     * The application must not yet be managed. 
-     * The application will not be started as part of this call (callers can
-     * subsequently call {@link #start()} or {@link #getApplications()}.
-     * 
-     * @see #application(ApplicationBuilder)
-     */
-    public BrooklynLauncher application(Application app) {
-        if (Entities.isManaged(app)) throw new IllegalArgumentException("Application must not already be managed");
-        appsToManage.add(checkNotNull(app, "app"));
-        return this;
-    }
-
-    /** 
-     * Specifies that the launcher should build and manage the given Brooklyn application.
-     * The application must not yet be managed. 
-     * The application will not be started as part of this call (callers can
-     * subsequently call {@link #start()} or {@link #getApplications()}.
-     * 
-     * @see #application(Application)
-     */
-    public BrooklynLauncher application(ApplicationBuilder appBuilder) {
-        appBuildersToManage.add(checkNotNull(appBuilder, "appBuilder"));
-        return this;
-    }
-
-    /** 
-     * Specifies that the launcher should build and manage the Brooklyn application
-     * described by the given spec.
-     * The application will not be started as part of this call (callers can
-     * subsequently call {@link #start()} or {@link #getApplications()}.
-     * 
-     * @see #application(Application)
-     */
-    public BrooklynLauncher application(EntitySpec<? extends StartableApplication> appSpec) {
-        appBuildersToManage.add(new ApplicationBuilder(checkNotNull(appSpec, "appSpec")) {
-                @Override protected void doBuild() {
-                }});
-        return this;
-    }
-
-    /**
-     * Specifies that the launcher should build and manage the Brooklyn application
-     * described by the given YAML blueprint.
-     * The application will not be started as part of this call (callers can
-     * subsequently call {@link #start()} or {@link #getApplications()}.
-     *
-     * @see #application(Application)
-     */
-    public BrooklynLauncher application(String yaml) {
-        this.yamlAppsToManage.add(yaml);
-        return this;
-    }
-
-    /**
-     * Adds a location to be passed in on {@link #start()}, when that calls
-     * {@code application.start(locations)}.
-     */
-    public BrooklynLauncher location(Location location) {
-        locations.add(checkNotNull(location, "location"));
-        return this;
-    }
-
-    /**
-     * Give the spec of an application, to be created.
-     * 
-     * @see #location(Location)
-     */
-    public BrooklynLauncher location(String spec) {
-        locationSpecs.add(checkNotNull(spec, "spec"));
-        return this;
-    }
-    
-    public BrooklynLauncher locations(List<String> specs) {
-        locationSpecs.addAll(checkNotNull(specs, "specs"));
-        return this;
-    }
-
-    public BrooklynLauncher persistenceLocation(@Nullable String persistenceLocationSpec) {
-        persistenceLocation = persistenceLocationSpec;
-        return this;
-    }
-
-    public BrooklynLauncher globalBrooklynPropertiesFile(String file) {
-        globalBrooklynPropertiesFile = file;
-        return this;
-    }
-    
-    public BrooklynLauncher localBrooklynPropertiesFile(String file) {
-        localBrooklynPropertiesFile = file;
-        return this;
-    }
-    
-    /** 
-     * Specifies the management context this launcher should use. 
-     * If not specified a new one is created automatically.
-     */
-    public BrooklynLauncher managementContext(ManagementContext context) {
-        if (brooklynProperties != null) throw new IllegalStateException("Cannot set brooklynProperties and managementContext");
-        this.managementContext = context;
-        return this;
-    }
-
-    /**
-     * Specifies the brooklyn properties to be used. 
-     * Must not be set if managementContext is explicitly set.
-     */
-    public BrooklynLauncher brooklynProperties(BrooklynProperties brooklynProperties){
-        if (managementContext != null) throw new IllegalStateException("Cannot set brooklynProperties and managementContext");
-        if (this.brooklynProperties!=null && brooklynProperties!=null && this.brooklynProperties!=brooklynProperties)
-            LOG.warn("Brooklyn properties being reset in "+this+"; set null first if you wish to clear it", new Throwable("Source of brooklyn properties reset"));
-        this.brooklynProperties = brooklynProperties;
-        return this;
-    }
-    
-    /**
-     * Specifies a property to be added to the brooklyn properties
-     */
-    public BrooklynLauncher brooklynProperties(String field, Object value) {
-        brooklynAdditionalProperties.put(checkNotNull(field, "field"), value);
-        return this;
-    }
-    public <T> BrooklynLauncher brooklynProperties(ConfigKey<T> key, T value) {
-        return brooklynProperties(key.getName(), value);
-    }
-
-    /** 
-     * Specifies whether the launcher will start the Brooklyn web console 
-     * (and any additional webapps specified); default true.
-     */
-    public BrooklynLauncher webconsole(boolean startWebApps) {
-        this.startWebApps = startWebApps;
-        return this;
-    }
-
-    public BrooklynLauncher installSecurityFilter(Boolean val) {
-        this.skipSecurityFilter = val == null ? null : !val;
-        return this;
-    }
-
-    /** 
-     * As {@link #webconsolePort(PortRange)} taking a single port
-     */ 
-    public BrooklynLauncher webconsolePort(int port) {
-        return webconsolePort(PortRanges.fromInteger(port));
-    }
-
-    /**
-     * As {@link #webconsolePort(PortRange)} taking a string range
-     */
-    public BrooklynLauncher webconsolePort(String port) {
-        if (port==null) return webconsolePort((PortRange)null);
-        return webconsolePort(PortRanges.fromString(port));
-    }
-
-    /**
-     * Specifies the port where the web console (and any additional webapps specified) will listen;
-     * default (null) means "8081+" being the first available >= 8081 (or "8443+" for https).
-     */ 
-    public BrooklynLauncher webconsolePort(PortRange port) {
-        this.port = port;
-        return this;
-    }
-
-    /**
-     * Specifies whether the webconsole should use https.
-     */ 
-    public BrooklynLauncher webconsoleHttps(Boolean useHttps) {
-        this.useHttps = useHttps;
-        return this;
-    }
-
-    /**
-     * Specifies the NIC where the web console (and any additional webapps specified) will be bound;
-     * default 0.0.0.0, unless no security is specified (e.g. users) in which case it is localhost.
-     */ 
-    public BrooklynLauncher bindAddress(InetAddress bindAddress) {
-        this.bindAddress = bindAddress;
-        return this;
-    }
-
-    /**
-     * Specifies the address that the management context's REST API will be available on. Defaults
-     * to {@link #bindAddress} if it is not 0.0.0.0.
-     * @see #bindAddress(java.net.InetAddress)
-     */
-    public BrooklynLauncher publicAddress(InetAddress publicAddress) {
-        this.publicAddress = publicAddress;
-        return this;
-    }
-
-    /**
-     * Specifies additional flags to be passed to {@link BrooklynWebServer}.
-     */ 
-    public BrooklynLauncher webServerFlags(Map<String,?> webServerFlags) {
-        this.webconsoleFlags  = webServerFlags;
-        return this;
-    }
-
-    /** 
-     * Specifies an additional webapp to host on the webconsole port.
-     * @param contextPath The context path (e.g. "/hello", or equivalently just "hello") where the webapp will be hosted.
-     *      "/" will override the brooklyn console webapp.
-     * @param warUrl The URL from which the WAR should be loaded, supporting classpath:// protocol in addition to file:// and http(s)://.
-     */
-    public BrooklynLauncher webapp(String contextPath, String warUrl) {
-        webApps.put(contextPath, warUrl);
-        return this;
-    }
-
-    public BrooklynLauncher ignorePersistenceErrors(boolean ignorePersistenceErrors) {
-        this.ignorePersistenceErrors = ignorePersistenceErrors;
-        return this;
-    }
-
-    public BrooklynLauncher ignoreCatalogErrors(boolean ignoreCatalogErrors) {
-        this.ignoreCatalogErrors = ignoreCatalogErrors;
-        return this;
-    }
-
-    public BrooklynLauncher ignoreWebErrors(boolean ignoreWebErrors) {
-        this.ignoreWebErrors = ignoreWebErrors;
-        return this;
-    }
-
-    public BrooklynLauncher ignoreAppErrors(boolean ignoreAppErrors) {
-        this.ignoreAppErrors = ignoreAppErrors;
-        return this;
-    }
-
-    public BrooklynLauncher stopWhichAppsOnShutdown(StopWhichAppsOnShutdown stopWhich) {
-        this.stopWhichAppsOnShutdown = stopWhich;
-        return this;
-    }
-
-    public BrooklynLauncher customizeManagement(Function<ManagementContext,Void> customizeManagement) {
-        this.customizeManagement = customizeManagement;
-        return this;
-    }
-
-    @Beta
-    public BrooklynLauncher catalogInitialization(CatalogInitialization catInit) {
-        if (this.catalogInitialization!=null)
-            throw new IllegalStateException("Initial catalog customization already set.");
-        this.catalogInitialization = catInit;
-        return this;
-    }
-
-    public BrooklynLauncher shutdownOnExit(boolean val) {
-        LOG.warn("Call to deprecated `shutdownOnExit`", new Throwable("source of deprecated call"));
-        stopWhichAppsOnShutdown = StopWhichAppsOnShutdown.THESE_IF_NOT_PERSISTED;
-        return this;
-    }
-
-    public BrooklynLauncher persistMode(PersistMode persistMode) {
-        this.persistMode = persistMode;
-        return this;
-    }
-
-    public BrooklynLauncher highAvailabilityMode(HighAvailabilityMode highAvailabilityMode) {
-        this.highAvailabilityMode = highAvailabilityMode;
-        return this;
-    }
-
-    public BrooklynLauncher persistenceDir(@Nullable String persistenceDir) {
-        this.persistenceDir = persistenceDir;
-        return this;
-    }
-
-    public BrooklynLauncher persistenceDir(@Nullable File persistenceDir) {
-        if (persistenceDir==null) return persistenceDir((String)null);
-        return persistenceDir(persistenceDir.getAbsolutePath());
-    }
-
-    public BrooklynLauncher persistPeriod(Duration persistPeriod) {
-        this.persistPeriod = persistPeriod;
-        return this;
-    }
-
-    public BrooklynLauncher haHeartbeatTimeout(Duration val) {
-        this.haHeartbeatTimeoutOverride = val;
-        return this;
-    }
-
-    public BrooklynLauncher startBrooklynNode(boolean val) {
-        this.startBrooklynNode = val;
-        return this;
-    }
-
-    /**
-     * Controls both the frequency of heartbeats, and the frequency of checking the health of other nodes.
-     */
-    public BrooklynLauncher haHeartbeatPeriod(Duration val) {
-        this.haHeartbeatPeriodOverride = val;
-        return this;
-    }
-
-    /**
-     * @param destinationDir Directory for state to be copied to
-     */
-    public void copyPersistedState(String destinationDir) {
-        copyPersistedState(destinationDir, null, null);
-    }
-
-    /**
-     * A listener to call when the user requests a shutdown (i.e. through the REST API)
-     */
-    public BrooklynLauncher shutdownHandler(ShutdownHandler shutdownHandler) {
-        this.shutdownHandler = shutdownHandler;
-        return this;
-    }
-
-    /**
-     * @param destinationDir Directory for state to be copied to
-     * @param destinationLocation Optional location if target for copied state is a blob store.
-     */
-    public void copyPersistedState(String destinationDir, @Nullable String destinationLocation) {
-        copyPersistedState(destinationDir, destinationLocation, null);
-    }
-
-    /**
-     * @param destinationDir Directory for state to be copied to
-     * @param destinationLocationSpec Optional location if target for copied state is a blob store.
-     * @param transformer Optional transformations to apply to retrieved state before it is copied.
-     */
-    public void copyPersistedState(String destinationDir, @Nullable String destinationLocationSpec, @Nullable CompoundTransformer transformer) {
-        initManagementContext();
-        try {
-            highAvailabilityMode = HighAvailabilityMode.HOT_STANDBY;
-            initPersistence();
-        } catch (Exception e) {
-            handleSubsystemStartupError(ignorePersistenceErrors, "persistence", e);
-        }
-        
-        try {
-            BrooklynMementoRawData memento = managementContext.getRebindManager().retrieveMementoRawData();
-            if (transformer != null) memento = transformer.transform(memento);
-            
-            ManagementPlaneSyncRecord planeState = managementContext.getHighAvailabilityManager().loadManagementPlaneSyncRecord(true);
-            
-            LOG.info("Persisting state to "+destinationDir+(destinationLocationSpec!=null ? " @ "+destinationLocationSpec : ""));
-            PersistenceObjectStore destinationObjectStore = BrooklynPersistenceUtils.newPersistenceObjectStore(
-                managementContext, destinationLocationSpec, destinationDir);
-            BrooklynPersistenceUtils.writeMemento(managementContext, memento, destinationObjectStore);
-            BrooklynPersistenceUtils.writeManagerMemento(managementContext, planeState, destinationObjectStore);
-
-        } catch (Exception e) {
-            Exceptions.propagateIfFatal(e);
-            LOG.debug("Error copying persisted state (rethrowing): " + e, e);
-            throw new FatalRuntimeException("Error copying persisted state: " +
-                Exceptions.collapseText(e), e);
-        }
-    }
-
-    /** @deprecated since 0.7.0 use {@link #copyPersistedState} instead */
-    // Make private after deprecation
-    @Deprecated
-    public BrooklynMementoRawData retrieveState() {
-        initManagementContext();
-        initPersistence();
-        return managementContext.getRebindManager().retrieveMementoRawData();
-    }
-
-    /**
-     * @param memento The state to copy
-     * @param destinationDir Directory for state to be copied to
-     * @param destinationLocation Optional location if target for copied state is a blob store.
-     * @deprecated since 0.7.0 use {@link #copyPersistedState} instead
-     */
-    // Make private after deprecation
-    @Deprecated
-    public void persistState(BrooklynMementoRawData memento, String destinationDir, @Nullable String destinationLocationSpec) {
-        initManagementContext();
-        PersistenceObjectStore destinationObjectStore = BrooklynPersistenceUtils.newPersistenceObjectStore(
-            managementContext, destinationLocationSpec, destinationDir);
-        BrooklynPersistenceUtils.writeMemento(managementContext, memento, destinationObjectStore);
-    }
-
-    /**
-     * Starts the web server (with web console) and Brooklyn applications, as per the specifications configured. 
-     * @return An object containing details of the web server and the management context.
-     */
-    public BrooklynLauncher start() {
-        if (started) throw new IllegalStateException("Cannot start() or launch() multiple times");
-        started = true;
-
-        // Create the management context
-        initManagementContext();
-
-        // Inform catalog initialization that it is starting up
-        CatalogInitialization catInit = ((ManagementContextInternal)managementContext).getCatalogInitialization();
-        catInit.setStartingUp(true);
-
-        // Start webapps as soon as mgmt context available -- can use them to detect progress of other processes
-        if (startWebApps) {
-            try {
-                startWebApps();
-            } catch (Exception e) {
-                handleSubsystemStartupError(ignoreWebErrors, "core web apps", e);
-            }
-        }
-        
-        // Add a CAMP platform
-        campPlatform = new BrooklynCampPlatformLauncherNoServer()
-                .useManagementContext(managementContext)
-                .launch()
-                .getCampPlatform();
-        // TODO start CAMP rest _server_ in the below (at /camp) ?
-
-        try {
-            initPersistence();
-            startPersistence();
-        } catch (Exception e) {
-            handleSubsystemStartupError(ignorePersistenceErrors, "persistence", e);
-        }
-
-        try {
-            // run cat init now if it hasn't yet been run; 
-            // will also run if there was an ignored error in catalog above, allowing it to fail startup here if requested
-            if (catInit!=null && !catInit.hasRunOfficialInitialization()) {
-                if (persistMode==PersistMode.DISABLED) {
-                    LOG.debug("Loading catalog as part of launch sequence (it was not loaded as part of any rebind sequence)");
-                    catInit.populateCatalog(ManagementNodeState.MASTER, true, true, null);
-                } else {
-                    // should have loaded during rebind
-                    ManagementNodeState state = managementContext.getHighAvailabilityManager().getNodeState();
-                    LOG.warn("Loading catalog for "+state+" as part of launch sequence (it was not loaded as part of the rebind sequence)");
-                    catInit.populateCatalog(state, true, true, null);
-                }
-            }
-        } catch (Exception e) {
-            handleSubsystemStartupError(ignoreCatalogErrors, "initial catalog", e);
-        }
-        catInit.setStartingUp(false);
-
-        // Create the locations. Must happen after persistence is started in case the
-        // management context's catalog is loaded from persisted state. (Location
-        // resolution uses the catalog's classpath to scan for resolvers.)
-        locations.addAll(managementContext.getLocationRegistry().resolve(locationSpecs));
-
-        // Already rebinded successfully, so previous apps are now available.
-        // Allow the startup to be visible in console for newly created apps.
-        ((LocalManagementContext)managementContext).noteStartupComplete();
-
-        // TODO create apps only after becoming master, analogously to catalog initialization
-        try {
-            createApps();
-            startApps();
-        } catch (Exception e) {
-            handleSubsystemStartupError(ignoreAppErrors, "brooklyn autostart apps", e);
-        }
-
-        if (startBrooklynNode) {
-            try {
-                startBrooklynNode();
-            } catch (Exception e) {
-                handleSubsystemStartupError(ignoreAppErrors, "brooklyn node / self entity", e);
-            }
-        }
-        
-        if (persistMode != PersistMode.DISABLED) {
-            // Make sure the new apps are persisted in case process exits immediately.
-            managementContext.getRebindManager().forcePersistNow(false, null);
-        }
-        return this;
-    }
-
-    private void initManagementContext() {
-        // Create the management context
-        if (managementContext == null) {
-            if (brooklynProperties == null) {
-                BrooklynProperties.Factory.Builder builder = BrooklynProperties.Factory.builderDefault();
-                if (globalBrooklynPropertiesFile != null) {
-                    if (fileExists(globalBrooklynPropertiesFile)) {
-                        LOG.debug("Using global properties file "+globalBrooklynPropertiesFile);
-                        // brooklyn.properties stores passwords (web-console and cloud credentials), 
-                        // so ensure it has sensible permissions
-                        checkFileReadable(globalBrooklynPropertiesFile);
-                        checkFilePermissionsX00(globalBrooklynPropertiesFile);
-                    } else {
-                        LOG.debug("Global properties file "+globalBrooklynPropertiesFile+" does not exist, will ignore");
-                    }
-                    builder.globalPropertiesFile(globalBrooklynPropertiesFile);
-                } else {
-                    LOG.debug("Global properties file disabled");
-                    builder.globalPropertiesFile(null);
-                }
-                
-                if (localBrooklynPropertiesFile != null) {
-                    checkFileReadable(localBrooklynPropertiesFile);
-                    checkFilePermissionsX00(localBrooklynPropertiesFile);
-                    builder.localPropertiesFile(localBrooklynPropertiesFile);
-                }
-                managementContext = new LocalManagementContext(builder, brooklynAdditionalProperties);
-            } else {
-                if (globalBrooklynPropertiesFile != null)
-                    LOG.warn("Ignoring globalBrooklynPropertiesFile "+globalBrooklynPropertiesFile+" because explicit brooklynProperties supplied");
-                if (localBrooklynPropertiesFile != null)
-                    LOG.warn("Ignoring localBrooklynPropertiesFile "+localBrooklynPropertiesFile+" because explicit brooklynProperties supplied");
-                managementContext = new LocalManagementContext(brooklynProperties, brooklynAdditionalProperties);
-            }
-            brooklynProperties = ((ManagementContextInternal)managementContext).getBrooklynProperties();
-            
-            // We created the management context, so we are responsible for terminating it
-            BrooklynShutdownHooks.invokeTerminateOnShutdown(managementContext);
-            
-        } else if (brooklynProperties == null) {
-            brooklynProperties = ((ManagementContextInternal)managementContext).getBrooklynProperties();
-            brooklynProperties.addFromMap(brooklynAdditionalProperties);
-        }
-        
-        if (catalogInitialization!=null) {
-            ((ManagementContextInternal)managementContext).setCatalogInitialization(catalogInitialization);
-        }
-        
-        if (customizeManagement!=null) {
-            customizeManagement.apply(managementContext);
-        }
-    }
-
-    private boolean fileExists(String file) {
-        return new File(Os.tidyPath(file)).exists();
-    }
-
-    private void checkFileReadable(String file) {
-        File f = new File(Os.tidyPath(file));
-        if (!f.exists()) {
-            throw new FatalRuntimeException("File "+file+" does not exist");
-        }
-        if (!f.isFile()) {
-            throw new FatalRuntimeException(file+" is not a file");
-        }
-        if (!f.canRead()) {
-            throw new FatalRuntimeException(file+" is not readable");
-        }
-    }
-    
-    private void checkFilePermissionsX00(String file) {
-        File f = new File(Os.tidyPath(file));
-        
-        Maybe<String> permission = FileUtil.getFilePermissions(f);
-        if (permission.isAbsent()) {
-            LOG.debug("Could not determine permissions of file; assuming ok: "+f);
-        } else {
-            if (!permission.get().subSequence(4, 10).equals("------")) {
-                throw new FatalRuntimeException("Invalid permissions for file "+file+"; expected ?00 but was "+permission.get());
-            }
-        }
-    }
-    
-    private void handleSubsystemStartupError(boolean ignoreSuchErrors, String system, Exception e) {
-        Exceptions.propagateIfFatal(e);
-        if (ignoreSuchErrors) {
-            LOG.error("Subsystem for "+system+" had startup error (continuing with startup): "+e, e);
-            if (managementContext!=null)
-                ((ManagementContextInternal)managementContext).errors().add(e);
-        } else {
-            throw Exceptions.propagate(e);
-        }
-    }
-
-    protected void startWebApps() {
-        // No security options in properties and no command line options overriding.
-        if (Boolean.TRUE.equals(skipSecurityFilter) && bindAddress==null) {
-            LOG.info("Starting Brooklyn web-console on loopback because security is explicitly disabled and no bind address specified");
-            bindAddress = Networking.LOOPBACK;
-        } else if (BrooklynWebConfig.hasNoSecurityOptions(brooklynProperties)) {
-            if (bindAddress==null) {
-                LOG.info("Starting Brooklyn web-console with passwordless access on localhost and protected access from any other interfaces (no bind address specified)");
-            } else {
-                if (Arrays.equals(new byte[] { 127, 0, 0, 1 }, bindAddress.getAddress())) { 
-                    LOG.info("Starting Brooklyn web-console with passwordless access on localhost");
-                } else if (Arrays.equals(new byte[] { 0, 0, 0, 0 }, bindAddress.getAddress())) { 
-                    LOG.info("Starting Brooklyn web-console with passwordless access on localhost and random password (logged) required from any other interfaces");
-                } else { 
-                    LOG.info("Starting Brooklyn web-console with passwordless access on localhost (if permitted) and random password (logged) required from any other interfaces");
-                }
-            }
-            brooklynProperties.put(
-                    BrooklynWebConfig.SECURITY_PROVIDER_CLASSNAME,
-                    BrooklynUserWithRandomPasswordSecurityProvider.class.getName());
-        } else {
-            LOG.debug("Starting Brooklyn using security properties: "+brooklynProperties.submap(ConfigPredicates.startingWith(BrooklynWebConfig.BASE_NAME_SECURITY)).asMapWithStringKeys());
-        }
-        if (bindAddress == null) bindAddress = Networking.ANY_NIC;
-
-        LOG.debug("Starting Brooklyn web-console with bindAddress "+bindAddress+" and properties "+brooklynProperties);
-        try {
-            webServer = new BrooklynWebServer(webconsoleFlags, managementContext);
-            webServer.setBindAddress(bindAddress);
-            webServer.setPublicAddress(publicAddress);
-            if (port!=null) webServer.setPort(port);
-            if (useHttps!=null) webServer.setHttpsEnabled(useHttps);
-            webServer.setShutdownHandler(shutdownHandler);
-            webServer.putAttributes(brooklynProperties);
-            if (skipSecurityFilter != Boolean.TRUE) {
-                webServer.setSecurityFilter(BrooklynPropertiesSecurityFilter.class);
-            }
-            for (Map.Entry<String, String> webapp : webApps.entrySet()) {
-                webServer.addWar(webapp.getKey(), webapp.getValue());
-            }
-            webServer.start();
-
-        } catch (Exception e) {
-            LOG.warn("Failed to start Brooklyn web-console (rethrowing): " + Exceptions.collapseText(e));
-            throw new FatalRuntimeException("Failed to start Brooklyn web-console: " + Exceptions.collapseText(e), e);
-        }
-    }
-
-    protected void initPersistence() {
-        // Prepare the rebind directory, and initialise the RebindManager as required
-        final PersistenceObjectStore objectStore;
-        if (persistMode == PersistMode.DISABLED) {
-            LOG.info("Persistence disabled");
-            objectStore = null;
-            
-        } else {
-            try {
-                if (persistenceLocation == null) {
-                    persistenceLocation = brooklynProperties.getConfig(BrooklynServerConfig.PERSISTENCE_LOCATION_SPEC);
-                }
-                persistenceDir = BrooklynServerPaths.newMainPersistencePathResolver(brooklynProperties).location(persistenceLocation).dir(persistenceDir).resolve();
-                objectStore = BrooklynPersistenceUtils.newPersistenceObjectStore(managementContext, persistenceLocation, persistenceDir, 
-                    persistMode, highAvailabilityMode);
-                    
-                RebindManager rebindManager = managementContext.getRebindManager();
-                
-                BrooklynMementoPersisterToObjectStore persister = new BrooklynMementoPersisterToObjectStore(
-                    objectStore,
-                    ((ManagementContextInternal)managementContext).getBrooklynProperties(),
-                    managementContext.getCatalogClassLoader());
-                PersistenceExceptionHandler persistenceExceptionHandler = PersistenceExceptionHandlerImpl.builder().build();
-                ((RebindManagerImpl) rebindManager).setPeriodicPersistPeriod(persistPeriod);
-                rebindManager.setPersister(persister, persistenceExceptionHandler);
-            } catch (FatalConfigurationRuntimeException e) {
-                throw e;
-            } catch (Exception e) {
-                Exceptions.propagateIfFatal(e);
-                LOG.debug("Error initializing persistence subsystem (rethrowing): "+e, e);
-                throw new FatalRuntimeException("Error initializing persistence subsystem: "+
-                    Exceptions.collapseText(e), e);
-            }
-        }
-        
-        // Initialise the HA manager as required
-        if (highAvailabilityMode == HighAvailabilityMode.DISABLED) {
-            LOG.info("High availability disabled");
-        } else {
-            if (objectStore==null)
-                throw new FatalConfigurationRuntimeException("Cannot run in HA mode when no persistence configured.");
-
-            HighAvailabilityManager haManager = managementContext.getHighAvailabilityManager();
-            ManagementPlaneSyncRecordPersister persister =
-                new ManagementPlaneSyncRecordPersisterToObjectStore(managementContext,
-                    objectStore,
-                    managementContext.getCatalogClassLoader());
-            ((HighAvailabilityManagerImpl)haManager).setHeartbeatTimeout(haHeartbeatTimeoutOverride);
-            ((HighAvailabilityManagerImpl)haManager).setPollPeriod(haHeartbeatPeriodOverride);
-            haManager.setPersister(persister);
-        }
-    }
-    
-    protected void startPersistence() {
-        // Now start the HA Manager and the Rebind manager, as required
-        if (highAvailabilityMode == HighAvailabilityMode.DISABLED) {
-            HighAvailabilityManager haManager = managementContext.getHighAvailabilityManager();
-            haManager.disabled();
-
-            if (persistMode != PersistMode.DISABLED) {
-                startPersistenceWithoutHA();
-            }
-            
-        } else {
-            // Let the HA manager decide when objectstore.prepare and rebindmgr.rebind need to be called 
-            // (based on whether other nodes in plane are already running).
-            
-            HighAvailabilityMode startMode=null;
-            switch (highAvailabilityMode) {
-                case AUTO:
-                case MASTER:
-                case STANDBY:
-                case HOT_STANDBY:
-                case HOT_BACKUP:
-                    startMode = highAvailabilityMode;
-                    break;
-                case DISABLED:
-                    throw new IllegalStateException("Unexpected code-branch for high availability mode "+highAvailabilityMode);
-            }
-            if (startMode==null)
-                throw new IllegalStateException("Unexpected high availability mode "+highAvailabilityMode);
-            
-            LOG.debug("Management node (with HA) starting");
-            HighAvailabilityManager haManager = managementContext.getHighAvailabilityManager();
-            // prepare after HA mode is known, to prevent backups happening in standby mode
-            haManager.start(startMode);
-        }
-    }
-
-    private void startPersistenceWithoutHA() {
-        RebindManager rebindManager = managementContext.getRebindManager();
-        if (Strings.isNonBlank(persistenceLocation))
-            LOG.info("Management node (no HA) rebinding to entities at "+persistenceLocation+" in "+persistenceDir);
-        else
-            LOG.info("Management node (no HA) rebinding to entities on file system in "+persistenceDir);
-
-        ClassLoader classLoader = managementContext.getCatalogClassLoader();
-        try {
-            rebindManager.rebind(classLoader, null, ManagementNodeState.MASTER);
-        } catch (Exception e) {
-            Exceptions.propagateIfFatal(e);
-            LOG.debug("Error rebinding to persisted state (rethrowing): "+e, e);
-            throw new FatalRuntimeException("Error rebinding to persisted state: "+
-                Exceptions.collapseText(e), e);
-        }
-        rebindManager.startPersistence();
-    }
-
-    protected void createApps() {
-        for (ApplicationBuilder appBuilder : appBuildersToManage) {
-            StartableApplication app = appBuilder.manage(managementContext);
-            apps.add(app);
-        }
-        for (Application app : appsToManage) {
-            Entities.startManagement(app, managementContext);
-            apps.add(app);
-        }
-        for (String blueprint : yamlAppsToManage) {
-            Application app = getAppFromYaml(blueprint);
-            // Note: BrooklynAssemblyTemplateInstantiator automatically puts applications under management.
-            apps.add(app);
-        }
-    }
-
-    protected void startBrooklynNode() {
-        final String classpath = System.getenv("INITIAL_CLASSPATH");
-        if (Strings.isBlank(classpath)) {
-            LOG.warn("Cannot find INITIAL_CLASSPATH environment variable, skipping BrooklynNode entity creation");
-            return;
-        }
-        if (webServer == null || !startWebApps) {
-            LOG.info("Skipping BrooklynNode entity creation, BrooklynWebServer not running");
-            return;
-        }
-        ApplicationBuilder brooklyn = new ApplicationBuilder() {
-            @SuppressWarnings("deprecation")
-            @Override
-            protected void doBuild() {
-                addChild(EntitySpec.create(LocalBrooklynNode.class)
-                        .configure(SoftwareProcess.ENTITY_STARTED, true)
-                        .configure(SoftwareProcess.RUN_DIR, System.getenv("ROOT"))
-                        .configure(SoftwareProcess.INSTALL_DIR, System.getenv("BROOKLYN_HOME"))
-                        .configure(BrooklynNode.ENABLED_HTTP_PROTOCOLS, ImmutableList.of(webServer.getHttpsEnabled() ? "https" : "http"))
-                        .configure(webServer.getHttpsEnabled() ? BrooklynNode.HTTPS_PORT : BrooklynNode.HTTP_PORT, PortRanges.fromInteger(webServer.getActualPort()))
-                        .configure(BrooklynNode.WEB_CONSOLE_BIND_ADDRESS, bindAddress)
-                        .configure(BrooklynNode.WEB_CONSOLE_PUBLIC_ADDRESS, publicAddress)
-                        .configure(BrooklynNode.CLASSPATH, Splitter.on(":").splitToList(classpath))
-                        .configure(BrooklynNode.NO_WEB_CONSOLE_AUTHENTICATION, Boolean.TRUE.equals(skipSecurityFilter))
-                        .displayName("Brooklyn Console"));
-            }
-        };
-        LocationSpec<?> spec = LocationSpec.create(LocalhostMachine.class).displayName("Local Brooklyn");
-        Location localhost = managementContext.getLocationManager().createLocation(spec);
-        brooklyn.appDisplayName("Brooklyn")
-                .manage(managementContext)
-                .start(ImmutableList.of(localhost));
-    }
-
-    protected Application getAppFromYaml(String input) {
-        AssemblyTemplate at = campPlatform.pdp().registerDeploymentPlan(new StringReader(input));
-        BrooklynAssemblyTemplateInstantiator instantiator;
-        try {
-            AssemblyTemplateInstantiator ati = at.getInstantiator().newInstance();
-            if (ati instanceof BrooklynAssemblyTemplateInstantiator) {
-                instantiator = BrooklynAssemblyTemplateInstantiator.class.cast(ati);
-            } else {
-                throw new IllegalStateException("Cannot create application with instantiator: " + ati);
-            }
-        } catch (Exception e) {
-            throw Exceptions.propagate(e);
-        }
-        Application app = instantiator.create(at, campPlatform);
-        return app;
-    }
-    
-    protected void startApps() {
-        if ((stopWhichAppsOnShutdown==StopWhichAppsOnShutdown.ALL) || 
-            (stopWhichAppsOnShutdown==StopWhichAppsOnShutdown.ALL_IF_NOT_PERSISTED && persistMode==PersistMode.DISABLED)) {
-            BrooklynShutdownHooks.invokeStopAppsOnShutdown(managementContext);
-        }
-
-        List<Throwable> appExceptions = Lists.newArrayList();
-        for (Application app : apps) {
-            if (app instanceof Startable) {
-                
-                if ((stopWhichAppsOnShutdown==StopWhichAppsOnShutdown.THESE) || 
-                    (stopWhichAppsOnShutdown==StopWhichAppsOnShutdown.THESE_IF_NOT_PERSISTED && persistMode==PersistMode.DISABLED)) {
-                    BrooklynShutdownHooks.invokeStopOnShutdown(app);
-                }
-                try {
-                    LOG.info("Starting brooklyn application {} in location{} {}", new Object[] { app, locations.size()!=1?"s":"", locations });
-                    ((Startable)app).start(locations);
-                } catch (Exception e) {
-                    LOG.error("Error starting "+app+": "+Exceptions.collapseText(e), Exceptions.getFirstInteresting(e));
-                    appExceptions.add(Exceptions.collapse(e));
-                    
-                    if (Thread.currentThread().isInterrupted()) {
-                        LOG.error("Interrupted while starting applications; aborting");
-                        break;
-                    }
-                }
-            }
-        }
-        if (!appExceptions.isEmpty()) {
-            Throwable t = Exceptions.create(appExceptions);
-            throw new FatalRuntimeException("Error starting applications: "+Exceptions.collapseText(t), t);
-        }
-    }
-    
-    public boolean isStarted() {
-        return started;
-    }
-    
-    /**
-     * Terminates this launch, but does <em>not</em> stop the applications (i.e. external processes
-     * are left running, etc). However, by terminating the management console the brooklyn applications
-     * become unusable.
-     */
-    public void terminate() {
-        if (!started) return; // no-op
-        
-        if (webServer != null) {
-            try {
-                webServer.stop();
-            } catch (Exception e) {
-                LOG.warn("Error stopping web-server; continuing with termination", e);
-            }
-        }
-
-        // TODO Do we want to do this as part of managementContext.terminate, so after other threads are terminated etc?
-        // Otherwise the app can change between this persist and the terminate.
-        if (persistMode != PersistMode.DISABLED) {
-            try {
-                Stopwatch stopwatch = Stopwatch.createStarted();
-                if (managementContext.getHighAvailabilityManager().getPersister() != null) {
-                    managementContext.getHighAvailabilityManager().getPersister().waitForWritesCompleted(Duration.TEN_SECONDS);
-                }
-                managementContext.getRebindManager().waitForPendingComplete(Duration.TEN_SECONDS, true);
-                LOG.info("Finished waiting for persist; took "+Time.makeTimeStringRounded(stopwatch));
-            } catch (RuntimeInterruptedException e) {
-                Thread.currentThread().interrupt(); // keep going with shutdown
-                LOG.warn("Persistence interrupted during shutdown: "+e, e);
-            } catch (InterruptedException e) {
-                Thread.currentThread().interrupt(); // keep going with shutdown
-                LOG.warn("Persistence interrupted during shutdown: "+e, e);
-            } catch (TimeoutException e) {
-                LOG.warn("Timeout after 10 seconds waiting for persistence to write all data; continuing");
-            }
-        }
-        
-        if (managementContext instanceof ManagementContextInternal) {
-            ((ManagementContextInternal)managementContext).terminate();
-        }
-        
-        for (Location loc : locations) {
-            if (loc instanceof Closeable) {
-                Streams.closeQuietly((Closeable)loc);
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/brooklyn/launcher/BrooklynServerDetails.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynServerDetails.java b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynServerDetails.java
deleted file mode 100644
index b041956..0000000
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynServerDetails.java
+++ /dev/null
@@ -1,47 +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 brooklyn.launcher;
-
-import brooklyn.management.ManagementContext;
-
-public class BrooklynServerDetails {
-
-    protected BrooklynWebServer webServer;
-    protected ManagementContext mgmtContext;
-    
-    public BrooklynServerDetails(BrooklynWebServer webServer, ManagementContext mgmtContext) {
-        super();
-        this.webServer = webServer;
-        this.mgmtContext = mgmtContext;
-    }
-
-    public BrooklynWebServer getWebServer() {
-        return webServer;
-    }
-    
-    public String getWebServerUrl() {
-        if (webServer==null) return null;
-        return webServer.getRootUrl();
-    }
-    
-    public ManagementContext getManagementContext() {
-        return mgmtContext;
-    }
-    
-}


[4/8] incubator-brooklyn git commit: brooklyn-launcher: add org.apache package prefix

Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/BrooklynGlobalConfig.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/BrooklynGlobalConfig.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/BrooklynGlobalConfig.java
new file mode 100644
index 0000000..9ae0504
--- /dev/null
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/BrooklynGlobalConfig.java
@@ -0,0 +1,66 @@
+/*
+ * 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.brooklyn.launcher.config;
+
+import brooklyn.config.BrooklynServiceAttributes;
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.BrooklynConfigKeys;
+import brooklyn.location.cloud.CloudLocationConfig;
+import brooklyn.management.internal.BrooklynGarbageCollector;
+import brooklyn.rest.BrooklynWebConfig;
+import brooklyn.util.internal.BrooklynSystemProperties;
+import brooklyn.util.internal.StringSystemProperty;
+import brooklyn.util.time.Duration;
+
+/**
+ * Convenience collection of popular global configuration values.
+ * (Also a handy way to recall where config keys are set.)
+ * <p>
+ * These can typically be set in brooklyn.properties for global applicability.
+ * In some cases (eg SSH_CONFIG_* keys) they can also be set on entities/locations 
+ * for behaviour specific to that entity.
+ * <p>
+ * Also see:
+ * <li> {@link BrooklynSystemProperties}
+ * <li> {@link BrooklynServiceAttributes}
+ * <li> {@link CloudLocationConfig} and classes in that hierarchy.
+ */
+public class BrooklynGlobalConfig {
+
+    public static final ConfigKey<Boolean> REQUIRE_HTTPS = BrooklynWebConfig.HTTPS_REQUIRED;
+    
+    public static final ConfigKey<Duration> GC_PERIOD = BrooklynGarbageCollector.GC_PERIOD;
+    public static final ConfigKey<Boolean> DO_SYSTEM_GC = BrooklynGarbageCollector.DO_SYSTEM_GC;
+    public static final ConfigKey<Integer> MAX_TASKS_PER_TAG = BrooklynGarbageCollector.MAX_TASKS_PER_TAG;
+    public static final ConfigKey<Integer> MAX_TASKS_PER_ENTITY = BrooklynGarbageCollector.MAX_TASKS_PER_ENTITY;
+    public static final ConfigKey<Integer> MAX_TASKS_GLOBAL = BrooklynGarbageCollector.MAX_TASKS_GLOBAL;
+    public static final ConfigKey<Duration> MAX_TASK_AGE = BrooklynGarbageCollector.MAX_TASK_AGE;
+
+    public static final StringSystemProperty LOCALHOST_IP_ADDRESS = BrooklynServiceAttributes.LOCALHOST_IP_ADDRESS;
+    
+    // brooklyn.ssh.config.noDeleteAfterExec = true   will cause scripts to be left in situ for debugging
+    public static final ConfigKey<Boolean> SSH_CONFIG_NO_DELETE_SCRIPT = BrooklynConfigKeys.SSH_CONFIG_NO_DELETE_SCRIPT;
+    
+    public static final ConfigKey<String> SSH_CONFIG_SCRIPT_DIR = BrooklynConfigKeys.SSH_CONFIG_SCRIPT_DIR;
+    public static final ConfigKey<String> SSH_CONFIG_SCRIPT_HEADER = BrooklynConfigKeys.SSH_CONFIG_SCRIPT_HEADER;
+    public static final ConfigKey<String> SSH_CONFIG_DIRECT_HEADER = BrooklynConfigKeys.SSH_CONFIG_DIRECT_HEADER;
+
+    // TODO other constants from elsewhere
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/CustomResourceLocator.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/CustomResourceLocator.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/CustomResourceLocator.java
new file mode 100644
index 0000000..78ad7c6
--- /dev/null
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/CustomResourceLocator.java
@@ -0,0 +1,127 @@
+/*
+ * 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.brooklyn.launcher.config;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.BrooklynVersion;
+import brooklyn.config.ConfigMap;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.os.Os;
+
+/** class which allows non-standard locators to be registered for URL's being loaded */
+public class CustomResourceLocator {
+
+    private static final Logger log = LoggerFactory.getLogger(CustomResourceLocator.class);
+    
+    protected final ResourceUtils r;
+    private ConfigMap config;
+
+    public interface ResourceLocator {
+        public boolean isApplicable(String url, ConfigMap config);
+        public InputStream locate(String url, ConfigMap config, ResourceUtils r);
+    }
+    
+    private static List<ResourceLocator> locators = new ArrayList<ResourceLocator>();
+    
+    public CustomResourceLocator(ConfigMap config, ResourceUtils r) {
+        this.config = config;
+        this.r = r;
+    }
+    
+    public static void registerAlternateLocator(ResourceLocator locator) {
+        locators.add(0, locator);
+    }
+    
+    /** returns the first known locator for the given url/config pair */
+    public static ResourceLocator getLocatorFor(String url, ConfigMap config) {
+        for (ResourceLocator l: locators) {
+            if (l.isApplicable(url, config)) return l;
+        }
+        return null;
+    }
+    
+    /** finds the file indicated at the URL, using some rewrites if necessary to work around some known issues.
+     * <p>
+     * in particular, eclipse often does not copy WAR files as instructed by maven, so brooklyn.war might not be found */
+    public InputStream getResourceFromUrl(String url) {
+        // TODO we could allow the source to be overridden from config,
+        // by allowing configuration e.g.
+        // brooklyn.path.override.brooklyn.war=classpath://brooklyn-replacement-webapp.war
+        // (not sure if this is a good idea or not)
+        
+        try {
+            return r.getResourceFromUrl(url);
+        } catch (Exception e) {
+            ResourceLocator locator = getLocatorFor(url, config);
+            if (locator!=null) {
+                log.debug("Unable to load resource from "+url+"; attempting with locator "+locator);
+                try {
+                    InputStream result = locator.locate(url, config, r);
+                    if (result!=null) return result;
+                    if (result==null)
+                        log.warn("Unable to load resource from "+url+", even with custom locator; rethrowing original exception");
+                } catch (Exception e2) {
+                    log.warn("Unable to load resource from "+url+", even with custom locator; rethrowing original exception, new exception is: "+e2);
+                }
+            }
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    public static class SearchingClassPathInDevMode implements ResourceLocator {
+        private final String urlToSearchFor;
+        private final String classpathSuffixToSearchFor;
+        private final String classpathSuffixToUse;
+
+        public SearchingClassPathInDevMode(String urlToSearchFor, String classpathSuffixToSearchFor, String classpathSuffixToUse) {
+            this.urlToSearchFor = urlToSearchFor;
+            this.classpathSuffixToSearchFor = Os.nativePath(classpathSuffixToSearchFor);
+            this.classpathSuffixToUse = classpathSuffixToUse;
+        }
+        
+        @Override
+        public boolean isApplicable(String url, ConfigMap config) {
+            return BrooklynVersion.isDevelopmentEnvironment() && urlToSearchFor.equals(url);
+        }
+
+        @Override
+        public InputStream locate(String url, ConfigMap config, ResourceUtils r) {
+            String cp = System.getProperty("java.class.path");
+            int cpi = cp.indexOf(classpathSuffixToSearchFor);
+            if (cpi==-1) return null;
+            String path = cp.substring(0, cpi);
+            int lps = path.lastIndexOf(File.pathSeparatorChar);
+            if (lps>=0) path = path.substring(lps+1);
+            path = path + classpathSuffixToUse;
+            log.debug("Looking for "+url+" in revised location "+path);
+            InputStream result = r.getResourceFromUrl(path);
+            log.info("Using "+url+" from revised location "+path);
+            return result;
+        }
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/StopWhichAppsOnShutdown.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/StopWhichAppsOnShutdown.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/StopWhichAppsOnShutdown.java
new file mode 100644
index 0000000..e5851f7
--- /dev/null
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/config/StopWhichAppsOnShutdown.java
@@ -0,0 +1,23 @@
+/*
+ * 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.brooklyn.launcher.config;
+
+public enum StopWhichAppsOnShutdown {
+    ALL, ALL_IF_NOT_PERSISTED, NONE, THESE, THESE_IF_NOT_PERSISTED
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/main/java/org/apache/brooklyn/util/web/ContextHandlerCollectionHotSwappable.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/util/web/ContextHandlerCollectionHotSwappable.java b/usage/launcher/src/main/java/org/apache/brooklyn/util/web/ContextHandlerCollectionHotSwappable.java
new file mode 100644
index 0000000..4a69adf
--- /dev/null
+++ b/usage/launcher/src/main/java/org/apache/brooklyn/util/web/ContextHandlerCollectionHotSwappable.java
@@ -0,0 +1,62 @@
+/*
+ * 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.brooklyn.util.web;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.handler.ContextHandlerCollection;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+public class ContextHandlerCollectionHotSwappable extends ContextHandlerCollection {
+
+    public synchronized void updateHandler(WebAppContext context) throws Exception {
+        Handler[] hl0 = getHandlers();
+        List<Handler> hl = hl0!=null ? new ArrayList<Handler>(Arrays.asList(hl0)) : new ArrayList<Handler>();
+        // remove any previous version
+        removeContextFromList(hl, context.getContextPath());
+        // have to add before the root war (remove root war then add back)
+        Handler oldRoot = removeContextFromList(hl, "/");
+        // now add and add back any root
+        hl.add(context);
+        if (oldRoot!=null) hl.add(oldRoot);
+        setHandlers(hl.toArray(new Handler[0]));
+        
+        // and if we are already running, start the new context
+        if (isRunning()) {
+            context.start();
+        }
+    }
+
+    public static Handler removeContextFromList(List<Handler> hl, String contextPath) {
+        Iterator<Handler> hi = hl.iterator();
+        while (hi.hasNext()) {
+            Handler h = hi.next();
+            if ((h instanceof WebAppContext) && ((WebAppContext)h).getContextPath().equals(contextPath)) {
+                hi.remove();
+                return h;
+            }
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/entity/basic/VanillaSoftwareYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/entity/basic/VanillaSoftwareYamlTest.java b/usage/launcher/src/test/java/brooklyn/entity/basic/VanillaSoftwareYamlTest.java
deleted file mode 100644
index 8fbca64..0000000
--- a/usage/launcher/src/test/java/brooklyn/entity/basic/VanillaSoftwareYamlTest.java
+++ /dev/null
@@ -1,97 +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 brooklyn.entity.basic;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.Application;
-import brooklyn.entity.Entity;
-import brooklyn.entity.trait.Startable;
-import brooklyn.launcher.SimpleYamlLauncherForTests;
-import brooklyn.launcher.camp.SimpleYamlLauncher;
-import brooklyn.test.Asserts;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.os.Os;
-import brooklyn.util.text.Strings;
-
-import com.google.common.collect.Iterables;
-
-public class VanillaSoftwareYamlTest {
-
-    private static final Logger log = LoggerFactory.getLogger(VanillaSoftwareYamlTest.class);
-    
-    @Test(groups="Integration")
-    public void testVanillaSoftwareYaml() {
-        SimpleYamlLauncher l = new SimpleYamlLauncherForTests();
-        try {
-            Application app = l.launchAppYaml("vanilla-software-blueprint.yaml");
-            log.info("started "+app);
-
-            String runDir = Iterables.getOnlyElement(app.getChildren()).getAttribute(SoftwareProcess.RUN_DIR);
-            final String filePath = Os.mergePaths(runDir, "DATE");
-
-            String fileContents = new ResourceUtils(this).getResourceAsString(filePath);
-            Long d1 = Long.parseLong( Strings.getFirstWordAfter(fileContents, "utc") );
-            Assert.assertTrue( Math.abs(d1*1000-System.currentTimeMillis())<15000, "Time UTC does not match system; "+d1+" v "+System.currentTimeMillis() );
-
-            Asserts.succeedsEventually(new Runnable() {
-                public void run() {
-                    String fileContents = new ResourceUtils(this).getResourceAsString(filePath);
-                    Assert.assertTrue(fileContents.contains("checkRunning"));
-                }
-            });
-
-            app.invoke(Startable.STOP, null).getUnchecked();
-            Asserts.succeedsEventually(new Runnable() {
-                public void run() {
-                    String fileContents = new ResourceUtils(this).getResourceAsString(filePath);
-                    Assert.assertTrue(fileContents.contains("stop"));
-                }
-            });
-
-        } finally {
-            l.destroyAll();
-        }
-        log.info("DONE");
-    }
-    
-    /** yaml variant of VanillaSoftwareProcessAndChildrenIntegrationTest */
-    @Test(groups="Integration")
-    public void testVanillaSoftwareYamlWithChildStartedAfter() {
-        SimpleYamlLauncher l = new SimpleYamlLauncherForTests();
-        try {
-            Application app = l.launchAppYaml("vanilla-software-with-child-blueprint.yaml");
-            log.info("started "+app);
-
-            Entity p1 = Iterables.getOnlyElement( app.getChildren() );
-            Long d1 = Long.parseLong( Strings.getFirstWordAfter(new ResourceUtils(this).getResourceAsString(Os.mergePaths(p1.getAttribute(SoftwareProcess.RUN_DIR), "DATE")), "utc") );
-            
-            Entity p2 = Iterables.getOnlyElement( p1.getChildren() );
-            Long d2 = Long.parseLong( Strings.getFirstWordAfter(new ResourceUtils(this).getResourceAsString(Os.mergePaths(p2.getAttribute(SoftwareProcess.RUN_DIR), "DATE")), "utc") );
-            Assert.assertTrue( d2-d1 > 2 && d2-d1 < 10, "p2 should have started 3s after parent, but it did not ("+(d2-d1)+"s difference" );
-        } finally {
-            l.destroyAll();
-        }
-        log.info("DONE");
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorIntegrationTest.java b/usage/launcher/src/test/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorIntegrationTest.java
deleted file mode 100644
index a523019..0000000
--- a/usage/launcher/src/test/java/brooklyn/entity/brooklynnode/BrooklynEntityMirrorIntegrationTest.java
+++ /dev/null
@@ -1,179 +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 brooklyn.entity.brooklynnode;
-
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.launcher.BrooklynWebServer;
-import brooklyn.management.ManagementContext;
-import brooklyn.management.ha.HighAvailabilityMode;
-import brooklyn.rest.filter.BrooklynPropertiesSecurityFilter;
-import brooklyn.test.Asserts;
-import brooklyn.test.EntityTestUtils;
-import brooklyn.test.HttpTestUtils;
-import brooklyn.test.entity.LocalManagementContextForTests;
-import brooklyn.test.entity.TestApplication;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.time.Duration;
-
-/**
- * Test for EntityMirror, launching an in-memory server and ensuring we can mirror.
- * Here so that we can access the REST server.
- * <p>
- * May require <code>-Dbrooklyn.localhost.address=127.0.0.1</code> so that the console which binds to localhost is addressible.
- * (That and the time it takes to run are the only reasons this is Integration.)
- */
-@Test
-public class BrooklynEntityMirrorIntegrationTest {
-
-    private static final Logger log = LoggerFactory.getLogger(BrooklynEntityMirrorIntegrationTest.class);
-    
-    private BrooklynWebServer server;
-    private TestApplication serverApp;
-    private ManagementContext serverMgmt;
-    
-    private TestApplication localApp;
-    private ManagementContext localMgmt;
-
-    @BeforeMethod(alwaysRun=true)
-    public void setUp() throws Exception {
-        localApp = TestApplication.Factory.newManagedInstanceForTests();
-        localMgmt = localApp.getManagementContext();
-    }
-
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        if (serverMgmt!=null) Entities.destroyAll(serverMgmt);
-        if (server!=null) server.stop();
-        if (localMgmt!=null) Entities.destroyAll(localMgmt);
-        
-        serverMgmt = null;
-    }
-
-    
-    protected void setUpServer() {
-        setUpServer(new LocalManagementContextForTests(), false);
-    }
-    protected void setUpServer(ManagementContext mgmt, boolean useSecurityFilter) {
-        try {
-            if (serverMgmt!=null) throw new IllegalStateException("server already set up");
-            
-            serverMgmt = mgmt;
-            server = new BrooklynWebServer(mgmt);
-            if (useSecurityFilter) server.setSecurityFilter(BrooklynPropertiesSecurityFilter.class);
-            server.start();
-            
-            serverMgmt.getHighAvailabilityManager().disabled();
-            serverApp = ApplicationBuilder.newManagedApp(TestApplication.class, serverMgmt);
-            
-            ((LocalManagementContextForTests)serverMgmt).noteStartupComplete();
-        } catch (Exception e) {
-            throw Exceptions.propagate(e);
-        }
-    }
-
-    protected String getBaseUri() {
-        return server.getRootUrl();
-    }
-    
-    @Test(groups="Integration")
-    public void testServiceMirroring() throws Exception {
-        setUpServer();
-        
-        String catalogItemId = "test-catalog-item:1.0";
-        String catalogItemIdGA = "test-catalog-item:1.0-GA";
-        serverApp.setAttribute(TestApplication.MY_ATTRIBUTE, "austria");
-        serverApp.setCatalogItemId(catalogItemId);
-
-        String serviceId = serverApp.getId();
-        Entity mirror = localApp.addChild(EntitySpec.create(BrooklynEntityMirror.class)
-            .configure(BrooklynEntityMirror.POLL_PERIOD, Duration.millis(100))
-            .configure(BrooklynEntityMirror.MIRRORED_ENTITY_ID, serviceId)
-            .configure(BrooklynEntityMirror.MIRRORED_ENTITY_URL, 
-                getBaseUri()+"/v1/applications/"+serviceId+"/entities/"+serviceId)
-        );
-
-        EntityTestUtils.assertAttributeEqualsEventually(mirror, TestApplication.MY_ATTRIBUTE, "austria");
-        EntityTestUtils.assertAttributeEqualsEventually(mirror, BrooklynEntityMirror.MIRROR_CATALOG_ITEM_ID, catalogItemId);
-        assertTrue(mirror.getAttribute(BrooklynEntityMirror.MIRROR_SUMMARY) != null, "entity summary is null");
-        log.info("Sensors mirrored are: "+((EntityInternal)mirror).getAllAttributes());
-        
-        serverApp.setAttribute(TestApplication.MY_ATTRIBUTE, "bermuda");
-        serverApp.setCatalogItemId(catalogItemIdGA);
-        EntityTestUtils.assertAttributeEqualsEventually(mirror, TestApplication.MY_ATTRIBUTE, "bermuda");
-        EntityTestUtils.assertAttributeEqualsEventually(mirror, BrooklynEntityMirror.MIRROR_CATALOG_ITEM_ID, catalogItemIdGA);
-
-        serverApp.stop();
-        assertUnmanagedEventually(mirror);
-    }
-
-    @Test(groups="Integration")
-    public void testServiceMirroringHttps() throws Exception {
-        LocalManagementContextForTests mgmtHttps = new LocalManagementContextForTests();
-        mgmtHttps.getBrooklynProperties().put("brooklyn.webconsole.security.https.required", true);
-        mgmtHttps.getBrooklynProperties().put("brooklyn.webconsole.security.users", "admin");
-        mgmtHttps.getBrooklynProperties().put("brooklyn.webconsole.security.user.admin.password", "P5ssW0rd");
-
-        setUpServer(mgmtHttps, true);
-        Assert.assertTrue(getBaseUri().startsWith("https:"), "URL is not https: "+getBaseUri());
-        // check auth is required
-        HttpTestUtils.assertHttpStatusCodeEquals(getBaseUri(), 401);
-        
-        serverApp.setAttribute(TestApplication.MY_ATTRIBUTE, "austria");
-
-        String serviceId = serverApp.getId();
-        Entity mirror = localApp.addChild(EntitySpec.create(BrooklynEntityMirror.class)
-            .configure(BrooklynEntityMirror.POLL_PERIOD, Duration.millis(100))
-            .configure(BrooklynEntityMirror.MANAGEMENT_USER, "admin")
-            .configure(BrooklynEntityMirror.MANAGEMENT_PASSWORD, "P5ssW0rd")
-            .configure(BrooklynEntityMirror.MIRRORED_ENTITY_ID, serviceId)
-            .configure(BrooklynEntityMirror.MIRRORED_ENTITY_URL, 
-                getBaseUri()+"/v1/applications/"+serviceId+"/entities/"+serviceId)
-        );
-
-        EntityTestUtils.assertAttributeEqualsEventually(mirror, TestApplication.MY_ATTRIBUTE, "austria");
-        log.info("Sensors mirrored are: "+((EntityInternal)mirror).getAllAttributes());
-        
-        serverApp.setAttribute(TestApplication.MY_ATTRIBUTE, "bermuda");
-        EntityTestUtils.assertAttributeEqualsEventually(mirror, TestApplication.MY_ATTRIBUTE, "bermuda");
-
-        serverApp.stop();
-        assertUnmanagedEventually(mirror);
-    }
-
-    private static void assertUnmanagedEventually(final Entity entity) {
-        Asserts.succeedsEventually(new Runnable() {
-            @Override public void run() {
-                assertFalse(Entities.isManaged(entity));
-            }});
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/entity/brooklynnode/BrooklynNodeRestTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/entity/brooklynnode/BrooklynNodeRestTest.java b/usage/launcher/src/test/java/brooklyn/entity/brooklynnode/BrooklynNodeRestTest.java
deleted file mode 100644
index 34d7b07..0000000
--- a/usage/launcher/src/test/java/brooklyn/entity/brooklynnode/BrooklynNodeRestTest.java
+++ /dev/null
@@ -1,146 +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 brooklyn.entity.brooklynnode;
-
-import java.net.URI;
-import java.util.concurrent.Callable;
-
-import org.apache.http.client.HttpClient;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.Application;
-import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.entity.basic.Attributes;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.launcher.SimpleYamlLauncherForTests;
-import brooklyn.launcher.camp.SimpleYamlLauncher;
-import brooklyn.location.Location;
-import brooklyn.management.Task;
-import brooklyn.test.EntityTestUtils;
-import brooklyn.test.HttpTestUtils;
-import brooklyn.test.entity.TestApplication;
-import brooklyn.test.entity.TestEntity;
-import brooklyn.util.collections.Jsonya;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.collections.MutableSet;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
-import brooklyn.util.net.Urls;
-import brooklyn.util.repeat.Repeater;
-import brooklyn.util.time.Duration;
-
-import com.google.common.collect.Iterables;
-
-/** REST-accessible extension of {@link BrooklynNodeTest} */
-public class BrooklynNodeRestTest {
-
-    private static final Logger log = LoggerFactory.getLogger(BrooklynNodeRestTest.class);
-    
-    // takes a while when run on its own, because initializing war and making some requests;
-    // but there are no waits (beyond 10ms), the delay is all classloading;
-    // and this tests a lot of things, REST API, Brooklyn Node, yaml deployment,
-    // so feels worth it to have as a unit test
-    // FIXME[BROOKLYN-43]: Test fails if security is configured in brooklyn.properties.
-    @Test(groups = "WIP")
-    public void testBrooklynNodeRestDeployAndMirror() {
-        final SimpleYamlLauncher l = new SimpleYamlLauncherForTests();
-        try {
-            TestApplication app = ApplicationBuilder.newManagedApp(TestApplication.class, l.getManagementContext());
-
-            BrooklynNode bn = app.createAndManageChild(EntitySpec.create(BrooklynNode.class, SameBrooklynNodeImpl.class));
-            bn.start(MutableSet.<Location>of());
-            
-            URI uri = bn.getAttribute(BrooklynNode.WEB_CONSOLE_URI);
-            Assert.assertNotNull(uri);
-            EntityTestUtils.assertAttributeEqualsEventually(bn, Attributes.SERVICE_UP, true);
-            log.info("Created BrooklynNode: "+bn);
-
-            // deploy
-            Task<?> t = bn.invoke(BrooklynNode.DEPLOY_BLUEPRINT, ConfigBag.newInstance()
-                .configure(BrooklynNode.DeployBlueprintEffector.BLUEPRINT_TYPE, TestApplication.class.getName())
-                .configure(BrooklynNode.DeployBlueprintEffector.BLUEPRINT_CONFIG, MutableMap.<String,Object>of("x", 1, "y", "Y"))
-                .getAllConfig());
-            log.info("Deployment result: "+t.getUnchecked());
-            
-            MutableSet<Application> apps = MutableSet.copyOf( l.getManagementContext().getApplications() );
-            Assert.assertEquals(apps.size(), 2);
-            apps.remove(app);
-            
-            Application newApp = Iterables.getOnlyElement(apps);
-            Entities.dumpInfo(newApp);
-            
-            Assert.assertEquals(newApp.getConfig(new BasicConfigKey<Integer>(Integer.class, "x")), (Integer)1);
-            
-            // check mirror
-            String newAppId = newApp.getId();
-            BrooklynEntityMirror mirror = app.createAndManageChild(EntitySpec.create(BrooklynEntityMirror.class)
-                .configure(BrooklynEntityMirror.MIRRORED_ENTITY_URL, 
-                    Urls.mergePaths(uri.toString(), "/v1/applications/"+newAppId+"/entities/"+newAppId))
-                .configure(BrooklynEntityMirror.MIRRORED_ENTITY_ID, newAppId)
-                .configure(BrooklynEntityMirror.POLL_PERIOD, Duration.millis(10)));
-            
-            Entities.dumpInfo(mirror);
-            
-            EntityTestUtils.assertAttributeEqualsEventually(mirror, Attributes.SERVICE_UP, true);
-            
-            ((EntityInternal)newApp).setAttribute(TestEntity.NAME, "foo");
-            EntityTestUtils.assertAttributeEqualsEventually(mirror, TestEntity.NAME, "foo");
-            log.info("Mirror successfully validated");
-            
-            // also try deploying by invoking deploy through json
-            // (catch issues when effector params are map)
-            HttpClient client = HttpTool.httpClientBuilder().build();
-            HttpToolResponse result = HttpTool.httpPost(client, URI.create(Urls.mergePaths(uri.toString(), "/v1/applications/"+app.getId()+"/entities/"+bn.getId()
-                    +"/effectors/deployBlueprint")), 
-                MutableMap.of(com.google.common.net.HttpHeaders.CONTENT_TYPE, "application/json"), 
-                Jsonya.newInstance()
-                    .put("blueprintType", TestApplication.class.getName())
-                    .put("blueprintConfig", MutableMap.of(TestEntity.CONF_NAME.getName(), "foo"))
-                .toString().getBytes());
-            log.info("Deploy effector invoked, result: "+result);
-            HttpTestUtils.assertHealthyStatusCode( result.getResponseCode() );
-            
-            Repeater.create().every(Duration.millis(10)).until(new Callable<Boolean>() {
-                @Override
-                public Boolean call() throws Exception {
-                    return l.getManagementContext().getApplications().size() == 3;
-                }
-            }).limitTimeTo(Duration.TEN_SECONDS).runRequiringTrue();
-            
-            apps = MutableSet.copyOf( l.getManagementContext().getApplications() );
-            apps.removeAll( MutableSet.of(app, newApp) );
-            Application newApp2 = Iterables.getOnlyElement(apps);
-            Entities.dumpInfo(newApp2);
-            
-            EntityTestUtils.assertAttributeEqualsEventually(newApp2, Attributes.SERVICE_UP, true);
-            Assert.assertEquals(newApp2.getConfig(TestEntity.CONF_NAME), "foo");
-            
-        } finally {
-            l.destroyAll();
-        }
-        log.info("DONE");
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/entity/database/mssql/MssqlBlueprintLiveTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/entity/database/mssql/MssqlBlueprintLiveTest.java b/usage/launcher/src/test/java/brooklyn/entity/database/mssql/MssqlBlueprintLiveTest.java
deleted file mode 100644
index f5ef36f..0000000
--- a/usage/launcher/src/test/java/brooklyn/entity/database/mssql/MssqlBlueprintLiveTest.java
+++ /dev/null
@@ -1,60 +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 brooklyn.entity.database.mssql;
-
-import java.io.StringReader;
-import java.util.Map;
-
-import org.testng.annotations.Test;
-
-import brooklyn.launcher.blueprints.AbstractBlueprintTest;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.text.TemplateProcessor;
-
-import com.google.common.collect.ImmutableMap;
-
-/**
- * Assumes that brooklyn.properties contains something like the following (but with real values!):
- * 
- * {@code
- * test.mssql.download.url = http://myserver.com/sql2012.iso
- * test.mssql.download.user = myname
- * test.mssql.download.password = mypassword
- * test.mssql.sa.password = mypassword
- * test.mssql.instance.name = MYNAME
- * }
- */
-public class MssqlBlueprintLiveTest extends AbstractBlueprintTest {
-
-    // TODO Needs further testing
-    
-    @Test(groups={"Live"})
-    public void testMssql() throws Exception {
-        Map<String, String> substitutions = ImmutableMap.of(
-                "mssql.download.url", mgmt.getConfig().getFirst("test.mssql.download.url"),
-                "mssql.download.user", mgmt.getConfig().getFirst("test.mssql.download.user"),
-                "mssql.download.password", mgmt.getConfig().getFirst("test.mssql.download.password"),
-                "mssql.sa.password", mgmt.getConfig().getFirst("test.mssql.sa.password"),
-                "mssql.instance.name", mgmt.getConfig().getFirst("test.mssql.instance.name"));
-
-        String rawYaml = new ResourceUtils(this).getResourceAsString("mssql-test.yaml");
-        String yaml = TemplateProcessor.processTemplateContents(rawYaml, substitutions);
-        runTest(new StringReader(yaml));
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java b/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java
deleted file mode 100644
index c20cae8..0000000
--- a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherHighAvailabilityTest.java
+++ /dev/null
@@ -1,257 +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 brooklyn.launcher;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.io.File;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.entity.Application;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.entity.rebind.RebindTestUtils;
-import brooklyn.entity.rebind.persister.PersistMode;
-import brooklyn.management.ManagementContext;
-import brooklyn.management.ha.HighAvailabilityMode;
-import brooklyn.management.ha.ManagementPlaneSyncRecordPersister;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.test.Asserts;
-import brooklyn.test.entity.LocalManagementContextForTests;
-import brooklyn.test.entity.TestApplication;
-import brooklyn.util.os.Os;
-import brooklyn.util.time.Duration;
-
-import com.google.common.base.Predicates;
-import com.google.common.collect.Iterables;
-import com.google.common.io.Files;
-
-public class BrooklynLauncherHighAvailabilityTest {
-
-    private static final Logger log = LoggerFactory.getLogger(BrooklynLauncherHighAvailabilityTest.class);
-    
-    private static final Duration TIMEOUT = Duration.THIRTY_SECONDS;
-    
-    private BrooklynLauncher primary;
-    private BrooklynLauncher secondary;
-    private BrooklynLauncher tertiary;
-    private File persistenceDir;
-
-    @BeforeMethod(alwaysRun=true)
-    public void setUp() throws Exception {
-        persistenceDir = Files.createTempDir();
-        Os.deleteOnExitRecursively(persistenceDir);
-    }
-
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        if (primary != null) primary.terminate();
-        primary = null;
-        if (secondary != null) secondary.terminate();
-        secondary = null;
-        if (tertiary != null) tertiary.terminate();
-        tertiary = null;
-        if (persistenceDir != null) RebindTestUtils.deleteMementoDir(persistenceDir);
-        persistenceDir = null;
-    }
-    
-    @Test
-    public void testStandbyTakesOverWhenPrimaryTerminatedGracefully() throws Exception {
-        doTestStandbyTakesOver(true);
-    }
-
-    @Test(invocationCount=10, groups="Integration")
-    /** test issues with termination and promotion; 
-     * previously we got FileNotFound errors, though these should be fixed with
-     * the various PersistenceObjectStore prepare methods */
-    public void testStandbyTakesOverWhenPrimaryTerminatedGracefullyManyTimes() throws Exception {
-        testStandbyTakesOverWhenPrimaryTerminatedGracefully();
-    }
-
-    @Test(groups="Integration") // because slow waiting for timeouts to promote standbys
-    public void testStandbyTakesOverWhenPrimaryFails() throws Exception {
-        doTestStandbyTakesOver(false);
-    }
-    
-    protected void doTestStandbyTakesOver(boolean stopGracefully) throws Exception {
-        log.info("STARTING standby takeover test");
-        primary = BrooklynLauncher.newInstance();
-        primary.webconsole(false)
-                .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
-                .highAvailabilityMode(HighAvailabilityMode.AUTO)
-                .persistMode(PersistMode.AUTO)
-                .persistenceDir(persistenceDir)
-                .persistPeriod(Duration.millis(10))
-                .haHeartbeatPeriod(Duration.millis(10))
-                .haHeartbeatTimeout(Duration.millis(1000))
-                .application(EntitySpec.create(TestApplication.class))
-                .start();
-        ManagementContext primaryManagementContext = primary.getServerDetails().getManagementContext();
-        log.info("started mgmt primary "+primaryManagementContext);
-        
-        assertOnlyApp(primary.getServerDetails().getManagementContext(), TestApplication.class);
-        primaryManagementContext.getRebindManager().getPersister().waitForWritesCompleted(TIMEOUT);
-        
-        // Secondary will come up as standby
-        secondary = BrooklynLauncher.newInstance();
-        secondary.webconsole(false)
-                .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
-                .highAvailabilityMode(HighAvailabilityMode.AUTO)
-                .persistMode(PersistMode.AUTO)
-                .persistenceDir(persistenceDir)
-                .persistPeriod(Duration.millis(10))
-                .haHeartbeatPeriod(Duration.millis(10))
-                .haHeartbeatTimeout(Duration.millis(1000))
-                .start();
-        ManagementContext secondaryManagementContext = secondary.getServerDetails().getManagementContext();
-        log.info("started mgmt secondary "+secondaryManagementContext);
-        
-        // TODO can assert it sees the apps read only
-//        assertNoApps(secondary.getServerDetails().getManagementContext());
-
-        // Terminate primary; expect secondary to take over
-        if (stopGracefully) {
-            ((ManagementContextInternal)primaryManagementContext).terminate();
-        } else {
-            ManagementPlaneSyncRecordPersister planePersister = ((ManagementContextInternal)primaryManagementContext).getHighAvailabilityManager().getPersister();
-            planePersister.stop(); // can no longer write heartbeats
-            ((ManagementContextInternal)primaryManagementContext).terminate();
-        }
-        
-        assertOnlyAppEventually(secondaryManagementContext, TestApplication.class);
-        
-        // Start tertiary (force up as standby)
-        tertiary = BrooklynLauncher.newInstance();
-        tertiary.webconsole(false)
-                .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
-                .highAvailabilityMode(HighAvailabilityMode.STANDBY)
-                .persistMode(PersistMode.AUTO)
-                .persistenceDir(persistenceDir)
-                .persistPeriod(Duration.millis(10))
-                .haHeartbeatPeriod(Duration.millis(10))
-                .haHeartbeatTimeout(Duration.millis(1000))
-                .start();
-        ManagementContext tertiaryManagementContext = tertiary.getServerDetails().getManagementContext();
-        log.info("started mgmt tertiary "+primaryManagementContext);
-        
-        assertNoApps(tertiary.getServerDetails().getManagementContext());
-
-        // Terminate secondary; expect tertiary to take over
-        if (stopGracefully) {
-            ((ManagementContextInternal)secondaryManagementContext).terminate();
-        } else {
-            ManagementPlaneSyncRecordPersister planePersister = ((ManagementContextInternal)secondaryManagementContext).getHighAvailabilityManager().getPersister();
-            planePersister.stop(); // can no longer write heartbeats
-            ((ManagementContextInternal)secondaryManagementContext).terminate();
-        }
-        
-        assertOnlyAppEventually(tertiaryManagementContext, TestApplication.class);
-    }
-    
-    public void testHighAvailabilityMasterModeFailsIfAlreadyHasMaster() throws Exception {
-        primary = BrooklynLauncher.newInstance();
-        primary.webconsole(false)
-                .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
-                .highAvailabilityMode(HighAvailabilityMode.AUTO)
-                .persistMode(PersistMode.AUTO)
-                .persistenceDir(persistenceDir)
-                .persistPeriod(Duration.millis(10))
-                .application(EntitySpec.create(TestApplication.class))
-                .start();
-
-        try {
-            // Secondary will come up as standby
-            secondary = BrooklynLauncher.newInstance();
-            secondary.webconsole(false)
-                    .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
-                    .highAvailabilityMode(HighAvailabilityMode.MASTER)
-                    .persistMode(PersistMode.AUTO)
-                    .persistenceDir(persistenceDir)
-                    .persistPeriod(Duration.millis(10))
-                    .start();
-            fail();
-        } catch (IllegalStateException e) {
-            // success
-        }
-    }
-    
-    @Test
-    public void testHighAvailabilityStandbyModeFailsIfNoExistingMaster() throws Exception {
-        try {
-            primary = BrooklynLauncher.newInstance();
-            primary.webconsole(false)
-                    .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
-                    .highAvailabilityMode(HighAvailabilityMode.STANDBY)
-                    .persistMode(PersistMode.AUTO)
-                    .persistenceDir(persistenceDir)
-                    .persistPeriod(Duration.millis(10))
-                    .ignorePersistenceErrors(false)
-                    .application(EntitySpec.create(TestApplication.class))
-                    .start();
-            fail();
-        } catch (IllegalStateException e) {
-            // success
-        }
-    }
-    
-    @Test
-    public void testHighAvailabilityHotStandbyModeFailsIfNoExistingMaster() throws Exception {
-        try {
-            primary = BrooklynLauncher.newInstance();
-            primary.webconsole(false)
-                    .brooklynProperties(LocalManagementContextForTests.setEmptyCatalogAsDefault(BrooklynProperties.Factory.newEmpty()))
-                    .highAvailabilityMode(HighAvailabilityMode.HOT_STANDBY)
-                    .persistMode(PersistMode.AUTO)
-                    .persistenceDir(persistenceDir)
-                    .persistPeriod(Duration.millis(10))
-                    .ignorePersistenceErrors(false)
-                    .application(EntitySpec.create(TestApplication.class))
-                    .start();
-            fail();
-        } catch (IllegalStateException e) {
-            // success
-        }
-    }
-    
-    private void assertOnlyApp(ManagementContext managementContext, Class<? extends Application> expectedType) {
-        assertEquals(managementContext.getApplications().size(), 1, "apps="+managementContext.getApplications());
-        assertNotNull(Iterables.find(managementContext.getApplications(), Predicates.instanceOf(TestApplication.class), null), "apps="+managementContext.getApplications());
-    }
-    
-    private void assertNoApps(ManagementContext managementContext) {
-        if (!managementContext.getApplications().isEmpty())
-            log.warn("FAILED assertion (rethrowing), apps="+managementContext.getApplications());
-        assertTrue(managementContext.getApplications().isEmpty(), "apps="+managementContext.getApplications());
-    }
-    
-    private void assertOnlyAppEventually(final ManagementContext managementContext, final Class<? extends Application> expectedType) {
-        Asserts.succeedsEventually(new Runnable() {
-            @Override public void run() {
-                assertOnlyApp(managementContext, expectedType);
-            }});
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java b/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
deleted file mode 100644
index 7d84d6b..0000000
--- a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindCatalogTest.java
+++ /dev/null
@@ -1,116 +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 brooklyn.launcher;
-
-import java.io.File;
-import java.util.List;
-
-import javax.annotation.Nullable;
-
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.io.Files;
-
-import org.apache.brooklyn.catalog.BrooklynCatalog;
-import org.apache.brooklyn.catalog.CatalogItem;
-import brooklyn.catalog.internal.CatalogInitialization;
-import brooklyn.entity.rebind.persister.PersistMode;
-import brooklyn.test.entity.LocalManagementContextForTests;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.os.Os;
-
-public class BrooklynLauncherRebindCatalogTest {
-
-    private static final String TEST_VERSION = "test-version";
-    private static final String CATALOG_INITIAL = "classpath://rebind-test-catalog.bom";
-    private static final String CATALOG_ADDITIONS = "rebind-test-catalog-additions.bom";
-    private static final Iterable<String> EXPECTED_DEFAULT_IDS = ImmutableSet.of("one:" + TEST_VERSION, "two:" + TEST_VERSION);
-    private static final Iterable<String> EXPECTED_ADDED_IDS = ImmutableSet.of("three:" + TEST_VERSION, "four:" + TEST_VERSION);
-
-    private List<BrooklynLauncher> launchers = Lists.newCopyOnWriteArrayList();
-    
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        for (BrooklynLauncher launcher : launchers) {
-            launcher.terminate();
-        }
-        launchers.clear();
-    }
-    
-    private BrooklynLauncher newLauncherForTests(String persistenceDir) {
-        CatalogInitialization catalogInitialization = new CatalogInitialization(CATALOG_INITIAL, false, null, false);
-        BrooklynLauncher launcher = BrooklynLauncher.newInstance()
-                .brooklynProperties(LocalManagementContextForTests.builder(true).buildProperties())
-                .catalogInitialization(catalogInitialization)
-                .persistMode(PersistMode.AUTO)
-                .persistenceDir(persistenceDir)
-                .webconsole(false);
-        launchers.add(launcher);
-        return launcher;
-    }
-
-    @Test
-    public void testRebindDoesNotEffectCatalog() {
-        String persistenceDir = newTempPersistenceContainerName();
-
-        BrooklynLauncher launcher = newLauncherForTests(persistenceDir);
-        launcher.start();
-        BrooklynCatalog catalog = launcher.getServerDetails().getManagementContext().getCatalog();
-
-        assertCatalogConsistsOfIds(catalog.getCatalogItems(), EXPECTED_DEFAULT_IDS);
-
-        catalog.deleteCatalogItem("one", TEST_VERSION);
-        catalog.deleteCatalogItem("two", TEST_VERSION);
-
-        Assert.assertEquals(Iterables.size(catalog.getCatalogItems()), 0);
-
-        catalog.addItems(new ResourceUtils(this).getResourceAsString(CATALOG_ADDITIONS));
-
-        assertCatalogConsistsOfIds(catalog.getCatalogItems(), EXPECTED_ADDED_IDS);
-
-        launcher.terminate();
-
-        BrooklynLauncher newLauncher = newLauncherForTests(persistenceDir);
-        newLauncher.start();
-        assertCatalogConsistsOfIds(newLauncher.getServerDetails().getManagementContext().getCatalog().getCatalogItems(), EXPECTED_ADDED_IDS);
-    }
-
-    private void assertCatalogConsistsOfIds(Iterable<CatalogItem<Object, Object>> catalogItems, Iterable<String> ids) {
-        Iterable<String> idsFromItems = Iterables.transform(catalogItems, new Function<CatalogItem<?,?>, String>() {
-            @Nullable
-            @Override
-            public String apply(CatalogItem<?, ?> catalogItem) {
-                return catalogItem.getCatalogItemId();
-            }
-        });
-        Assert.assertTrue(Iterables.elementsEqual(ids, idsFromItems), String.format("Expected %s, found %s", ids, idsFromItems));
-    }
-
-    protected String newTempPersistenceContainerName() {
-        File persistenceDirF = Files.createTempDir();
-        Os.deleteOnExitRecursively(persistenceDirF);
-        return persistenceDirF.getAbsolutePath();
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java b/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java
deleted file mode 100644
index 426f939..0000000
--- a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestFixture.java
+++ /dev/null
@@ -1,256 +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 brooklyn.launcher;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import java.util.List;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.BrooklynServerConfig;
-import brooklyn.entity.Application;
-import brooklyn.entity.basic.EntityPredicates;
-import brooklyn.entity.basic.StartableApplication;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
-import brooklyn.entity.rebind.persister.PersistMode;
-import brooklyn.entity.rebind.persister.PersistenceObjectStore;
-import brooklyn.location.Location;
-import brooklyn.management.ManagementContext;
-import brooklyn.management.ha.HighAvailabilityMode;
-import brooklyn.test.Asserts;
-import brooklyn.test.entity.LocalManagementContextForTests;
-import brooklyn.test.entity.TestApplication;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.exceptions.FatalConfigurationRuntimeException;
-import brooklyn.util.time.Duration;
-
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-
-public abstract class BrooklynLauncherRebindTestFixture {
-
-    @SuppressWarnings("unused")
-    private static final Logger log = LoggerFactory.getLogger(BrooklynLauncherRebindTestFixture.class);
-    
-    protected String persistenceDir;
-    protected String persistenceLocationSpec;
-    protected List<BrooklynLauncher> launchers = MutableList.of();
-    
-    @BeforeMethod(alwaysRun=true)
-    public void setUp() throws Exception {
-        persistenceDir = newTempPersistenceContainerName();
-    }
-    
-    protected abstract String newTempPersistenceContainerName();
-
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        for (BrooklynLauncher l: launchers) {
-            if (l.isStarted()) {
-                l.terminate();
-                PersistenceObjectStore store = getPersistenceStore(l.getServerDetails().getManagementContext());
-                if (store!=null) store.deleteCompletely();
-            }
-        }
-    }
-
-    protected BrooklynLauncher newLauncherBase() {
-        BrooklynLauncher l = BrooklynLauncher.newInstance()
-            .webconsole(false);
-        launchers.add(l);
-        return l;
-    }
-    protected BrooklynLauncher newLauncherDefault(PersistMode mode) {
-        return newLauncherBase()
-                .managementContext(newManagementContextForTests(null))
-                .persistMode(mode)
-                .persistenceDir(persistenceDir)
-                .persistPeriod(Duration.millis(10));
-    }
-    protected LocalManagementContextForTests newManagementContextForTests(BrooklynProperties props) {
-        if (props==null)
-            return new LocalManagementContextForTests();
-        else
-            return new LocalManagementContextForTests(props);
-    }
-
-    protected ManagementContext lastMgmt() {
-        return Iterables.getLast(launchers).getServerDetails().getManagementContext();
-    }
-    
-    @Test
-    public void testRebindsToExistingApp() throws Exception {
-        populatePersistenceDir(persistenceDir, EntitySpec.create(TestApplication.class).displayName("myorig"));
-        
-        // Rebind to the app we just started last time
-        
-        newLauncherDefault(PersistMode.REBIND).start();
-        
-        assertOnlyApp(lastMgmt(), TestApplication.class);
-        assertNotNull(Iterables.find(lastMgmt().getApplications(), EntityPredicates.displayNameEqualTo("myorig"), null), "apps="+lastMgmt().getApplications());
-    }
-
-    @Test
-    public void testRebindCanAddNewApps() throws Exception {
-        populatePersistenceDir(persistenceDir, EntitySpec.create(TestApplication.class).displayName("myorig"));
-        
-        // Rebind to the app we started last time
-        newLauncherDefault(PersistMode.REBIND)
-                .application(EntitySpec.create(TestApplication.class).displayName("mynew"))
-                .start();
-        
-        // New app was added, and orig app was rebound
-        assertEquals(lastMgmt().getApplications().size(), 2, "apps="+lastMgmt().getApplications());
-        assertNotNull(Iterables.find(lastMgmt().getApplications(), EntityPredicates.displayNameEqualTo("mynew"), null), "apps="+lastMgmt().getApplications());
-
-        // And subsequently can create new apps
-        StartableApplication app3 = lastMgmt().getEntityManager().createEntity(
-                EntitySpec.create(TestApplication.class).displayName("mynew2"));
-        app3.start(ImmutableList.<Location>of());
-    }
-
-    @Test
-    public void testAutoRebindsToExistingApp() throws Exception {
-        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
-        populatePersistenceDir(persistenceDir, appSpec);
-        
-        // Auto will rebind if the dir exists
-        newLauncherDefault(PersistMode.AUTO).start();
-        
-        assertOnlyApp(lastMgmt(), TestApplication.class);
-    }
-
-    @Test
-    public void testCleanDoesNotRebindToExistingApp() throws Exception {
-        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
-        populatePersistenceDir(persistenceDir, appSpec);
-        
-        // Auto will rebind if the dir exists
-        newLauncherDefault(PersistMode.CLEAN).start();
-        
-        assertTrue(lastMgmt().getApplications().isEmpty(), "apps="+lastMgmt().getApplications());
-    }
-
-    @Test
-    public void testAutoRebindCreatesNewIfEmptyDir() throws Exception {
-        // Auto will rebind if the dir exists
-        newLauncherDefault(PersistMode.AUTO)
-                .application(EntitySpec.create(TestApplication.class))
-                .start();
-        
-        assertOnlyApp(lastMgmt(), TestApplication.class);
-        assertMementoContainerNonEmptyForTypeEventually("entities");
-    }
-
-    @Test
-    public void testRebindRespectsPersistenceDirSetInProperties() throws Exception {
-        String persistenceDir2 = newTempPersistenceContainerName();
-        
-        BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newDefault();
-        brooklynProperties.put(BrooklynServerConfig.PERSISTENCE_DIR, persistenceDir2);
-        LocalManagementContextForTests mgmt = newManagementContextForTests(brooklynProperties);
-        
-        // Rebind to the app we started last time
-        newLauncherBase()
-                .persistMode(PersistMode.AUTO)
-                .persistPeriod(Duration.millis(10))
-                .managementContext(mgmt)
-                .start();
-        
-        checkPersistenceContainerNameIs(persistenceDir2);
-    }
-
-    // assumes default persistence dir is rebindable
-    @Test(groups="Integration")
-    public void testRebindRespectsDefaultPersistenceDir() throws Exception {
-        newLauncherDefault(PersistMode.AUTO)
-                .persistenceDir((String)null)
-                .start();
-        
-        checkPersistenceContainerNameIsDefault();
-    }
-    
-    protected abstract void checkPersistenceContainerNameIsDefault();
-    protected abstract void checkPersistenceContainerNameIs(String expected);
-
-    @Test
-    public void testPersistenceFailsIfNoDir() throws Exception {
-        runRebindFails(PersistMode.REBIND, badContainerName(), "does not exist");
-    }
-
-    protected abstract String badContainerName();
-
-    @Test
-    public void testExplicitRebindFailsIfEmpty() throws Exception {
-        runRebindFails(PersistMode.REBIND, persistenceDir, "directory is empty");
-    }
-
-    protected void runRebindFails(PersistMode persistMode, String dir, String errmsg) throws Exception {
-        try {
-            newLauncherDefault(persistMode)
-                    .persistenceDir(dir)
-                    .start();
-        } catch (FatalConfigurationRuntimeException e) {
-            if (!e.toString().contains(errmsg)) {
-                throw e;
-            }
-        }
-    }
-
-    protected void populatePersistenceDir(String dir, EntitySpec<? extends StartableApplication> appSpec) throws Exception {
-        BrooklynLauncher launcher = newLauncherDefault(PersistMode.CLEAN)
-                .highAvailabilityMode(HighAvailabilityMode.MASTER)
-                .persistenceDir(dir)
-                .application(appSpec)
-                .start();
-        launcher.terminate();
-        assertMementoContainerNonEmptyForTypeEventually("entities");
-    }
-    
-    protected void assertOnlyApp(ManagementContext managementContext, Class<? extends Application> expectedType) {
-        assertEquals(managementContext.getApplications().size(), 1, "apps="+managementContext.getApplications());
-        assertNotNull(Iterables.find(managementContext.getApplications(), Predicates.instanceOf(TestApplication.class), null), "apps="+managementContext.getApplications());
-    }
-    
-    protected void assertMementoContainerNonEmptyForTypeEventually(final String type) {
-        Asserts.succeedsEventually(ImmutableMap.of("timeout", Duration.TEN_SECONDS), new Runnable() {
-            @Override public void run() {
-                getPersistenceStore(lastMgmt()).listContentsWithSubPath(type);
-            }});
-    }
-
-    static PersistenceObjectStore getPersistenceStore(ManagementContext managementContext) {
-        if (managementContext==null) return null;
-        BrooklynMementoPersisterToObjectStore persister = (BrooklynMementoPersisterToObjectStore)managementContext.getRebindManager().getPersister();
-        if (persister==null) return null;
-        return persister.getObjectStore();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java b/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java
deleted file mode 100644
index 57b8682..0000000
--- a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindTestToFiles.java
+++ /dev/null
@@ -1,153 +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 brooklyn.launcher;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotEquals;
-import static org.testng.Assert.assertTrue;
-
-import java.io.File;
-
-import org.testng.annotations.Test;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.BrooklynServerPaths;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
-import brooklyn.entity.rebind.persister.FileBasedObjectStore;
-import brooklyn.entity.rebind.persister.PersistMode;
-import brooklyn.management.ManagementContext;
-import brooklyn.management.ha.HighAvailabilityMode;
-import brooklyn.test.entity.TestApplication;
-import brooklyn.util.javalang.JavaClassNames;
-import brooklyn.util.os.Os;
-import brooklyn.util.text.Identifiers;
-
-import com.google.common.base.Joiner;
-import com.google.common.io.Files;
-
-public class BrooklynLauncherRebindTestToFiles extends BrooklynLauncherRebindTestFixture {
-
-    protected String newTempPersistenceContainerName() {
-        File persistenceDirF = Files.createTempDir();
-        Os.deleteOnExitRecursively(persistenceDirF);
-        return persistenceDirF.getAbsolutePath();
-    }
-    
-    protected String badContainerName() {
-        return "/path/does/not/exist/"+Identifiers.makeRandomId(4);
-    }
-    
-    protected void checkPersistenceContainerNameIs(String expected) {
-        String expectedFqp = new File(Os.tidyPath(expected)).getAbsolutePath();
-        assertEquals(getPersistenceDir(lastMgmt()).getAbsolutePath(), expectedFqp);
-    }
-
-    static File getPersistenceDir(ManagementContext managementContext) {
-        BrooklynMementoPersisterToObjectStore persister = (BrooklynMementoPersisterToObjectStore)managementContext.getRebindManager().getPersister();
-        FileBasedObjectStore store = (FileBasedObjectStore)persister.getObjectStore();
-        return store.getBaseDir();
-    }
-
-    protected void checkPersistenceContainerNameIsDefault() {
-        String expected = BrooklynServerPaths.newMainPersistencePathResolver(BrooklynProperties.Factory.newEmpty()).location(null).dir(null).resolve();
-        checkPersistenceContainerNameIs(expected);
-    }
-
-    @Test
-    public void testPersistenceFailsIfIsFile() throws Exception {
-        File tempF = File.createTempFile("test-"+JavaClassNames.niceClassAndMethod(), ".not_dir");
-        tempF.deleteOnExit();
-        String tempFileName = tempF.getAbsolutePath();
-        
-        try {
-            runRebindFails(PersistMode.AUTO, tempFileName, "must not be a file");
-            runRebindFails(PersistMode.REBIND, tempFileName, "must not be a file");
-            runRebindFails(PersistMode.CLEAN, tempFileName, "must not be a file");
-        } finally {
-            new File(tempFileName).delete();
-        }
-    }
-    
-    @Test
-    public void testPersistenceFailsIfNotWritable() throws Exception {
-        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
-        populatePersistenceDir(persistenceDir, appSpec);
-        new File(persistenceDir).setWritable(false);
-        try {
-            runRebindFails(PersistMode.AUTO, persistenceDir, "not writable");
-            runRebindFails(PersistMode.REBIND, persistenceDir, "not writable");
-            runRebindFails(PersistMode.CLEAN, persistenceDir, "not writable");
-        } finally {
-            new File(persistenceDir).setWritable(true);
-        }
-    }
-
-    @Test
-    public void testPersistenceFailsIfNotReadable() throws Exception {
-        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
-        populatePersistenceDir(persistenceDir, appSpec);
-        new File(persistenceDir).setReadable(false);
-        try {
-            runRebindFails(PersistMode.AUTO, persistenceDir, "not readable");
-            runRebindFails(PersistMode.REBIND, persistenceDir, "not readable");
-            runRebindFails(PersistMode.CLEAN, persistenceDir, "not readable");
-        } finally {
-            new File(persistenceDir).setReadable(true);
-        }
-    }
-
-    @Test(groups="Integration")
-    public void testCopyPersistedState() throws Exception {
-        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
-        populatePersistenceDir(persistenceDir, appSpec);
-
-        File destinationDir = Files.createTempDir();
-        String destination = destinationDir.getAbsolutePath();
-        String destinationLocation = null; // i.e. file system, rather than object store
-        try {
-            // Auto will rebind if the dir exists
-            BrooklynLauncher launcher = newLauncherDefault(PersistMode.AUTO)
-                    .highAvailabilityMode(HighAvailabilityMode.MASTER)
-                    .webconsole(false);
-            launcher.copyPersistedState(destination, destinationLocation);
-            launcher.terminate();
-            
-            File entities = new File(Os.mergePaths(destination), "entities");
-            assertTrue(entities.isDirectory(), "entities directory should exist");
-            assertEquals(entities.listFiles().length, 1, "entities directory should contain one file (contained: "+
-                    Joiner.on(", ").join(entities.listFiles()) +")");
-
-            File nodes = new File(Os.mergePaths(destination, "nodes"));
-            assertTrue(nodes.isDirectory(), "nodes directory should exist");
-            assertNotEquals(nodes.listFiles().length, 0, "nodes directory should not be empty");
-
-            // Should now have a usable copy in the destinationDir
-            // Auto will rebind if the dir exists
-            newLauncherDefault(PersistMode.AUTO)
-                    .webconsole(false)
-                    .persistenceDir(destinationDir)
-                    .start();
-            assertOnlyApp(lastMgmt(), TestApplication.class);
-            
-        } finally {
-            Os.deleteRecursively(destinationDir);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java b/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java
deleted file mode 100644
index 258ba5b..0000000
--- a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherRebindToCloudObjectStoreTest.java
+++ /dev/null
@@ -1,174 +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 brooklyn.launcher;
-
-import static org.testng.Assert.assertEquals;
-
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.BrooklynServerPaths;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore;
-import brooklyn.entity.rebind.persister.PersistMode;
-import brooklyn.entity.rebind.persister.jclouds.BlobStoreTest;
-import brooklyn.entity.rebind.persister.jclouds.JcloudsBlobStoreBasedObjectStore;
-import brooklyn.management.ManagementContext;
-import brooklyn.mementos.BrooklynMementoRawData;
-import brooklyn.test.entity.LocalManagementContextForTests;
-import brooklyn.test.entity.TestApplication;
-import brooklyn.util.javalang.JavaClassNames;
-import brooklyn.util.os.Os;
-import brooklyn.util.text.Identifiers;
-
-@Test(groups="Live")
-public class BrooklynLauncherRebindToCloudObjectStoreTest extends BrooklynLauncherRebindTestFixture {
-
-    // FIXME BrooklynLauncherRebindToCloudObjectStoreTest.testCleanDoesNotRebindToExistingApp failed:
-    //     apps=[Application[mDNfOA7w]] expected [true] but found [false]
-    // Should it really delete everything in the bucket?! Only if we can back up first!
-
-    // FIXME brooklyn.util.exceptions.FatalRuntimeException: Error rebinding to persisted state: Writes not allowed in brooklyn.entity.rebind.persister.BrooklynMementoPersisterToObjectStore@7d2f7563
-    //     at brooklyn.launcher.BrooklynLauncher.persistState(BrooklynLauncher.java:502)
-    //     at brooklyn.launcher.BrooklynLauncherRebindToCloudObjectStoreTest.testCopyPersistedState(BrooklynLauncherRebindToCloudObjectStoreTest.java:144)
-    // Presumably a previous run wasn't tearing down properly, so it joined as a standby rather than being master?! 
-    
-    { persistenceLocationSpec = BlobStoreTest.PERSIST_TO_OBJECT_STORE_FOR_TEST_SPEC; }
-
-    @BeforeMethod(alwaysRun=true)
-    public void setUp() throws Exception {
-        persistenceDir = newTempPersistenceContainerName();
-    }
-
-    @Override
-    protected BrooklynLauncher newLauncherBase() {
-        return super.newLauncherBase().persistenceLocation(persistenceLocationSpec);
-    }
-    
-    protected LocalManagementContextForTests newManagementContextForTests(BrooklynProperties props) {
-        BrooklynProperties p2 = BrooklynProperties.Factory.newDefault();
-        if (props!=null) p2.putAll(props);
-        return new LocalManagementContextForTests(p2);
-    }
-
-    @Override
-    protected String newTempPersistenceContainerName() {
-        return "test-"+JavaClassNames.callerStackElement(0).getClassName()+"-"+Identifiers.makeRandomId(4);
-    }
-    
-    protected String badContainerName() {
-        return "container-does-not-exist-"+Identifiers.makeRandomId(4);
-    }
-    
-    protected void checkPersistenceContainerNameIs(String expected) {
-        assertEquals(getPersistenceContainerName(lastMgmt()), expected);
-    }
-
-    static String getPersistenceContainerName(ManagementContext managementContext) {
-        BrooklynMementoPersisterToObjectStore persister = (BrooklynMementoPersisterToObjectStore)managementContext.getRebindManager().getPersister();
-        JcloudsBlobStoreBasedObjectStore store = (JcloudsBlobStoreBasedObjectStore)persister.getObjectStore();
-        return store.getContainerName();
-    }
-
-    protected void checkPersistenceContainerNameIsDefault() {
-        checkPersistenceContainerNameIs(BrooklynServerPaths.DEFAULT_PERSISTENCE_CONTAINER_NAME);
-    }
-
-    @Override @Test(groups="Live")
-    public void testRebindsToExistingApp() throws Exception {
-        super.testRebindsToExistingApp();
-    }
-
-    @Override @Test(groups="Live")
-    public void testRebindCanAddNewApps() throws Exception {
-        super.testRebindCanAddNewApps();
-    }
-
-    @Override @Test(groups="Live")
-    public void testAutoRebindsToExistingApp() throws Exception {
-        super.testAutoRebindsToExistingApp();
-    }
-
-    // TODO Marked as work-in-progress because "clean" does not backup and then clean out the existing
-    // object store's bucket. Unclear what best behaviour there should be: should we really delete
-    // the data?! We better be confident about our backup!
-    @Override @Test(groups={"Live", "WIP"})
-    public void testCleanDoesNotRebindToExistingApp() throws Exception {
-        super.testCleanDoesNotRebindToExistingApp();
-    }
-
-    @Override @Test(groups="Live")
-    public void testAutoRebindCreatesNewIfEmptyDir() throws Exception {
-        super.testAutoRebindCreatesNewIfEmptyDir();
-    }
-
-    @Override @Test(groups="Live")
-    public void testRebindRespectsPersistenceDirSetInProperties() throws Exception {
-        super.testRebindRespectsPersistenceDirSetInProperties();
-    }
-
-    @Override @Test(groups="Live")
-    public void testRebindRespectsDefaultPersistenceDir() throws Exception {
-        super.testRebindRespectsDefaultPersistenceDir();
-    }
-
-    @Override @Test(groups="Live")
-    public void testPersistenceFailsIfNoDir() throws Exception {
-        super.testPersistenceFailsIfNoDir();
-    }
-
-    @Override @Test(groups="Live")
-    public void testExplicitRebindFailsIfEmpty() throws Exception {
-        super.testExplicitRebindFailsIfEmpty();
-    }
-
-    // TODO Remove duplication from BrooklynLauncherRebindTestToFiles.testCopyPersistedState()
-    @Test(groups="Live")
-    public void testCopyPersistedState() throws Exception {
-        EntitySpec<TestApplication> appSpec = EntitySpec.create(TestApplication.class);
-        populatePersistenceDir(persistenceDir, appSpec);
-        
-        String destinationDir = newTempPersistenceContainerName();
-        String destinationLocation = persistenceLocationSpec;
-        try {
-            // Auto will rebind if the dir exists
-            BrooklynLauncher launcher = newLauncherDefault(PersistMode.AUTO)
-                    .webconsole(false)
-                    .persistenceLocation(persistenceLocationSpec);
-            BrooklynMementoRawData memento = launcher.retrieveState();
-            launcher.persistState(memento, destinationDir, destinationLocation);
-            launcher.terminate();
-            
-            assertEquals(memento.getEntities().size(), 1, "entityMementos="+memento.getEntities().keySet());
-            
-            // Should now have a usable copy in the destionationDir
-            // Auto will rebind if the dir exists
-            newLauncherDefault(PersistMode.AUTO)
-                    .webconsole(false)
-                    .persistenceDir(destinationDir)
-                    .persistenceLocation(destinationLocation)
-                    .start();
-            assertOnlyApp(lastMgmt(), TestApplication.class);
-            
-        } finally {
-            Os.deleteRecursively(destinationDir);
-        }
-    }
-}


[3/8] incubator-brooklyn git commit: brooklyn-launcher: add org.apache package prefix

Posted by ha...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherTest.java b/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherTest.java
deleted file mode 100644
index 0886390..0000000
--- a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynLauncherTest.java
+++ /dev/null
@@ -1,367 +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 brooklyn.launcher;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertSame;
-import static org.testng.Assert.assertTrue;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.net.URI;
-import java.nio.charset.Charset;
-import java.util.Properties;
-
-import org.testng.Assert;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.catalog.internal.CatalogInitialization;
-import brooklyn.config.BrooklynProperties;
-import brooklyn.config.BrooklynServerConfig;
-import brooklyn.entity.Application;
-import brooklyn.entity.basic.ApplicationBuilder;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.entity.rebind.RebindTestUtils;
-import brooklyn.location.Location;
-import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
-import brooklyn.management.ManagementContext;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.test.HttpTestUtils;
-import brooklyn.test.entity.LocalManagementContextForTests;
-import brooklyn.test.entity.TestApplication;
-import brooklyn.test.entity.TestApplicationImpl;
-import brooklyn.test.entity.TestEntity;
-import brooklyn.util.exceptions.FatalRuntimeException;
-import brooklyn.util.io.FileUtil;
-import brooklyn.util.net.Urls;
-import brooklyn.util.os.Os;
-import brooklyn.util.text.StringFunctions;
-import brooklyn.util.text.Strings;
-
-import com.google.api.client.util.Preconditions;
-import com.google.common.base.Charsets;
-import com.google.common.base.Function;
-import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.common.io.Files;
-
-public class BrooklynLauncherTest {
-    
-    private BrooklynLauncher launcher;
-    private File persistenceDir;
-    
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        if (launcher != null) launcher.terminate();
-        if (persistenceDir != null) RebindTestUtils.deleteMementoDir(persistenceDir);
-        launcher = null;
-    }
-    
-    // Integration because takes a few seconds to start web-console
-    @Test(groups="Integration")
-    public void testStartsWebServerOnExpectectedPort() throws Exception {
-        launcher = newLauncherForTests(true)
-                .webconsolePort("10000+")
-                .start();
-        
-        String webServerUrlStr = launcher.getServerDetails().getWebServerUrl();
-        URI webServerUri = new URI(webServerUrlStr);
-        
-        assertEquals(launcher.getApplications(), ImmutableList.of());
-        assertTrue(webServerUri.getPort() >= 10000 && webServerUri.getPort() < 10100, "port="+webServerUri.getPort()+"; uri="+webServerUri);
-        HttpTestUtils.assertUrlReachable(webServerUrlStr);
-    }
-    
-    // Integration because takes a few seconds to start web-console
-    @Test(groups="Integration")
-    public void testWebServerTempDirRespectsDataDirConfig() throws Exception {
-        String dataDirName = ".brooklyn-foo"+Strings.makeRandomId(4);
-        String dataDir = "~/"+dataDirName;
-
-        launcher = newLauncherForTests(true)
-                .brooklynProperties(BrooklynServerConfig.MGMT_BASE_DIR, dataDir)
-                .start();
-        
-        ManagementContext managementContext = launcher.getServerDetails().getManagementContext();
-        String expectedTempDir = Os.mergePaths(Os.home(), dataDirName, "planes", managementContext.getManagementPlaneId(), managementContext.getManagementNodeId(), "jetty");
-        
-        File webappTempDir = launcher.getServerDetails().getWebServer().getWebappTempDir();
-        assertEquals(webappTempDir.getAbsolutePath(), expectedTempDir);
-    }
-    
-    @Test
-    public void testCanDisableWebServerStartup() throws Exception {
-        launcher = newLauncherForTests(true)
-                .webconsole(false)
-                .start();
-        
-        assertNull(launcher.getServerDetails().getWebServer());
-        assertNull(launcher.getServerDetails().getWebServerUrl());
-        Assert.assertTrue( ((ManagementContextInternal)launcher.getServerDetails().getManagementContext()).errors().isEmpty() );
-    }
-    
-    @Test
-    public void testStartsAppInstance() throws Exception {
-        launcher = newLauncherForTests(true)
-                .webconsole(false)
-                .application(new TestApplicationImpl())
-                .start();
-        
-        assertOnlyApp(launcher, TestApplication.class);
-    }
-    
-    @Test
-    public void testStartsAppFromSpec() throws Exception {
-        launcher = newLauncherForTests(true)
-                .webconsole(false)
-                .application(EntitySpec.create(TestApplication.class))
-                .start();
-        
-        assertOnlyApp(launcher, TestApplication.class);
-    }
-    
-    @Test
-    public void testStartsAppFromBuilder() throws Exception {
-        launcher = newLauncherForTests(true)
-                .webconsole(false)
-                .application(new ApplicationBuilder(EntitySpec.create(TestApplication.class)) {
-                        @Override protected void doBuild() {
-                        }})
-                .start();
-        
-        assertOnlyApp(launcher, TestApplication.class);
-    }
-
-    @Test
-    public void testStartsAppFromYAML() throws Exception {
-        String yaml = "name: example-app\n" +
-                "services:\n" +
-                "- serviceType: brooklyn.test.entity.TestEntity\n" +
-                "  name: test-app";
-        launcher = newLauncherForTests(true)
-                .webconsole(false)
-                .application(yaml)
-                .start();
-
-        assertEquals(launcher.getApplications().size(), 1, "apps="+launcher.getApplications());
-        Application app = Iterables.getOnlyElement(launcher.getApplications());
-        assertEquals(app.getChildren().size(), 1, "children=" + app.getChildren());
-        assertTrue(Iterables.getOnlyElement(app.getChildren()) instanceof TestEntity);
-    }
-    
-    @Test  // may take 2s initializing location if running this test case alone, but noise if running suite 
-    public void testStartsAppInSuppliedLocations() throws Exception {
-        launcher = newLauncherForTests(true)
-                .webconsole(false)
-                .location("localhost")
-                .application(new ApplicationBuilder(EntitySpec.create(TestApplication.class)) {
-                        @Override protected void doBuild() {
-                        }})
-                .start();
-        
-        Application app = Iterables.find(launcher.getApplications(), Predicates.instanceOf(TestApplication.class));
-        assertOnlyLocation(app, LocalhostMachineProvisioningLocation.class);
-    }
-    
-    @Test
-    public void testUsesSuppliedManagementContext() throws Exception {
-        LocalManagementContext myManagementContext = LocalManagementContextForTests.newInstance();
-        launcher = newLauncherForTests(false)
-                .webconsole(false)
-                .managementContext(myManagementContext)
-                .start();
-        
-        assertSame(launcher.getServerDetails().getManagementContext(), myManagementContext);
-    }
-    
-    @Test
-    public void testUsesSuppliedBrooklynProperties() throws Exception {
-        BrooklynProperties props = LocalManagementContextForTests.builder(true).buildProperties();
-        props.put("mykey", "myval");
-        launcher = newLauncherForTests(false)
-                .webconsole(false)
-                .brooklynProperties(props)
-                .start();
-        
-        assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("mykey"), "myval");
-    }
-
-    @Test
-    public void testUsesSupplementaryBrooklynProperties() throws Exception {
-        launcher = newLauncherForTests(true)
-                .webconsole(false)
-                .brooklynProperties("mykey", "myval")
-                .start();
-        
-        assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("mykey"), "myval");
-    }
-    
-    @Test
-    public void testReloadBrooklynPropertiesRestoresProgrammaticProperties() throws Exception {
-        launcher = newLauncherForTests(true)
-                .webconsole(false)
-                .brooklynProperties("mykey", "myval")
-                .start();
-        LocalManagementContext managementContext = (LocalManagementContext)launcher.getServerDetails().getManagementContext();
-        assertEquals(managementContext.getConfig().getFirst("mykey"), "myval");
-        managementContext.getBrooklynProperties().put("mykey", "newval");
-        assertEquals(managementContext.getConfig().getFirst("mykey"), "newval");
-        managementContext.reloadBrooklynProperties();
-        assertEquals(managementContext.getConfig().getFirst("mykey"), "myval");
-    }
-    
-    @Test
-    public void testReloadBrooklynPropertiesFromFile() throws Exception {
-        File globalPropertiesFile = File.createTempFile("local-brooklyn-properties-test", ".properties");
-        FileUtil.setFilePermissionsTo600(globalPropertiesFile);
-        try {
-            String property = "mykey=myval";
-            Files.append(getMinimalLauncherPropertiesString()+property, globalPropertiesFile, Charsets.UTF_8);
-            launcher = newLauncherForTests(false)
-                    .webconsole(false)
-                    .globalBrooklynPropertiesFile(globalPropertiesFile.getAbsolutePath())
-                    .start();
-            LocalManagementContext managementContext = (LocalManagementContext)launcher.getServerDetails().getManagementContext();
-            assertEquals(managementContext.getConfig().getFirst("mykey"), "myval");
-            property = "mykey=newval";
-            Files.write(getMinimalLauncherPropertiesString()+property, globalPropertiesFile, Charsets.UTF_8);
-            managementContext.reloadBrooklynProperties();
-            assertEquals(managementContext.getConfig().getFirst("mykey"), "newval");
-        } finally {
-            globalPropertiesFile.delete();
-        }
-    }
-
-    @Test(groups="Integration")
-    public void testChecksGlobalBrooklynPropertiesPermissionsX00() throws Exception {
-        File propsFile = File.createTempFile("testChecksGlobalBrooklynPropertiesPermissionsX00", ".properties");
-        propsFile.setReadable(true, false);
-        try {
-            launcher = newLauncherForTests(false)
-                    .webconsole(false)
-                    .globalBrooklynPropertiesFile(propsFile.getAbsolutePath())
-                    .start();
-
-            Assert.fail("Should have thrown");
-        } catch (FatalRuntimeException e) {
-            if (!e.toString().contains("Invalid permissions for file")) throw e;
-        } finally {
-            propsFile.delete();
-        }
-    }
-
-    @Test(groups="Integration")
-    public void testChecksLocalBrooklynPropertiesPermissionsX00() throws Exception {
-        File propsFile = File.createTempFile("testChecksLocalBrooklynPropertiesPermissionsX00", ".properties");
-        propsFile.setReadable(true, false);
-        try {
-            launcher = newLauncherForTests(false)
-                    .webconsole(false)
-                    .localBrooklynPropertiesFile(propsFile.getAbsolutePath())
-                    .start();
-            
-            Assert.fail("Should have thrown");
-        } catch (FatalRuntimeException e) {
-            if (!e.toString().contains("Invalid permissions for file")) throw e;
-        } finally {
-            propsFile.delete();
-        }
-    }
-
-    @Test(groups="Integration")
-    public void testStartsWithBrooklynPropertiesPermissionsX00() throws Exception {
-        File globalPropsFile = File.createTempFile("testChecksLocalBrooklynPropertiesPermissionsX00_global", ".properties");
-        Files.write(getMinimalLauncherPropertiesString()+"key_in_global=1", globalPropsFile, Charset.defaultCharset());
-        File localPropsFile = File.createTempFile("testChecksLocalBrooklynPropertiesPermissionsX00_local", ".properties");
-        Files.write("key_in_local=2", localPropsFile, Charset.defaultCharset());
-        FileUtil.setFilePermissionsTo600(globalPropsFile);
-        FileUtil.setFilePermissionsTo600(localPropsFile);
-        try {
-            launcher = newLauncherForTests(false)
-                    .webconsole(false)
-                    .localBrooklynPropertiesFile(localPropsFile.getAbsolutePath())
-                    .globalBrooklynPropertiesFile(globalPropsFile.getAbsolutePath())
-                    .start();
-            assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("key_in_global"), "1");
-            assertEquals(launcher.getServerDetails().getManagementContext().getConfig().getFirst("key_in_local"), "2");
-        } finally {
-            globalPropsFile.delete();
-            localPropsFile.delete();
-        }
-    }
-    
-    @Test  // takes a bit of time because starts webapp, but also tests rest api so useful
-    public void testErrorsCaughtByApiAndRestApiWorks() throws Exception {
-        launcher = newLauncherForTests(true)
-                .catalogInitialization(new CatalogInitialization(null, false, null, false).addPopulationCallback(new Function<CatalogInitialization, Void>() {
-                    @Override
-                    public Void apply(CatalogInitialization input) {
-                        throw new RuntimeException("deliberate-exception-for-testing");
-                    }
-                }))
-                .start();
-        // such an error should be thrown, then caught in this calling thread
-        ManagementContext mgmt = launcher.getServerDetails().getManagementContext();
-        Assert.assertFalse( ((ManagementContextInternal)mgmt).errors().isEmpty() );
-        Assert.assertTrue( ((ManagementContextInternal)mgmt).errors().get(0).toString().contains("deliberate"), ""+((ManagementContextInternal)mgmt).errors() );
-        HttpTestUtils.assertContentMatches(
-            Urls.mergePaths(launcher.getServerDetails().getWebServerUrl(), "v1/server/up"), 
-            "true");
-        HttpTestUtils.assertContentMatches(
-            Urls.mergePaths(launcher.getServerDetails().getWebServerUrl(), "v1/server/healthy"), 
-            "false");
-        // TODO test errors api?
-    }
-
-    private BrooklynLauncher newLauncherForTests(boolean minimal) {
-        Preconditions.checkArgument(launcher==null, "can only be used if no launcher yet");
-        BrooklynLauncher launcher = BrooklynLauncher.newInstance();
-        if (minimal)
-            launcher.brooklynProperties(LocalManagementContextForTests.builder(true).buildProperties());
-        return launcher;
-    }
-
-    private String getMinimalLauncherPropertiesString() throws IOException {
-        BrooklynProperties p1 = LocalManagementContextForTests.builder(true).buildProperties();
-        Properties p = new Properties();
-        p.putAll(Maps.transformValues(p1.asMapWithStringKeys(), StringFunctions.toStringFunction()));
-        Writer w = new StringWriter();
-        p.store(w, "test");
-        w.close();
-        return w.toString()+"\n";
-    }
-
-    private void assertOnlyApp(BrooklynLauncher launcher, Class<? extends Application> expectedType) {
-        assertEquals(launcher.getApplications().size(), 1, "apps="+launcher.getApplications());
-        assertNotNull(Iterables.find(launcher.getApplications(), Predicates.instanceOf(TestApplication.class), null), "apps="+launcher.getApplications());
-    }
-    
-    private void assertOnlyLocation(Application app, Class<? extends Location> expectedType) {
-        assertEquals(app.getLocations().size(), 1, "locs="+app.getLocations());
-        assertNotNull(Iterables.find(app.getLocations(), Predicates.instanceOf(LocalhostMachineProvisioningLocation.class), null), "locs="+app.getLocations());
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/launcher/BrooklynWebServerTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynWebServerTest.java b/usage/launcher/src/test/java/brooklyn/launcher/BrooklynWebServerTest.java
deleted file mode 100644
index b40a023..0000000
--- a/usage/launcher/src/test/java/brooklyn/launcher/BrooklynWebServerTest.java
+++ /dev/null
@@ -1,209 +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 brooklyn.launcher;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.security.KeyStore;
-import java.security.SecureRandom;
-import java.util.List;
-import java.util.Map;
-
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLPeerUnverifiedException;
-
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.rest.BrooklynWebConfig;
-import brooklyn.test.entity.LocalManagementContextForTests;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.http.HttpTool;
-import brooklyn.util.http.HttpToolResponse;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-
-public class BrooklynWebServerTest {
-
-    public static final Logger log = LoggerFactory.getLogger(BrooklynWebServer.class);
-
-    private BrooklynProperties brooklynProperties;
-    private BrooklynWebServer webServer;
-    private List<LocalManagementContext> managementContexts = Lists.newCopyOnWriteArrayList();
-    
-    @BeforeMethod(alwaysRun=true)
-    public void setUp(){
-        brooklynProperties = BrooklynProperties.Factory.newEmpty();
-    }
-
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        for (LocalManagementContext managementContext : managementContexts) {
-            Entities.destroyAll(managementContext);
-        }
-        managementContexts.clear();
-        if (webServer != null) webServer.stop();
-    }
-    
-    private LocalManagementContext newManagementContext(BrooklynProperties brooklynProperties) {
-        LocalManagementContext result = new LocalManagementContextForTests(brooklynProperties);
-        managementContexts.add(result);
-        return result;
-    }
-    
-    @Test
-    public void verifyHttp() throws Exception {
-        webServer = new BrooklynWebServer(newManagementContext(brooklynProperties));
-        try {
-            webServer.start();
-    
-            HttpToolResponse response = HttpTool.execAndConsume(new DefaultHttpClient(), new HttpGet(webServer.getRootUrl()));
-            assertEquals(response.getResponseCode(), 200);
-        } finally {
-            webServer.stop();
-        }
-    }
-
-    @DataProvider(name="keystorePaths")
-    public Object[][] getKeystorePaths() {
-        return new Object[][] {
-                {getFile("server.ks")},
-                {new File(getFile("server.ks")).toURI().toString()},
-                {"classpath://server.ks"}};
-    }
-    
-    @Test(dataProvider="keystorePaths")
-    public void verifyHttps(String keystoreUrl) throws Exception {
-        Map<String,?> flags = ImmutableMap.<String,Object>builder()
-                .put("httpsEnabled", true)
-                .put("keystoreUrl", keystoreUrl)
-                .put("keystorePassword", "password")
-                .build();
-        webServer = new BrooklynWebServer(flags, newManagementContext(brooklynProperties));
-        webServer.start();
-        
-        try {
-            KeyStore keyStore = load("client.ks", "password");
-            KeyStore trustStore = load("client.ts", "password");
-            SSLSocketFactory socketFactory = new SSLSocketFactory(SSLSocketFactory.TLS, keyStore, "password", trustStore, (SecureRandom)null, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
-
-            HttpToolResponse response = HttpTool.execAndConsume(
-                    HttpTool.httpClientBuilder()
-                            .port(webServer.getActualPort())
-                            .https(true)
-                            .socketFactory(socketFactory)
-                            .build(),
-                    new HttpGet(webServer.getRootUrl()));
-            assertEquals(response.getResponseCode(), 200);
-        } finally {
-            webServer.stop();
-        }
-    }
-
-    @Test
-    public void verifyHttpsFromConfig() throws Exception {
-        brooklynProperties.put(BrooklynWebConfig.HTTPS_REQUIRED, true);
-        brooklynProperties.put(BrooklynWebConfig.KEYSTORE_URL, getFile("server.ks"));
-        brooklynProperties.put(BrooklynWebConfig.KEYSTORE_PASSWORD, "password");
-        verifyHttpsFromConfig(brooklynProperties);
-    }
-
-    @Test
-    public void verifyHttpsCiphers() throws Exception {
-        brooklynProperties.put(BrooklynWebConfig.HTTPS_REQUIRED, true);
-        brooklynProperties.put(BrooklynWebConfig.TRANSPORT_PROTOCOLS, "XXX");
-        brooklynProperties.put(BrooklynWebConfig.TRANSPORT_CIPHERS, "XXX");
-        try {
-            verifyHttpsFromConfig(brooklynProperties);
-            fail("Expected to fail due to unsupported ciphers during connection negotiation");
-        } catch (Exception e) {
-            assertTrue(Exceptions.getFirstThrowableOfType(e, SSLPeerUnverifiedException.class) != null ||
-                    Exceptions.getFirstThrowableOfType(e, SSLHandshakeException.class) != null,
-                    "Expected to fail due to inability to negotiate");
-        }
-    }
-
-    private void verifyHttpsFromConfig(BrooklynProperties brooklynProperties) throws Exception {
-        webServer = new BrooklynWebServer(MutableMap.of(), newManagementContext(brooklynProperties));
-        webServer.start();
-        
-        try {
-            KeyStore keyStore = load("client.ks", "password");
-            KeyStore trustStore = load("client.ts", "password");
-            SSLSocketFactory socketFactory = new SSLSocketFactory(SSLSocketFactory.TLS, keyStore, "password", trustStore, (SecureRandom)null, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
-
-            HttpToolResponse response = HttpTool.execAndConsume(
-                    HttpTool.httpClientBuilder()
-                            .port(webServer.getActualPort())
-                            .https(true)
-                            .socketFactory(socketFactory)
-                            .build(),
-                    new HttpGet(webServer.getRootUrl()));
-            assertEquals(response.getResponseCode(), 200);
-        } finally {
-            webServer.stop();
-        }
-    }
-
-    private KeyStore load(String name, String password) throws Exception {
-        KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
-        FileInputStream instream = new FileInputStream(new File(getFile(name)));
-        keystore.load(instream, password.toCharArray());
-        return keystore;
-    }
-    
-    @Test
-    public void testGetFileFromUrl() throws Exception {
-        // On Windows will treat as relative paths
-        String url = "file:///tmp/special%40file%20with%20spaces";
-        String file = "/tmp/special@file with spaces";
-        assertEquals(getFile(new URL(url)), new File(file).getAbsolutePath());
-    }
-
-    private String getFile(String classpathResource) {
-        // this works because both IDE and Maven run tests with classes/resources on the file system
-        return getFile(getClass().getResource("/" + classpathResource));
-    }
-
-    private String getFile(URL url) {
-        try {
-            return new File(url.toURI()).getAbsolutePath();
-        } catch (URISyntaxException e) {
-            throw Exceptions.propagate(e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/launcher/SimpleYamlLauncherForTests.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/SimpleYamlLauncherForTests.java b/usage/launcher/src/test/java/brooklyn/launcher/SimpleYamlLauncherForTests.java
deleted file mode 100644
index 9ab8131..0000000
--- a/usage/launcher/src/test/java/brooklyn/launcher/SimpleYamlLauncherForTests.java
+++ /dev/null
@@ -1,31 +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 brooklyn.launcher;
-
-import brooklyn.launcher.camp.SimpleYamlLauncher;
-import brooklyn.management.ManagementContext;
-import brooklyn.test.entity.LocalManagementContextForTests;
-
-public class SimpleYamlLauncherForTests extends SimpleYamlLauncher {
-
-    protected ManagementContext newManagementContext() {
-        return new LocalManagementContextForTests();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java b/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java
deleted file mode 100644
index c89b399..0000000
--- a/usage/launcher/src/test/java/brooklyn/launcher/WebAppRunnerTest.java
+++ /dev/null
@@ -1,168 +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 brooklyn.launcher;
-
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.fail;
-
-import java.util.List;
-import java.util.Map;
-
-import org.apache.brooklyn.test.TestResourceUnavailableException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.config.BrooklynProperties;
-import brooklyn.entity.basic.Entities;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.test.HttpTestUtils;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.net.Networking;
-
-import com.google.common.collect.Lists;
-
-
-/**
- * These tests require the brooklyn.war to work. (Should be placed by maven build.)
- */
-public class WebAppRunnerTest {
-
-    public static final Logger log = LoggerFactory.getLogger(WebAppRunnerTest.class);
-            
-    List<LocalManagementContext> managementContexts = Lists.newCopyOnWriteArrayList();
-    
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        for (LocalManagementContext managementContext : managementContexts) {
-            Entities.destroyAll(managementContext);
-        }
-        managementContexts.clear();
-    }
-    
-    LocalManagementContext newManagementContext(BrooklynProperties brooklynProperties) {
-        LocalManagementContext result = new LocalManagementContext(brooklynProperties);
-        managementContexts.add(result);
-        return result;
-    }
-    
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    BrooklynWebServer createWebServer(Map properties) {
-        Map bigProps = MutableMap.copyOf(properties);
-        Map attributes = MutableMap.copyOf( (Map) bigProps.get("attributes") );
-        bigProps.put("attributes", attributes);
-
-        BrooklynProperties brooklynProperties = BrooklynProperties.Factory.newEmpty();
-        brooklynProperties.putAll(bigProps);
-        brooklynProperties.put("brooklyn.webconsole.security.provider","brooklyn.rest.security.provider.AnyoneSecurityProvider");
-        brooklynProperties.put("brooklyn.webconsole.security.https.required","false");
-        return new BrooklynWebServer(bigProps, newManagementContext(brooklynProperties));
-    }
-    
-    @Test
-    public void testStartWar1() throws Exception {
-        if (!Networking.isPortAvailable(8090))
-            fail("Another process is using port 8090 which is required for this test.");
-        BrooklynWebServer server = createWebServer(MutableMap.of("port", 8090));
-        assertNotNull(server);
-        
-        try {
-            server.start();
-            assertBrooklynEventuallyAt("http://localhost:8090/");
-        } finally {
-            server.stop();
-        }
-    }
-
-    public static void assertBrooklynEventuallyAt(String url) {
-        HttpTestUtils.assertContentEventuallyContainsText(url, "Brooklyn Web Console");
-    }
-
-    @Test
-    public void testStartSecondaryWar() throws Exception {
-        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
-
-        if (!Networking.isPortAvailable(8090))
-            fail("Another process is using port 8090 which is required for this test.");
-        BrooklynWebServer server = createWebServer(
-            MutableMap.of("port", 8090, "war", "brooklyn.war", "wars", MutableMap.of("hello", "hello-world.war")) );
-        assertNotNull(server);
-        
-        try {
-            server.start();
-
-            assertBrooklynEventuallyAt("http://localhost:8090/");
-            HttpTestUtils.assertContentEventuallyContainsText("http://localhost:8090/hello",
-                "This is the home page for a sample application");
-
-        } finally {
-            server.stop();
-        }
-    }
-
-    @Test
-    public void testStartSecondaryWarAfter() throws Exception {
-        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
-
-        if (!Networking.isPortAvailable(8090))
-            fail("Another process is using port 8090 which is required for this test.");
-        BrooklynWebServer server = createWebServer(MutableMap.of("port", 8090, "war", "brooklyn.war"));
-        assertNotNull(server);
-        
-        try {
-            server.start();
-            server.deploy("/hello", "hello-world.war");
-
-            assertBrooklynEventuallyAt("http://localhost:8090/");
-            HttpTestUtils.assertContentEventuallyContainsText("http://localhost:8090/hello",
-                "This is the home page for a sample application");
-
-        } finally {
-            server.stop();
-        }
-    }
-
-    @Test
-    public void testStartWithLauncher() throws Exception {
-        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/hello-world.war");
-
-        BrooklynLauncher launcher = BrooklynLauncher.newInstance()
-                .brooklynProperties(BrooklynProperties.Factory.newEmpty())
-                .brooklynProperties("brooklyn.webconsole.security.provider","brooklyn.rest.security.provider.AnyoneSecurityProvider")
-                .webapp("/hello", "hello-world.war")
-                .start();
-        BrooklynServerDetails details = launcher.getServerDetails();
-        
-        try {
-            details.getWebServer().deploy("/hello2", "hello-world.war");
-
-            assertBrooklynEventuallyAt(details.getWebServerUrl());
-            HttpTestUtils.assertContentEventuallyContainsText(details.getWebServerUrl()+"hello", "This is the home page for a sample application");
-            HttpTestUtils.assertContentEventuallyContainsText(details.getWebServerUrl()+"hello2", "This is the home page for a sample application");
-            HttpTestUtils.assertHttpStatusCodeEventuallyEquals(details.getWebServerUrl()+"hello0", 404);
-
-        } finally {
-            details.getWebServer().stop();
-            ((ManagementContextInternal)details.getManagementContext()).terminate();
-        }
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/launcher/YamlLauncher.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/YamlLauncher.java b/usage/launcher/src/test/java/brooklyn/launcher/YamlLauncher.java
deleted file mode 100644
index 1bd8ab8..0000000
--- a/usage/launcher/src/test/java/brooklyn/launcher/YamlLauncher.java
+++ /dev/null
@@ -1,35 +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 brooklyn.launcher;
-
-import brooklyn.launcher.camp.SimpleYamlLauncher;
-
-public class YamlLauncher {
-
-    public static void main(String[] args) {
-        SimpleYamlLauncher l = new SimpleYamlLauncher();
-        l.setShutdownAppsOnExit(true);
-        
-        l.launchAppYaml("java-web-app-and-db-with-function.yaml");
-//        l.launchAppYaml("java-web-app-and-memsql.yaml");
-//        l.launchAppYaml("memsql.yaml");
-//        l.launchAppYaml("classpath://mongo-blueprint.yaml");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/blueprints/AbstractBlueprintTest.java b/usage/launcher/src/test/java/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
deleted file mode 100644
index 63a8bfb..0000000
--- a/usage/launcher/src/test/java/brooklyn/launcher/blueprints/AbstractBlueprintTest.java
+++ /dev/null
@@ -1,202 +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 brooklyn.launcher.blueprints;
-
-import static org.testng.Assert.assertNotEquals;
-
-import java.io.File;
-import java.io.Reader;
-import java.io.StringReader;
-import java.util.Collection;
-
-import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherAbstract;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-
-import brooklyn.entity.Application;
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.Attributes;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.Lifecycle;
-import brooklyn.entity.basic.SoftwareProcess;
-import brooklyn.entity.rebind.RebindOptions;
-import brooklyn.entity.rebind.RebindTestUtils;
-import brooklyn.entity.rebind.persister.FileBasedObjectStore;
-import brooklyn.launcher.BrooklynLauncher;
-import brooklyn.launcher.SimpleYamlLauncherForTests;
-import brooklyn.launcher.camp.BrooklynCampPlatformLauncher;
-import brooklyn.management.ManagementContext;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.test.Asserts;
-import brooklyn.test.EntityTestUtils;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.os.Os;
-
-public abstract class AbstractBlueprintTest {
-
-    private static final Logger LOG = LoggerFactory.getLogger(AbstractBlueprintTest.class);
-    
-    protected File mementoDir;
-    protected ClassLoader classLoader = AbstractBlueprintTest.class.getClassLoader();
-    
-    protected ManagementContext mgmt;
-    protected SimpleYamlLauncherForTests launcher;
-    protected BrooklynLauncher viewer;
-
-    @BeforeMethod(alwaysRun=true)
-    public void setUp() throws Exception {
-        mementoDir = Os.newTempDir(getClass());
-        mgmt = createOrigManagementContext();
-        LOG.info("Test "+getClass()+" persisting to "+mementoDir);
-
-        launcher = new SimpleYamlLauncherForTests() {
-            @Override
-            protected BrooklynCampPlatformLauncherAbstract newPlatformLauncher() {
-                return new BrooklynCampPlatformLauncher() {
-                    protected ManagementContext newManagementContext() {
-                        return AbstractBlueprintTest.this.mgmt;
-                    }
-                };
-            }
-        };
-        viewer = BrooklynLauncher.newInstance()
-                .managementContext(mgmt)
-                .start();
-    }
-
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws Exception {
-        try {
-            if (mgmt != null) {
-                for (Application app: mgmt.getApplications()) {
-                    LOG.debug("destroying app "+app+" (managed? "+Entities.isManaged(app)+"; mgmt is "+mgmt+")");
-                    try {
-                        Entities.destroy(app);
-                        LOG.debug("destroyed app "+app+"; mgmt now "+mgmt);
-                    } catch (Exception e) {
-                        LOG.error("problems destroying app "+app, e);
-                    }
-                }
-            }
-            if (launcher != null) launcher.destroyAll();
-            if (viewer != null) viewer.terminate();
-            if (mgmt != null) Entities.destroyAll(mgmt);
-            if (mementoDir != null) FileBasedObjectStore.deleteCompletely(mementoDir);
-        } catch (Throwable t) {
-            LOG.error("Caught exception in tearDown method", t);
-        } finally {
-            mgmt = null;
-            launcher = null;
-        }
-    }
-
-    protected void runTest(String yamlFile) throws Exception {
-        final Application app = launcher.launchAppYaml(yamlFile);
-        
-        assertNoFires(app);
-        
-        Application newApp = rebind();
-        assertNoFires(newApp);
-    }
-    
-    protected void runTest(Reader yaml) throws Exception {
-        final Application app = launcher.launchAppYaml(yaml);
-        
-        assertNoFires(app);
-        
-        Application newApp = rebind();
-        assertNoFires(newApp);
-    }
-    
-    protected void assertNoFires(final Entity app) {
-        EntityTestUtils.assertAttributeEqualsEventually(app, Attributes.SERVICE_UP, true);
-        EntityTestUtils.assertAttributeEqualsEventually(app, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
-        
-        Asserts.succeedsEventually(new Runnable() {
-            public void run() {
-                for (Entity entity : Entities.descendants(app)) {
-                    assertNotEquals(entity.getAttribute(Attributes.SERVICE_STATE_ACTUAL), Lifecycle.ON_FIRE);
-                    assertNotEquals(entity.getAttribute(Attributes.SERVICE_UP), false);
-                    
-                    if (entity instanceof SoftwareProcess) {
-                        EntityTestUtils.assertAttributeEquals(entity, Attributes.SERVICE_STATE_ACTUAL, Lifecycle.RUNNING);
-                        EntityTestUtils.assertAttributeEquals(entity, Attributes.SERVICE_UP, Boolean.TRUE);
-                    }
-                }
-            }});
-    }
-
-    protected Reader loadYaml(String url, String location) {
-        String yaml = 
-                "location: "+location+"\n"+
-                new ResourceUtils(this).getResourceAsString(url);
-        return new StringReader(yaml);
-    }
-    
-    
-    //////////////////////////////////////////////////////////////////
-    // FOR REBIND                                                   //
-    // See brooklyn.entity.rebind.RebindTestFixture in core's tests //
-    //////////////////////////////////////////////////////////////////
-
-    /** rebinds, and sets newApp */
-    protected Application rebind() throws Exception {
-        return rebind(RebindOptions.create());
-    }
-
-    protected Application rebind(RebindOptions options) throws Exception {
-        ManagementContext origMgmt = mgmt;
-        ManagementContext newMgmt = createNewManagementContext();
-        Collection<Application> origApps = origMgmt.getApplications();
-        
-        options = RebindOptions.create(options);
-        if (options.classLoader == null) options.classLoader(classLoader);
-        if (options.mementoDir == null) options.mementoDir(mementoDir);
-        if (options.origManagementContext == null) options.origManagementContext(origMgmt);
-        if (options.newManagementContext == null) options.newManagementContext(newMgmt);
-        
-        for (Application origApp : origApps) {
-            RebindTestUtils.waitForPersisted(origApp);
-        }
-        
-        mgmt = options.newManagementContext;
-        Application newApp = RebindTestUtils.rebind(options);
-        return newApp;
-    }
-    
-    /** @return A started management context */
-    protected LocalManagementContext createOrigManagementContext() {
-        return RebindTestUtils.managementContextBuilder(mementoDir, classLoader)
-                .persistPeriodMillis(1)
-                .forLive(true)
-                .emptyCatalog(true)
-                .buildStarted();
-    }
-
-    /** @return An unstarted management context */
-    protected LocalManagementContext createNewManagementContext() {
-        return RebindTestUtils.managementContextBuilder(mementoDir, classLoader)
-                .persistPeriodMillis(1)
-                .forLive(true)
-                .emptyCatalog(true)
-                .buildUnstarted();
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/launcher/blueprints/CouchbaseBlueprintTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/blueprints/CouchbaseBlueprintTest.java b/usage/launcher/src/test/java/brooklyn/launcher/blueprints/CouchbaseBlueprintTest.java
deleted file mode 100644
index 3450489..0000000
--- a/usage/launcher/src/test/java/brooklyn/launcher/blueprints/CouchbaseBlueprintTest.java
+++ /dev/null
@@ -1,69 +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 brooklyn.launcher.blueprints;
-
-import org.testng.annotations.Test;
-
-public class CouchbaseBlueprintTest extends AbstractBlueprintTest {
-
-    @Test(groups={"Live"})
-    public void testCouchbaseNode() throws Exception {
-        runTest("couchbase-node.yaml");
-    }
-
-    @Test(groups={"Live"})
-    public void testCouchbaseCluster() throws Exception {
-        runTest("couchbase-cluster.yaml");
-    }
-
-    @Test(groups={"Live"})
-    public void testCouchbaseClusterSingleNode() throws Exception {
-        runTest("couchbase-cluster-singleNode.yaml");
-    }
-    
-    @Test(groups={"Live"})
-    public void testCouchbaseWithPillowfight() throws Exception {
-        runTest("couchbase-w-pillowfight.yaml");
-    }
-
-    /**
-     * FIXME Failed with "Unable to match required VM template constraints" - caused by NPE:
-     *   Caused by: java.lang.NullPointerException: id
-     *     at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:229)
-     *     at org.jclouds.softlayer.domain.OperatingSystem.<init>(OperatingSystem.java:106)
-     *     at org.jclouds.softlayer.domain.OperatingSystem$Builder.build(OperatingSystem.java:87)
-     *     at org.jclouds.softlayer.domain.ContainerVirtualGuestConfiguration$4.apply(ContainerVirtualGuestConfiguration.java:209)
-     *     at org.jclouds.softlayer.domain.ContainerVirtualGuestConfiguration$4.apply(ContainerVirtualGuestConfiguration.java:206)
-     * This blueprint uses {minRam: 16384, minCores: 4}.
-     * Suspect this is already fixed by Andrea Turli in latest jclouds.
-     */
-    @Test(groups={"Live", "WIP"})
-    public void testCouchbaseWithLoadgen() throws Exception {
-        runTest("couchbase-w-loadgen.yaml");
-    }
-
-    /**
-     * FIXME Failed with "Unable to match required VM template constraints" - caused by NPE
-     * (see error described at {@link #testCouchbaseWithLoadgen()}.
-     */
-    @Test(groups={"Live", "WIP"})
-    public void testCouchbaseReplicationWithPillowfight() throws Exception {
-        runTest("couchbase-replication-w-pillowfight.yaml");
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/brooklyn/launcher/blueprints/MongoDbBlueprintTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/brooklyn/launcher/blueprints/MongoDbBlueprintTest.java b/usage/launcher/src/test/java/brooklyn/launcher/blueprints/MongoDbBlueprintTest.java
deleted file mode 100644
index 2f77552..0000000
--- a/usage/launcher/src/test/java/brooklyn/launcher/blueprints/MongoDbBlueprintTest.java
+++ /dev/null
@@ -1,51 +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 brooklyn.launcher.blueprints;
-
-import org.testng.annotations.Test;
-
-public class MongoDbBlueprintTest extends AbstractBlueprintTest {
-
-    // TODO Some tests are failing! Needs investigated.
-
-    @Test(groups={"Integration", "WIP"})
-    public void testMongoSharded() throws Exception {
-        runTest("mongo-sharded.yaml");
-    }
-
-    @Test(groups={"Integration"})
-    public void testMongoReplicaSet() throws Exception {
-        runTest("mongo-blueprint.yaml");
-    }
-
-    @Test(groups={"Integration"})
-    public void testMongoClientAndSingleServer() throws Exception {
-        runTest("mongo-client-single-server.yaml");
-    }
-
-    @Test(groups={"Integration", "WIP"})
-    public void testMongoScripts() throws Exception {
-        runTest("mongo-scripts.yaml");
-    }
-
-    @Test(groups="Integration")
-    public void testMongoSingleServer() throws Exception {
-        runTest("mongo-single-server-blueprint.yaml");
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/entity/basic/VanillaSoftwareYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/entity/basic/VanillaSoftwareYamlTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/entity/basic/VanillaSoftwareYamlTest.java
new file mode 100644
index 0000000..1181dff
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/entity/basic/VanillaSoftwareYamlTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.brooklyn.entity.basic;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Application;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.SoftwareProcess;
+import brooklyn.entity.trait.Startable;
+import org.apache.brooklyn.launcher.SimpleYamlLauncherForTests;
+import org.apache.brooklyn.launcher.camp.SimpleYamlLauncher;
+import brooklyn.test.Asserts;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.os.Os;
+import brooklyn.util.text.Strings;
+
+import com.google.common.collect.Iterables;
+
+public class VanillaSoftwareYamlTest {
+
+    private static final Logger log = LoggerFactory.getLogger(VanillaSoftwareYamlTest.class);
+    
+    @Test(groups="Integration")
+    public void testVanillaSoftwareYaml() {
+        SimpleYamlLauncher l = new SimpleYamlLauncherForTests();
+        try {
+            Application app = l.launchAppYaml("vanilla-software-blueprint.yaml");
+            log.info("started "+app);
+
+            String runDir = Iterables.getOnlyElement(app.getChildren()).getAttribute(SoftwareProcess.RUN_DIR);
+            final String filePath = Os.mergePaths(runDir, "DATE");
+
+            String fileContents = new ResourceUtils(this).getResourceAsString(filePath);
+            Long d1 = Long.parseLong( Strings.getFirstWordAfter(fileContents, "utc") );
+            Assert.assertTrue( Math.abs(d1*1000-System.currentTimeMillis())<15000, "Time UTC does not match system; "+d1+" v "+System.currentTimeMillis() );
+
+            Asserts.succeedsEventually(new Runnable() {
+                public void run() {
+                    String fileContents = new ResourceUtils(this).getResourceAsString(filePath);
+                    Assert.assertTrue(fileContents.contains("checkRunning"));
+                }
+            });
+
+            app.invoke(Startable.STOP, null).getUnchecked();
+            Asserts.succeedsEventually(new Runnable() {
+                public void run() {
+                    String fileContents = new ResourceUtils(this).getResourceAsString(filePath);
+                    Assert.assertTrue(fileContents.contains("stop"));
+                }
+            });
+
+        } finally {
+            l.destroyAll();
+        }
+        log.info("DONE");
+    }
+    
+    /** yaml variant of VanillaSoftwareProcessAndChildrenIntegrationTest */
+    @Test(groups="Integration")
+    public void testVanillaSoftwareYamlWithChildStartedAfter() {
+        SimpleYamlLauncher l = new SimpleYamlLauncherForTests();
+        try {
+            Application app = l.launchAppYaml("vanilla-software-with-child-blueprint.yaml");
+            log.info("started "+app);
+
+            Entity p1 = Iterables.getOnlyElement( app.getChildren() );
+            Long d1 = Long.parseLong( Strings.getFirstWordAfter(new ResourceUtils(this).getResourceAsString(Os.mergePaths(p1.getAttribute(SoftwareProcess.RUN_DIR), "DATE")), "utc") );
+            
+            Entity p2 = Iterables.getOnlyElement( p1.getChildren() );
+            Long d2 = Long.parseLong( Strings.getFirstWordAfter(new ResourceUtils(this).getResourceAsString(Os.mergePaths(p2.getAttribute(SoftwareProcess.RUN_DIR), "DATE")), "utc") );
+            Assert.assertTrue( d2-d1 > 2 && d2-d1 < 10, "p2 should have started 3s after parent, but it did not ("+(d2-d1)+"s difference" );
+        } finally {
+            l.destroyAll();
+        }
+        log.info("DONE");
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynEntityMirrorIntegrationTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynEntityMirrorIntegrationTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynEntityMirrorIntegrationTest.java
new file mode 100644
index 0000000..f42c574
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynEntityMirrorIntegrationTest.java
@@ -0,0 +1,180 @@
+/*
+ * 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.brooklyn.entity.brooklynnode;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.brooklynnode.BrooklynEntityMirror;
+import brooklyn.entity.proxying.EntitySpec;
+import org.apache.brooklyn.launcher.BrooklynWebServer;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.HighAvailabilityMode;
+import brooklyn.rest.filter.BrooklynPropertiesSecurityFilter;
+import brooklyn.test.Asserts;
+import brooklyn.test.EntityTestUtils;
+import brooklyn.test.HttpTestUtils;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.time.Duration;
+
+/**
+ * Test for EntityMirror, launching an in-memory server and ensuring we can mirror.
+ * Here so that we can access the REST server.
+ * <p>
+ * May require <code>-Dbrooklyn.localhost.address=127.0.0.1</code> so that the console which binds to localhost is addressible.
+ * (That and the time it takes to run are the only reasons this is Integration.)
+ */
+@Test
+public class BrooklynEntityMirrorIntegrationTest {
+
+    private static final Logger log = LoggerFactory.getLogger(BrooklynEntityMirrorIntegrationTest.class);
+    
+    private BrooklynWebServer server;
+    private TestApplication serverApp;
+    private ManagementContext serverMgmt;
+    
+    private TestApplication localApp;
+    private ManagementContext localMgmt;
+
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        localApp = TestApplication.Factory.newManagedInstanceForTests();
+        localMgmt = localApp.getManagementContext();
+    }
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws Exception {
+        if (serverMgmt!=null) Entities.destroyAll(serverMgmt);
+        if (server!=null) server.stop();
+        if (localMgmt!=null) Entities.destroyAll(localMgmt);
+        
+        serverMgmt = null;
+    }
+
+    
+    protected void setUpServer() {
+        setUpServer(new LocalManagementContextForTests(), false);
+    }
+    protected void setUpServer(ManagementContext mgmt, boolean useSecurityFilter) {
+        try {
+            if (serverMgmt!=null) throw new IllegalStateException("server already set up");
+            
+            serverMgmt = mgmt;
+            server = new BrooklynWebServer(mgmt);
+            if (useSecurityFilter) server.setSecurityFilter(BrooklynPropertiesSecurityFilter.class);
+            server.start();
+            
+            serverMgmt.getHighAvailabilityManager().disabled();
+            serverApp = ApplicationBuilder.newManagedApp(TestApplication.class, serverMgmt);
+            
+            ((LocalManagementContextForTests)serverMgmt).noteStartupComplete();
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+
+    protected String getBaseUri() {
+        return server.getRootUrl();
+    }
+    
+    @Test(groups="Integration")
+    public void testServiceMirroring() throws Exception {
+        setUpServer();
+        
+        String catalogItemId = "test-catalog-item:1.0";
+        String catalogItemIdGA = "test-catalog-item:1.0-GA";
+        serverApp.setAttribute(TestApplication.MY_ATTRIBUTE, "austria");
+        serverApp.setCatalogItemId(catalogItemId);
+
+        String serviceId = serverApp.getId();
+        Entity mirror = localApp.addChild(EntitySpec.create(BrooklynEntityMirror.class)
+            .configure(BrooklynEntityMirror.POLL_PERIOD, Duration.millis(100))
+            .configure(BrooklynEntityMirror.MIRRORED_ENTITY_ID, serviceId)
+            .configure(BrooklynEntityMirror.MIRRORED_ENTITY_URL, 
+                getBaseUri()+"/v1/applications/"+serviceId+"/entities/"+serviceId)
+        );
+
+        EntityTestUtils.assertAttributeEqualsEventually(mirror, TestApplication.MY_ATTRIBUTE, "austria");
+        EntityTestUtils.assertAttributeEqualsEventually(mirror, BrooklynEntityMirror.MIRROR_CATALOG_ITEM_ID, catalogItemId);
+        assertTrue(mirror.getAttribute(BrooklynEntityMirror.MIRROR_SUMMARY) != null, "entity summary is null");
+        log.info("Sensors mirrored are: "+((EntityInternal)mirror).getAllAttributes());
+        
+        serverApp.setAttribute(TestApplication.MY_ATTRIBUTE, "bermuda");
+        serverApp.setCatalogItemId(catalogItemIdGA);
+        EntityTestUtils.assertAttributeEqualsEventually(mirror, TestApplication.MY_ATTRIBUTE, "bermuda");
+        EntityTestUtils.assertAttributeEqualsEventually(mirror, BrooklynEntityMirror.MIRROR_CATALOG_ITEM_ID, catalogItemIdGA);
+
+        serverApp.stop();
+        assertUnmanagedEventually(mirror);
+    }
+
+    @Test(groups="Integration")
+    public void testServiceMirroringHttps() throws Exception {
+        LocalManagementContextForTests mgmtHttps = new LocalManagementContextForTests();
+        mgmtHttps.getBrooklynProperties().put("brooklyn.webconsole.security.https.required", true);
+        mgmtHttps.getBrooklynProperties().put("brooklyn.webconsole.security.users", "admin");
+        mgmtHttps.getBrooklynProperties().put("brooklyn.webconsole.security.user.admin.password", "P5ssW0rd");
+
+        setUpServer(mgmtHttps, true);
+        Assert.assertTrue(getBaseUri().startsWith("https:"), "URL is not https: "+getBaseUri());
+        // check auth is required
+        HttpTestUtils.assertHttpStatusCodeEquals(getBaseUri(), 401);
+        
+        serverApp.setAttribute(TestApplication.MY_ATTRIBUTE, "austria");
+
+        String serviceId = serverApp.getId();
+        Entity mirror = localApp.addChild(EntitySpec.create(BrooklynEntityMirror.class)
+            .configure(BrooklynEntityMirror.POLL_PERIOD, Duration.millis(100))
+            .configure(BrooklynEntityMirror.MANAGEMENT_USER, "admin")
+            .configure(BrooklynEntityMirror.MANAGEMENT_PASSWORD, "P5ssW0rd")
+            .configure(BrooklynEntityMirror.MIRRORED_ENTITY_ID, serviceId)
+            .configure(BrooklynEntityMirror.MIRRORED_ENTITY_URL, 
+                getBaseUri()+"/v1/applications/"+serviceId+"/entities/"+serviceId)
+        );
+
+        EntityTestUtils.assertAttributeEqualsEventually(mirror, TestApplication.MY_ATTRIBUTE, "austria");
+        log.info("Sensors mirrored are: "+((EntityInternal)mirror).getAllAttributes());
+        
+        serverApp.setAttribute(TestApplication.MY_ATTRIBUTE, "bermuda");
+        EntityTestUtils.assertAttributeEqualsEventually(mirror, TestApplication.MY_ATTRIBUTE, "bermuda");
+
+        serverApp.stop();
+        assertUnmanagedEventually(mirror);
+    }
+
+    private static void assertUnmanagedEventually(final Entity entity) {
+        Asserts.succeedsEventually(new Runnable() {
+            @Override public void run() {
+                assertFalse(Entities.isManaged(entity));
+            }});
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynNodeRestTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynNodeRestTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynNodeRestTest.java
new file mode 100644
index 0000000..4a630de
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/entity/brooklynnode/BrooklynNodeRestTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.brooklyn.entity.brooklynnode;
+
+import java.net.URI;
+import java.util.concurrent.Callable;
+
+import org.apache.http.client.HttpClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Application;
+import brooklyn.entity.basic.ApplicationBuilder;
+import brooklyn.entity.basic.Attributes;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.brooklynnode.BrooklynEntityMirror;
+import brooklyn.entity.brooklynnode.BrooklynNode;
+import brooklyn.entity.brooklynnode.SameBrooklynNodeImpl;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.event.basic.BasicConfigKey;
+import org.apache.brooklyn.launcher.SimpleYamlLauncherForTests;
+import org.apache.brooklyn.launcher.camp.SimpleYamlLauncher;
+import brooklyn.location.Location;
+import brooklyn.management.Task;
+import brooklyn.test.EntityTestUtils;
+import brooklyn.test.HttpTestUtils;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.test.entity.TestEntity;
+import brooklyn.util.collections.Jsonya;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.config.ConfigBag;
+import brooklyn.util.http.HttpTool;
+import brooklyn.util.http.HttpToolResponse;
+import brooklyn.util.net.Urls;
+import brooklyn.util.repeat.Repeater;
+import brooklyn.util.time.Duration;
+
+import com.google.common.collect.Iterables;
+
+/** REST-accessible extension of {@link BrooklynNodeTest} */
+public class BrooklynNodeRestTest {
+
+    private static final Logger log = LoggerFactory.getLogger(BrooklynNodeRestTest.class);
+    
+    // takes a while when run on its own, because initializing war and making some requests;
+    // but there are no waits (beyond 10ms), the delay is all classloading;
+    // and this tests a lot of things, REST API, Brooklyn Node, yaml deployment,
+    // so feels worth it to have as a unit test
+    // FIXME[BROOKLYN-43]: Test fails if security is configured in brooklyn.properties.
+    @Test(groups = "WIP")
+    public void testBrooklynNodeRestDeployAndMirror() {
+        final SimpleYamlLauncher l = new SimpleYamlLauncherForTests();
+        try {
+            TestApplication app = ApplicationBuilder.newManagedApp(TestApplication.class, l.getManagementContext());
+
+            BrooklynNode bn = app.createAndManageChild(EntitySpec.create(BrooklynNode.class, SameBrooklynNodeImpl.class));
+            bn.start(MutableSet.<Location>of());
+            
+            URI uri = bn.getAttribute(BrooklynNode.WEB_CONSOLE_URI);
+            Assert.assertNotNull(uri);
+            EntityTestUtils.assertAttributeEqualsEventually(bn, Attributes.SERVICE_UP, true);
+            log.info("Created BrooklynNode: "+bn);
+
+            // deploy
+            Task<?> t = bn.invoke(BrooklynNode.DEPLOY_BLUEPRINT, ConfigBag.newInstance()
+                .configure(BrooklynNode.DeployBlueprintEffector.BLUEPRINT_TYPE, TestApplication.class.getName())
+                .configure(BrooklynNode.DeployBlueprintEffector.BLUEPRINT_CONFIG, MutableMap.<String,Object>of("x", 1, "y", "Y"))
+                .getAllConfig());
+            log.info("Deployment result: "+t.getUnchecked());
+            
+            MutableSet<Application> apps = MutableSet.copyOf( l.getManagementContext().getApplications() );
+            Assert.assertEquals(apps.size(), 2);
+            apps.remove(app);
+            
+            Application newApp = Iterables.getOnlyElement(apps);
+            Entities.dumpInfo(newApp);
+            
+            Assert.assertEquals(newApp.getConfig(new BasicConfigKey<Integer>(Integer.class, "x")), (Integer)1);
+            
+            // check mirror
+            String newAppId = newApp.getId();
+            BrooklynEntityMirror mirror = app.createAndManageChild(EntitySpec.create(BrooklynEntityMirror.class)
+                .configure(BrooklynEntityMirror.MIRRORED_ENTITY_URL, 
+                    Urls.mergePaths(uri.toString(), "/v1/applications/"+newAppId+"/entities/"+newAppId))
+                .configure(BrooklynEntityMirror.MIRRORED_ENTITY_ID, newAppId)
+                .configure(BrooklynEntityMirror.POLL_PERIOD, Duration.millis(10)));
+            
+            Entities.dumpInfo(mirror);
+            
+            EntityTestUtils.assertAttributeEqualsEventually(mirror, Attributes.SERVICE_UP, true);
+            
+            ((EntityInternal)newApp).setAttribute(TestEntity.NAME, "foo");
+            EntityTestUtils.assertAttributeEqualsEventually(mirror, TestEntity.NAME, "foo");
+            log.info("Mirror successfully validated");
+            
+            // also try deploying by invoking deploy through json
+            // (catch issues when effector params are map)
+            HttpClient client = HttpTool.httpClientBuilder().build();
+            HttpToolResponse result = HttpTool.httpPost(client, URI.create(Urls.mergePaths(uri.toString(), "/v1/applications/"+app.getId()+"/entities/"+bn.getId()
+                    +"/effectors/deployBlueprint")), 
+                MutableMap.of(com.google.common.net.HttpHeaders.CONTENT_TYPE, "application/json"), 
+                Jsonya.newInstance()
+                    .put("blueprintType", TestApplication.class.getName())
+                    .put("blueprintConfig", MutableMap.of(TestEntity.CONF_NAME.getName(), "foo"))
+                .toString().getBytes());
+            log.info("Deploy effector invoked, result: "+result);
+            HttpTestUtils.assertHealthyStatusCode( result.getResponseCode() );
+            
+            Repeater.create().every(Duration.millis(10)).until(new Callable<Boolean>() {
+                @Override
+                public Boolean call() throws Exception {
+                    return l.getManagementContext().getApplications().size() == 3;
+                }
+            }).limitTimeTo(Duration.TEN_SECONDS).runRequiringTrue();
+            
+            apps = MutableSet.copyOf( l.getManagementContext().getApplications() );
+            apps.removeAll( MutableSet.of(app, newApp) );
+            Application newApp2 = Iterables.getOnlyElement(apps);
+            Entities.dumpInfo(newApp2);
+            
+            EntityTestUtils.assertAttributeEqualsEventually(newApp2, Attributes.SERVICE_UP, true);
+            Assert.assertEquals(newApp2.getConfig(TestEntity.CONF_NAME), "foo");
+            
+        } finally {
+            l.destroyAll();
+        }
+        log.info("DONE");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6f58ef3e/usage/launcher/src/test/java/org/apache/brooklyn/entity/database/mssql/MssqlBlueprintLiveTest.java
----------------------------------------------------------------------
diff --git a/usage/launcher/src/test/java/org/apache/brooklyn/entity/database/mssql/MssqlBlueprintLiveTest.java b/usage/launcher/src/test/java/org/apache/brooklyn/entity/database/mssql/MssqlBlueprintLiveTest.java
new file mode 100644
index 0000000..9103792
--- /dev/null
+++ b/usage/launcher/src/test/java/org/apache/brooklyn/entity/database/mssql/MssqlBlueprintLiveTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.brooklyn.entity.database.mssql;
+
+import java.io.StringReader;
+import java.util.Map;
+
+import org.testng.annotations.Test;
+
+import org.apache.brooklyn.launcher.blueprints.AbstractBlueprintTest;
+import brooklyn.util.ResourceUtils;
+import brooklyn.util.text.TemplateProcessor;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Assumes that brooklyn.properties contains something like the following (but with real values!):
+ * 
+ * {@code
+ * test.mssql.download.url = http://myserver.com/sql2012.iso
+ * test.mssql.download.user = myname
+ * test.mssql.download.password = mypassword
+ * test.mssql.sa.password = mypassword
+ * test.mssql.instance.name = MYNAME
+ * }
+ */
+public class MssqlBlueprintLiveTest extends AbstractBlueprintTest {
+
+    // TODO Needs further testing
+    
+    @Test(groups={"Live"})
+    public void testMssql() throws Exception {
+        Map<String, String> substitutions = ImmutableMap.of(
+                "mssql.download.url", mgmt.getConfig().getFirst("test.mssql.download.url"),
+                "mssql.download.user", mgmt.getConfig().getFirst("test.mssql.download.user"),
+                "mssql.download.password", mgmt.getConfig().getFirst("test.mssql.download.password"),
+                "mssql.sa.password", mgmt.getConfig().getFirst("test.mssql.sa.password"),
+                "mssql.instance.name", mgmt.getConfig().getFirst("test.mssql.instance.name"));
+
+        String rawYaml = new ResourceUtils(this).getResourceAsString("mssql-test.yaml");
+        String yaml = TemplateProcessor.processTemplateContents(rawYaml, substitutions);
+        runTest(new StringReader(yaml));
+    }
+}