You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ge...@apache.org on 2017/06/06 12:25:21 UTC

[01/17] brooklyn-server git commit: uninstall removes catalog items

Repository: brooklyn-server
Updated Branches:
  refs/heads/master 27feabcc9 -> f3aa339fd


uninstall removes catalog items


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

Branch: refs/heads/master
Commit: f76118cec3d7f8a1a2788d16dc7268843cb073b7
Parents: 8a4886f
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed May 3 17:06:53 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri May 5 12:43:59 2017 +0100

----------------------------------------------------------------------
 .../brooklyn/api/typereg/RegisteredType.java    |  1 +
 .../CatalogOsgiVersionMoreEntityRebindTest.java | 18 +++----------
 .../brooklyn/core/mgmt/ha/OsgiManager.java      | 28 +++++++++++++-------
 3 files changed, 23 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f76118ce/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
index fad3d35..8225187 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
@@ -37,6 +37,7 @@ public interface RegisteredType extends Identifiable {
     
     String getSymbolicName();
     String getVersion();
+    /** Bundle in symbolicname:id format where this type is defined */
     String getContainingBundle();
 
     Collection<OsgiBundleWithUrl> getLibraries();

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f76118ce/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
index 16814c0..e47f719 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
@@ -242,27 +242,15 @@ public class CatalogOsgiVersionMoreEntityRebindTest extends AbstractYamlRebindTe
             Entity app2 = createAndStartApplication(yaml);
             Asserts.shouldHaveFailedPreviously("Expected deployment to fail after uninstall; instead got "+app2);
         } catch (Exception e) {
-            // org.apache.brooklyn.util.exceptions.CompoundRuntimeException: Unable to instantiate item; 2 errors including: 
-            // Transformer for brooklyn-camp gave an error creating this plan: Transformer for catalog gave an error creating this plan: 
-            // Unable to instantiate org.apache.brooklyn.test.osgi.entities.more.MoreEntity; 
-            // 2 errors including: Error in definition of org.apache.brooklyn.test.osgi.entities.more.MoreEntity:0.12.0-SNAPSHOT: 
-            // Unable to create spec for type brooklyn:org.apache.brooklyn.test.osgi.entities.more.MoreEntity. 
-            // The reference brooklyn:org.apache.brooklyn.test.osgi.entities.more.MoreEntity looks like a URL 
-            // (running the CAMP Brooklyn assembly-template instantiator) but 
-            // the protocol brooklyn isn't white listed ([classpath, http, https]). 
-            // It's also neither a catalog item nor a java type.
-            // TODO different error after catalog item uninstalled
-            Asserts.expectedFailureContainsIgnoreCase(e, BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, "not", "registered");
+            Asserts.expectedFailureContainsIgnoreCase(e, "unable to match", BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
         }
         
         try {
             StartableApplication app2 = rebind();
             Asserts.shouldHaveFailedPreviously("Expected deployment to fail rebind; instead got "+app2);
         } catch (Exception e) {
-            Asserts.expectedFailure(e);
-            // TODO should fail to rebind this app
-            // (currently fails to load the catalog item, since it wasn't removed)
-            // Asserts.expectedFailureContainsIgnoreCase(e, BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, "simple-app-yaml");
+            // should fail to rebind this entity
+            Asserts.expectedFailureContainsIgnoreCase(e, more.getId(), "unable to load", BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
         }
     }
     

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f76118ce/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
index cdb40f4..17d5645 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
@@ -38,6 +38,7 @@ import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
+import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.BrooklynFeatureEnablement;
 import org.apache.brooklyn.core.BrooklynVersion;
@@ -74,6 +75,7 @@ import com.google.common.annotations.Beta;
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
@@ -297,6 +299,8 @@ public class OsgiManager {
         }
     }
     
+    
+    
     /**
      * Removes this bundle from Brooklyn management, 
      * removes all catalog items it defined,
@@ -318,15 +322,11 @@ public class OsgiManager {
         }
         mgmt.getRebindManager().getChangeListener().onUnmanaged(bundleMetadata);
         
-        // TODO uninstall things that come from this bundle
-//        mgmt.getTypeRegistry().getMatching(new Predicate<RegisteredType>() {
-//            @Override
-//            public boolean apply(RegisteredType input) {
-//                XXX;
-//                input.getLibraries();
-//                return false;
-//            }
-//        });
+        // uninstall things that come from this bundle
+        List<RegisteredType> thingsFromHere = ImmutableList.copyOf(getTypesFromBundle( bundleMetadata.getVersionedName() ));
+        for (RegisteredType t: thingsFromHere) {
+            mgmt.getCatalog().deleteCatalogItem(t.getSymbolicName(), t.getVersion());
+        }
         
         Bundle bundle = framework.getBundleContext().getBundle(bundleMetadata.getOsgiUniqueUrl());
         if (bundle==null) {
@@ -339,6 +339,16 @@ public class OsgiManager {
             throw Exceptions.propagate(e);
         }
     }
+
+    protected Iterable<RegisteredType> getTypesFromBundle(final VersionedName vn) {
+        final String bundleId = vn.toString();
+        return mgmt.getTypeRegistry().getMatching(new Predicate<RegisteredType>() {
+            @Override
+            public boolean apply(RegisteredType input) {
+                return bundleId.equals(input.getContainingBundle());
+            }
+        });
+    }
     
     // TODO DO on snapshot install, uninstall old equivalent snapshots (items in use might stay in use though?)
     


[06/17] brooklyn-server git commit: Fixup of tests which failed following BOM auto-install

Posted by ge...@apache.org.
Fixup of tests which failed following BOM auto-install

Tests assume BOMs wouldn't be installed, and either test wasn't expecting to read BOM or BOM had a problem


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

Branch: refs/heads/master
Commit: abdb13e6a13e5f298b798c64856e95c94c1345f4
Parents: 062fdc4
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon May 8 11:10:33 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon May 8 13:14:59 2017 +0100

----------------------------------------------------------------------
 .../catalog/CatalogMakeOsgiBundleTest.java      |   7 ++++--
 .../catalog/CatalogOsgiLibraryTest.java         |   9 +++-----
 .../CatalogOsgiVersionMoreEntityTest.java       |   4 +++-
 .../catalog/CatalogOsgiYamlEntityTest.java      |  15 ++++++-------
 .../brooklyn/test/lite/CampYamlLiteTest.java    |  22 ++++++++++++++-----
 .../src/main/resources/catalog.bom              |   7 +++---
 .../java/org/apache/brooklyn/util/os/Os.java    |   5 ++++-
 .../brooklyn-test-osgi-com-example-entities.jar | Bin 22130 -> 22138 bytes
 .../osgi/brooklyn-test-osgi-entities.jar        | Bin 22067 -> 22072 bytes
 .../brooklyn-test-osgi-more-entities_0.1.0.jar  | Bin 15997 -> 16003 bytes
 .../brooklyn-test-osgi-more-entities_0.2.0.jar  | Bin 16903 -> 16924 bytes
 ...-test-osgi-more-entities_evil-twin_0.2.0.jar | Bin 14091 -> 14099 bytes
 12 files changed, 43 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/abdb13e6/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java
index 044a2ea..397bcf7 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java
@@ -49,6 +49,7 @@ import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.core.osgi.BundleMaker;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.osgi.VersionedName;
 import org.apache.brooklyn.util.text.Identifiers;
 import org.apache.brooklyn.util.text.Strings;
 import org.osgi.framework.Bundle;
@@ -90,7 +91,8 @@ public class CatalogMakeOsgiBundleTest extends AbstractYamlTest {
             Entities.destroy(app);
         }
         for (Bundle b: bundlesToRemove) {
-            b.uninstall();
+            ((ManagementContextInternal)mgmt()).getOsgiManager().get().uninstallUploadedBundle(
+                ((ManagementContextInternal)mgmt()).getOsgiManager().get().getManagedBundle(new VersionedName(b)));
         }
         bundlesToRemove.clear();
     }
@@ -157,7 +159,8 @@ public class CatalogMakeOsgiBundleTest extends AbstractYamlTest {
         
         jf = bm.copyAddingManifest(jf, MutableMap.of(
                 "Manifest-Version", "1.0", 
-                "Bundle-SymbolicName", customName));
+                "Bundle-SymbolicName", customName,
+                "Bundle-Version", "0.0.0.SNAPSHOT"));
         
         Assert.assertTrue(bm.hasOsgiManifest(jf));
         

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/abdb13e6/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiLibraryTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiLibraryTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiLibraryTest.java
index 111ec4b..aebd80d 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiLibraryTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiLibraryTest.java
@@ -178,9 +178,8 @@ public class CatalogOsgiLibraryTest extends AbstractYamlTest {
                     "    - type: " + BasicApplication.class.getName());
             Asserts.shouldHaveFailedPreviously();
         } catch (Exception e) {
-            if (!e.toString().contains("Bundle from " + wrongUrl + " failed to install")) {
-                throw e;
-            }
+            Asserts.expectedFailureContains(e, wrongUrl);
+            Asserts.expectedFailureContainsIgnoreCase(e, "not found");
         }
     }
 
@@ -199,9 +198,7 @@ public class CatalogOsgiLibraryTest extends AbstractYamlTest {
                     "    - type: " + BasicApplication.class.getName());
             Asserts.shouldHaveFailedPreviously();
         } catch (Exception e) {
-            if (!e.toString().contains("not a jar file")) {
-                throw e;
-            }
+            Asserts.expectedFailureContainsIgnoreCase(e, "opening zip");
         }
     }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/abdb13e6/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
index aebfed9..8961c6f 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -33,6 +33,7 @@ import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
 import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityMatcher;
+import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.osgi.OsgiVersionMoreEntityTest;
@@ -180,7 +181,8 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest implement
         OsgiVersionMoreEntityTest.assertV2MethodCall(moreEntity);
     }
 
-    @Test
+    @Test(groups="Broken")  // won't work until search path is based on bundles instead of registered types
+    // (though it would work if we set versions properly in the OSGi bundles, but brooklyn types there all declare brooklyn version)
     public void testMoreEntityBothV1AndV2() throws Exception {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar");
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar");

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/abdb13e6/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlEntityTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlEntityTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlEntityTest.java
index 7b726bc..fe86ed0 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlEntityTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlEntityTest.java
@@ -39,6 +39,7 @@ import org.apache.brooklyn.core.test.entity.TestEntity;
 import org.apache.brooklyn.core.test.entity.TestEntityImpl;
 import org.apache.brooklyn.entity.stock.BasicApplication;
 import org.apache.brooklyn.entity.stock.BasicEntity;
+import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.test.support.TestResourceUnavailableException;
 import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.osgi.OsgiTestResources;
@@ -224,9 +225,9 @@ public class CatalogOsgiYamlEntityTest extends AbstractYamlTest {
                 "    version: " + nonExistentVersion,
                 "  item:",
                 "    type: " + SIMPLE_ENTITY_TYPE);
-            fail();
+            Asserts.shouldHaveFailedPreviously();
         } catch (IllegalStateException e) {
-            Assert.assertEquals(e.getMessage(), "Bundle from null failed to install: Bundle CatalogBundleDto{symbolicName=" + nonExistentId + ", version=" + nonExistentVersion + ", url=null} not previously registered, but URL is empty.");
+            Asserts.expectedFailureContainsIgnoreCase(e, nonExistentId, nonExistentVersion, "no input stream", "no URL");
         }
     }
 
@@ -305,13 +306,11 @@ public class CatalogOsgiYamlEntityTest extends AbstractYamlTest {
                 "",
                 "  item:",
                 "    type: " + SIMPLE_ENTITY_TYPE);
-            fail();
+            Asserts.shouldHaveFailedPreviously();
         } catch (IllegalStateException e) {
-            assertEquals(e.getMessage(), "Bundle from " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL + " failed to install: " +
-                    "Bundle already installed as " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_NAME + ":" +
-                    OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_VERSION + " but user explicitly requested " +
-                    "CatalogBundleDto{symbolicName=" + nonExistentId + ", version=" + nonExistentVersion + ", url=" +
-                    OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL + "}");
+            Asserts.expectedFailureContainsIgnoreCase(e, nonExistentId, nonExistentVersion,
+                "symbolic name mismatch", OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_NAME,
+                OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/abdb13e6/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
index 1257b3e..2b1b488 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
@@ -52,6 +52,7 @@ import org.apache.brooklyn.core.mgmt.osgi.OsgiStandaloneTest;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
 import org.apache.brooklyn.core.test.entity.TestApplication;
 import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.test.support.TestResourceUnavailableException;
@@ -156,6 +157,7 @@ public class CampYamlLiteTest {
     @Test
     public void testYamlServiceForCatalog() {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+        installWithoutCatalogBom(mgmt, OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL);
 
         CatalogItem<?, ?> realItem = Iterables.getOnlyElement(mgmt.getCatalog().addItems(Streams.readFullyStringAndClose(getClass().getResourceAsStream("test-app-service-blueprint.yaml"))));
         Iterable<CatalogItem<Object, Object>> retrievedItems = mgmt.getCatalog()
@@ -184,13 +186,13 @@ public class CampYamlLiteTest {
 
         String symbolicName = "my.catalog.app.id";
         String bundleUrl = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL;
-        String yaml = getSampleMyCatalogAppYaml(symbolicName, bundleUrl);
+        String yaml = prepAndGetSampleMyCatalogAppYaml(symbolicName, bundleUrl);
 
         mgmt.getCatalog().addItems(yaml);
 
         assertMgmtHasSampleMyCatalogApp(symbolicName, bundleUrl);
     }
-
+ 
     @SuppressWarnings("deprecation")
     @Test
     public void testResetXmlWithCustomEntity() throws IOException {
@@ -198,10 +200,11 @@ public class CampYamlLiteTest {
 
         String symbolicName = "my.catalog.app.id";
         String bundleUrl = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL;
-        String yaml = getSampleMyCatalogAppYaml(symbolicName, bundleUrl);
+        String yaml = prepAndGetSampleMyCatalogAppYaml(symbolicName, bundleUrl);
 
         LocalManagementContext mgmt2 = LocalManagementContextForTests.newInstanceWithOsgi();
         try {
+            installWithoutCatalogBom(mgmt2, bundleUrl);
             CampPlatformWithJustBrooklynMgmt platform2 = new CampPlatformWithJustBrooklynMgmt(mgmt2);
             MockWebPlatform.populate(platform2, TestAppAssemblyInstantiator.class);
 
@@ -215,7 +218,9 @@ public class CampYamlLiteTest {
         assertMgmtHasSampleMyCatalogApp(symbolicName, bundleUrl);
     }
 
-    private String getSampleMyCatalogAppYaml(String symbolicName, String bundleUrl) {
+    private String prepAndGetSampleMyCatalogAppYaml(String symbolicName, String bundleUrl) {
+        installWithoutCatalogBom(mgmt, bundleUrl);
+        
         return Joiner.on("\n").join(
                 "brooklyn.catalog:",
                 "  id: " + symbolicName,
@@ -227,7 +232,14 @@ public class CampYamlLiteTest {
                 "  libraries:",
                 "  - url: " + bundleUrl,
                 "  item:",
-                "    type: io.camp.mock:AppServer");
+                "    type: " + MockWebPlatform.APPSERVER.getName());
+    }
+
+    protected void installWithoutCatalogBom(LocalManagementContext mgmt, String bundleUrl) {
+        // install bundle for class access but without loading its catalog.bom, 
+        // since we only have mock matchers here
+        // (if we don't do this, the default routines install it and try to process the catalog.bom, failing)
+        mgmt.getOsgiManager().get().installDeferredStart(new BasicManagedBundle(null, null, bundleUrl), null).get();
     }
 
     private void assertMgmtHasSampleMyCatalogApp(String symbolicName, String bundleUrl) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/abdb13e6/utils/common/dependencies/osgi/more-entities-v2/src/main/resources/catalog.bom
----------------------------------------------------------------------
diff --git a/utils/common/dependencies/osgi/more-entities-v2/src/main/resources/catalog.bom b/utils/common/dependencies/osgi/more-entities-v2/src/main/resources/catalog.bom
index 3ae38e5..6307508 100644
--- a/utils/common/dependencies/osgi/more-entities-v2/src/main/resources/catalog.bom
+++ b/utils/common/dependencies/osgi/more-entities-v2/src/main/resources/catalog.bom
@@ -38,6 +38,7 @@ brooklyn.catalog:
     - id: org.apache.brooklyn.test.osgi.entities.more.MoreTemplate
       itemType: template
       item:
-        type: org.apache.brooklyn.test.osgi.entities.more.MoreTemplate
-        name: More Template
-        description: Cataliog item OSGi test template
+        services:
+        - type: org.apache.brooklyn.test.osgi.entities.more.MoreTemplate
+          name: More Template
+          description: Catalog item OSGi test template

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/abdb13e6/utils/common/src/main/java/org/apache/brooklyn/util/os/Os.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/os/Os.java b/utils/common/src/main/java/org/apache/brooklyn/util/os/Os.java
index bd28558..f1c35dc 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/os/Os.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/os/Os.java
@@ -533,10 +533,13 @@ public class Os {
 
     /** creates a private temp file which will be deleted on exit;
      * either prefix or ext may be null; 
-     * if ext is non-empty and not > 4 chars and not starting with a ., then a dot will be inserted */
+     * if ext is non-empty and not > 4 chars and not starting with a ., then a dot will be inserted;
+     * if either name part is too long it will be shortened to prevent filesystem errors */
     public static File newTempFile(String prefix, String ext) {
         String sanitizedPrefix = (Strings.isNonEmpty(prefix) ? Strings.makeValidFilename(prefix) + "-" : "");
+        if (sanitizedPrefix.length()>101) sanitizedPrefix = sanitizedPrefix.substring(0, 100)+"--";
         String extWithPrecedingSeparator = (Strings.isNonEmpty(ext) ? ext.startsWith(".") || ext.length()>4 ? ext : "."+ext : "");
+        if (extWithPrecedingSeparator.length()>13) sanitizedPrefix = sanitizedPrefix.substring(0, 12)+"--";
         try {
             File tempFile = File.createTempFile(sanitizedPrefix, extWithPrecedingSeparator, new File(tmp()));
             tempFile.deleteOnExit();

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/abdb13e6/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-com-example-entities.jar
----------------------------------------------------------------------
diff --git a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-com-example-entities.jar b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-com-example-entities.jar
index 86dfd8b..7180c4d 100644
Binary files a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-com-example-entities.jar and b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-com-example-entities.jar differ

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/abdb13e6/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar
----------------------------------------------------------------------
diff --git a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar
index 60fece6..681071c 100644
Binary files a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar and b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar differ

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/abdb13e6/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar
----------------------------------------------------------------------
diff --git a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar
index 9994cfb..d0504f0 100644
Binary files a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar and b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar differ

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/abdb13e6/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
----------------------------------------------------------------------
diff --git a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
index 3d1ce7b..872b412 100644
Binary files a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar and b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar differ

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/abdb13e6/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar
----------------------------------------------------------------------
diff --git a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar
index f00a115..c777bfb 100644
Binary files a/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar and b/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar differ


[11/17] brooklyn-server git commit: record VersionedName instead of string for containing bundle, as per PR

Posted by ge...@apache.org.
record VersionedName instead of string for containing bundle, as per PR


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

Branch: refs/heads/master
Commit: f4205fde2c380a3193953c5305e398f974069111
Parents: 3cf028a
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Jun 5 11:23:37 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Jun 5 11:23:37 2017 +0100

----------------------------------------------------------------------
 .../java/org/apache/brooklyn/api/catalog/CatalogItem.java     | 3 ++-
 .../java/org/apache/brooklyn/api/typereg/RegisteredType.java  | 3 ++-
 .../apache/brooklyn/core/catalog/internal/CatalogItemDo.java  | 3 ++-
 .../core/catalog/internal/CatalogItemDtoAbstract.java         | 7 +++----
 .../org/apache/brooklyn/core/typereg/BasicRegisteredType.java | 5 +++--
 .../org/apache/brooklyn/core/typereg/RegisteredTypes.java     | 4 +---
 6 files changed, 13 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f4205fde/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java b/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
index f3440d9..a9c93fa 100644
--- a/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
+++ b/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
@@ -38,6 +38,7 @@ import org.apache.brooklyn.api.policy.PolicySpec;
 import org.apache.brooklyn.api.sensor.Enricher;
 import org.apache.brooklyn.api.sensor.EnricherSpec;
 import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
+import org.apache.brooklyn.util.osgi.VersionedName;
 
 import com.google.common.annotations.Beta;
 
@@ -129,7 +130,7 @@ public interface CatalogItem<T,SpecT> extends BrooklynObject, Rebindable {
 
     public String getSymbolicName();
     
-    public String getContainingBundle();
+    public VersionedName getContainingBundle();
 
     public String getVersion();
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f4205fde/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
index 8225187..8385355 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
@@ -26,6 +26,7 @@ import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.Identifiable;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
+import org.apache.brooklyn.util.osgi.VersionedName;
 
 import com.google.common.annotations.Beta;
 
@@ -38,7 +39,7 @@ public interface RegisteredType extends Identifiable {
     String getSymbolicName();
     String getVersion();
     /** Bundle in symbolicname:id format where this type is defined */
-    String getContainingBundle();
+    VersionedName getContainingBundle();
 
     Collection<OsgiBundleWithUrl> getLibraries();
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f4205fde/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
index 2c1bec6..805513d 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.api.mgmt.rebind.mementos.CatalogItemMemento;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
 import org.apache.brooklyn.core.relations.EmptyRelationSupport;
+import org.apache.brooklyn.util.osgi.VersionedName;
 
 import com.google.common.base.Preconditions;
 
@@ -199,7 +200,7 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObj
     }
     
     @Override
-    public String getContainingBundle() {
+    public VersionedName getContainingBundle() {
         return itemDto.getContainingBundle();
     }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f4205fde/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
index 4644d8d..2fab74e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
@@ -37,7 +37,6 @@ import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.core.flags.FlagUtils;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
 import org.apache.brooklyn.util.osgi.VersionedName;
-import org.apache.brooklyn.util.text.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -53,7 +52,7 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
 
     private @SetFromFlag String symbolicName;
     private @SetFromFlag String version = BasicBrooklynCatalog.NO_VERSION;
-    private @SetFromFlag String containingBundle;
+    private @SetFromFlag VersionedName containingBundle;
 
     private @SetFromFlag String displayName;
     private @SetFromFlag String description;
@@ -124,7 +123,7 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
     }
     
     @Override
-    public String getContainingBundle() {
+    public VersionedName getContainingBundle() {
         return containingBundle;
     }
 
@@ -355,7 +354,7 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
     }
 
     public void setContainingBundle(VersionedName versionedName) {
-        this.containingBundle = Strings.toString(versionedName);
+        this.containingBundle = versionedName;
     }
     
     protected void setDescription(String description) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f4205fde/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
index f345ec9..9251659 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.javalang.JavaClassNames;
+import org.apache.brooklyn.util.osgi.VersionedName;
 
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableSet;
@@ -39,7 +40,7 @@ public class BasicRegisteredType implements RegisteredType {
     final RegisteredTypeKind kind;
     final String symbolicName;
     final String version;
-    String containingBundle;
+    VersionedName containingBundle;
     
     final List<OsgiBundleWithUrl> bundles = MutableList.of();
     String displayName;
@@ -85,7 +86,7 @@ public class BasicRegisteredType implements RegisteredType {
     }
     
     @Override
-    public String getContainingBundle() {
+    public VersionedName getContainingBundle() {
         return containingBundle;
     }
     

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f4205fde/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
index 72feedd..acefe6b 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
@@ -48,7 +48,6 @@ import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.guava.Maybe.Absent;
 import org.apache.brooklyn.util.text.NaturalOrderComparator;
-import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.text.VersionComparator;
 import org.apache.brooklyn.util.yaml.Yamls;
 import org.slf4j.Logger;
@@ -171,8 +170,7 @@ public class RegisteredTypes {
 
     @Beta
     public static RegisteredType setContainingBundle(RegisteredType type, @Nullable ManagedBundle bundle) {
-        ((BasicRegisteredType)type).containingBundle =
-            bundle==null ? null : Strings.toString(bundle.getVersionedName());
+        ((BasicRegisteredType)type).containingBundle = bundle==null ? null : bundle.getVersionedName();
         return type;
     }
 


[02/17] brooklyn-server git commit: record the containing bundle for any catalog item / registered type

Posted by ge...@apache.org.
record the containing bundle for any catalog item / registered type


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

Branch: refs/heads/master
Commit: 8a4886fd72709ae13fb6b4ed312df2826d8123ba
Parents: bc11ab2
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed May 3 15:44:38 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri May 5 12:43:59 2017 +0100

----------------------------------------------------------------------
 .../brooklyn/api/catalog/BrooklynCatalog.java      | 15 ++++++++++++---
 .../apache/brooklyn/api/catalog/CatalogItem.java   |  2 ++
 .../brooklyn/api/typereg/RegisteredType.java       |  1 +
 .../catalog/CatalogOsgiVersionMoreEntityTest.java  |  1 +
 .../catalog/internal/BasicBrooklynCatalog.java     | 15 ++++++++++++++-
 .../core/catalog/internal/CatalogBundleLoader.java |  7 ++++++-
 .../core/catalog/internal/CatalogItemDo.java       |  5 +++++
 .../catalog/internal/CatalogItemDtoAbstract.java   | 17 +++++++++++++++--
 .../apache/brooklyn/core/mgmt/ha/OsgiManager.java  |  6 ++++++
 .../brooklyn/core/typereg/BasicRegisteredType.java |  6 ++++++
 .../brooklyn/core/typereg/RegisteredTypes.java     | 10 ++++++++++
 11 files changed, 78 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8a4886fd/api/src/main/java/org/apache/brooklyn/api/catalog/BrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/catalog/BrooklynCatalog.java b/api/src/main/java/org/apache/brooklyn/api/catalog/BrooklynCatalog.java
index 3bda040..75fe634 100644
--- a/api/src/main/java/org/apache/brooklyn/api/catalog/BrooklynCatalog.java
+++ b/api/src/main/java/org/apache/brooklyn/api/catalog/BrooklynCatalog.java
@@ -21,7 +21,11 @@ package org.apache.brooklyn.api.catalog;
 import java.util.Collection;
 import java.util.NoSuchElementException;
 
+import javax.annotation.Nullable;
+
 import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.typereg.ManagedBundle;
+
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Predicate;
 
@@ -111,12 +115,17 @@ public interface BrooklynCatalog {
     CatalogItem<?,?> addItem(String yaml, boolean forceUpdate);
     
     /**
-     * Adds items (represented in yaml) to the catalog.
-     * Fails if the same version exists in catalog.
+     * As {@link #addItemsFromBundle(String, ManagedBundle)} with a null bundle.
+     */
+    Iterable<? extends CatalogItem<?,?>> addItems(String yaml);
+    
+    /**
+     * Adds items (represented in yaml) to the catalog coming from the indicated managed bundle.
+     * Fails if the same version exists in catalog (unless snapshot).
      *
      * @throws IllegalArgumentException if the yaml was invalid
      */
-    Iterable<? extends CatalogItem<?,?>> addItems(String yaml);
+    Iterable<? extends CatalogItem<?,?>> addItems(String yaml, @Nullable ManagedBundle definingBundle);
     
     /**
      * Adds items (represented in yaml) to the catalog.

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8a4886fd/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java b/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
index 6f27af7..342cd2a 100644
--- a/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
+++ b/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
@@ -123,6 +123,8 @@ public interface CatalogItem<T,SpecT> extends BrooklynObject, Rebindable {
     @Nullable public String getIconUrl();
 
     public String getSymbolicName();
+    
+    public String getContainingBundle();
 
     public String getVersion();
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8a4886fd/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
index 1eb7391..fad3d35 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
@@ -37,6 +37,7 @@ public interface RegisteredType extends Identifiable {
     
     String getSymbolicName();
     String getVersion();
+    String getContainingBundle();
 
     Collection<OsgiBundleWithUrl> getLibraries();
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8a4886fd/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
index 5c28c8b..cb38df5 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -83,6 +83,7 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest implement
         // types installed
         RegisteredType t = mgmt().getTypeRegistry().get(BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
         Assert.assertNotNull(t);
+        Assert.assertEquals(t.getContainingBundle(), b.getSymbolicName()+":"+b.getVersion());
         
         // can deploy
         createAndStartApplication("services: [ { type: "+BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY+" } ]");

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8a4886fd/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
index 2634ecf..9769f7e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
@@ -39,6 +39,7 @@ import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationSpec;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.core.catalog.CatalogPredicates;
 import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
 import org.apache.brooklyn.core.location.BasicLocationRegistry;
@@ -980,7 +981,12 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
 
     @Override
     public List<? extends CatalogItem<?,?>> addItems(String yaml) {
-        return addItems(yaml, false);
+        return addItems(yaml, null);
+    }
+    
+    @Override
+    public List<? extends CatalogItem<?, ?>> addItems(String yaml, ManagedBundle bundle) {
+        return addItems(yaml, bundle, false);
     }
 
     @Override
@@ -990,12 +996,19 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     
     @Override
     public List<? extends CatalogItem<?,?>> addItems(String yaml, boolean forceUpdate) {
+        return addItems(yaml, null, forceUpdate);
+    }
+    
+    private List<? extends CatalogItem<?,?>> addItems(String yaml, ManagedBundle bundle, boolean forceUpdate) {
         log.debug("Adding manual catalog item to "+mgmt+": "+yaml);
         checkNotNull(yaml, "yaml");
         List<CatalogItemDtoAbstract<?, ?>> result = collectCatalogItems(yaml);
 
         // do this at the end for atomic updates; if there are intra-yaml references, we handle them specially
         for (CatalogItemDtoAbstract<?, ?> item: result) {
+            if (bundle!=null && bundle.getVersionedName()!=null) {
+                item.setContainingBundle(bundle.getVersionedName());
+            }
             addItemDto(item, forceUpdate);
         }
         return result;

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8a4886fd/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleLoader.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleLoader.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleLoader.java
index b1f8fd3..4bf8824 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleLoader.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogBundleLoader.java
@@ -29,8 +29,11 @@ import java.util.Map;
 
 import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.typereg.ManagedBundle;
+import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.osgi.VersionedName;
 import org.apache.brooklyn.util.stream.Streams;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.yaml.Yamls;
@@ -69,6 +72,8 @@ public class CatalogBundleLoader {
      * @throws RuntimeException if the catalog items failed to be added to the catalog
      */
     public Iterable<? extends CatalogItem<?, ?>> scanForCatalog(Bundle bundle) {
+        ManagedBundle mb = ((ManagementContextInternal)managementContext).getOsgiManager().get().getManagedBundle(
+            new VersionedName(bundle));
 
         Iterable<? extends CatalogItem<?, ?>> catalogItems = MutableList.of();
 
@@ -77,7 +82,7 @@ public class CatalogBundleLoader {
             LOG.debug("Found catalog BOM in {} {} {}", CatalogUtils.bundleIds(bundle));
             String bomText = readBom(bom);
             String bomWithLibraryPath = addLibraryDetails(bundle, bomText);
-            catalogItems = this.managementContext.getCatalog().addItems(bomWithLibraryPath);
+            catalogItems = this.managementContext.getCatalog().addItems(bomWithLibraryPath, mb);
             for (CatalogItem<?, ?> item : catalogItems) {
                 LOG.debug("Added to catalog: {}, {}", item.getSymbolicName(), item.getVersion());
             }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8a4886fd/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
index 90697fe..cf3c2d7 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
@@ -197,6 +197,11 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObj
     public String getSymbolicName() {
         return itemDto.getSymbolicName();
     }
+    
+    @Override
+    public String getContainingBundle() {
+        return itemDto.getContainingBundle();
+    }
 
     @Override
     public String getVersion() {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8a4886fd/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
index 5aec768..e072b80 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
@@ -20,7 +20,6 @@ package org.apache.brooklyn.core.catalog.internal;
 
 import java.util.Collection;
 import java.util.Collections;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -37,6 +36,8 @@ import org.apache.brooklyn.core.relations.EmptyRelationSupport;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.core.flags.FlagUtils;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import org.apache.brooklyn.util.osgi.VersionedName;
+import org.apache.brooklyn.util.text.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -52,6 +53,7 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
 
     private @SetFromFlag String symbolicName;
     private @SetFromFlag String version = BasicBrooklynCatalog.NO_VERSION;
+    private @SetFromFlag String containingBundle;
 
     private @SetFromFlag String displayName;
     private @SetFromFlag String description;
@@ -120,6 +122,11 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
     public String getRegisteredTypeName() {
         return getSymbolicName();
     }
+    
+    @Override
+    public String getContainingBundle() {
+        return containingBundle;
+    }
 
     @Override
     public String getDisplayName() {
@@ -191,7 +198,7 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(symbolicName, planYaml, javaType, nullIfEmpty(libraries), version, getCatalogItemId(),
+        return Objects.hashCode(symbolicName, containingBundle, planYaml, javaType, nullIfEmpty(libraries), version, getCatalogItemId(),
             getCatalogItemIdSearchPath());
     }
 
@@ -202,6 +209,7 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
         if (getClass() != obj.getClass()) return false;
         CatalogItemDtoAbstract<?,?> other = (CatalogItemDtoAbstract<?,?>) obj;
         if (!Objects.equal(symbolicName, other.symbolicName)) return false;
+        if (!Objects.equal(containingBundle, other.containingBundle)) return false;
         if (!Objects.equal(planYaml, other.planYaml)) return false;
         if (!Objects.equal(javaType, other.javaType)) return false;
         if (!Objects.equal(nullIfEmpty(libraries), nullIfEmpty(other.libraries))) return false;
@@ -360,6 +368,10 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
         this.version = version;
     }
 
+    public void setContainingBundle(VersionedName versionedName) {
+        this.containingBundle = Strings.toString(versionedName);
+    }
+    
     protected void setDescription(String description) {
         this.description = description;
     }
@@ -439,4 +451,5 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
         Object val = map.get(key);
         return val != null ? String.valueOf(val) : null;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8a4886fd/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
index a56bb52..cdb40f4 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
@@ -221,6 +221,12 @@ public class OsgiManager {
             return managedBundleIds.get(vn);
         }
     }
+    
+    public ManagedBundle getManagedBundle(VersionedName vn) {
+        synchronized (managedBundles) {
+            return managedBundles.get(managedBundleIds.get(vn));
+        }
+    }
 
     public Bundle installUploadedBundle(ManagedBundle bundleMetadata, InputStream zipIn, boolean loadCatalogBom) {
         try {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8a4886fd/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
index e0e2305..f345ec9 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
@@ -39,6 +39,7 @@ public class BasicRegisteredType implements RegisteredType {
     final RegisteredTypeKind kind;
     final String symbolicName;
     final String version;
+    String containingBundle;
     
     final List<OsgiBundleWithUrl> bundles = MutableList.of();
     String displayName;
@@ -84,6 +85,11 @@ public class BasicRegisteredType implements RegisteredType {
     }
     
     @Override
+    public String getContainingBundle() {
+        return containingBundle;
+    }
+    
+    @Override
     public Collection<OsgiBundleWithUrl> getLibraries() {
         return ImmutableSet.copyOf(bundles);
     }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8a4886fd/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
index b3886bd..72feedd 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
@@ -33,6 +33,7 @@ import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
+import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
 import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext;
@@ -47,6 +48,7 @@ import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.guava.Maybe.Absent;
 import org.apache.brooklyn.util.text.NaturalOrderComparator;
+import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.text.VersionComparator;
 import org.apache.brooklyn.util.yaml.Yamls;
 import org.slf4j.Logger;
@@ -100,6 +102,7 @@ public class RegisteredTypes {
         }
         
         BasicRegisteredType type = (BasicRegisteredType) spec(item.getSymbolicName(), item.getVersion(), impl, item.getCatalogItemJavaType());
+        type.containingBundle = item.getContainingBundle();
         type.displayName = item.getDisplayName();
         type.description = item.getDescription();
         type.iconUrl = item.getIconUrl();
@@ -167,6 +170,13 @@ public class RegisteredTypes {
     }
 
     @Beta
+    public static RegisteredType setContainingBundle(RegisteredType type, @Nullable ManagedBundle bundle) {
+        ((BasicRegisteredType)type).containingBundle =
+            bundle==null ? null : Strings.toString(bundle.getVersionedName());
+        return type;
+    }
+
+    @Beta
     public static RegisteredType addSuperType(RegisteredType type, @Nullable Class<?> superType) {
         if (superType!=null) {
             ((BasicRegisteredType)type).superTypes.add(superType);


[04/17] brooklyn-server git commit: refactor osgi installation to facilitate upgrades and richer return semantics

Posted by ge...@apache.org.
refactor osgi installation to facilitate upgrades and richer return semantics

rebind can break however -- we need to phase the bundle installs and the bundle starts


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

Branch: refs/heads/master
Commit: 145245479ea31c6aeffffb86533cb988b39f1820
Parents: f76118c
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu May 4 17:35:32 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri May 5 12:49:30 2017 +0100

----------------------------------------------------------------------
 .../catalog/CatalogMakeOsgiBundleTest.java      |   9 +-
 .../CatalogOsgiVersionMoreEntityRebindTest.java |  80 ++++-
 .../CatalogOsgiVersionMoreEntityTest.java       |  15 +-
 .../apache/brooklyn/core/BrooklynVersion.java   |   3 +-
 .../catalog/internal/BasicBrooklynCatalog.java  |  10 +-
 .../core/catalog/internal/CatalogUtils.java     |   3 +-
 .../core/mgmt/ha/OsgiArchiveInstaller.java      | 359 +++++++++++++++++++
 .../mgmt/ha/OsgiBundleInstallationResult.java   |  71 ++++
 .../brooklyn/core/mgmt/ha/OsgiManager.java      | 129 ++-----
 .../core/mgmt/rebind/RebindContextImpl.java     |   4 +-
 .../core/typereg/BasicManagedBundle.java        |   5 +
 .../apache/brooklyn/rest/domain/ApiError.java   |  21 +-
 .../rest/resources/CatalogResource.java         | 137 ++-----
 .../brooklyn/util/maven/MavenArtifact.java      |   3 +-
 .../brooklyn/util/text/VersionComparator.java   |   9 +-
 .../util/text/VersionComparatorTest.java        |   7 +
 16 files changed, 636 insertions(+), 229 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java
index 6eca121..044a2ea 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogMakeOsgiBundleTest.java
@@ -37,10 +37,11 @@ import org.apache.brooklyn.core.BrooklynFeatureEnablement;
 import org.apache.brooklyn.core.catalog.internal.CatalogBomScanner;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
 import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
+import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.sensor.Sensors;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
-import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
@@ -172,10 +173,8 @@ public class CatalogMakeOsgiBundleTest extends AbstractYamlTest {
 
     private void installBundle(File jf) {
         try (FileInputStream fin = new FileInputStream(jf)) {
-            BasicManagedBundle bundleMetadata = new BasicManagedBundle();
-            Bundle bundle =
-                ((LocalManagementContext)mgmt()).getOsgiManager().get().installUploadedBundle(bundleMetadata, fin, true);
-            bundlesToRemove.add(bundle);
+            OsgiBundleInstallationResult br = ((ManagementContextInternal)mgmt()).getOsgiManager().get().install(fin).get();
+            bundlesToRemove.add(br.getBundle());
         } catch (Exception e) {
             throw Exceptions.propagate(e);
         }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
index e47f719..a258fcd 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
@@ -33,10 +33,10 @@ import org.apache.brooklyn.camp.brooklyn.AbstractYamlRebindTest;
 import org.apache.brooklyn.core.effector.Effectors;
 import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.entity.StartableApplication;
+import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.osgi.OsgiVersionMoreEntityTest;
 import org.apache.brooklyn.core.test.entity.TestEntity;
-import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.entity.stock.BasicApplication;
 import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.test.support.TestResourceUnavailableException;
@@ -70,8 +70,8 @@ public class CatalogOsgiVersionMoreEntityRebindTest extends AbstractYamlRebindTe
     @Test
     public void testRebindAppIncludingBundle() throws Exception {
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_COM_EXAMPLE_PATH);
-        ((ManagementContextInternal)mgmt()).getOsgiManager().get().installUploadedBundle(new BasicManagedBundle(), 
-            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V1_URL), true);
+        ((ManagementContextInternal)mgmt()).getOsgiManager().get().install( 
+            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V1_URL) );
         
         createAndStartApplication("services: [ { type: "+BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY+" } ]");
         
@@ -208,15 +208,14 @@ public class CatalogOsgiVersionMoreEntityRebindTest extends AbstractYamlRebindTe
         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_OSGI_MORE_ENTITIES_0_1_0_PATH);
         
         // install dependency
-        ((ManagementContextInternal)mgmt()).getOsgiManager().get().installUploadedBundle(new BasicManagedBundle(), 
-            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_OSGI_ENTITIES_URL), true);
+        ((ManagementContextInternal)mgmt()).getOsgiManager().get().install( 
+            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_OSGI_ENTITIES_URL) );
 
         // now the v2 bundle
-        BasicManagedBundle mb = new BasicManagedBundle();
-        Bundle b2a = ((ManagementContextInternal)mgmt()).getOsgiManager().get().installUploadedBundle(mb, 
-            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_URL), true);
+        OsgiBundleInstallationResult b = ((ManagementContextInternal)mgmt()).getOsgiManager().get().install( 
+            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_URL) ).get();
 
-        Assert.assertEquals(mb.getVersionedName().toString(), BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL+":"+"0.2.0");
+        Assert.assertEquals(b.getVersionedName().toString(), BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL+":"+"0.2.0");
         
         String yaml = Strings.lines("name: simple-app-yaml",
                 "services:",
@@ -228,8 +227,8 @@ public class CatalogOsgiVersionMoreEntityRebindTest extends AbstractYamlRebindTe
             more.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), MutableMap.of("name", "Bob")).get(),
             "HI BOB FROM V2");
         
-        ((ManagementContextInternal)mgmt()).getOsgiManager().get().uninstallUploadedBundle(mb);
-        Assert.assertEquals(b2a.getState(), Bundle.UNINSTALLED);
+        ((ManagementContextInternal)mgmt()).getOsgiManager().get().uninstallUploadedBundle(b.getMetadata());
+        Assert.assertEquals(b.getBundle().getState(), Bundle.UNINSTALLED);
 
         // can still call things
         Assert.assertEquals(
@@ -237,7 +236,7 @@ public class CatalogOsgiVersionMoreEntityRebindTest extends AbstractYamlRebindTe
             "HI CLAUDIA FROM V2");
         
         // but still uninstalled, and attempt to create makes error 
-        Assert.assertEquals(b2a.getState(), Bundle.UNINSTALLED);
+        Assert.assertEquals(b.getBundle().getState(), Bundle.UNINSTALLED);
         try {
             Entity app2 = createAndStartApplication(yaml);
             Asserts.shouldHaveFailedPreviously("Expected deployment to fail after uninstall; instead got "+app2);
@@ -254,5 +253,62 @@ public class CatalogOsgiVersionMoreEntityRebindTest extends AbstractYamlRebindTe
         }
     }
     
+    @Test
+    public void testClassAccessAfterUpgrade() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_OSGI_MORE_ENTITIES_0_1_0_PATH);
+        
+        // install dependency
+        ((ManagementContextInternal)mgmt()).getOsgiManager().get().install( 
+            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_OSGI_ENTITIES_URL) ).checkNoError();
+
+        // now the v2 bundle
+        OsgiBundleInstallationResult b2a = ((ManagementContextInternal)mgmt()).getOsgiManager().get().install( 
+            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_URL) ).get();
+
+        Assert.assertEquals(b2a.getVersionedName().toString(), BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL+":"+"0.2.0");
+        Assert.assertEquals(b2a.getCode(), OsgiBundleInstallationResult.ResultCode.INSTALLED_NEW_BUNDLE);
+        
+        String yaml = Strings.lines("name: simple-app-yaml",
+                "services:",
+                "- type: " + BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
+        Entity app = createAndStartApplication(yaml);
+        Entity more = Iterables.getOnlyElement( app.getChildren() );
+        
+        Assert.assertEquals(
+            more.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), MutableMap.of("name", "Bob")).get(),
+            "HI BOB FROM V2");
+        
+        // unforced upgrade should report already installed
+        Assert.assertEquals( ((ManagementContextInternal)mgmt()).getOsgiManager().get().install(
+            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL) ).get().getCode(),
+            OsgiBundleInstallationResult.ResultCode.IGNORING_BUNDLE_AREADY_INSTALLED);
+        
+        // force upgrade
+        OsgiBundleInstallationResult b2b = ((ManagementContextInternal)mgmt()).getOsgiManager().get().install(b2a.getMetadata(), 
+            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL), true, true).get();
+        Assert.assertEquals(b2a.getBundle(), b2b.getBundle());
+        Assert.assertEquals(b2b.getCode(), OsgiBundleInstallationResult.ResultCode.UPDATED_EXISTING_BUNDLE);
+
+        // calls to things previously instantiated get the old behaviour
+        Assert.assertEquals(
+            more.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), MutableMap.of("name", "Claudia")).get(),
+            "HI CLAUDIA FROM V2");
+        
+        // but new deployment gets the new behaviour 
+        StartableApplication app2 = (StartableApplication) createAndStartApplication(yaml);
+        Entity more2 = Iterables.getOnlyElement( app2.getChildren() );
+        Assert.assertEquals(
+            more2.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), MutableMap.of("name", "Daphne")).get(),
+            "HO DAPHNE FROM V2 EVIL TWIN");
+        app2.stop();
+        
+        // and after rebind on the old we get new behaviour
+        StartableApplication app1 = rebind();
+        Entity more1 = Iterables.getOnlyElement( app1.getChildren() );
+        Assert.assertEquals(
+            more1.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), MutableMap.of("name", "Eric")).get(),
+            "HO ERIC FROM V2 EVIL TWIN");
+    }
+    
 
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
index cb38df5..aebfed9 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -33,10 +33,10 @@ import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
 import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityMatcher;
+import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.osgi.OsgiVersionMoreEntityTest;
 import org.apache.brooklyn.core.objs.BrooklynTypes;
-import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
 import org.apache.brooklyn.test.Asserts;
@@ -44,7 +44,6 @@ import org.apache.brooklyn.test.support.TestResourceUnavailableException;
 import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.osgi.OsgiTestResources;
 import org.apache.brooklyn.util.text.Strings;
-import org.osgi.framework.Bundle;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
@@ -69,21 +68,19 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest implement
 
     @Test
     public void testBrooklynManagedBundleInstall() throws Exception {
-        BasicManagedBundle mb = new BasicManagedBundle();
-        Bundle b = ((ManagementContextInternal)mgmt()).getOsgiManager().get().installUploadedBundle(mb, 
-            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V1_URL), true);
-        Assert.assertEquals(mb.getSymbolicName(), b.getSymbolicName());
-        Assert.assertEquals(mb.getVersion(), "0.1.0");
+        OsgiBundleInstallationResult br = ((ManagementContextInternal)mgmt()).getOsgiManager().get().install( 
+            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V1_URL) ).get();
+        Assert.assertEquals(br.getVersionedName().toString(), BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL+":"+"0.1.0");
         
         // bundle installed
         Map<String, ManagedBundle> bundles = ((ManagementContextInternal)mgmt()).getOsgiManager().get().getManagedBundles();
         Asserts.assertSize(bundles.keySet(), 1);
-        Assert.assertEquals(mb.getId(), Iterables.getOnlyElement( bundles.keySet() ));
+        Assert.assertEquals(br.getMetadata().getId(), Iterables.getOnlyElement( bundles.keySet() ));
         
         // types installed
         RegisteredType t = mgmt().getTypeRegistry().get(BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
         Assert.assertNotNull(t);
-        Assert.assertEquals(t.getContainingBundle(), b.getSymbolicName()+":"+b.getVersion());
+        Assert.assertEquals(t.getContainingBundle(), br.getVersionedName().toString());
         
         // can deploy
         createAndStartApplication("services: [ { type: "+BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY+" } ]");

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/core/src/main/java/org/apache/brooklyn/core/BrooklynVersion.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/BrooklynVersion.java b/core/src/main/java/org/apache/brooklyn/core/BrooklynVersion.java
index fc9556d..161eff0 100644
--- a/core/src/main/java/org/apache/brooklyn/core/BrooklynVersion.java
+++ b/core/src/main/java/org/apache/brooklyn/core/BrooklynVersion.java
@@ -46,6 +46,7 @@ import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.osgi.OsgiUtil;
 import org.apache.brooklyn.util.stream.Streams;
 import org.apache.brooklyn.util.text.Strings;
+import org.apache.brooklyn.util.text.VersionComparator;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Constants;
 import org.osgi.framework.FrameworkUtil;
@@ -155,7 +156,7 @@ public class BrooklynVersion implements BrooklynVersionService {
 
     @Override
     public boolean isSnapshot() {
-        return (getVersion().indexOf("-SNAPSHOT") >= 0);
+        return VersionComparator.isSnapshot(getVersion());
     }
 
     private void readPropertiesFromMavenResource(ClassLoader resourceLoader) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
index 9769f7e..c91b7cd 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
@@ -425,17 +425,25 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         return getFirstAsMap(itemDef, "brooklyn.catalog").orNull();        
     }
     
+    /** @deprecated since 0.12.0 - use {@link #getVersionedName(Map, boolean)} */
+    @Deprecated
     public static VersionedName getVersionedName(Map<?,?> catalogMetadata) {
+        return getVersionedName(catalogMetadata, true);
+    }
+    
+    public static VersionedName getVersionedName(Map<?,?> catalogMetadata, boolean required) {
         String version = getFirstAs(catalogMetadata, String.class, "version").orNull();
         String bundle = getFirstAs(catalogMetadata, String.class, "bundle").orNull();
         if (Strings.isBlank(bundle) && Strings.isBlank(version)) {
+            if (!required) return null;
             throw new IllegalStateException("Catalog BOM must define bundle and version");
         }
         if (Strings.isBlank(bundle)) {
+            if (!required) return null;
             throw new IllegalStateException("Catalog BOM must define bundle");
         }
         if (Strings.isBlank(version)) {
-            throw new IllegalStateException("Catalog BOM must define version");
+            throw new IllegalStateException("Catalog BOM must define version if bundle is defined");
         }
         return new VersionedName(bundle, Version.valueOf(version));
     }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
index 776894f..394814d 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
@@ -43,6 +43,7 @@ import org.apache.brooklyn.core.mgmt.ha.OsgiManager;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.rebind.RebindManagerImpl.RebindTracker;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
+import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
@@ -170,7 +171,7 @@ public class CatalogUtils {
                     new Object[] {managementContext, Joiner.on(", ").join(libraries)});
             Stopwatch timer = Stopwatch.createStarted();
             for (CatalogBundle bundleUrl : libraries) {
-                osgi.get().registerBundle(bundleUrl);
+                osgi.get().install(BasicManagedBundle.of(bundleUrl), null, true, false).get();
             }
             if (log.isDebugEnabled()) 
                 logDebugOrTraceIfRebinding(log, 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
new file mode 100644
index 0000000..0e069bd
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
@@ -0,0 +1,359 @@
+/*
+ * 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.core.mgmt.ha;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.apache.brooklyn.api.typereg.ManagedBundle;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
+import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult.ResultCode;
+import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.typereg.BasicManagedBundle;
+import org.apache.brooklyn.util.core.ResourceUtils;
+import org.apache.brooklyn.util.core.osgi.BundleMaker;
+import org.apache.brooklyn.util.core.osgi.Osgis;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.exceptions.ReferenceWithError;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.os.Os;
+import org.apache.brooklyn.util.osgi.VersionedName;
+import org.apache.brooklyn.util.stream.Streams;
+import org.apache.brooklyn.util.text.Strings;
+import org.apache.brooklyn.util.text.VersionComparator;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+import com.google.common.base.Objects;
+
+// package-private so we can move this one if/when we move OsgiManager
+class OsgiArchiveInstaller {
+
+    final private OsgiManager osgiManager;
+    private ManagedBundle suppliedKnownBundleMetadata;
+    private InputStream zipIn;
+    
+    private boolean loadCatalogBom;
+    private boolean force;
+    
+    private File zipFile;
+    private Manifest discoveredManifest;
+    private VersionedName discoveredBomVersionedName;
+    OsgiBundleInstallationResult result;
+    
+    private ManagedBundle inferredMetadata;
+    
+    OsgiArchiveInstaller(OsgiManager osgiManager, ManagedBundle knownBundleMetadata, InputStream zipIn) {
+        this.osgiManager = osgiManager;
+        this.suppliedKnownBundleMetadata = knownBundleMetadata;
+        this.zipIn = zipIn;
+    }
+
+    public void setLoadCatalogBom(boolean loadCatalogBom) {
+        this.loadCatalogBom = loadCatalogBom;
+    }
+    
+    public void setForce(boolean force) {
+        this.force = force;
+    }
+
+    private ManagementContextInternal mgmt() {
+        return (ManagementContextInternal) osgiManager.mgmt;
+    }
+    
+    private synchronized void init() {
+        if (result!=null) {
+            if (zipFile!=null || zipIn==null) return;
+            throw new IllegalStateException("This installer instance has already been used and the input stream discarded");
+        }
+        result = new OsgiBundleInstallationResult();
+        inferredMetadata = suppliedKnownBundleMetadata==null ? new BasicManagedBundle() : suppliedKnownBundleMetadata;
+    }
+    
+    private synchronized void makeLocalZipFileFromInputStreamOrUrl() {
+        if (zipIn==null) {
+            Maybe<Bundle> installedBundle = Maybe.absent();
+            if (suppliedKnownBundleMetadata!=null) {
+                // if no input stream, look for a URL and/or a matching bundle
+                if (installedBundle.isAbsent() && suppliedKnownBundleMetadata.getOsgiUniqueUrl()!=null) {
+                    installedBundle = Osgis.bundleFinder(osgiManager.framework).requiringFromUrl(suppliedKnownBundleMetadata.getOsgiUniqueUrl()).find();
+                }
+                if (installedBundle.isAbsent() && suppliedKnownBundleMetadata.getUrl()!=null) {
+                    installedBundle = Osgis.bundleFinder(osgiManager.framework).requiringFromUrl(suppliedKnownBundleMetadata.getUrl()).find();
+                }
+                if (installedBundle.isAbsent() && suppliedKnownBundleMetadata.isNameResolved()) {
+                    installedBundle = Osgis.bundleFinder(osgiManager.framework).symbolicName(suppliedKnownBundleMetadata.getSymbolicName()).version(suppliedKnownBundleMetadata.getVersion()).find();
+                }
+                if (suppliedKnownBundleMetadata.getUrl()!=null) {
+                    if (installedBundle.isAbsent() || force) {
+                        // reload 
+                        zipIn = ResourceUtils.create(mgmt()).getResourceFromUrl(suppliedKnownBundleMetadata.getUrl());
+                    }
+                }
+            }
+            
+            if (installedBundle.isPresent()) {
+                result.bundle = installedBundle.get();
+                
+                if (zipIn==null) {
+                    // no way to install (no url), or no need to install (not forced); just ignore it
+                    result.metadata = osgiManager.getManagedBundle(new VersionedName(installedBundle.get()));
+                    result.setIgnoringAlreadyInstalled();
+                    return;
+                }
+            } else {
+                result.metadata = suppliedKnownBundleMetadata;
+                throw new IllegalArgumentException("No input stream available and no URL could be found; nothing to install");
+            }
+        }
+        
+        zipFile = Os.newTempFile("brooklyn-bundle-transient-"+suppliedKnownBundleMetadata, "zip");
+        try {
+            FileOutputStream fos = new FileOutputStream(zipFile);
+            Streams.copy(zipIn, fos);
+            zipIn.close();
+            fos.close();
+        } catch (Exception e) {
+            throw Exceptions.propagate(e);
+        } finally {
+            zipIn = null;
+        }
+    }
+
+    private void discoverManifestFromCatalogBom(boolean isCatalogBomRequired) {
+        discoveredManifest = new BundleMaker(mgmt()).getManifest(zipFile);
+        ZipFile zf = null;
+        try {
+            try {
+                zf = new ZipFile(zipFile);
+            } catch (IOException e) {
+                throw new IllegalArgumentException("Invalid ZIP/JAR archive: "+e);
+            }
+            ZipEntry bom = zf.getEntry("catalog.bom");
+            if (bom==null) {
+                bom = zf.getEntry("/catalog.bom");
+            }
+            if (bom==null) {
+                if (isCatalogBomRequired) {
+                    throw new IllegalArgumentException("Archive must contain a catalog.bom file in the root");
+                } else {
+                    return;
+                }
+            }
+            String bomS;
+            try {
+                bomS = Streams.readFullyString(zf.getInputStream(bom));
+            } catch (IOException e) {
+                throw new IllegalArgumentException("Error reading catalog.bom from ZIP/JAR archive: "+e);
+            }
+            discoveredBomVersionedName = BasicBrooklynCatalog.getVersionedName( BasicBrooklynCatalog.getCatalogMetadata(bomS), false );
+        } finally {
+            Streams.closeQuietly(zf);
+        }
+    }
+    
+    private void updateManifestFromAllSourceInformation() {
+        if (discoveredBomVersionedName!=null) {
+            matchSetOrFail("catalog.bom in archive", discoveredBomVersionedName.getSymbolicName(), discoveredBomVersionedName.getVersion().toString());
+        }
+        
+        boolean manifestNeedsUpdating = false;
+        if (discoveredManifest==null) {
+            discoveredManifest = new Manifest();
+            manifestNeedsUpdating = true;
+        }
+        if (!matchSetOrFail("MANIFEST.MF in archive", discoveredManifest.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME),
+                discoveredManifest.getMainAttributes().getValue(Constants.BUNDLE_VERSION) )) {
+            manifestNeedsUpdating = true;                
+            discoveredManifest.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, inferredMetadata.getSymbolicName());
+            discoveredManifest.getMainAttributes().putValue(Constants.BUNDLE_VERSION, inferredMetadata.getVersion());
+        }
+        if (Strings.isBlank(inferredMetadata.getSymbolicName())) {
+            throw new IllegalArgumentException("Missing bundle symbolic name in BOM or MANIFEST");
+        }
+        if (Strings.isBlank(inferredMetadata.getVersion())) {
+            throw new IllegalArgumentException("Missing bundle version in BOM or MANIFEST");
+        }
+        if (discoveredManifest.getMainAttributes().getValue(Attributes.Name.MANIFEST_VERSION)==null) {
+            discoveredManifest.getMainAttributes().putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
+            manifestNeedsUpdating = true;                
+        }
+        if (manifestNeedsUpdating) {
+            File zf2 = new BundleMaker(mgmt()).copyAddingManifest(zipFile, discoveredManifest);
+            zipFile.delete();
+            zipFile = zf2;
+        }
+    }
+    
+    private synchronized void close() {
+        if (zipFile!=null) {
+            zipFile.delete();
+            zipFile = null;
+        }
+    }
+    
+    /**
+     * Installs a bundle, taking from ZIP input stream if supplied, falling back to URL in the {@link ManagedBundle} metadata supplied.
+     * It will take metadata from any of: a MANIFEST.MF in the ZIP; a catalog.bom in the ZIP; the {@link ManagedBundle} metadata supplied.
+     * If metadata is supplied in multiple such places, it must match.
+     * Appropriate metadata will be added to the ZIP and installation attempted.
+     * <p>
+     * If a matching bundle is already installed, the installation will stop with a {@link ResultCode#IGNORING_BUNDLE_AREADY_INSTALLED}
+     * unless the bundle is a snapshot or "force" is specified.
+     * In the latter two cases, if there is an installed matching bundle, that bundle will be updated with the input stream here,
+     * with any catalog items from the old bundle removed and those from this bundle installed.
+     * <p>
+     * Default behaviour is {@link #setLoadCatalogBom(boolean)} true and {@link #setForce(boolean)} false.
+     * <p>
+     * The return value is extensive but should be self-evident, and will include a list of any registered types (catalog items) installed. 
+     */
+    public ReferenceWithError<OsgiBundleInstallationResult> install() {
+        boolean startedInstallation = false;
+        
+        try {
+            init();
+            makeLocalZipFileFromInputStreamOrUrl();
+            if (result.code!=null) return ReferenceWithError.newInstanceWithoutError(result);
+            discoverManifestFromCatalogBom(false);
+            if (result.code!=null) return ReferenceWithError.newInstanceWithoutError(result);
+            updateManifestFromAllSourceInformation();
+            if (result.code!=null) return ReferenceWithError.newInstanceWithoutError(result);
+            assert inferredMetadata.isNameResolved() : "Should have resolved "+inferredMetadata;
+
+            Boolean updating = null;
+            result.metadata = osgiManager.getManagedBundle(inferredMetadata.getVersionedName());
+            if (result.getMetadata()!=null) {
+                // already have a managed bundle
+                if (canUpdate()) { 
+                    result.bundle = osgiManager.framework.getBundleContext().getBundle(result.getMetadata().getOsgiUniqueUrl());
+                    if (result.getBundle()==null) {
+                        throw new IllegalStateException("Detected already managing bundle "+result.getMetadata().getVersionedName()+" but framework cannot find it");
+                    }
+                    updating = true;
+                } else {
+                    result.setIgnoringAlreadyInstalled();
+                    return ReferenceWithError.newInstanceWithoutError(result);
+                }
+            } else {
+                result.metadata = inferredMetadata;
+                // no such managed bundle
+                Maybe<Bundle> b = Osgis.bundleFinder(osgiManager.framework).symbolicName(result.getMetadata().getSymbolicName()).version(result.getMetadata().getVersion()).find();
+                if (b.isPresent()) {
+                    // if it's non-brooklyn installed then fail
+                    // (e.g. someone trying to install brooklyn or guice through this mechanism!)
+                    result.bundle = b.get();
+                    result.code = OsgiBundleInstallationResult.ResultCode.ERROR_INSTALLING_BUNDLE;
+                    throw new IllegalStateException("Bundle "+result.getMetadata().getVersionedName()+" already installed in framework but not managed by Brooklyn; cannot install or update through Brooklyn");
+                }
+                // normal install
+                updating = false;
+            }
+            
+            startedInstallation = true;
+            try (InputStream fin = new FileInputStream(zipFile)) {
+                if (!updating) {
+                    // install new
+                    assert result.getBundle()==null;
+                    result.bundle = osgiManager.framework.getBundleContext().installBundle(result.getMetadata().getOsgiUniqueUrl(), fin);
+                } else {
+                    result.bundle.update(fin);
+                }
+            }
+            
+            osgiManager.checkCorrectlyInstalled(result.getMetadata(), result.bundle);
+            ((BasicManagedBundle)result.getMetadata()).setTempLocalFileWhenJustUploaded(zipFile);
+            zipFile = null; // don't close/delete it here, we'll use it for uploading, then it will delete it
+            
+            if (!updating) { 
+                synchronized (osgiManager.managedBundles) {
+                    osgiManager.managedBundles.put(result.getMetadata().getId(), result.getMetadata());
+                    osgiManager.managedBundleIds.put(result.getMetadata().getVersionedName(), result.getMetadata().getId());
+                }
+                result.code = OsgiBundleInstallationResult.ResultCode.INSTALLED_NEW_BUNDLE;
+                result.message = "Installed "+result.getMetadata().getVersionedName()+" with ID "+result.getMetadata().getId();
+                mgmt().getRebindManager().getChangeListener().onManaged(result.getMetadata());
+            } else {
+                result.code = OsgiBundleInstallationResult.ResultCode.UPDATED_EXISTING_BUNDLE;
+                result.message = "Updated "+result.getMetadata().getVersionedName()+" as existing ID "+result.getMetadata().getId();
+                mgmt().getRebindManager().getChangeListener().onChanged(result.getMetadata());
+            }
+            // setting the above before the code below means if there is a problem starting or loading catalog items
+            // a user has to remove then add again, or forcibly reinstall;
+            // that seems fine and probably better than allowing bundles to start and catalog items to be installed 
+            // when brooklyn isn't aware it is supposed to be managing it
+            
+            // starting here  flags wiring issues earlier
+            // but may break some things running from the IDE
+            result.bundle.start();
+
+            if (updating!=null) {
+                osgiManager.uninstallCatalogItemsFromBundle( result.getVersionedName() );
+                // (ideally removal and addition would be atomic)
+            }
+            if (loadCatalogBom) {
+                osgiManager.loadCatalogBom(result.bundle);
+            }
+
+            return ReferenceWithError.newInstanceWithoutError(result);
+            
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            result.code = startedInstallation ? OsgiBundleInstallationResult.ResultCode.ERROR_INSTALLING_BUNDLE : OsgiBundleInstallationResult.ResultCode.ERROR_PREPARING_BUNDLE;
+            result.message = "Bundle "+inferredMetadata+" failed "+
+                (startedInstallation ? "installation" : "preparation") + ": " + Exceptions.collapseText(e);
+            return ReferenceWithError.newInstanceThrowingError(result, new IllegalStateException(result.message, e));
+        } finally {
+            close();
+        }
+    }
+
+    private boolean canUpdate() {
+        return force || VersionComparator.isSnapshot(inferredMetadata.getVersion());
+    }
+
+    /** true if the supplied name and version are complete; updates if the known data is incomplete;
+     * throws if there is a mismatch; false if the supplied data is incomplete */
+    private boolean matchSetOrFail(String source, String name, String version) {
+        boolean suppliedIsComplete = true;
+        if (Strings.isBlank(name)) {
+            suppliedIsComplete = false;
+        } else if (Strings.isBlank(inferredMetadata.getSymbolicName())) {
+            ((BasicManagedBundle)inferredMetadata).setSymbolicName(name);
+        } else if (!Objects.equal(inferredMetadata.getSymbolicName(), name)){
+            throw new IllegalArgumentException("Symbolic name mismatch '"+name+"' from "+source+" (expected '"+inferredMetadata.getSymbolicName()+"')");
+        }
+        
+        if (Strings.isBlank(version)) {
+            suppliedIsComplete = false;
+        } else if (Strings.isBlank(inferredMetadata.getVersion())) {
+            ((BasicManagedBundle)inferredMetadata).setVersion(version);
+        } else if (!Objects.equal(inferredMetadata.getVersion(), version)){
+            throw new IllegalArgumentException("Bundle version mismatch '"+version+"' from "+source+" (expected '"+inferredMetadata.getVersion()+"')");
+        }
+        
+        return suppliedIsComplete;
+    }    
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiBundleInstallationResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiBundleInstallationResult.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiBundleInstallationResult.java
new file mode 100644
index 0000000..50ca081
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiBundleInstallationResult.java
@@ -0,0 +1,71 @@
+/*
+ * 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.core.mgmt.ha;
+
+import java.util.List;
+
+import org.apache.brooklyn.api.typereg.ManagedBundle;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.osgi.VersionedName;
+import org.osgi.framework.Bundle;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+
+@Beta
+public class OsgiBundleInstallationResult {
+    String message;
+    ManagedBundle metadata;
+    Bundle bundle;
+    ResultCode code;
+    
+    public enum ResultCode { 
+        INSTALLED_NEW_BUNDLE,
+        UPDATED_EXISTING_BUNDLE, 
+        IGNORING_BUNDLE_AREADY_INSTALLED, 
+        ERROR_PREPARING_BUNDLE,
+        ERROR_INSTALLING_BUNDLE 
+    }
+    final List<String> catalogItemsInstalled = MutableList.of();
+    
+    public String getMessage() {
+        return message;
+    }
+    public Bundle getBundle() {
+        return bundle;
+    }
+    public ManagedBundle getMetadata() {
+        return metadata;
+    }
+    public ResultCode getCode() {
+        return code;
+    }
+    public List<String> getCatalogItemsInstalled() {
+        return ImmutableList.copyOf(catalogItemsInstalled);
+    }
+    public VersionedName getVersionedName() {
+        if (getMetadata()==null) return null;
+        return getMetadata().getVersionedName();
+    }
+    
+    void setIgnoringAlreadyInstalled() {
+        code = OsgiBundleInstallationResult.ResultCode.IGNORING_BUNDLE_AREADY_INSTALLED;
+        message = "Bundle "+getMetadata().getVersionedName()+" already installed as "+getMetadata().getId();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
index 17d5645..1685541 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
@@ -19,8 +19,6 @@
 package org.apache.brooklyn.core.mgmt.ha;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.InputStream;
 import java.net.URL;
 import java.util.Arrays;
@@ -33,6 +31,8 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
+import javax.annotation.Nullable;
+
 import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
@@ -47,7 +47,6 @@ import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.mgmt.persist.OsgiClassPrefixer;
 import org.apache.brooklyn.core.server.BrooklynServerConfig;
 import org.apache.brooklyn.core.server.BrooklynServerPaths;
-import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.collections.MutableSet;
@@ -55,13 +54,13 @@ import org.apache.brooklyn.util.core.osgi.Osgis;
 import org.apache.brooklyn.util.core.osgi.Osgis.BundleFinder;
 import org.apache.brooklyn.util.core.osgi.SystemFrameworkLoader;
 import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.exceptions.ReferenceWithError;
 import org.apache.brooklyn.util.exceptions.UserFacingException;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.os.Os;
 import org.apache.brooklyn.util.os.Os.DeletionResult;
 import org.apache.brooklyn.util.osgi.VersionedName;
 import org.apache.brooklyn.util.repeat.Repeater;
-import org.apache.brooklyn.util.stream.Streams;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.time.Duration;
 import org.osgi.framework.Bundle;
@@ -96,18 +95,18 @@ public class OsgiManager {
     
     /* see `Osgis` class for info on starting framework etc */
     
-    protected final ManagementContext mgmt;
-    protected final OsgiClassPrefixer osgiClassPrefixer;
-    protected Framework framework;
-    protected boolean reuseFramework;
+    final ManagementContext mgmt;
+    final OsgiClassPrefixer osgiClassPrefixer;
+    Framework framework;
+    
+    private boolean reuseFramework;
     private Set<Bundle> bundlesAtStartup;
-    protected File osgiCacheDir;
-    protected Map<String, ManagedBundle> managedBundles = MutableMap.of();
-    protected Map<VersionedName, String> managedBundleIds = MutableMap.of();
-    protected AtomicInteger numberOfReusableFrameworksCreated = new AtomicInteger();
-
+    private File osgiCacheDir;
+    Map<String, ManagedBundle> managedBundles = MutableMap.of();
+    Map<VersionedName, String> managedBundleIds = MutableMap.of();
     
-    protected static final List<Framework> OSGI_FRAMEWORK_CONTAINERS_FOR_REUSE = MutableList.of();
+    private static AtomicInteger numberOfReusableFrameworksCreated = new AtomicInteger();
+    private static final List<Framework> OSGI_FRAMEWORK_CONTAINERS_FOR_REUSE = MutableList.of();
     
     public OsgiManager(ManagementContext mgmt) {
         this.mgmt = mgmt;
@@ -230,76 +229,21 @@ public class OsgiManager {
         }
     }
 
-    public Bundle installUploadedBundle(ManagedBundle bundleMetadata, InputStream zipIn, boolean loadCatalogBom) {
-        try {
-            Bundle alreadyBundle = checkBundleInstalledThrowIfInconsistent(bundleMetadata, false);
-            if (alreadyBundle!=null) {
-                return alreadyBundle;
-            }
-
-            File zipF = Os.newTempFile("brooklyn-bundle-transient-"+bundleMetadata, "zip");
-            FileOutputStream fos = new FileOutputStream(zipF);
-            Streams.copy(zipIn, fos);
-            zipIn.close();
-            fos.close();
-            
-            ManagedBundle existingBundleToUpdate = null;
-            synchronized (managedBundles) {
-                String id = managedBundleIds.get(bundleMetadata.getVersionedName());
-                if (id!=null) {
-                    existingBundleToUpdate = managedBundles.get(id); 
-                }
-            }
-            
-            Bundle bundleInstalled;
-            if (existingBundleToUpdate==null) {
-                // install new
-                bundleInstalled = framework.getBundleContext().installBundle(bundleMetadata.getOsgiUniqueUrl(), 
-                    new FileInputStream(zipF));
-            } else {
-                // update
-                bundleInstalled = framework.getBundleContext().getBundle(existingBundleToUpdate.getOsgiUniqueUrl());
-                if (bundleInstalled==null) {
-                    throw new IllegalStateException("Detected bundle "+existingBundleToUpdate+" should be installed but framework cannot find it");
-                }
-                try (InputStream fin = new FileInputStream(zipF)) {
-                    bundleInstalled.update(fin);
-                }
-                bundleMetadata = existingBundleToUpdate;
-            }
-            checkCorrectlyInstalled(bundleMetadata, bundleInstalled);
-            if (!bundleMetadata.isNameResolved()) {
-                ((BasicManagedBundle)bundleMetadata).setSymbolicName(bundleInstalled.getSymbolicName());
-                ((BasicManagedBundle)bundleMetadata).setVersion(bundleInstalled.getVersion().toString());
-            }
-            ((BasicManagedBundle)bundleMetadata).setTempLocalFileWhenJustUploaded(zipF);
-            
-            synchronized (managedBundles) {
-                managedBundles.put(bundleMetadata.getId(), bundleMetadata);
-                managedBundleIds.put(bundleMetadata.getVersionedName(), bundleMetadata.getId());
-            }
-            mgmt.getRebindManager().getChangeListener().onChanged(bundleMetadata);
-            
-            // starting here  flags wiring issues earlier
-            // but may break some things running from the IDE
-            bundleInstalled.start();
-
-            if (existingBundleToUpdate!=null) {
-                // TODO remove old catalog items (see below)
-                // (ideally the removal and addition would be atomic)
-            }
-            if (loadCatalogBom) {
-                loadCatalogBom(bundleInstalled);
-            }
-            
-            return bundleInstalled;
-        } catch (Exception e) {
-            Exceptions.propagateIfFatal(e);
-            throw new IllegalStateException("Bundle "+bundleMetadata+" failed to install: " + Exceptions.collapseText(e), e);
-        }
+    /** See {@link OsgiArchiveInstaller#install()}, using default values */
+    public ReferenceWithError<OsgiBundleInstallationResult> install(InputStream zipIn) {
+        return install(null, zipIn, true, false);
     }
     
-    
+    /** See {@link OsgiArchiveInstaller#install()} */
+    public ReferenceWithError<OsgiBundleInstallationResult> install(@Nullable ManagedBundle knownBundleMetadata, @Nullable InputStream zipIn,
+            boolean loadCatalogBom, boolean forceUpdateOfNonSnapshots) {
+        
+        OsgiArchiveInstaller installer = new OsgiArchiveInstaller(this, knownBundleMetadata, zipIn);
+        installer.setLoadCatalogBom(loadCatalogBom);
+        installer.setForce(forceUpdateOfNonSnapshots);
+        
+        return installer.install();
+    }
     
     /**
      * Removes this bundle from Brooklyn management, 
@@ -321,12 +265,8 @@ public class OsgiManager {
             managedBundleIds.remove(bundleMetadata.getVersionedName());
         }
         mgmt.getRebindManager().getChangeListener().onUnmanaged(bundleMetadata);
-        
-        // uninstall things that come from this bundle
-        List<RegisteredType> thingsFromHere = ImmutableList.copyOf(getTypesFromBundle( bundleMetadata.getVersionedName() ));
-        for (RegisteredType t: thingsFromHere) {
-            mgmt.getCatalog().deleteCatalogItem(t.getSymbolicName(), t.getVersion());
-        }
+
+        uninstallCatalogItemsFromBundle( bundleMetadata.getVersionedName() );
         
         Bundle bundle = framework.getBundleContext().getBundle(bundleMetadata.getOsgiUniqueUrl());
         if (bundle==null) {
@@ -340,6 +280,13 @@ public class OsgiManager {
         }
     }
 
+    void uninstallCatalogItemsFromBundle(VersionedName bundle) {
+        List<RegisteredType> thingsFromHere = ImmutableList.copyOf(getTypesFromBundle( bundle ));
+        for (RegisteredType t: thingsFromHere) {
+            mgmt.getCatalog().deleteCatalogItem(t.getSymbolicName(), t.getVersion());
+        }
+    }
+
     protected Iterable<RegisteredType> getTypesFromBundle(final VersionedName vn) {
         final String bundleId = vn.toString();
         return mgmt.getTypeRegistry().getMatching(new Predicate<RegisteredType>() {
@@ -350,8 +297,8 @@ public class OsgiManager {
         });
     }
     
-    // TODO DO on snapshot install, uninstall old equivalent snapshots (items in use might stay in use though?)
-    
+    /** @deprecated since 0.12.0 use {@link #install(ManagedBundle, InputStream, boolean, boolean)} */
+    @Deprecated
     public synchronized Bundle registerBundle(CatalogBundle bundleMetadata) {
         try {
             Bundle alreadyBundle = checkBundleInstalledThrowIfInconsistent(bundleMetadata, true);
@@ -402,7 +349,7 @@ public class OsgiManager {
         return catalogItems;
     }
     
-    private void checkCorrectlyInstalled(OsgiBundleWithUrl bundle, Bundle b) {
+    void checkCorrectlyInstalled(OsgiBundleWithUrl bundle, Bundle b) {
         String nv = b.getSymbolicName()+":"+b.getVersion().toString();
 
         if (!isBundleNameEqualOrAbsent(bundle, b)) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextImpl.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextImpl.java
index 1e9cbba..13c85f6 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextImpl.java
@@ -36,7 +36,7 @@ import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.sensor.Enricher;
 import org.apache.brooklyn.api.sensor.Feed;
 import org.apache.brooklyn.api.typereg.ManagedBundle;
-import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
+import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.util.collections.MutableMap;
 
 import com.google.common.collect.Maps;
@@ -91,7 +91,7 @@ public class RebindContextImpl implements RebindContext {
 
     // we don't track register/unregister of bundles; it isn't needed as it happens so early
     public void installBundle(ManagedBundle bundle, InputStream zipInput) {
-        ((LocalManagementContext)mgmt).getOsgiManager().get().installUploadedBundle(bundle, zipInput, true);
+        ((ManagementContextInternal)mgmt).getOsgiManager().get().install(bundle, zipInput, true, false).checkNoError();
     }
     
     public void unregisterPolicy(Policy policy) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
index 37e706f..4799c06 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.core.typereg;
 import java.io.File;
 import java.util.Map;
 
+import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
 import org.apache.brooklyn.api.mgmt.rebind.RebindSupport;
 import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
@@ -181,4 +182,8 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage
         throw new UnsupportedOperationException();
     }
 
+    public static ManagedBundle of(CatalogBundle bundleUrl) {
+        return new BasicManagedBundle(bundleUrl.getSymbolicName(), bundleUrl.getVersion(), bundleUrl.getUrl());
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/ApiError.java
----------------------------------------------------------------------
diff --git a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/ApiError.java b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/ApiError.java
index bec524b..a2a1834 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/ApiError.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/ApiError.java
@@ -72,6 +72,7 @@ public class ApiError implements Serializable {
     public static class Builder {
         private String message;
         private String details;
+        private Object data;
         private Integer errorCode;
 
         public Builder message(String message) {
@@ -80,7 +81,12 @@ public class ApiError implements Serializable {
         }
 
         public Builder details(String details) {
-            this.details = checkNotNull(details, "details");
+            this.details = details;
+            return this;
+        }
+
+        public Builder data(Object data) {
+            this.data = data;
             return this;
         }
 
@@ -111,7 +117,7 @@ public class ApiError implements Serializable {
         }
 
         public ApiError build() {
-            return new ApiError(message, details, errorCode);
+            return new ApiError(message, details, data, errorCode);
         }
 
         /** @deprecated since 0.7.0; use {@link #copy(ApiError)} */
@@ -136,18 +142,23 @@ public class ApiError implements Serializable {
 
     @JsonInclude(JsonInclude.Include.NON_EMPTY)
     private final String details;
+    
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private final Object data;
 
     @JsonInclude(JsonInclude.Include.NON_NULL)
     private final Integer error;
 
     public ApiError(String message) { this(message, null); }
-    public ApiError(String message, String details) { this(message, details, null); }
+    public ApiError(String message, String details) { this(message, details, null, null); }
     public ApiError(
             @JsonProperty("message") String message,
             @JsonProperty("details") String details,
+            @JsonProperty("data") Object data,
             @JsonProperty("error") Integer error) {
         this.message = checkNotNull(message, "message");
         this.details = details != null ? details : "";
+        this.data = data;
         this.error = error;
     }
 
@@ -159,6 +170,10 @@ public class ApiError implements Serializable {
         return details;
     }
 
+    public Object getData() {
+        return data;
+    }
+    
     public Integer getError() {
         return error;
     }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index d0f7270..7359e4d 100644
--- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@ -19,9 +19,6 @@
 package org.apache.brooklyn.rest.resources;
 
 import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
 import java.io.InputStreamReader;
 import java.net.URI;
 import java.util.ArrayList;
@@ -29,8 +26,6 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.jar.Attributes;
-import java.util.jar.Manifest;
 
 import javax.annotation.Nullable;
 import javax.ws.rs.core.MediaType;
@@ -44,8 +39,10 @@ import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
 import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.core.catalog.CatalogPredicates;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
@@ -54,8 +51,8 @@ import org.apache.brooklyn.core.catalog.internal.CatalogItemComparator;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.StringAndArgument;
+import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
-import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
 import org.apache.brooklyn.rest.api.CatalogApi;
 import org.apache.brooklyn.rest.domain.ApiError;
@@ -65,24 +62,16 @@ import org.apache.brooklyn.rest.domain.CatalogLocationSummary;
 import org.apache.brooklyn.rest.domain.CatalogPolicySummary;
 import org.apache.brooklyn.rest.filter.HaHotStateRequired;
 import org.apache.brooklyn.rest.transform.CatalogTransformer;
-import org.apache.brooklyn.rest.util.DefaultExceptionMapper;
 import org.apache.brooklyn.rest.util.WebResourceUtils;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.ResourceUtils;
-import org.apache.brooklyn.util.core.osgi.BundleMaker;
 import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.apache.brooklyn.util.os.Os;
-import org.apache.brooklyn.util.osgi.VersionedName;
-import org.apache.brooklyn.util.stream.Streams;
+import org.apache.brooklyn.util.exceptions.ReferenceWithError;
 import org.apache.brooklyn.util.text.StringPredicates;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.yaml.Yamls;
-import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
-import org.apache.commons.compress.archivers.zip.ZipFile;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -161,6 +150,29 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
         }
     }
 
+    public static class BundleInstallationRestResult {
+        String message;
+        ManagedBundle metadata;
+        
+        enum ResultCode { 
+            INSTALLED_NEW_BUNDLE,
+            UPDATED_EXISTING_BUNDLE, 
+            IGNORING_BUNDLE_AREADY_INSTALLED, 
+            ERROR_PREPARING_BUNDLE,
+            ERROR_INSTALLING_BUNDLE 
+        }
+        Map<String,Object> catalogItemsInstalled;
+        
+        public String getMessage() {
+            return message;
+        }
+        
+        public static BundleInstallationRestResult of(OsgiBundleInstallationResult result, ManagementContext mgmt) {
+            // TODO 
+            return null;
+        }
+    }
+    
     @Override
     @Beta
     public Response createFromArchive(byte[] zipInput) {
@@ -169,92 +181,15 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
                 Entitlements.getEntitlementContext().user());
         }
 
-        BundleMaker bm = new BundleMaker(mgmtInternal());
-        File f=null, f2=null;
-        try {
-            f = Os.newTempFile("brooklyn-posted-archive", "zip");
-            try {
-                Files.write(zipInput, f);
-            } catch (IOException e) {
-                Exceptions.propagate(e);
-            }
-            
-            ZipFile zf;
-            try {
-                zf = new ZipFile(f);
-            } catch (IOException e) {
-                throw new IllegalArgumentException("Invalid ZIP/JAR archive: "+e);
-            }
-            ZipArchiveEntry bom = zf.getEntry("catalog.bom");
-            if (bom==null) {
-                bom = zf.getEntry("/catalog.bom");
-            }
-            if (bom==null) {
-                throw new IllegalArgumentException("Archive must contain a catalog.bom file in the root");
-            }
-            String bomS;
-            try {
-                bomS = Streams.readFullyString(zf.getInputStream(bom));
-            } catch (IOException e) {
-                throw new IllegalArgumentException("Error reading catalog.bom from ZIP/JAR archive: "+e);
-            }
-
-            try {
-                zf.close();
-            } catch (IOException e) {
-                log.debug("Swallowed exception closing zipfile. Full error logged at trace: {}", e.getMessage());
-                log.trace("Exception closing zipfile", e);
-            }
-
-            VersionedName vn = BasicBrooklynCatalog.getVersionedName( BasicBrooklynCatalog.getCatalogMetadata(bomS) );
-            
-            Manifest mf = bm.getManifest(f);
-            if (mf==null) {
-                mf = new Manifest();
-            }
-            String bundleNameInMF = mf.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
-            if (Strings.isNonBlank(bundleNameInMF)) {
-                if (!bundleNameInMF.equals(vn.getSymbolicName())) {
-                    throw new IllegalArgumentException("JAR MANIFEST symbolic-name '"+bundleNameInMF+"' does not match '"+vn.getSymbolicName()+"' defined in BOM");
-                }
-            } else {
-                bundleNameInMF = vn.getSymbolicName();
-                mf.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, bundleNameInMF);
-            }
-            
-            String bundleVersionInMF = mf.getMainAttributes().getValue(Constants.BUNDLE_VERSION);
-            if (Strings.isNonBlank(bundleVersionInMF)) {
-                if (!bundleVersionInMF.equals(vn.getVersion().toString())) {
-                    throw new IllegalArgumentException("JAR MANIFEST version '"+bundleVersionInMF+"' does not match '"+vn.getVersion()+"' defined in BOM");
-                }
-            } else {
-                bundleVersionInMF = vn.getVersion().toString();
-                mf.getMainAttributes().putValue(Constants.BUNDLE_VERSION, bundleVersionInMF);
-            }
-            if (mf.getMainAttributes().getValue(Attributes.Name.MANIFEST_VERSION)==null) {
-                mf.getMainAttributes().putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
-            }
-            
-            f2 = bm.copyAddingManifest(f, mf);
-            
-            BasicManagedBundle bundleMetadata = new BasicManagedBundle(bundleNameInMF, bundleVersionInMF, null);
-            Bundle bundle;
-            try (FileInputStream f2in = new FileInputStream(f2)) {
-                bundle = ((ManagementContextInternal)mgmt()).getOsgiManager().get().installUploadedBundle(bundleMetadata, f2in, false);
-            } catch (Exception e) {
-                throw Exceptions.propagate(e);
-            }
-
-            Iterable<? extends CatalogItem<?, ?>> catalogItems = MutableList.copyOf( 
-                ((ManagementContextInternal)mgmt()).getOsgiManager().get().loadCatalogBom(bundle) );
-
-            return buildCreateResponse(catalogItems);
-        } catch (RuntimeException ex) {
-            throw WebResourceUtils.badRequest(ex);
-        } finally {
-            if (f!=null) f.delete();
-            if (f2!=null) f2.delete();
+        ReferenceWithError<OsgiBundleInstallationResult> result = ((ManagementContextInternal)mgmt()).getOsgiManager().get()
+            .install(new ByteArrayInputStream(zipInput));
+        
+        if (result.hasError()) {
+            return ApiError.builder().errorCode(Status.BAD_REQUEST).message(result.getWithoutError().getMessage())
+                .data(result).build().asJsonResponse();
         }
+
+        return Response.status(Status.CREATED).entity( BundleInstallationRestResult.of(result.get(), mgmt()) ).build();
     }
 
     private Response buildCreateResponse(Iterable<? extends CatalogItem<?, ?>> catalogItems) {
@@ -575,4 +510,4 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
         return result;
     }
 }
- 
\ No newline at end of file
+ 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/utils/common/src/main/java/org/apache/brooklyn/util/maven/MavenArtifact.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/maven/MavenArtifact.java b/utils/common/src/main/java/org/apache/brooklyn/util/maven/MavenArtifact.java
index b9de2f1..248b72e 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/maven/MavenArtifact.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/maven/MavenArtifact.java
@@ -26,6 +26,7 @@ import javax.annotation.Nullable;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.javalang.JavaClassNames;
 import org.apache.brooklyn.util.text.Strings;
+import org.apache.brooklyn.util.text.VersionComparator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -100,7 +101,7 @@ public class MavenArtifact {
     }
 
     public boolean isSnapshot() {
-        return getVersion().toUpperCase().contains("SNAPSHOT");
+        return VersionComparator.isSnapshot(getVersion());
     }
     
     /** @see #customFileNameAfterArtifactMarker */

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/utils/common/src/main/java/org/apache/brooklyn/util/text/VersionComparator.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/text/VersionComparator.java b/utils/common/src/main/java/org/apache/brooklyn/util/text/VersionComparator.java
index 94553b0..071f591 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/text/VersionComparator.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/text/VersionComparator.java
@@ -52,14 +52,19 @@ public class VersionComparator implements Comparator<String> {
         return INSTANCE;
     }
 
+    public static boolean isSnapshot(String version) {
+        if (version==null) return false;
+        return version.toUpperCase().contains(SNAPSHOT);
+    }
+    
     @Override
     public int compare(String v1, String v2) {
         if (v1==null && v2==null) return 0;
         if (v1==null) return -1;
         if (v2==null) return 1;
         
-        boolean isV1Snapshot = v1.toUpperCase().contains(SNAPSHOT);
-        boolean isV2Snapshot = v2.toUpperCase().contains(SNAPSHOT);
+        boolean isV1Snapshot = isSnapshot(v1);
+        boolean isV2Snapshot = isSnapshot(v2);
         if (isV1Snapshot == isV2Snapshot) {
             // if snapshot status is the same, look at dot-split parts first
             return compareDotSplitParts(splitOnDot(v1), splitOnDot(v2));

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/14524547/utils/common/src/test/java/org/apache/brooklyn/util/text/VersionComparatorTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/text/VersionComparatorTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/text/VersionComparatorTest.java
index 3a4a71c..6c65a8a 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/text/VersionComparatorTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/text/VersionComparatorTest.java
@@ -92,6 +92,13 @@ public class VersionComparatorTest {
         assertVersionOrder("0.10.0-SNAPSHOT", "0.10.0.SNAPSHOT", "0.10.0-GA", "0.10.0.GA", "0.10.0");
     }
     
+    @Test
+    public void testIsSnapshot() {
+        Assert.assertTrue(VersionComparator.isSnapshot("0.10.0-SNAPSHOT"));
+        Assert.assertTrue(VersionComparator.isSnapshot("0.10.0.snapshot"));
+        Assert.assertFalse(VersionComparator.isSnapshot("0.10.0"));
+    }
+    
     private static void assertVersionOrder(String v1, String v2, String ...otherVersions) {
         List<String> versions = MutableList.<String>of().append(v1, v2, otherVersions);
         


[09/17] brooklyn-server git commit: address PR comments - the straightforward ones

Posted by ge...@apache.org.
address PR comments - the straightforward ones


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

Branch: refs/heads/master
Commit: bb7c04dd1d49bdabdd76390bff0ee27b7ff1a62a
Parents: f562ce7
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Jun 5 11:05:00 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Jun 5 11:05:00 2017 +0100

----------------------------------------------------------------------
 .../brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java   | 14 +++++++++-----
 .../org/apache/brooklyn/core/mgmt/ha/OsgiManager.java |  8 ++++----
 .../brooklyn/rest/resources/CatalogResource.java      |  3 ++-
 3 files changed, 15 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bb7c04dd/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
index 4044f23..4088564 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
@@ -58,6 +58,10 @@ class OsgiArchiveInstaller {
 
     private static final Logger log = LoggerFactory.getLogger(OsgiArchiveInstaller.class);
     
+    // must be 1.0; see bottom of
+    // http://www.eclipse.org/virgo/documentation/virgo-documentation-3.7.0.M01/docs/virgo-user-guide/html/ch02s02.html
+    private static final String OSGI_MANIFEST_VERSION_VALUE = "1.0";
+
     final private OsgiManager osgiManager;
     private ManagedBundle suppliedKnownBundleMetadata;
     private InputStream zipIn;
@@ -161,11 +165,9 @@ class OsgiArchiveInstaller {
         }
         
         zipFile = Os.newTempFile("brooklyn-bundle-transient-"+suppliedKnownBundleMetadata, "zip");
-        try {
-            FileOutputStream fos = new FileOutputStream(zipFile);
+        try (FileOutputStream fos = new FileOutputStream(zipFile)) {
             Streams.copy(zipIn, fos);
             zipIn.close();
-            fos.close();
         } catch (Exception e) {
             throw Exceptions.propagate(e);
         } finally {
@@ -228,7 +230,7 @@ class OsgiArchiveInstaller {
             throw new IllegalArgumentException("Missing bundle version in BOM or MANIFEST");
         }
         if (discoveredManifest.getMainAttributes().getValue(Attributes.Name.MANIFEST_VERSION)==null) {
-            discoveredManifest.getMainAttributes().putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
+            discoveredManifest.getMainAttributes().putValue(Attributes.Name.MANIFEST_VERSION.toString(), OSGI_MANIFEST_VERSION_VALUE);
             manifestNeedsUpdating = true;                
         }
         if (manifestNeedsUpdating) {
@@ -333,7 +335,7 @@ class OsgiArchiveInstaller {
             if (!updating) { 
                 synchronized (osgiManager.managedBundles) {
                     osgiManager.managedBundles.put(result.getMetadata().getId(), result.getMetadata());
-                    osgiManager.managedBundlesByNam.put(result.getMetadata().getVersionedName(), result.getMetadata().getId());
+                    osgiManager.managedBundlesByName.put(result.getMetadata().getVersionedName(), result.getMetadata().getId());
                     if (Strings.isNonBlank(result.getMetadata().getUrl())) {
                         osgiManager.managedBundlesByUrl.put(result.getMetadata().getUrl(), result.getMetadata().getId());
                     }
@@ -346,6 +348,8 @@ class OsgiArchiveInstaller {
                 result.message = "Updated "+result.getMetadata().getVersionedName()+" as existing ID "+result.getMetadata().getId();
                 mgmt().getRebindManager().getChangeListener().onChanged(result.getMetadata());
             }
+            log.info(result.message);
+            
             // setting the above before the code below means if there is a problem starting or loading catalog items
             // a user has to remove then add again, or forcibly reinstall;
             // that seems fine and probably better than allowing bundles to start and catalog items to be installed 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bb7c04dd/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
index 9936ba9..6b9c526 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
@@ -103,7 +103,7 @@ public class OsgiManager {
     private Set<Bundle> bundlesAtStartup;
     private File osgiCacheDir;
     Map<String, ManagedBundle> managedBundles = MutableMap.of();
-    Map<VersionedName, String> managedBundlesByNam = MutableMap.of();
+    Map<VersionedName, String> managedBundlesByName = MutableMap.of();
     Map<String, String> managedBundlesByUrl = MutableMap.of();
     
     private static AtomicInteger numberOfReusableFrameworksCreated = new AtomicInteger();
@@ -220,13 +220,13 @@ public class OsgiManager {
 
     public String getManagedBundleId(VersionedName vn) {
         synchronized (managedBundles) {
-            return managedBundlesByNam.get(vn);
+            return managedBundlesByName.get(vn);
         }
     }
     
     public ManagedBundle getManagedBundle(VersionedName vn) {
         synchronized (managedBundles) {
-            return managedBundles.get(managedBundlesByNam.get(vn));
+            return managedBundles.get(managedBundlesByName.get(vn));
         }
     }
 
@@ -282,7 +282,7 @@ public class OsgiManager {
             if (metadata==null) {
                 throw new IllegalStateException("No such bundle registered: "+bundleMetadata);
             }
-            managedBundlesByNam.remove(bundleMetadata.getVersionedName());
+            managedBundlesByName.remove(bundleMetadata.getVersionedName());
             managedBundlesByUrl.remove(bundleMetadata.getUrl());
         }
         mgmt.getRebindManager().getChangeListener().onUnmanaged(bundleMetadata);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bb7c04dd/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index 730482a..57c4ead 100644
--- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@ -181,7 +181,8 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
                     //RegisteredType ci = mgmt.getTypeRegistry().get(id);
                     
                     CatalogItem<?, ?> ci = CatalogUtils.getCatalogItemOptionalVersion(mgmt, id);
-                    CatalogTransformer.catalogItemSummary(brooklynU, ci, ui.getBaseUriBuilder());
+                    CatalogItemSummary summary = CatalogTransformer.catalogItemSummary(brooklynU, ci, ui.getBaseUriBuilder());
+                    result.types.put(id, summary);
                 }
             }
             return result;


[15/17] brooklyn-server git commit: better detail in REST API response when posting ZIP

Posted by ge...@apache.org.
better detail in REST API response when posting ZIP

preserves backwards compatibility, adding a detail=true flag which gives richer info.
see extended comment in code.

also fixes bug where the added/changed items weren't actually listed,
and where it tried to return the full BasicManagedBundle when it just wants an ID.


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

Branch: refs/heads/master
Commit: 33d9fd63aae2f7da3b2467bba3e47df8269d5acd
Parents: e1b0be1
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Jun 5 13:58:56 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Jun 5 14:00:14 2017 +0100

----------------------------------------------------------------------
 .../apache/brooklyn/core/mgmt/ha/OsgiManager.java   |  7 +++----
 .../org/apache/brooklyn/rest/api/CatalogApi.java    | 16 ++++++++++++++--
 .../brooklyn/rest/resources/CatalogResource.java    | 12 ++++++------
 3 files changed, 23 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/33d9fd63/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
index 69021fe..2f61d16 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
@@ -372,12 +372,11 @@ public class OsgiManager {
     // possibly remove that other capability, so that bundles with BOMs _have_ to be installed via this method.
     // (load order gets confusing with auto-scanning...)
     public List<? extends CatalogItem<?,?>> loadCatalogBom(Bundle bundle) {
-        List<? extends CatalogItem<?, ?>> catalogItems = MutableList.of();
-        loadCatalogBom(mgmt, bundle, catalogItems);
-        return catalogItems;
+        return MutableList.copyOf(loadCatalogBom(mgmt, bundle));
     }
     
-    private static Iterable<? extends CatalogItem<?, ?>> loadCatalogBom(ManagementContext mgmt, Bundle bundle, Iterable<? extends CatalogItem<?, ?>> catalogItems) {
+    private static Iterable<? extends CatalogItem<?, ?>> loadCatalogBom(ManagementContext mgmt, Bundle bundle) {
+        Iterable<? extends CatalogItem<?, ?>> catalogItems = MutableList.of();
         if (!BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_LOAD_BUNDLE_CATALOG_BOM)) {
             // if the above feature is not enabled, let's do it manually (as a contract of this method)
             try {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/33d9fd63/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java
----------------------------------------------------------------------
diff --git a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java
index 972c2a6..fe2346f 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java
@@ -88,13 +88,22 @@ public interface CatalogApi {
             @Valid String yaml);
 
     @Beta
+    /* TODO the polymorphic return type dependent on 'detail' is ugly, 
+     * but we're stuck in this API because backwards compatibility expects the types map
+     * whereas typical usage wants more feedback. we should introduce a 
+     * /registry and/or /types and/or /bundles endpoint that always provides details
+     * (and an approach to handling types more aligned with BrooklynTypeRegistry and OSGi bundling).
+     * Not too concerned here as this method is beta and the above switch will probably naturally happen soon. 
+     * The main client who cares about this is the Go CLI. */
     @POST
     @Consumes({"application/x-zip", "application/x-jar"})
     @ApiOperation(
             value = "Add a catalog items (e.g. new type of entity, policy or location) by uploading a ZIP/JAR archive.",
             notes = "Accepts either an OSGi bundle JAR, or ZIP which will be turned into bundle JAR. Bother format must "
                     + "contain a catalog.bom at the root of the archive, which must contain the bundle and version key."
-                    + "Return value is map of ID to CatalogItemSummary.",
+                    + "Return value is map of ID to CatalogItemSummary unless detail=true is passed as a parameter in which "
+                    + "case the return value is a BundleInstallationRestResult map containing the types map in types along "
+                    + "with a message, bundle, and code.",
             response = String.class,
             hidden = true)
     @ApiResponses(value = {
@@ -106,7 +115,10 @@ public interface CatalogApi {
                     name = "archive",
                     value = "Bundle to install, in ZIP or JAR format, requiring catalog.bom containing bundle name and version",
                     required = true)
-            byte[] archive);
+            byte[] archive,
+            @ApiParam(name="detail", value="Provide a wrapping details map", required=false)
+            @QueryParam("detail") @DefaultValue("false")
+            boolean detail);
 
     @Beta
     @POST

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/33d9fd63/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index 57c4ead..612e2a0 100644
--- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@ -45,7 +45,6 @@ import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.policy.PolicySpec;
 import org.apache.brooklyn.api.sensor.Enricher;
 import org.apache.brooklyn.api.sensor.EnricherSpec;
-import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.core.catalog.CatalogPredicates;
 import org.apache.brooklyn.core.catalog.internal.CatalogItemComparator;
@@ -130,7 +129,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
             return createFromYaml(new String(item));
         }
         
-        return createFromArchive(item);
+        return createFromArchive(item, false);
     }
     
     @Override
@@ -159,7 +158,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
         // as Osgi result, but without bundle, and with maps of catalog items installed
         
         String message;
-        ManagedBundle metadata;
+        String bundle;
         OsgiBundleInstallationResult.ResultCode code;
         
         Map<String,Object> types;
@@ -172,7 +171,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
         public static BundleInstallationRestResult of(OsgiBundleInstallationResult in, ManagementContext mgmt, BrooklynRestResourceUtils brooklynU, UriInfo ui) {
             BundleInstallationRestResult result = new BundleInstallationRestResult();
             result.message = in.getMessage();
-            result.metadata = in.getMetadata();
+            result.bundle = in.getMetadata().getVersionedName().toString();
             result.code = in.getCode();
             if (in.getCatalogItemsInstalled()!=null) {
                 result.types = MutableMap.of();
@@ -191,7 +190,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     
     @Override
     @Beta
-    public Response createFromArchive(byte[] zipInput) {
+    public Response createFromArchive(byte[] zipInput, boolean detail) {
         if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.ROOT, null)) {
             throw WebResourceUtils.forbidden("User '%s' is not authorized to add catalog item",
                 Entitlements.getEntitlementContext().user());
@@ -205,7 +204,8 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
                 .data(BundleInstallationRestResult.of(result.getWithoutError(), mgmt(), brooklyn(), ui)).build().asJsonResponse();
         }
 
-        return Response.status(Status.CREATED).entity( BundleInstallationRestResult.of(result.get(), mgmt(), brooklyn(), ui) ).build();
+        BundleInstallationRestResult resultR = BundleInstallationRestResult.of(result.get(), mgmt(), brooklyn(), ui);
+        return Response.status(Status.CREATED).entity( detail ? resultR : resultR.types ).build();
     }
 
     private Response buildCreateResponse(Iterable<? extends CatalogItem<?, ?>> catalogItems) {


[13/17] brooklyn-server git commit: notes on containing bundle being a versioned name

Posted by ge...@apache.org.
notes on containing bundle being a versioned name


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

Branch: refs/heads/master
Commit: 5fad03d9770e339a94e1f554c60370315c580f0e
Parents: 7260bf9
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Jun 5 11:27:30 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Jun 5 11:27:30 2017 +0100

----------------------------------------------------------------------
 .../main/java/org/apache/brooklyn/api/typereg/RegisteredType.java | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/5fad03d9/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
index 8225187..0696dfc 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
@@ -38,6 +38,9 @@ public interface RegisteredType extends Identifiable {
     String getSymbolicName();
     String getVersion();
     /** Bundle in symbolicname:id format where this type is defined */
+    // TODO would prefer this to be VersionedName if/when everything comes from OSGi bundles
+    // unrevert 7260bf9cf3f3ebaaa790693e1b7217a81bef78a7 to start that, and adjust serialization
+    // as described in that commit message (supporting String in xstream serialization for VN)
     String getContainingBundle();
 
     Collection<OsgiBundleWithUrl> getLibraries();


[03/17] brooklyn-server git commit: basic support for uninstalling bundle, and sketch of reinstall

Posted by ge...@apache.org.
basic support for uninstalling bundle, and sketch of reinstall

doesn't yet remove catalog items, and no effort yet to test reinstall.
(need to record the defining bundle on registered types.)


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

Branch: refs/heads/master
Commit: bc11ab250efcf316c975edac85f4ffa1f6cb0c07
Parents: 5b6bf73
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed May 3 15:21:11 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Fri May 5 12:43:59 2017 +0100

----------------------------------------------------------------------
 .../brooklyn/api/typereg/ManagedBundle.java     |  3 +
 .../BrooklynComponentTemplateResolver.java      |  2 +
 .../CatalogOsgiVersionMoreEntityRebindTest.java | 69 +++++++++++++++
 .../CatalogOsgiVersionMoreEntityTest.java       |  1 +
 .../brooklyn/core/mgmt/ha/OsgiManager.java      | 91 ++++++++++++++++++--
 .../core/typereg/BasicManagedBundle.java        | 11 ++-
 6 files changed, 170 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bc11ab25/api/src/main/java/org/apache/brooklyn/api/typereg/ManagedBundle.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/ManagedBundle.java b/api/src/main/java/org/apache/brooklyn/api/typereg/ManagedBundle.java
index 4f975b7..66ca592 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/ManagedBundle.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/ManagedBundle.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.api.typereg;
 
 import org.apache.brooklyn.api.mgmt.rebind.Rebindable;
 import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.util.osgi.VersionedName;
 
 /** Describes an OSGi bundle which Brooklyn manages, including persisting */
 public interface ManagedBundle extends BrooklynObject, Rebindable, OsgiBundleWithUrl {
@@ -29,4 +30,6 @@ public interface ManagedBundle extends BrooklynObject, Rebindable, OsgiBundleWit
      * This typically includes the unique {@link #getId()} of this item. */
     String getOsgiUniqueUrl();
 
+    VersionedName getVersionedName();
+
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bc11ab25/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index 34f67c3..7e9b562 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -174,6 +174,8 @@ public class BrooklynComponentTemplateResolver {
                     // TODO propagate exception so we can provide better error messages
                     msgDetails = "The reference " + type + " looks like a URL (running the CAMP Brooklyn assembly-template instantiator) but couldn't load it (missing or invalid syntax?). " +
                             "It's also neither a catalog item nor a java type.";
+                } else if ("brooklyn".equals(proto)){
+                    msgDetails = "The reference " + type + " is not a registered catalog item nor a java type.";
                 } else {
                     msgDetails = "The reference " + type + " looks like a URL (running the CAMP Brooklyn assembly-template instantiator) but the protocol " +
                             proto + " isn't white listed (" + BrooklynCampConstants.YAML_URL_PROTOCOL_WHITELIST + "). " +

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bc11ab25/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
index a3ca51b..16814c0 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
@@ -30,6 +30,7 @@ import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.api.typereg.RegisteredType;
 import org.apache.brooklyn.camp.brooklyn.AbstractYamlRebindTest;
+import org.apache.brooklyn.core.effector.Effectors;
 import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.entity.StartableApplication;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
@@ -39,10 +40,13 @@ import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.entity.stock.BasicApplication;
 import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.test.support.TestResourceUnavailableException;
+import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.ClassLoaderUtils;
 import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.javalang.Reflections;
 import org.apache.brooklyn.util.osgi.OsgiTestResources;
+import org.apache.brooklyn.util.text.Strings;
+import org.osgi.framework.Bundle;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
@@ -198,4 +202,69 @@ public class CatalogOsgiVersionMoreEntityRebindTest extends AbstractYamlRebindTe
         Effector<?> newEffector = newEntity.getEntityType().getEffectorByName("myEffector").get();
         newEntity.invoke(newEffector, ImmutableMap.<String, Object>of()).get();
     }
+    
+    @Test
+    public void testClassAccessAfterUninstall() throws Exception {
+        TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), BROOKLYN_TEST_OSGI_MORE_ENTITIES_0_1_0_PATH);
+        
+        // install dependency
+        ((ManagementContextInternal)mgmt()).getOsgiManager().get().installUploadedBundle(new BasicManagedBundle(), 
+            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_OSGI_ENTITIES_URL), true);
+
+        // now the v2 bundle
+        BasicManagedBundle mb = new BasicManagedBundle();
+        Bundle b2a = ((ManagementContextInternal)mgmt()).getOsgiManager().get().installUploadedBundle(mb, 
+            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_URL), true);
+
+        Assert.assertEquals(mb.getVersionedName().toString(), BROOKLYN_TEST_MORE_ENTITIES_SYMBOLIC_NAME_FULL+":"+"0.2.0");
+        
+        String yaml = Strings.lines("name: simple-app-yaml",
+                "services:",
+                "- type: " + BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
+        Entity app = createAndStartApplication(yaml);
+        Entity more = Iterables.getOnlyElement( app.getChildren() );
+        
+        Assert.assertEquals(
+            more.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), MutableMap.of("name", "Bob")).get(),
+            "HI BOB FROM V2");
+        
+        ((ManagementContextInternal)mgmt()).getOsgiManager().get().uninstallUploadedBundle(mb);
+        Assert.assertEquals(b2a.getState(), Bundle.UNINSTALLED);
+
+        // can still call things
+        Assert.assertEquals(
+            more.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), MutableMap.of("name", "Claudia")).get(),
+            "HI CLAUDIA FROM V2");
+        
+        // but still uninstalled, and attempt to create makes error 
+        Assert.assertEquals(b2a.getState(), Bundle.UNINSTALLED);
+        try {
+            Entity app2 = createAndStartApplication(yaml);
+            Asserts.shouldHaveFailedPreviously("Expected deployment to fail after uninstall; instead got "+app2);
+        } catch (Exception e) {
+            // org.apache.brooklyn.util.exceptions.CompoundRuntimeException: Unable to instantiate item; 2 errors including: 
+            // Transformer for brooklyn-camp gave an error creating this plan: Transformer for catalog gave an error creating this plan: 
+            // Unable to instantiate org.apache.brooklyn.test.osgi.entities.more.MoreEntity; 
+            // 2 errors including: Error in definition of org.apache.brooklyn.test.osgi.entities.more.MoreEntity:0.12.0-SNAPSHOT: 
+            // Unable to create spec for type brooklyn:org.apache.brooklyn.test.osgi.entities.more.MoreEntity. 
+            // The reference brooklyn:org.apache.brooklyn.test.osgi.entities.more.MoreEntity looks like a URL 
+            // (running the CAMP Brooklyn assembly-template instantiator) but 
+            // the protocol brooklyn isn't white listed ([classpath, http, https]). 
+            // It's also neither a catalog item nor a java type.
+            // TODO different error after catalog item uninstalled
+            Asserts.expectedFailureContainsIgnoreCase(e, BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, "not", "registered");
+        }
+        
+        try {
+            StartableApplication app2 = rebind();
+            Asserts.shouldHaveFailedPreviously("Expected deployment to fail rebind; instead got "+app2);
+        } catch (Exception e) {
+            Asserts.expectedFailure(e);
+            // TODO should fail to rebind this app
+            // (currently fails to load the catalog item, since it wasn't removed)
+            // Asserts.expectedFailureContainsIgnoreCase(e, BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, "simple-app-yaml");
+        }
+    }
+    
+
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bc11ab25/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
index 118c518..5c28c8b 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -73,6 +73,7 @@ public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest implement
         Bundle b = ((ManagementContextInternal)mgmt()).getOsgiManager().get().installUploadedBundle(mb, 
             new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V1_URL), true);
         Assert.assertEquals(mb.getSymbolicName(), b.getSymbolicName());
+        Assert.assertEquals(mb.getVersion(), "0.1.0");
         
         // bundle installed
         Map<String, ManagedBundle> bundles = ((ManagementContextInternal)mgmt()).getOsgiManager().get().getManagedBundles();

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bc11ab25/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
index 6f6d230..a56bb52 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
@@ -58,6 +58,7 @@ import org.apache.brooklyn.util.exceptions.UserFacingException;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.os.Os;
 import org.apache.brooklyn.util.os.Os.DeletionResult;
+import org.apache.brooklyn.util.osgi.VersionedName;
 import org.apache.brooklyn.util.repeat.Repeater;
 import org.apache.brooklyn.util.stream.Streams;
 import org.apache.brooklyn.util.text.Strings;
@@ -100,6 +101,7 @@ public class OsgiManager {
     private Set<Bundle> bundlesAtStartup;
     protected File osgiCacheDir;
     protected Map<String, ManagedBundle> managedBundles = MutableMap.of();
+    protected Map<VersionedName, String> managedBundleIds = MutableMap.of();
     protected AtomicInteger numberOfReusableFrameworksCreated = new AtomicInteger();
 
     
@@ -209,9 +211,17 @@ public class OsgiManager {
     }
 
     public Map<String, ManagedBundle> getManagedBundles() {
-        return ImmutableMap.copyOf(managedBundles);
+        synchronized (managedBundles) {
+            return ImmutableMap.copyOf(managedBundles);
+        }
     }
-    
+
+    public String getManagedBundleId(VersionedName vn) {
+        synchronized (managedBundles) {
+            return managedBundleIds.get(vn);
+        }
+    }
+
     public Bundle installUploadedBundle(ManagedBundle bundleMetadata, InputStream zipIn, boolean loadCatalogBom) {
         try {
             Bundle alreadyBundle = checkBundleInstalledThrowIfInconsistent(bundleMetadata, false);
@@ -225,8 +235,30 @@ public class OsgiManager {
             zipIn.close();
             fos.close();
             
-            Bundle bundleInstalled = framework.getBundleContext().installBundle(bundleMetadata.getOsgiUniqueUrl(), 
-                new FileInputStream(zipF));
+            ManagedBundle existingBundleToUpdate = null;
+            synchronized (managedBundles) {
+                String id = managedBundleIds.get(bundleMetadata.getVersionedName());
+                if (id!=null) {
+                    existingBundleToUpdate = managedBundles.get(id); 
+                }
+            }
+            
+            Bundle bundleInstalled;
+            if (existingBundleToUpdate==null) {
+                // install new
+                bundleInstalled = framework.getBundleContext().installBundle(bundleMetadata.getOsgiUniqueUrl(), 
+                    new FileInputStream(zipF));
+            } else {
+                // update
+                bundleInstalled = framework.getBundleContext().getBundle(existingBundleToUpdate.getOsgiUniqueUrl());
+                if (bundleInstalled==null) {
+                    throw new IllegalStateException("Detected bundle "+existingBundleToUpdate+" should be installed but framework cannot find it");
+                }
+                try (InputStream fin = new FileInputStream(zipF)) {
+                    bundleInstalled.update(fin);
+                }
+                bundleMetadata = existingBundleToUpdate;
+            }
             checkCorrectlyInstalled(bundleMetadata, bundleInstalled);
             if (!bundleMetadata.isNameResolved()) {
                 ((BasicManagedBundle)bundleMetadata).setSymbolicName(bundleInstalled.getSymbolicName());
@@ -236,6 +268,7 @@ public class OsgiManager {
             
             synchronized (managedBundles) {
                 managedBundles.put(bundleMetadata.getId(), bundleMetadata);
+                managedBundleIds.put(bundleMetadata.getVersionedName(), bundleMetadata.getId());
             }
             mgmt.getRebindManager().getChangeListener().onChanged(bundleMetadata);
             
@@ -243,6 +276,10 @@ public class OsgiManager {
             // but may break some things running from the IDE
             bundleInstalled.start();
 
+            if (existingBundleToUpdate!=null) {
+                // TODO remove old catalog items (see below)
+                // (ideally the removal and addition would be atomic)
+            }
             if (loadCatalogBom) {
                 loadCatalogBom(bundleInstalled);
             }
@@ -254,8 +291,50 @@ public class OsgiManager {
         }
     }
     
-    // TODO uninstall bundle, and call change listener onRemoved ?
-    // TODO on snapshot install, uninstall old equivalent snapshots (items in use might stay in use though?)
+    /**
+     * Removes this bundle from Brooklyn management, 
+     * removes all catalog items it defined,
+     * and then uninstalls the bundle from OSGi.
+     * <p>
+     * No checking is done whether anything is using the bundle;
+     * behaviour of such things is not guaranteed. They will work for many things
+     * but attempts to load new classes may fail.
+     * <p>
+     * Callers should typically fail if anything from this bundle is in use.
+     */
+    public void uninstallUploadedBundle(ManagedBundle bundleMetadata) {
+        synchronized (managedBundles) {
+            ManagedBundle metadata = managedBundles.remove(bundleMetadata.getId());
+            if (metadata==null) {
+                throw new IllegalStateException("No such bundle registered: "+bundleMetadata);
+            }
+            managedBundleIds.remove(bundleMetadata.getVersionedName());
+        }
+        mgmt.getRebindManager().getChangeListener().onUnmanaged(bundleMetadata);
+        
+        // TODO uninstall things that come from this bundle
+//        mgmt.getTypeRegistry().getMatching(new Predicate<RegisteredType>() {
+//            @Override
+//            public boolean apply(RegisteredType input) {
+//                XXX;
+//                input.getLibraries();
+//                return false;
+//            }
+//        });
+        
+        Bundle bundle = framework.getBundleContext().getBundle(bundleMetadata.getOsgiUniqueUrl());
+        if (bundle==null) {
+            throw new IllegalStateException("No such bundle installed: "+bundleMetadata);
+        }
+        try {
+            bundle.stop();
+            bundle.uninstall();
+        } catch (BundleException e) {
+            throw Exceptions.propagate(e);
+        }
+    }
+    
+    // TODO DO on snapshot install, uninstall old equivalent snapshots (items in use might stay in use though?)
     
     public synchronized Bundle registerBundle(CatalogBundle bundleMetadata) {
         try {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/bc11ab25/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
index 1ee8aa5..37e706f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
@@ -28,6 +28,8 @@ import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.mgmt.rebind.BasicManagedBundleRebindSupport;
 import org.apache.brooklyn.core.objs.AbstractBrooklynObject;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
+import org.apache.brooklyn.util.osgi.VersionedName;
+import org.osgi.framework.Version;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.MoreObjects;
@@ -51,7 +53,8 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage
             Preconditions.checkNotNull(name, "Either a URL or both name and version are required");
             Preconditions.checkNotNull(version, "Either a URL or both name and version are required");
         }
-
+        Version.parseVersion(version);
+        
         this.symbolicName = name;
         this.version = version;
         this.url = url;
@@ -81,6 +84,12 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage
     }
     
     @Override
+    public VersionedName getVersionedName() {
+        if (symbolicName==null) return null;
+        return new VersionedName(symbolicName, Version.parseVersion(version));
+    }
+    
+    @Override
     public String getUrl() {
         return url;
     }


[08/17] brooklyn-server git commit: Merge branch 'master' into bundle-uninstall-and-snapshot

Posted by ge...@apache.org.
Merge branch 'master' into bundle-uninstall-and-snapshot

conflicts - imports (resolved), and osgi test jars (rebuilt)


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

Branch: refs/heads/master
Commit: f562ce72e2697155dc3cf6897b9bdb90d0768f3f
Parents: 71ede73 15447e1
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu May 11 13:25:46 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu May 11 13:25:46 2017 +0100

----------------------------------------------------------------------
 .../brooklyn/api/catalog/CatalogItem.java       |   5 +
 .../spi/creation/CampInternalUtils.java         |  52 +++++
 .../brooklyn/spi/creation/CampResolver.java     |   3 +
 .../spi/creation/CampTypePlanTransformer.java   |   1 +
 .../core/catalog/CatalogPredicates.java         |   4 +
 .../catalog/internal/BasicBrooklynCatalog.java  |   5 +
 .../catalog/internal/CatalogClasspathDo.java    |   8 +
 .../internal/CatalogEnricherItemDto.java        |  43 ++++
 .../catalog/internal/CatalogItemBuilder.java    |   7 +
 .../internal/JavaCatalogToSpecTransformer.java  |   6 +
 .../brooklyn/core/entity/AbstractEntity.java    |  65 +++---
 .../core/network/OnPublicNetworkEnricher.java   |   2 +
 .../core/network/OnSubnetNetworkEnricher.java   |   2 +
 .../brooklyn/core/sensor/AttributeMap.java      |  10 +
 .../core/typereg/RegisteredTypePredicates.java  |   2 +
 .../brooklyn/enricher/stock/Aggregator.java     |   3 +-
 .../brooklyn/enricher/stock/Combiner.java       |   3 +-
 .../apache/brooklyn/enricher/stock/Joiner.java  |   3 +-
 .../brooklyn/enricher/stock/MapAggregator.java  |   2 +
 .../enricher/stock/PercentageEnricher.java      |   2 +
 .../brooklyn/enricher/stock/Propagator.java     |   3 +-
 .../brooklyn/enricher/stock/Transformer.java    |   7 +-
 .../brooklyn/enricher/stock/UpdatingMap.java    |   2 +
 .../YamlRollingTimeWindowMeanEnricher.java      |   3 +
 .../stock/YamlTimeWeightedDeltaEnricher.java    |   2 +
 .../enricher/stock/reducer/Reducer.java         |   4 +-
 .../entity/group/AbstractGroupImpl.java         | 212 ++++++++++---------
 .../brooklyn/entity/group/DynamicCluster.java   |   2 +-
 core/src/main/resources/catalog.bom             |  60 +++++-
 .../internal/CatalogItemBuilderTest.java        |   7 +
 .../typereg/RegisteredTypePredicatesTest.java   |   3 +
 .../init/src/main/resources/catalog-classes.bom |  84 ++++++++
 .../brooklyn/policy/enricher/DeltaEnricher.java |   5 +-
 .../policy/enricher/HttpLatencyDetector.java    |   3 +-
 .../policy/enricher/RollingMeanEnricher.java    |   5 +-
 .../enricher/RollingTimeWindowMeanEnricher.java |   5 +-
 .../enricher/TimeFractionDeltaEnricher.java     |   5 +-
 .../enricher/TimeWeightedDeltaEnricher.java     |   7 +-
 .../policy/ha/ServiceFailureDetector.java       |   3 +-
 policy/src/main/resources/catalog.bom           |  30 +++
 .../apache/brooklyn/rest/api/CatalogApi.java    |  40 ++++
 .../rest/domain/CatalogEnricherSummary.java     |  80 +++++++
 .../rest/domain/EnricherConfigSummary.java      |  79 +++++++
 .../rest/resources/CatalogResource.java         |  55 ++++-
 .../rest/transform/CatalogTransformer.java      |  27 ++-
 .../rest/transform/EntityTransformer.java       |  10 +
 .../CatalogResourcePerformanceTest.java         |  15 +-
 .../rest/resources/CatalogResourceTest.java     |  99 +++++++++
 .../entity/AbstractMultiDistroLiveTest.java     |   8 +-
 .../entity/AbstractOpenstackLiveTest.java       |  33 +--
 .../test/osgi/entities/SimpleEnricher.java      |  42 ++++
 .../brooklyn/util/osgi/OsgiTestResources.java   |   1 +
 .../brooklyn-test-osgi-com-example-entities.jar | Bin 22138 -> 22139 bytes
 .../osgi/brooklyn-test-osgi-entities.jar        | Bin 22072 -> 22902 bytes
 .../brooklyn-test-osgi-more-entities_0.1.0.jar  | Bin 16003 -> 16003 bytes
 .../brooklyn-test-osgi-more-entities_0.2.0.jar  | Bin 16924 -> 16922 bytes
 ...-test-osgi-more-entities_evil-twin_0.2.0.jar | Bin 14099 -> 14098 bytes
 57 files changed, 998 insertions(+), 171 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f562ce72/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f562ce72/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f562ce72/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --cc rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index 76ebb63,7a7f7f7..730482a
--- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@@ -26,8 -29,11 +26,9 @@@ import java.util.Iterator
  import java.util.List;
  import java.util.Map;
  import java.util.Set;
 -import java.util.jar.Attributes;
 -import java.util.jar.Manifest;
  
  import javax.annotation.Nullable;
+ import javax.ws.rs.DefaultValue;
  import javax.ws.rs.core.MediaType;
  import javax.ws.rs.core.Response;
  import javax.ws.rs.core.Response.Status;
@@@ -39,21 -45,22 +40,24 @@@ import org.apache.brooklyn.api.entity.E
  import org.apache.brooklyn.api.entity.EntitySpec;
  import org.apache.brooklyn.api.location.Location;
  import org.apache.brooklyn.api.location.LocationSpec;
 +import org.apache.brooklyn.api.mgmt.ManagementContext;
  import org.apache.brooklyn.api.policy.Policy;
  import org.apache.brooklyn.api.policy.PolicySpec;
+ import org.apache.brooklyn.api.sensor.Enricher;
+ import org.apache.brooklyn.api.sensor.EnricherSpec;
 +import org.apache.brooklyn.api.typereg.ManagedBundle;
  import org.apache.brooklyn.api.typereg.RegisteredType;
  import org.apache.brooklyn.core.catalog.CatalogPredicates;
 -import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
  import org.apache.brooklyn.core.catalog.internal.CatalogItemComparator;
  import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
  import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
  import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.StringAndArgument;
 +import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
  import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 -import org.apache.brooklyn.core.typereg.BasicManagedBundle;
  import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
  import org.apache.brooklyn.rest.api.CatalogApi;
 +import org.apache.brooklyn.rest.domain.ApiError;
+ import org.apache.brooklyn.rest.domain.CatalogEnricherSummary;
  import org.apache.brooklyn.rest.domain.CatalogEntitySummary;
  import org.apache.brooklyn.rest.domain.CatalogItemSummary;
  import org.apache.brooklyn.rest.domain.CatalogLocationSummary;

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f562ce72/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f562ce72/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-com-example-entities.jar
----------------------------------------------------------------------
diff --cc utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-com-example-entities.jar
index 7180c4d,86dfd8b..51cf119
Binary files differ

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f562ce72/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar
----------------------------------------------------------------------
diff --cc utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar
index 681071c,4f00f80..6d0cf2d
Binary files differ

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f562ce72/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar
----------------------------------------------------------------------
diff --cc utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar
index d0504f0,9994cfb..84fc378
Binary files differ

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f562ce72/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
----------------------------------------------------------------------
diff --cc utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
index 872b412,3d1ce7b..24113f6
Binary files differ

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/f562ce72/utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar
----------------------------------------------------------------------
diff --cc utils/common/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_evil-twin_0.2.0.jar
index c777bfb,f00a115..21a114a
Binary files differ


[10/17] brooklyn-server git commit: utils for working with VersionedName better

Posted by ge...@apache.org.
utils for working with VersionedName better


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

Branch: refs/heads/master
Commit: 3cf028a6aa811696ddb60d3e55a746de4a40ff3d
Parents: bb7c04d
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Jun 5 11:23:23 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Jun 5 11:23:23 2017 +0100

----------------------------------------------------------------------
 .../coerce/CommonAdaptorTypeCoercions.java      |  2 +-
 .../brooklyn/util/osgi/VersionedName.java       |  7 ++++
 .../brooklyn/util/osgi/VersionedNameTest.java   | 43 ++++++++++++++++++++
 3 files changed, 51 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3cf028a6/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
index 03745e6..2bc2a98 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
@@ -41,8 +41,8 @@ import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.net.Cidr;
 import org.apache.brooklyn.util.net.Networking;
 import org.apache.brooklyn.util.net.UserAndHostAndPort;
-import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.text.StringEscapes.JavaStringEscapes;
+import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.time.Duration;
 import org.apache.brooklyn.util.time.Time;
 import org.apache.brooklyn.util.yaml.Yamls;

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3cf028a6/utils/common/src/main/java/org/apache/brooklyn/util/osgi/VersionedName.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/osgi/VersionedName.java b/utils/common/src/main/java/org/apache/brooklyn/util/osgi/VersionedName.java
index 2d89be2..5807904 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/osgi/VersionedName.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/osgi/VersionedName.java
@@ -76,4 +76,11 @@ public class VersionedName {
         return Objects.equal(symbolicName, o.symbolicName) && Objects.equal(version, o.version);
     }
 
+    public static VersionedName fromString(String nameOptionalColonVersion) {
+        if (nameOptionalColonVersion==null) return null;
+        int colon = nameOptionalColonVersion.indexOf(':');
+        if (colon<0) throw new IllegalArgumentException("Versioned name '"+nameOptionalColonVersion+"' must be of form 'name:version'");
+        return new VersionedName(nameOptionalColonVersion.substring(0, colon), Version.parseVersion(nameOptionalColonVersion.substring(colon+1)));
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3cf028a6/utils/common/src/test/java/org/apache/brooklyn/util/osgi/VersionedNameTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/osgi/VersionedNameTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/osgi/VersionedNameTest.java
new file mode 100644
index 0000000..c838258
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/osgi/VersionedNameTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 The Apache Software Foundation.
+ *
+ * Licensed 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.osgi;
+
+import org.apache.brooklyn.util.javalang.coerce.TypeCoercerExtensible;
+import org.osgi.framework.Version;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class VersionedNameTest {
+    
+    @Test
+    public void testVersionedNameFromString() {
+        VersionedName foo1 = new VersionedName("foo", new Version("1.0"));
+        Assert.assertEquals(foo1, VersionedName.fromString("foo:1.0"));
+        Assert.assertEquals(foo1, TypeCoercerExtensible.newDefault().coerce("foo:1.0", VersionedName.class));
+    }
+    
+    @Test(expectedExceptions=IllegalArgumentException.class)
+    public void testDoesNotAcceptInvalidVersions() {
+        Assert.assertEquals(new VersionedName("foo", new Version("1.0.0.alpha")), VersionedName.fromString("foo:1.0-alpha"));
+    }
+    
+    @Test
+    public void testManuallyCorrectingVersion() {
+        Assert.assertEquals(new VersionedName("foo", new Version("1.0.0.alpha")), VersionedName.fromString("foo:"+
+            OsgiUtils.toOsgiVersion("1.0-alpha")));
+    }
+
+}


[12/17] brooklyn-server git commit: Revert "record VersionedName instead of string for containing bundle, as per PR"

Posted by ge...@apache.org.
Revert "record VersionedName instead of string for containing bundle, as per PR"

This reverts commit f4205fde2c380a3193953c5305e398f974069111.

The "containingBundle" might, for a transitional period, need to support a reference to a catalog item instead of a bundle, in which case OSGi conventions might not be valid and we want this to be a string. TBC. Will add comment to that effect in the code shortly.

If/when reinstated we should also ensure the deserialization accepts strings (should probably also give a custom serializer so VersionedName is always written as a string to prevent bloat in the serialized format).


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

Branch: refs/heads/master
Commit: 7260bf9cf3f3ebaaa790693e1b7217a81bef78a7
Parents: f4205fd
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Jun 5 11:24:03 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Jun 5 11:24:03 2017 +0100

----------------------------------------------------------------------
 .../java/org/apache/brooklyn/api/catalog/CatalogItem.java     | 3 +--
 .../java/org/apache/brooklyn/api/typereg/RegisteredType.java  | 3 +--
 .../apache/brooklyn/core/catalog/internal/CatalogItemDo.java  | 3 +--
 .../core/catalog/internal/CatalogItemDtoAbstract.java         | 7 ++++---
 .../org/apache/brooklyn/core/typereg/BasicRegisteredType.java | 5 ++---
 .../org/apache/brooklyn/core/typereg/RegisteredTypes.java     | 4 +++-
 6 files changed, 12 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7260bf9c/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java b/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
index a9c93fa..f3440d9 100644
--- a/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
+++ b/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
@@ -38,7 +38,6 @@ import org.apache.brooklyn.api.policy.PolicySpec;
 import org.apache.brooklyn.api.sensor.Enricher;
 import org.apache.brooklyn.api.sensor.EnricherSpec;
 import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
-import org.apache.brooklyn.util.osgi.VersionedName;
 
 import com.google.common.annotations.Beta;
 
@@ -130,7 +129,7 @@ public interface CatalogItem<T,SpecT> extends BrooklynObject, Rebindable {
 
     public String getSymbolicName();
     
-    public VersionedName getContainingBundle();
+    public String getContainingBundle();
 
     public String getVersion();
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7260bf9c/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
index 8385355..8225187 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
@@ -26,7 +26,6 @@ import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.objs.BrooklynObject;
 import org.apache.brooklyn.api.objs.Identifiable;
 import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
-import org.apache.brooklyn.util.osgi.VersionedName;
 
 import com.google.common.annotations.Beta;
 
@@ -39,7 +38,7 @@ public interface RegisteredType extends Identifiable {
     String getSymbolicName();
     String getVersion();
     /** Bundle in symbolicname:id format where this type is defined */
-    VersionedName getContainingBundle();
+    String getContainingBundle();
 
     Collection<OsgiBundleWithUrl> getLibraries();
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7260bf9c/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
index 805513d..2c1bec6 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
@@ -31,7 +31,6 @@ import org.apache.brooklyn.api.mgmt.rebind.mementos.CatalogItemMemento;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
 import org.apache.brooklyn.core.relations.EmptyRelationSupport;
-import org.apache.brooklyn.util.osgi.VersionedName;
 
 import com.google.common.base.Preconditions;
 
@@ -200,7 +199,7 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObj
     }
     
     @Override
-    public VersionedName getContainingBundle() {
+    public String getContainingBundle() {
         return itemDto.getContainingBundle();
     }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7260bf9c/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
index 2fab74e..4644d8d 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
@@ -37,6 +37,7 @@ import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.core.flags.FlagUtils;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
 import org.apache.brooklyn.util.osgi.VersionedName;
+import org.apache.brooklyn.util.text.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -52,7 +53,7 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
 
     private @SetFromFlag String symbolicName;
     private @SetFromFlag String version = BasicBrooklynCatalog.NO_VERSION;
-    private @SetFromFlag VersionedName containingBundle;
+    private @SetFromFlag String containingBundle;
 
     private @SetFromFlag String displayName;
     private @SetFromFlag String description;
@@ -123,7 +124,7 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
     }
     
     @Override
-    public VersionedName getContainingBundle() {
+    public String getContainingBundle() {
         return containingBundle;
     }
 
@@ -354,7 +355,7 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
     }
 
     public void setContainingBundle(VersionedName versionedName) {
-        this.containingBundle = versionedName;
+        this.containingBundle = Strings.toString(versionedName);
     }
     
     protected void setDescription(String description) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7260bf9c/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
index 9251659..f345ec9 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
@@ -29,7 +29,6 @@ import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.javalang.JavaClassNames;
-import org.apache.brooklyn.util.osgi.VersionedName;
 
 import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableSet;
@@ -40,7 +39,7 @@ public class BasicRegisteredType implements RegisteredType {
     final RegisteredTypeKind kind;
     final String symbolicName;
     final String version;
-    VersionedName containingBundle;
+    String containingBundle;
     
     final List<OsgiBundleWithUrl> bundles = MutableList.of();
     String displayName;
@@ -86,7 +85,7 @@ public class BasicRegisteredType implements RegisteredType {
     }
     
     @Override
-    public VersionedName getContainingBundle() {
+    public String getContainingBundle() {
         return containingBundle;
     }
     

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7260bf9c/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
index acefe6b..72feedd 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
@@ -48,6 +48,7 @@ import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.guava.Maybe.Absent;
 import org.apache.brooklyn.util.text.NaturalOrderComparator;
+import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.text.VersionComparator;
 import org.apache.brooklyn.util.yaml.Yamls;
 import org.slf4j.Logger;
@@ -170,7 +171,8 @@ public class RegisteredTypes {
 
     @Beta
     public static RegisteredType setContainingBundle(RegisteredType type, @Nullable ManagedBundle bundle) {
-        ((BasicRegisteredType)type).containingBundle = bundle==null ? null : bundle.getVersionedName();
+        ((BasicRegisteredType)type).containingBundle =
+            bundle==null ? null : Strings.toString(bundle.getVersionedName());
         return type;
     }
 


[14/17] brooklyn-server git commit: synchronize osgi bundle managers inside dedicated package-private class

Posted by ge...@apache.org.
synchronize osgi bundle managers inside dedicated package-private class


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

Branch: refs/heads/master
Commit: e1b0be1847550a40e2fb853885fca35b09a03df2
Parents: 5fad03d
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Jun 5 11:52:47 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Jun 5 11:52:47 2017 +0100

----------------------------------------------------------------------
 .../core/mgmt/ha/OsgiArchiveInstaller.java      | 14 ++--
 .../brooklyn/core/mgmt/ha/OsgiManager.java      | 71 ++++++++++++++------
 2 files changed, 53 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e1b0be18/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
index 4088564..7d2267a 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
@@ -280,16 +280,16 @@ class OsgiArchiveInstaller {
             if (result.getMetadata()!=null) {
                 // already have a managed bundle - check if this is using a new/different URL
                 if (suppliedKnownBundleMetadata!=null && suppliedKnownBundleMetadata.getUrl()!=null) {
-                    String knownIdForThisUrl = osgiManager.managedBundlesByUrl.get(suppliedKnownBundleMetadata.getUrl());
+                    String knownIdForThisUrl = osgiManager.managedBundlesRecord.getManagedBundleIdFromUrl(suppliedKnownBundleMetadata.getUrl());
                     if (knownIdForThisUrl==null) {
                         // it's a new URL, but a bundle we already know about
                         log.warn("Request to install from "+suppliedKnownBundleMetadata.getUrl()+" which is not recognized but "+
                             "appears to match "+result.getMetadata()+"; now associating with the latter");
-                        osgiManager.managedBundlesByUrl.put(suppliedKnownBundleMetadata.getUrl(), result.getMetadata().getId());
+                        osgiManager.managedBundlesRecord.setManagedBundleUrl(suppliedKnownBundleMetadata.getUrl(), result.getMetadata().getId());
                     } else if (!knownIdForThisUrl.equals(result.getMetadata().getId())) {
                         log.warn("Request to install from "+suppliedKnownBundleMetadata.getUrl()+" which is associated to "+knownIdForThisUrl+" but "+
                             "appears to match "+result.getMetadata()+"; now associating with the latter");
-                        osgiManager.managedBundlesByUrl.put(suppliedKnownBundleMetadata.getUrl(), result.getMetadata().getId());
+                        osgiManager.managedBundlesRecord.setManagedBundleUrl(suppliedKnownBundleMetadata.getUrl(), result.getMetadata().getId());
                     }
                 }
                 if (canUpdate()) { 
@@ -333,13 +333,7 @@ class OsgiArchiveInstaller {
             zipFile = null; // don't close/delete it here, we'll use it for uploading, then it will delete it
             
             if (!updating) { 
-                synchronized (osgiManager.managedBundles) {
-                    osgiManager.managedBundles.put(result.getMetadata().getId(), result.getMetadata());
-                    osgiManager.managedBundlesByName.put(result.getMetadata().getVersionedName(), result.getMetadata().getId());
-                    if (Strings.isNonBlank(result.getMetadata().getUrl())) {
-                        osgiManager.managedBundlesByUrl.put(result.getMetadata().getUrl(), result.getMetadata().getId());
-                    }
-                }
+                osgiManager.managedBundlesRecord.addManagedBundle(result);
                 result.code = OsgiBundleInstallationResult.ResultCode.INSTALLED_NEW_BUNDLE;
                 result.message = "Installed "+result.getMetadata().getVersionedName()+" with ID "+result.getMetadata().getId();
                 mgmt().getRebindManager().getChangeListener().onManaged(result.getMetadata());

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e1b0be18/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
index 6b9c526..69021fe 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
@@ -102,9 +102,47 @@ public class OsgiManager {
     private boolean reuseFramework;
     private Set<Bundle> bundlesAtStartup;
     private File osgiCacheDir;
-    Map<String, ManagedBundle> managedBundles = MutableMap.of();
-    Map<VersionedName, String> managedBundlesByName = MutableMap.of();
-    Map<String, String> managedBundlesByUrl = MutableMap.of();
+    final ManagedBundlesRecord managedBundlesRecord = new ManagedBundlesRecord();
+    
+    static class ManagedBundlesRecord {
+        private Map<String, ManagedBundle> managedBundles = MutableMap.of();
+        private Map<VersionedName, String> managedBundlesByName = MutableMap.of();
+        private Map<String, String> managedBundlesByUrl = MutableMap.of();
+        
+        synchronized Map<String, ManagedBundle> getManagedBundles() {
+            return ImmutableMap.copyOf(managedBundles);
+        }
+
+        synchronized String getManagedBundleId(VersionedName vn) {
+            return managedBundlesByName.get(vn);
+        }
+
+        synchronized ManagedBundle getManagedBundle(VersionedName vn) {
+            return managedBundles.get(managedBundlesByName.get(vn));
+        }
+        
+        synchronized String getManagedBundleIdFromUrl(String url) {
+            return managedBundlesByUrl.get(url);
+        }
+        
+        synchronized ManagedBundle getManagedBundleFromUrl(String url) {
+            String id = getManagedBundleIdFromUrl(url);
+            if (id==null) return null;
+            return managedBundles.get(id);
+        }
+
+        synchronized void setManagedBundleUrl(String url, String id) {
+            managedBundlesByUrl.put(url, id);    
+        }
+        
+        synchronized void addManagedBundle(OsgiBundleInstallationResult result) {
+            managedBundles.put(result.getMetadata().getId(), result.getMetadata());
+            managedBundlesByName.put(result.getMetadata().getVersionedName(), result.getMetadata().getId());
+            if (Strings.isNonBlank(result.getMetadata().getUrl())) {
+                managedBundlesByUrl.put(result.getMetadata().getUrl(), result.getMetadata().getId());
+            }
+        }
+    }
     
     private static AtomicInteger numberOfReusableFrameworksCreated = new AtomicInteger();
     private static final List<Framework> OSGI_FRAMEWORK_CONTAINERS_FOR_REUSE = MutableList.of();
@@ -213,30 +251,20 @@ public class OsgiManager {
     }
 
     public Map<String, ManagedBundle> getManagedBundles() {
-        synchronized (managedBundles) {
-            return ImmutableMap.copyOf(managedBundles);
-        }
+        return managedBundlesRecord.getManagedBundles();
     }
 
     public String getManagedBundleId(VersionedName vn) {
-        synchronized (managedBundles) {
-            return managedBundlesByName.get(vn);
-        }
+        return managedBundlesRecord.getManagedBundleId(vn);
     }
     
     public ManagedBundle getManagedBundle(VersionedName vn) {
-        synchronized (managedBundles) {
-            return managedBundles.get(managedBundlesByName.get(vn));
-        }
+        return managedBundlesRecord.getManagedBundle(vn);
     }
 
     /** For bundles which are installed by a URL, see whether a bundle has been installed from that URL */
     public ManagedBundle getManagedBundleFromUrl(String url) {
-        synchronized (managedBundles) {
-            String id = managedBundlesByUrl.get(url);
-            if (id==null) return null;
-            return managedBundles.get(id);
-        }
+        return managedBundlesRecord.getManagedBundleFromUrl(url);
     }
     
     /** See {@link OsgiArchiveInstaller#install()}, using default values */
@@ -277,13 +305,13 @@ public class OsgiManager {
      * Callers should typically fail if anything from this bundle is in use.
      */
     public void uninstallUploadedBundle(ManagedBundle bundleMetadata) {
-        synchronized (managedBundles) {
-            ManagedBundle metadata = managedBundles.remove(bundleMetadata.getId());
+        synchronized (managedBundlesRecord) {
+            ManagedBundle metadata = managedBundlesRecord.managedBundles.remove(bundleMetadata.getId());
             if (metadata==null) {
                 throw new IllegalStateException("No such bundle registered: "+bundleMetadata);
             }
-            managedBundlesByName.remove(bundleMetadata.getVersionedName());
-            managedBundlesByUrl.remove(bundleMetadata.getUrl());
+            managedBundlesRecord.managedBundlesByName.remove(bundleMetadata.getVersionedName());
+            managedBundlesRecord.managedBundlesByUrl.remove(bundleMetadata.getUrl());
         }
         mgmt.getRebindManager().getChangeListener().onUnmanaged(bundleMetadata);
 
@@ -569,5 +597,4 @@ public class OsgiManager {
     public Framework getFramework() {
         return framework;
     }
-
 }


[16/17] brooklyn-server git commit: Merge branch 'master' into bundle-uninstall-and-snapshot

Posted by ge...@apache.org.
Merge branch 'master' into bundle-uninstall-and-snapshot


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

Branch: refs/heads/master
Commit: 55def2e0f8ceb6380414877e40381507318efc65
Parents: 33d9fd6 97eaf5a
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Jun 5 14:12:30 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Jun 5 14:12:30 2017 +0100

----------------------------------------------------------------------
 .mvn/jvm.config                                 |   2 +-
 .../apache/brooklyn/api/entity/EntityType.java  |  12 -
 .../brooklyn/api/location/LocationSpec.java     |  21 -
 .../brooklyn/api/sensor/EnricherSpec.java       |   2 +-
 .../interpret/PlanInterpretationContext.java    |   2 +-
 .../apache/brooklyn/camp/util/yaml/Yamls.java   |  24 --
 .../brooklyn/spi/dsl/methods/DslComponent.java  |   4 +-
 .../brooklyn/AbstractJcloudsStubYamlTest.java   |   9 +-
 .../camp/brooklyn/AbstractWindowsYamlTest.java  | 138 ++++++
 .../camp/brooklyn/ByonLocationsYamlTest.java    |  17 +
 .../JcloudsTemplateOptionsYamlTest.java         | 118 ++++++
 .../camp/brooklyn/WindowsYamlLiveTest.java      |  89 +---
 .../brooklyn/camp/brooklyn/WindowsYamlTest.java | 222 ++++++++++
 .../camp/brooklyn/spi/dsl/DslYamlTest.java      |  31 +-
 .../core/BrooklynFeatureEnablement.java         |   8 -
 .../brooklyn/core/entity/AbstractEntity.java    |  49 ---
 .../core/entity/EntityTypeSnapshot.java         |  26 --
 .../apache/brooklyn/core/feed/AbstractFeed.java |  20 -
 .../core/location/AbstractLocation.java         |  38 --
 .../core/location/LocationConfigUtils.java      | 102 -----
 .../brooklyn/core/mgmt/BrooklynTasks.java       |  25 --
 .../internal/AbstractManagementContext.java     |  26 +-
 .../core/mgmt/internal/EffectorUtils.java       |  34 --
 ...PropertyChangeToCollectionChangeAdapter.java |  68 ---
 .../core/mgmt/internal/LocalEntityManager.java  |  14 +-
 .../mgmt/internal/LocalManagementContext.java   |   2 +-
 .../core/mgmt/internal/ObservableSet.java       |  76 ++++
 .../core/mgmt/persist/XmlMementoSerializer.java |   1 -
 .../mgmt/rebind/BasicEntityRebindSupport.java   |  18 -
 .../mgmt/rebind/dto/BrooklynMementoImpl.java    |   3 +
 .../mgmt/rebind/dto/MementosGenerators.java     | 126 +-----
 .../mgmt/rebind/dto/MutableBrooklynMemento.java | 331 ---------------
 .../brooklyn/core/objs/BasicSpecParameter.java  |   3 +-
 .../objs/proxy/InternalLocationFactory.java     |  11 -
 .../core/sensor/DependentConfiguration.java     |  31 +-
 .../entity/group/AbstractGroupImpl.java         |  25 --
 .../brooklyn/entity/group/DynamicGroupImpl.java |   8 -
 .../brooklyn/entity/group/SequenceGroup.java    |   2 +-
 .../util/core/flags/MethodCoercions.java        |  89 +++-
 .../brooklyn/util/core/flags/TypeCoercions.java |  15 +-
 .../brooklyn/util/core/internal/Repeater.java   | 367 ----------------
 .../util/core/internal/ssh/SshTool.java         |   4 +
 .../util/core/task/BasicExecutionContext.java   |  19 +-
 .../brooklyn/util/core/task/BasicTask.java      |  13 +-
 .../core/effector/EffectorConcatenateTest.java  | 246 -----------
 .../core/effector/MethodEffectorTest.java       | 419 +++++++++++++++++++
 .../brooklyn/core/entity/AttributeTest.java     |  31 +-
 .../core/entity/EntitySetFromFlagTest.java      |  81 ++--
 .../brooklyn/core/entity/EntitySpecTest.java    |   2 +-
 .../brooklyn/core/entity/EntityTypeTest.java    |  46 +-
 .../entity/OwnedChildrenDeprecatedTest.java     | 215 ++++++++++
 .../brooklyn/core/entity/OwnedChildrenTest.java | 160 ++-----
 .../drivers/BasicEntityDriverManagerTest.java   |  33 +-
 .../drivers/EntityDriverRegistryTest.java       |  35 +-
 .../ReflectiveEntityDriverFactoryTest.java      |  63 +--
 .../RegistryEntityDriverFactoryTest.java        |  31 +-
 .../proxying/InternalEntityFactoryTest.java     |  32 +-
 .../core/location/AbstractLocationTest.java     |  33 +-
 .../core/mgmt/internal/ObservableSetTest.java   | 182 ++++++++
 .../mgmt/internal/TestEntityWithEffectors.java  |   2 +-
 .../core/mgmt/osgi/OsgiStandaloneTest.java      |   2 +-
 .../mgmt/osgi/OsgiVersionMoreEntityTest.java    |  28 +-
 .../core/mgmt/rebind/RebindCatalogItemTest.java |   3 +
 .../core/mgmt/rebind/RebindEntityTest.java      |  35 --
 .../mgmt/rebind/RebindManagerSorterTest.java    |   2 +-
 .../core/mgmt/rebind/RebindTestUtils.java       |  33 +-
 .../network/OnPublicNetworkEnricherTest.java    |   4 +-
 .../brooklyn/core/test/entity/TestEntity.java   |   4 +
 .../core/test/entity/TestEntityImpl.java        |  17 +-
 .../EntityPersistencePerformanceTest.java       |   2 +-
 .../YamlRollingTimeWindowMeanEnricherTest.java  |  23 +-
 .../brooklyn/entity/group/DynamicGroupTest.java | 285 +++++++------
 .../ssh/SshMachineLocationPerformanceTest.java  |   2 +-
 .../util/core/flags/MethodCoercionsTest.java    | 133 +++++-
 .../util/core/internal/RepeaterTest.java        | 251 -----------
 karaf/features/src/main/feature/feature.xml     |  11 +-
 .../brooklyn/launcher/common/BasicLauncher.java |  23 -
 .../jclouds/BasicJcloudsLocationCustomizer.java |   6 +
 .../jclouds/JcloudsByonLocationResolver.java    |   3 +-
 .../location/jclouds/JcloudsLocation.java       | 111 ++---
 .../jclouds/JcloudsLocationCustomizer.java      |   9 +
 .../jclouds/JcloudsLocationResolver.java        |   6 +-
 .../location/jclouds/JcloudsTypeCoercions.java  | 168 ++++++++
 .../brooklyn/location/jclouds/JcloudsUtil.java  | 279 ------------
 .../aws/AbstractEbsVolumeCustomizer.java        |  96 +++++
 .../jclouds/aws/EbsVolumeCustomizers.java       | 170 ++++++++
 .../jclouds/AbstractJcloudsStubbedUnitTest.java |  41 +-
 .../DefaultConnectivityResolverTest.java        |  30 +-
 .../JcloudsSshMachineLocationStubbedTest.java   |  21 +
 .../jclouds/JcloudsStubTemplateBuilder.java     | 204 ++++++---
 .../JcloudsTemplateOptionsStubbedTest.java      | 102 +++++
 .../JcloudsTypeCoercionsWithBuilderTest.java    | 308 ++++++++++++++
 .../JcloudsTypeCoercionsWithCreateTest.java     | 278 ++++++++++++
 ...loudsLocationUserLoginAndConfigLiveTest.java |  12 +-
 parent/pom.xml                                  |   4 +-
 .../autoscaling/AutoScalerPolicyTest.java       |  41 +-
 .../autoscaling/LocallyResizableEntity.java     |  49 +--
 .../autoscaling/LocallyResizableEntityImpl.java |  76 ++++
 .../policy/enricher/DeltaEnrichersTests.java    |  59 ++-
 .../enricher/RollingMeanEnricherTest.java       |  29 +-
 .../RollingTimeWindowMeanEnricherTest.java      |  30 +-
 .../AbstractFollowTheSunPolicyTest.java         |  42 +-
 .../followthesun/FollowTheSunModelTest.java     |  43 +-
 .../AbstractLoadBalancingPolicyTest.java        |  19 +-
 .../loadbalancing/LoadBalancingModelTest.java   |  28 +-
 .../LoadBalancingPolicyConcurrencyTest.java     |   8 +-
 .../loadbalancing/MockItemEntityImpl.java       |   5 +-
 pom.xml                                         |   2 +-
 .../rest/resources/CatalogResource.java         |   4 +-
 .../testing/mocks/RestMockSimpleEntity.java     |  19 -
 .../main/java/org/apache/brooklyn/cli/Main.java |  34 +-
 .../java/org/apache/brooklyn/cli/CliTest.java   |  26 +-
 .../src/test/resources/ExampleAppInFile.groovy  |  22 -
 .../entity/brooklynnode/BrooklynNodeImpl.java   |   8 -
 .../entity/java/VanillaJavaAppImpl.java         |  14 +-
 .../software/base/SoftwareProcessImpl.java      |  29 +-
 .../entity/machine/MachineEntityRebindTest.java |  72 +++-
 .../base/SoftwareProcessEntityTest.java         |  47 ++-
 .../MachineLifecycleEffectorTasksTest.java      |  16 +-
 .../base/lifecycle/StartStopSshDriverTest.java  |  26 +-
 .../apache/brooklyn/feed/jmx/JmxFeedTest.java   |  47 +--
 .../util/core/internal/winrm/WinRmTool.java     |   4 +
 .../internal/winrm/winrm4j/Winrm4jTool.java     |  22 +-
 .../core/internal/winrm/ExecCmdAsserts.java     | 120 ++++++
 .../core/internal/winrm/RecordingWinRmTool.java |   4 +
 .../framework/LoopOverGroupMembersTestCase.java |   1 +
 .../LoopOverGroupMembersTestCaseImpl.java       |  33 +-
 .../LoopOverGroupMembersTestCaseTest.java       |  69 ++-
 .../apache/brooklyn/test/EntityTestUtils.java   | 192 ---------
 .../brooklyn/test/PerformanceTestUtils.java     |  26 --
 .../org/apache/brooklyn/test/TestUtils.java     |  83 ----
 utils/common/pom.xml                            |   5 +
 .../org/apache/brooklyn/util/ShellUtils.java    | 185 --------
 .../javalang/MethodAccessibleReflections.java   | 173 ++++++++
 .../brooklyn/util/javalang/Reflections.java     |  47 ++-
 .../coerce/CommonAdaptorTryCoercions.java       | 150 +++++++
 .../coerce/CommonAdaptorTypeCoercions.java      |   4 -
 .../util/javalang/coerce/TryCoercer.java        |  45 ++
 .../javalang/coerce/TypeCoercerExtensible.java  | 101 ++---
 .../brooklyn/util/javalang/ReflectionsTest.java |  64 +++
 .../coerce/TypeCoercerExtensibleTest.java       |  82 ++++
 .../util/javalang/coerce/TypeCoercionsTest.java |  59 +++
 .../util/groovy/GroovJavaMethodsTest.java       |   4 +-
 143 files changed, 4858 insertions(+), 3972 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/55def2e0/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/55def2e0/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------


[07/17] brooklyn-server git commit: Merge branch 'master' into bundle-uninstall-and-snapshot

Posted by ge...@apache.org.
Merge branch 'master' into bundle-uninstall-and-snapshot

Removal of XML catalog support caused minor conflicts in imports and tests, easily resolved.


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

Branch: refs/heads/master
Commit: 71ede731aafa3f32ffac62e21c5eaab2fa9d21d7
Parents: abdb13e fc575d7
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon May 8 13:34:04 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon May 8 13:34:04 2017 +0100

----------------------------------------------------------------------
 .../brooklyn/api/catalog/CatalogItem.java       |   2 -
 .../catalog/AbstractCatalogXmlTest.java         | 108 ----------
 .../camp/brooklyn/catalog/CatalogScanTest.java  | 198 ++++++++++++++++++
 .../brooklyn/catalog/CatalogXmlOsgiTest.java    |  37 ----
 .../brooklyn/catalog/CatalogXmlVersionTest.java |  57 ------
 .../brooklyn/test/lite/CampYamlLiteTest.java    |  27 ---
 .../src/test/resources/osgi-catalog.xml         |  29 ---
 .../src/test/resources/simple-catalog.xml       |  47 -----
 .../core/catalog/CatalogPredicates.java         |  63 +++++-
 .../catalog/internal/BasicBrooklynCatalog.java  |  12 --
 .../internal/CatalogBundleConverter.java        |  63 ------
 .../catalog/internal/CatalogClasspathDo.java    |   5 +-
 .../core/catalog/internal/CatalogDo.java        |  14 --
 .../core/catalog/internal/CatalogDto.java       |  90 +--------
 .../core/catalog/internal/CatalogDtoUtils.java  |  66 ------
 .../catalog/internal/CatalogInitialization.java |  87 ++------
 .../core/catalog/internal/CatalogItemDo.java    |   5 -
 .../internal/CatalogItemDtoAbstract.java        |  18 --
 .../catalog/internal/CatalogXmlSerializer.java  |  77 -------
 .../internal/JavaCatalogToSpecTransformer.java  |   9 +-
 .../core/internal/storage/DataGrid.java         |  52 -----
 .../core/internal/storage/DataGridFactory.java  |  38 ----
 .../storage/impl/BrooklynStorageImpl.java       |  18 +-
 .../internal/storage/impl/InmemoryDatagrid.java |  86 ++++++++
 .../impl/inmemory/InMemoryDataGridFactory.java  |  40 ----
 .../storage/impl/inmemory/InmemoryDatagrid.java |  93 ---------
 .../internal/AbstractManagementContext.java     |  49 +----
 .../mgmt/internal/LocalManagementContext.java   |  28 +--
 .../core/server/BrooklynServerConfig.java       |   2 +-
 .../main/resources/brooklyn-catalog-empty.xml   |  20 --
 .../deserializingClassRenames.properties        |   4 -
 .../core/catalog/internal/CatalogDtoTest.java   |  36 +---
 .../core/catalog/internal/CatalogLoadTest.java  |  79 --------
 .../core/catalog/internal/CatalogScanTest.java  | 199 -------------------
 .../storage/impl/BrooklynStorageImplTest.java   |   6 +-
 .../core/mgmt/rebind/RebindCatalogItemTest.java |  84 ++++++--
 ...talogWhenCatalogPersistenceDisabledTest.java |  49 +++--
 .../core/test/BrooklynAppLiveTestSupport.java   |   3 +-
 .../longevity/EntityCleanupLongevityTest.java   |   2 +-
 .../EntityCleanupLongevityTestFixture.java      |  48 +++--
 .../brooklyn/catalog/internal/osgi-catalog.xml  |  31 ---
 .../rebind/rebind-catalog-item-test-catalog.xml |  28 ---
 pom.xml                                         |   2 -
 .../apache/brooklyn/rest/api/CatalogApi.java    |  11 -
 .../rest/resources/CatalogResource.java         |  19 +-
 .../rest/resources/CatalogResetTest.java        | 118 -----------
 .../src/test/resources/reset-catalog.xml        |  37 ----
 .../entity/brooklynnode/BrooklynNode.java       |  19 --
 .../brooklynnode/BrooklynNodeSshDriver.java     |  14 --
 .../BrooklynNodeIntegrationTest.java            |  24 ---
 storage/hazelcast/pom.xml                       |  88 --------
 .../storage/impl/hazelcast/EntityId.java        |  36 ----
 .../impl/hazelcast/EntityStreamSerializer.java  |  68 -------
 .../impl/hazelcast/HazelcastDataGrid.java       |  89 ---------
 .../hazelcast/HazelcastDataGridFactory.java     |  42 ----
 .../impl/hazelcast/HazelcastStorageTest.java    | 107 ----------
 56 files changed, 516 insertions(+), 2167 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/71ede731/api/src/main/java/org/apache/brooklyn/api/catalog/CatalogItem.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/71ede731/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
----------------------------------------------------------------------
diff --cc camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
index 2b1b488,68c7fed..506e838
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java
@@@ -40,8 -40,8 +40,6 @@@ import org.apache.brooklyn.camp.spi.Ass
  import org.apache.brooklyn.camp.spi.pdp.PdpYamlTest;
  import org.apache.brooklyn.camp.test.mock.web.MockWebPlatform;
  import org.apache.brooklyn.core.catalog.CatalogPredicates;
--import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
--import org.apache.brooklyn.core.catalog.internal.CatalogDto;
  import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
  import org.apache.brooklyn.core.config.ConfigKeys;
  import org.apache.brooklyn.core.effector.AddChildrenEffector;
@@@ -192,35 -190,8 +190,10 @@@ public class CampYamlLiteTest 
  
          assertMgmtHasSampleMyCatalogApp(symbolicName, bundleUrl);
      }
-  
-     @SuppressWarnings("deprecation")
-     @Test
-     public void testResetXmlWithCustomEntity() throws IOException {
-         TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
- 
-         String symbolicName = "my.catalog.app.id";
-         String bundleUrl = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL;
-         String yaml = prepAndGetSampleMyCatalogAppYaml(symbolicName, bundleUrl);
- 
-         LocalManagementContext mgmt2 = LocalManagementContextForTests.newInstanceWithOsgi();
-         try {
-             installWithoutCatalogBom(mgmt2, bundleUrl);
-             CampPlatformWithJustBrooklynMgmt platform2 = new CampPlatformWithJustBrooklynMgmt(mgmt2);
-             MockWebPlatform.populate(platform2, TestAppAssemblyInstantiator.class);
- 
-             mgmt2.getCatalog().addItems(yaml);
-             String xml = ((BasicBrooklynCatalog) mgmt2.getCatalog()).toXmlString();
-             ((BasicBrooklynCatalog) mgmt.getCatalog()).reset(CatalogDto.newDtoFromXmlContents(xml, "copy of temporary catalog"));
-         } finally {
-             mgmt2.terminate();
-         }
- 
-         assertMgmtHasSampleMyCatalogApp(symbolicName, bundleUrl);
-     }
  
 -    private String getSampleMyCatalogAppYaml(String symbolicName, String bundleUrl) {
 +    private String prepAndGetSampleMyCatalogAppYaml(String symbolicName, String bundleUrl) {
 +        installWithoutCatalogBom(mgmt, bundleUrl);
 +        
          return Joiner.on("\n").join(
                  "brooklyn.catalog:",
                  "  id: " + symbolicName,

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/71ede731/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/71ede731/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/71ede731/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/71ede731/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --cc rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index c5a2b59,f0dbf34..76ebb63
--- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@@ -39,14 -44,11 +39,12 @@@ import org.apache.brooklyn.api.entity.E
  import org.apache.brooklyn.api.entity.EntitySpec;
  import org.apache.brooklyn.api.location.Location;
  import org.apache.brooklyn.api.location.LocationSpec;
 +import org.apache.brooklyn.api.mgmt.ManagementContext;
  import org.apache.brooklyn.api.policy.Policy;
  import org.apache.brooklyn.api.policy.PolicySpec;
 +import org.apache.brooklyn.api.typereg.ManagedBundle;
  import org.apache.brooklyn.api.typereg.RegisteredType;
  import org.apache.brooklyn.core.catalog.CatalogPredicates;
--import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
- import org.apache.brooklyn.core.catalog.internal.CatalogDto;
  import org.apache.brooklyn.core.catalog.internal.CatalogItemComparator;
  import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
  import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;


[17/17] brooklyn-server git commit: Closes #672

Posted by ge...@apache.org.
Closes #672

Bundle uninstall and snapshot

Supports bundle install and auto-reinstall for snapshot POSTs.

Doesn't do anything for auto-upgrade but if you POST a new snapshot ZIP then redeploy, the newer version gets used.  Also cleanly uninstalls catalog items.


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

Branch: refs/heads/master
Commit: f3aa339fdb9caa17b0c527cf889376ea8bbaa453
Parents: 27feabc 55def2e
Author: Geoff Macartney <ge...@cloudsoftcorp.com>
Authored: Tue Jun 6 13:24:31 2017 +0100
Committer: Geoff Macartney <ge...@cloudsoftcorp.com>
Committed: Tue Jun 6 13:24:31 2017 +0100

----------------------------------------------------------------------
 .../brooklyn/api/catalog/BrooklynCatalog.java   |  15 +-
 .../brooklyn/api/catalog/CatalogItem.java       |   2 +
 .../brooklyn/api/typereg/ManagedBundle.java     |   3 +
 .../brooklyn/api/typereg/RegisteredType.java    |   5 +
 .../BrooklynComponentTemplateResolver.java      |   2 +
 .../catalog/CatalogMakeOsgiBundleTest.java      |  16 +-
 .../catalog/CatalogOsgiLibraryTest.java         |   9 +-
 .../CatalogOsgiVersionMoreEntityRebindTest.java | 119 +++++-
 .../CatalogOsgiVersionMoreEntityTest.java       |  17 +-
 .../catalog/CatalogOsgiYamlEntityTest.java      |  15 +-
 .../brooklyn/catalog/CatalogYamlRebindTest.java |   4 +
 .../brooklyn/test/lite/CampYamlLiteTest.java    |  19 +-
 .../apache/brooklyn/core/BrooklynVersion.java   |   3 +-
 .../catalog/internal/BasicBrooklynCatalog.java  |  27 +-
 .../catalog/internal/CatalogBundleLoader.java   |   7 +-
 .../core/catalog/internal/CatalogItemDo.java    |   5 +
 .../internal/CatalogItemDtoAbstract.java        |  17 +-
 .../core/catalog/internal/CatalogUtils.java     |  18 +-
 .../core/mgmt/ha/OsgiArchiveInstaller.java      | 427 +++++++++++++++++++
 .../mgmt/ha/OsgiBundleInstallationResult.java   |  80 ++++
 .../brooklyn/core/mgmt/ha/OsgiManager.java      | 259 +++++++----
 .../core/mgmt/rebind/RebindContextImpl.java     |  15 +-
 .../core/mgmt/rebind/RebindIteration.java       |  15 +-
 .../rebind/transformer/CompoundTransformer.java |  17 +-
 .../core/typereg/BasicManagedBundle.java        |  15 +-
 .../core/typereg/BasicRegisteredType.java       |   6 +
 .../brooklyn/core/typereg/RegisteredTypes.java  |  10 +
 .../brooklyn/core/BrooklynVersionTest.java      |   4 +-
 .../mgmt/osgi/OsgiVersionMoreEntityTest.java    |   4 +-
 ...nceStoreObjectAccessorWriterTestFixture.java |   2 +-
 .../mgmt/persist/XmlMementoSerializerTest.java  |  13 +-
 .../transformer/CompoundTransformerTest.java    |   1 -
 .../brooklyn/util/core/osgi/OsgiTestBase.java   |  18 +
 .../apache/brooklyn/rest/api/CatalogApi.java    |  16 +-
 .../apache/brooklyn/rest/domain/ApiError.java   |  21 +-
 .../rest/resources/CatalogResource.java         | 152 +++----
 .../rest/resources/CatalogResourceTest.java     |  28 +-
 .../src/main/resources/catalog.bom              |   7 +-
 .../brooklyn/util/maven/MavenArtifact.java      |   3 +-
 .../java/org/apache/brooklyn/util/os/Os.java    |   5 +-
 .../brooklyn/util/osgi/VersionedName.java       |   7 +
 .../brooklyn/util/text/VersionComparator.java   |   9 +-
 .../brooklyn/util/osgi/VersionedNameTest.java   |  43 ++
 .../util/text/VersionComparatorTest.java        |   7 +
 .../brooklyn-test-osgi-com-example-entities.jar | Bin 22130 -> 22139 bytes
 .../osgi/brooklyn-test-osgi-entities.jar        | Bin 22900 -> 22902 bytes
 .../brooklyn-test-osgi-more-entities_0.1.0.jar  | Bin 15997 -> 16003 bytes
 .../brooklyn-test-osgi-more-entities_0.2.0.jar  | Bin 16903 -> 16922 bytes
 ...-test-osgi-more-entities_evil-twin_0.2.0.jar | Bin 14091 -> 14098 bytes
 49 files changed, 1220 insertions(+), 267 deletions(-)
----------------------------------------------------------------------



[05/17] brooklyn-server git commit: install and start in separate phases when rebinding or loading libs

Posted by ge...@apache.org.
install and start in separate phases when rebinding or loading libs

also recognise bundles from their originally installed URL, and
misc other related cleanups; upgrade tests and others now passing!

note: transformers are only allowed to delete bundles, not change


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

Branch: refs/heads/master
Commit: 062fdc4d0d000ffc00941d31d15bbe4534a5d707
Parents: 1452454
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu May 4 17:51:49 2017 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon May 8 13:14:58 2017 +0100

----------------------------------------------------------------------
 .../CatalogOsgiVersionMoreEntityRebindTest.java |   2 +-
 .../brooklyn/catalog/CatalogYamlRebindTest.java |   4 +
 .../catalog/internal/BasicBrooklynCatalog.java  |   2 +-
 .../core/catalog/internal/CatalogUtils.java     |  17 ++-
 .../core/mgmt/ha/OsgiArchiveInstaller.java      | 112 +++++++++++++++----
 .../mgmt/ha/OsgiBundleInstallationResult.java   |   9 ++
 .../brooklyn/core/mgmt/ha/OsgiManager.java      |  91 +++++++++++----
 .../core/mgmt/rebind/RebindContextImpl.java     |  13 ++-
 .../core/mgmt/rebind/RebindIteration.java       |  15 ++-
 .../rebind/transformer/CompoundTransformer.java |  17 ++-
 .../core/typereg/BasicManagedBundle.java        |   1 -
 .../brooklyn/core/BrooklynVersionTest.java      |   4 +-
 .../mgmt/osgi/OsgiVersionMoreEntityTest.java    |   4 +-
 ...nceStoreObjectAccessorWriterTestFixture.java |   2 +-
 .../mgmt/persist/XmlMementoSerializerTest.java  |  13 ++-
 .../transformer/CompoundTransformerTest.java    |   1 -
 .../brooklyn/util/core/osgi/OsgiTestBase.java   |  18 +++
 .../rest/resources/CatalogResource.java         |  37 +++---
 .../rest/resources/CatalogResourceTest.java     |  28 +++--
 19 files changed, 299 insertions(+), 91 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
index a258fcd..d71142c 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityRebindTest.java
@@ -285,7 +285,7 @@ public class CatalogOsgiVersionMoreEntityRebindTest extends AbstractYamlRebindTe
         
         // force upgrade
         OsgiBundleInstallationResult b2b = ((ManagementContextInternal)mgmt()).getOsgiManager().get().install(b2a.getMetadata(), 
-            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL), true, true).get();
+            new ResourceUtils(getClass()).getResourceFromUrl(BROOKLYN_TEST_MORE_ENTITIES_V2_EVIL_TWIN_URL), true, true, true).get();
         Assert.assertEquals(b2a.getBundle(), b2b.getBundle());
         Assert.assertEquals(b2b.getCode(), OsgiBundleInstallationResult.ResultCode.UPDATED_EXISTING_BUNDLE);
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
index c4af503..127a110 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java
@@ -175,6 +175,10 @@ public class CatalogYamlRebindTest extends AbstractYamlRebindTest {
                         for (BrooklynObjectType type : BrooklynObjectType.values()) {
                             final List<String> contents = objectStore.listContentsWithSubPath(type.getSubPathName());
                             for (String path : contents) {
+                                if (path.endsWith(".jar")) {
+                                    // don't apply transformers to JARs
+                                    continue;
+                                }
                                 StoreObjectAccessor accessor = objectStore.newAccessor(path);
                                 String memento = checkNotNull(accessor.get(), path);
                                 String replacement = transformed.getObjectsOfType(type).get(idFromPath(type, path));

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
index c91b7cd..30bf841 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java
@@ -582,7 +582,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
 
         PlanInterpreterGuessingType planInterpreter = new PlanInterpreterGuessingType(null, item, sourceYaml, itemType, libraryBundles, result).reconstruct();
         if (!planInterpreter.isResolved()) {
-            throw Exceptions.create("Could not resolve item"
+            throw Exceptions.create("Could not resolve definition of item"
                 + (Strings.isNonBlank(id) ? " '"+id+"'" : Strings.isNonBlank(symbolicName) ? " '"+symbolicName+"'" : Strings.isNonBlank(name) ? " '"+name+"'" : "")
                 // better not to show yaml, takes up lots of space, and with multiple plan transformers there might be multiple errors; 
                 // some of the errors themselves may reproduce it

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
index 394814d..47dab6d 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
@@ -39,6 +39,7 @@ import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContextSequential;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
 import org.apache.brooklyn.core.mgmt.classloading.OsgiBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
 import org.apache.brooklyn.core.mgmt.ha.OsgiManager;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.rebind.RebindManagerImpl.RebindTracker;
@@ -47,6 +48,7 @@ import org.apache.brooklyn.core.typereg.BasicManagedBundle;
 import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
 import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
 import org.apache.brooklyn.core.typereg.RegisteredTypes;
+import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.time.Time;
@@ -170,13 +172,24 @@ public class CatalogUtils {
                     "Loading bundles in {}: {}", 
                     new Object[] {managementContext, Joiner.on(", ").join(libraries)});
             Stopwatch timer = Stopwatch.createStarted();
+            List<OsgiBundleInstallationResult> results = MutableList.of();
             for (CatalogBundle bundleUrl : libraries) {
-                osgi.get().install(BasicManagedBundle.of(bundleUrl), null, true, false).get();
+                OsgiBundleInstallationResult result = osgi.get().installDeferredStart(BasicManagedBundle.of(bundleUrl), null).get();
+                if (log.isDebugEnabled()) {
+                    logDebugOrTraceIfRebinding(log, "Installation of library "+bundleUrl+": "+result);
+                }
+                results.add(result);
             }
-            if (log.isDebugEnabled()) 
+            for (OsgiBundleInstallationResult r: results) {
+                if (r.getDeferredStart()!=null) {
+                    r.getDeferredStart().run();
+                }
+            }
+            if (log.isDebugEnabled()) { 
                 logDebugOrTraceIfRebinding(log, 
                     "Registered {} bundles in {}",
                     new Object[]{libraries.size(), Time.makeTimeStringRounded(timer)});
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
index 0e069bd..4044f23 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiArchiveInstaller.java
@@ -28,6 +28,7 @@ import java.util.jar.Manifest;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
+import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
 import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult.ResultCode;
@@ -45,19 +46,26 @@ import org.apache.brooklyn.util.stream.Streams;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.text.VersionComparator;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Objects;
 
 // package-private so we can move this one if/when we move OsgiManager
 class OsgiArchiveInstaller {
 
+    private static final Logger log = LoggerFactory.getLogger(OsgiArchiveInstaller.class);
+    
     final private OsgiManager osgiManager;
     private ManagedBundle suppliedKnownBundleMetadata;
     private InputStream zipIn;
     
-    private boolean loadCatalogBom;
-    private boolean force;
+    private boolean start = true;
+    private boolean loadCatalogBom = true;
+    private boolean force = false;
+    private boolean deferredStart = false;
     
     private File zipFile;
     private Manifest discoveredManifest;
@@ -65,13 +73,19 @@ class OsgiArchiveInstaller {
     OsgiBundleInstallationResult result;
     
     private ManagedBundle inferredMetadata;
+    private final boolean inputStreamSupplied;
     
     OsgiArchiveInstaller(OsgiManager osgiManager, ManagedBundle knownBundleMetadata, InputStream zipIn) {
         this.osgiManager = osgiManager;
         this.suppliedKnownBundleMetadata = knownBundleMetadata;
         this.zipIn = zipIn;
+        inputStreamSupplied = zipIn!=null;
     }
 
+    public void setStart(boolean start) {
+        this.start = start;
+    }
+    
     public void setLoadCatalogBom(boolean loadCatalogBom) {
         this.loadCatalogBom = loadCatalogBom;
     }
@@ -80,6 +94,10 @@ class OsgiArchiveInstaller {
         this.force = force;
     }
 
+    public void setDeferredStart(boolean deferredStart) {
+        this.deferredStart = deferredStart;
+    }    
+
     private ManagementContextInternal mgmt() {
         return (ManagementContextInternal) osgiManager.mgmt;
     }
@@ -98,6 +116,15 @@ class OsgiArchiveInstaller {
             Maybe<Bundle> installedBundle = Maybe.absent();
             if (suppliedKnownBundleMetadata!=null) {
                 // if no input stream, look for a URL and/or a matching bundle
+                if (!suppliedKnownBundleMetadata.isNameResolved()) {
+                    ManagedBundle mbFromUrl = osgiManager.getManagedBundleFromUrl(suppliedKnownBundleMetadata.getUrl());
+                    if (mbFromUrl!=null) {
+                        // user supplied just a URL (eg brooklyn.libraries), but we recognise it,
+                        // so don't try to reload it, just record the info we know about it to retrieve the bundle
+                        ((BasicManagedBundle)suppliedKnownBundleMetadata).setSymbolicName(mbFromUrl.getSymbolicName());
+                        ((BasicManagedBundle)suppliedKnownBundleMetadata).setVersion(mbFromUrl.getVersion());
+                    }
+                }
                 if (installedBundle.isAbsent() && suppliedKnownBundleMetadata.getOsgiUniqueUrl()!=null) {
                     installedBundle = Osgis.bundleFinder(osgiManager.framework).requiringFromUrl(suppliedKnownBundleMetadata.getOsgiUniqueUrl()).find();
                 }
@@ -115,19 +142,22 @@ class OsgiArchiveInstaller {
                 }
             }
             
-            if (installedBundle.isPresent()) {
-                result.bundle = installedBundle.get();
-                
-                if (zipIn==null) {
+            if (zipIn==null) {
+                if (installedBundle.isPresent()) {
                     // no way to install (no url), or no need to install (not forced); just ignore it
                     result.metadata = osgiManager.getManagedBundle(new VersionedName(installedBundle.get()));
+                    if (result.metadata==null) {
+                        // low-level installed bundle
+                        result.metadata = new BasicManagedBundle(installedBundle.get().getSymbolicName(), installedBundle.get().getVersion().toString(),
+                            suppliedKnownBundleMetadata!=null ? suppliedKnownBundleMetadata.getUrl() : null);
+                    }
                     result.setIgnoringAlreadyInstalled();
                     return;
                 }
-            } else {
                 result.metadata = suppliedKnownBundleMetadata;
                 throw new IllegalArgumentException("No input stream available and no URL could be found; nothing to install");
             }
+            result.bundle = installedBundle.orNull();
         }
         
         zipFile = Os.newTempFile("brooklyn-bundle-transient-"+suppliedKnownBundleMetadata, "zip");
@@ -243,10 +273,23 @@ class OsgiArchiveInstaller {
             if (result.code!=null) return ReferenceWithError.newInstanceWithoutError(result);
             assert inferredMetadata.isNameResolved() : "Should have resolved "+inferredMetadata;
 
-            Boolean updating = null;
+            final boolean updating;
             result.metadata = osgiManager.getManagedBundle(inferredMetadata.getVersionedName());
             if (result.getMetadata()!=null) {
-                // already have a managed bundle
+                // already have a managed bundle - check if this is using a new/different URL
+                if (suppliedKnownBundleMetadata!=null && suppliedKnownBundleMetadata.getUrl()!=null) {
+                    String knownIdForThisUrl = osgiManager.managedBundlesByUrl.get(suppliedKnownBundleMetadata.getUrl());
+                    if (knownIdForThisUrl==null) {
+                        // it's a new URL, but a bundle we already know about
+                        log.warn("Request to install from "+suppliedKnownBundleMetadata.getUrl()+" which is not recognized but "+
+                            "appears to match "+result.getMetadata()+"; now associating with the latter");
+                        osgiManager.managedBundlesByUrl.put(suppliedKnownBundleMetadata.getUrl(), result.getMetadata().getId());
+                    } else if (!knownIdForThisUrl.equals(result.getMetadata().getId())) {
+                        log.warn("Request to install from "+suppliedKnownBundleMetadata.getUrl()+" which is associated to "+knownIdForThisUrl+" but "+
+                            "appears to match "+result.getMetadata()+"; now associating with the latter");
+                        osgiManager.managedBundlesByUrl.put(suppliedKnownBundleMetadata.getUrl(), result.getMetadata().getId());
+                    }
+                }
                 if (canUpdate()) { 
                     result.bundle = osgiManager.framework.getBundleContext().getBundle(result.getMetadata().getOsgiUniqueUrl());
                     if (result.getBundle()==null) {
@@ -290,7 +333,10 @@ class OsgiArchiveInstaller {
             if (!updating) { 
                 synchronized (osgiManager.managedBundles) {
                     osgiManager.managedBundles.put(result.getMetadata().getId(), result.getMetadata());
-                    osgiManager.managedBundleIds.put(result.getMetadata().getVersionedName(), result.getMetadata().getId());
+                    osgiManager.managedBundlesByNam.put(result.getMetadata().getVersionedName(), result.getMetadata().getId());
+                    if (Strings.isNonBlank(result.getMetadata().getUrl())) {
+                        osgiManager.managedBundlesByUrl.put(result.getMetadata().getUrl(), result.getMetadata().getId());
+                    }
                 }
                 result.code = OsgiBundleInstallationResult.ResultCode.INSTALLED_NEW_BUNDLE;
                 result.message = "Installed "+result.getMetadata().getVersionedName()+" with ID "+result.getMetadata().getId();
@@ -305,16 +351,37 @@ class OsgiArchiveInstaller {
             // that seems fine and probably better than allowing bundles to start and catalog items to be installed 
             // when brooklyn isn't aware it is supposed to be managing it
             
-            // starting here  flags wiring issues earlier
+            // starting here flags wiring issues earlier
             // but may break some things running from the IDE
-            result.bundle.start();
-
-            if (updating!=null) {
-                osgiManager.uninstallCatalogItemsFromBundle( result.getVersionedName() );
-                // (ideally removal and addition would be atomic)
-            }
-            if (loadCatalogBom) {
-                osgiManager.loadCatalogBom(result.bundle);
+            // eg if it doesn't have OSGi deps, or if it doesn't have camp parser,
+            // or if caller is installing multiple things that depend on each other
+            // eg rebind code, brooklyn.libraries list -- deferred start allows caller to
+            // determine whether not to start or to start all after things are installed
+            Runnable startRunnable = new Runnable() {
+                public void run() {
+                    if (start) {
+                        try {
+                            result.bundle.start();
+                        } catch (BundleException e) {
+                            throw Exceptions.propagate(e);
+                        }
+                    }
+        
+                    if (loadCatalogBom) {
+                        if (updating) {
+                            osgiManager.uninstallCatalogItemsFromBundle( result.getVersionedName() );
+                            // (ideally removal and addition would be atomic)
+                        }
+                        for (CatalogItem<?,?> ci: osgiManager.loadCatalogBom(result.bundle)) {
+                            result.catalogItemsInstalled.add(ci.getId());
+                        }
+                    }
+                }
+            };
+            if (deferredStart) {
+                result.deferredStart = startRunnable;
+            } else {
+                startRunnable.run();
             }
 
             return ReferenceWithError.newInstanceWithoutError(result);
@@ -331,7 +398,9 @@ class OsgiArchiveInstaller {
     }
 
     private boolean canUpdate() {
-        return force || VersionComparator.isSnapshot(inferredMetadata.getVersion());
+        // only update if forced, or it's a snapshot for which a byte stream is supplied
+        // (IE don't update a snapshot verison every time its URL is referenced in a 'libraries' section)
+        return force || (VersionComparator.isSnapshot(inferredMetadata.getVersion()) && inputStreamSupplied);
     }
 
     /** true if the supplied name and version are complete; updates if the known data is incomplete;
@@ -355,5 +424,6 @@ class OsgiArchiveInstaller {
         }
         
         return suppliedIsComplete;
-    }    
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiBundleInstallationResult.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiBundleInstallationResult.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiBundleInstallationResult.java
index 50ca081..c3a725a 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiBundleInstallationResult.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiBundleInstallationResult.java
@@ -34,6 +34,7 @@ public class OsgiBundleInstallationResult {
     ManagedBundle metadata;
     Bundle bundle;
     ResultCode code;
+    Runnable deferredStart;
     
     public enum ResultCode { 
         INSTALLED_NEW_BUNDLE,
@@ -63,9 +64,17 @@ public class OsgiBundleInstallationResult {
         if (getMetadata()==null) return null;
         return getMetadata().getVersionedName();
     }
+    public Runnable getDeferredStart() {
+        return deferredStart;
+    }
     
     void setIgnoringAlreadyInstalled() {
         code = OsgiBundleInstallationResult.ResultCode.IGNORING_BUNDLE_AREADY_INSTALLED;
         message = "Bundle "+getMetadata().getVersionedName()+" already installed as "+getMetadata().getId();
     }
+    
+    @Override
+    public String toString() {
+        return OsgiBundleInstallationResult.class.getSimpleName()+"["+code+", "+metadata+", "+message+"]";
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
index 1685541..9936ba9 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/OsgiManager.java
@@ -103,7 +103,8 @@ public class OsgiManager {
     private Set<Bundle> bundlesAtStartup;
     private File osgiCacheDir;
     Map<String, ManagedBundle> managedBundles = MutableMap.of();
-    Map<VersionedName, String> managedBundleIds = MutableMap.of();
+    Map<VersionedName, String> managedBundlesByNam = MutableMap.of();
+    Map<String, String> managedBundlesByUrl = MutableMap.of();
     
     private static AtomicInteger numberOfReusableFrameworksCreated = new AtomicInteger();
     private static final List<Framework> OSGI_FRAMEWORK_CONTAINERS_FOR_REUSE = MutableList.of();
@@ -219,26 +220,45 @@ public class OsgiManager {
 
     public String getManagedBundleId(VersionedName vn) {
         synchronized (managedBundles) {
-            return managedBundleIds.get(vn);
+            return managedBundlesByNam.get(vn);
         }
     }
     
     public ManagedBundle getManagedBundle(VersionedName vn) {
         synchronized (managedBundles) {
-            return managedBundles.get(managedBundleIds.get(vn));
+            return managedBundles.get(managedBundlesByNam.get(vn));
         }
     }
 
+    /** For bundles which are installed by a URL, see whether a bundle has been installed from that URL */
+    public ManagedBundle getManagedBundleFromUrl(String url) {
+        synchronized (managedBundles) {
+            String id = managedBundlesByUrl.get(url);
+            if (id==null) return null;
+            return managedBundles.get(id);
+        }
+    }
+    
     /** See {@link OsgiArchiveInstaller#install()}, using default values */
     public ReferenceWithError<OsgiBundleInstallationResult> install(InputStream zipIn) {
-        return install(null, zipIn, true, false);
+        return new OsgiArchiveInstaller(this, null, zipIn).install();
+    }
+
+    /** See {@link OsgiArchiveInstaller#install()}, but deferring the start and catalog load */
+    public ReferenceWithError<OsgiBundleInstallationResult> installDeferredStart(@Nullable ManagedBundle knownBundleMetadata, @Nullable InputStream zipIn) {
+        OsgiArchiveInstaller installer = new OsgiArchiveInstaller(this, knownBundleMetadata, zipIn);
+        installer.setDeferredStart(true);
+        
+        return installer.install();
     }
     
-    /** See {@link OsgiArchiveInstaller#install()} */
+    /** See {@link OsgiArchiveInstaller#install()} - this exposes custom options */
+    @Beta
     public ReferenceWithError<OsgiBundleInstallationResult> install(@Nullable ManagedBundle knownBundleMetadata, @Nullable InputStream zipIn,
-            boolean loadCatalogBom, boolean forceUpdateOfNonSnapshots) {
+            boolean start, boolean loadCatalogBom, boolean forceUpdateOfNonSnapshots) {
         
         OsgiArchiveInstaller installer = new OsgiArchiveInstaller(this, knownBundleMetadata, zipIn);
+        installer.setStart(start);
         installer.setLoadCatalogBom(loadCatalogBom);
         installer.setForce(forceUpdateOfNonSnapshots);
         
@@ -262,7 +282,8 @@ public class OsgiManager {
             if (metadata==null) {
                 throw new IllegalStateException("No such bundle registered: "+bundleMetadata);
             }
-            managedBundleIds.remove(bundleMetadata.getVersionedName());
+            managedBundlesByNam.remove(bundleMetadata.getVersionedName());
+            managedBundlesByUrl.remove(bundleMetadata.getUrl());
         }
         mgmt.getRebindManager().getChangeListener().onUnmanaged(bundleMetadata);
 
@@ -280,7 +301,8 @@ public class OsgiManager {
         }
     }
 
-    void uninstallCatalogItemsFromBundle(VersionedName bundle) {
+    @Beta
+    public void uninstallCatalogItemsFromBundle(VersionedName bundle) {
         List<RegisteredType> thingsFromHere = ImmutableList.copyOf(getTypesFromBundle( bundle ));
         for (RegisteredType t: thingsFromHere) {
             mgmt.getCatalog().deleteCatalogItem(t.getSymbolicName(), t.getVersion());
@@ -338,11 +360,14 @@ public class OsgiManager {
 
                 catalogItems = new CatalogBundleLoader(applicationsPermitted, mgmt).scanForCatalog(bundle);
             } catch (RuntimeException ex) {
-                try {
-                    bundle.uninstall();
-                } catch (BundleException e) {
-                    log.error("Cannot uninstall bundle " + bundle.getSymbolicName() + ":" + bundle.getVersion(), e);
-                }
+                // TODO confirm -- as of May 2017 we no longer uninstall the bundle if install of catalog items fails;
+                // caller needs to upgrade, or uninstall then reinstall
+                // (this uninstall wouldn't have unmanaged it in brooklyn in any case)
+//                try {
+//                    bundle.uninstall();
+//                } catch (BundleException e) {
+//                    log.error("Cannot uninstall bundle " + bundle.getSymbolicName() + ":" + bundle.getVersion()+" (after error installing catalog items)", e);
+//                }
                 throw new IllegalArgumentException("Error installing catalog items", ex);
             }
         }
@@ -469,21 +494,39 @@ public class OsgiManager {
     }
 
     public Maybe<Bundle> findBundle(OsgiBundleWithUrl catalogBundle) {
-        //Either fail at install time when the user supplied name:version is different
-        //from the one reported from the bundle
-        //or
-        //Ignore user supplied name:version when URL is supplied to be able to find the
-        //bundle even if it's with a different version.
-        //
-        //For now we just log a warning if there's a version discrepancy at install time,
-        //so prefer URL if supplied.
-        BundleFinder bundleFinder = Osgis.bundleFinder(framework);
+        // Prefer OSGi Location as URL or the managed bundle recorded URL,
+        // not bothering to check name:version if supplied here (eg to forgive snapshot version discrepancies);
+        // but fall back to name/version if URL is not known.
+        // Version checking may be stricter at install time.
+        Maybe<Bundle> result = null;
         if (catalogBundle.getUrl() != null) {
+            BundleFinder bundleFinder = Osgis.bundleFinder(framework);
             bundleFinder.requiringFromUrl(catalogBundle.getUrl());
-        } else {
+            result = bundleFinder.find();
+            if (result.isPresent()) {
+                return result;
+            }
+            
+            ManagedBundle mb = getManagedBundleFromUrl(catalogBundle.getUrl());
+            if (mb!=null) {
+                bundleFinder.requiringFromUrl(null);
+                bundleFinder.symbolicName(mb.getSymbolicName()).version(mb.getVersion());
+                result = bundleFinder.find();
+                if (result.isPresent()) {
+                    return result;
+                }
+            }
+        }
+
+        if (catalogBundle.getSymbolicName()!=null) {
+            BundleFinder bundleFinder = Osgis.bundleFinder(framework);
             bundleFinder.symbolicName(catalogBundle.getSymbolicName()).version(catalogBundle.getVersion());
+            return bundleFinder.find();
+        }
+        if (result!=null) {
+            return result;
         }
-        return bundleFinder.find();
+        return Maybe.absent("Insufficient information in "+catalogBundle+" to find bundle");
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextImpl.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextImpl.java
index 13c85f6..6bea476 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextImpl.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindContextImpl.java
@@ -36,8 +36,10 @@ import org.apache.brooklyn.api.policy.Policy;
 import org.apache.brooklyn.api.sensor.Enricher;
 import org.apache.brooklyn.api.sensor.Feed;
 import org.apache.brooklyn.api.typereg.ManagedBundle;
+import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.util.collections.MutableMap;
+import org.osgi.framework.BundleException;
 
 import com.google.common.collect.Maps;
 
@@ -90,9 +92,16 @@ public class RebindContextImpl implements RebindContext {
     }
 
     // we don't track register/unregister of bundles; it isn't needed as it happens so early
-    public void installBundle(ManagedBundle bundle, InputStream zipInput) {
-        ((ManagementContextInternal)mgmt).getOsgiManager().get().install(bundle, zipInput, true, false).checkNoError();
+    // but we do need to know which ones to start subsequently
+    public OsgiBundleInstallationResult installBundle(ManagedBundle bundle, InputStream zipInput) {
+        return ((ManagementContextInternal)mgmt).getOsgiManager().get().installDeferredStart(bundle, zipInput).get();
     }
+    public void startBundle(OsgiBundleInstallationResult br) throws BundleException {
+        if (br.getDeferredStart()!=null) {
+            br.getDeferredStart().run();
+        }
+    }
+
     
     public void unregisterPolicy(Policy policy) {
         policies.remove(policy.getId());

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
index 34c795c..e92a774 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
@@ -34,8 +34,6 @@ import java.util.concurrent.Semaphore;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import com.google.common.collect.ImmutableList;
-
 import org.apache.brooklyn.api.catalog.BrooklynCatalog;
 import org.apache.brooklyn.api.catalog.CatalogItem;
 import org.apache.brooklyn.api.entity.Application;
@@ -82,6 +80,7 @@ import org.apache.brooklyn.core.location.AbstractLocation;
 import org.apache.brooklyn.core.location.internal.LocationInternal;
 import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContextSequential;
 import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
+import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
 import org.apache.brooklyn.core.mgmt.internal.BrooklynObjectManagementMode;
 import org.apache.brooklyn.core.mgmt.internal.BrooklynObjectManagerInternal;
 import org.apache.brooklyn.core.mgmt.internal.EntityManagerInternal;
@@ -115,6 +114,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Stopwatch;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -325,15 +325,24 @@ public abstract class RebindIteration {
         
         // Install bundles
         if (rebindManager.persistBundlesEnabled) {
+            List<OsgiBundleInstallationResult> installs = MutableList.of();
             logRebindingDebug("RebindManager installing bundles: {}", mementoManifest.getBundleIds());
             for (ManagedBundleMemento bundleM : mementoManifest.getBundles().values()) {
                 logRebindingDebug("RebindManager installing bundle {}", bundleM.getId());
                 try (InputStream in = bundleM.getJarContent().openStream()) {
-                    rebindContext.installBundle(instantiator.newManagedBundle(bundleM), in);
+                    installs.add(rebindContext.installBundle(instantiator.newManagedBundle(bundleM), in));
                 } catch (Exception e) {
                     exceptionHandler.onCreateFailed(BrooklynObjectType.MANAGED_BUNDLE, bundleM.getId(), bundleM.getSymbolicName(), e);
                 }
             }
+            // Start them all after we've installed them
+            for (OsgiBundleInstallationResult br: installs) {
+                try {
+                    rebindContext.startBundle(br);
+                } catch (Exception e) {
+                    exceptionHandler.onCreateFailed(BrooklynObjectType.MANAGED_BUNDLE, br.getMetadata().getId(), br.getMetadata().getSymbolicName(), e);
+                }
+            }
         } else {
             logRebindingDebug("Not rebinding bundles; feature disabled: {}", mementoManifest.getBundleIds());
         }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformer.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformer.java
index 78c8e91..5f2330d 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformer.java
@@ -28,7 +28,6 @@ import org.apache.brooklyn.api.mgmt.rebind.RebindExceptionHandler;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoPersister;
 import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoRawData;
 import org.apache.brooklyn.api.objs.BrooklynObjectType;
-import org.apache.brooklyn.core.mgmt.persist.BrooklynMementoPersisterToObjectStore;
 import org.apache.brooklyn.core.mgmt.rebind.transformer.impl.XsltTransformer;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.ResourceUtils;
@@ -46,6 +45,7 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Sets;
+import com.google.common.io.ByteSource;
 
 @Beta
 public class CompoundTransformer {
@@ -265,6 +265,7 @@ public class CompoundTransformer {
         Map<String, String> feeds = MutableMap.copyOf(rawData.getFeeds());
         Map<String, String> catalogItems = MutableMap.copyOf(rawData.getCatalogItems());
         Map<String, String> bundles = MutableMap.copyOf(rawData.getBundles());
+        Map<String, ByteSource> bundleJars = MutableMap.copyOf(rawData.getBundleJars());
 
         // TODO @neykov asks whether transformers should be run in registration order,
         // rather than in type order.  TBD.  (would be an easy change.)
@@ -328,7 +329,11 @@ public class CompoundTransformer {
                     LOG.warn("Unable to delete " + type + " id"+Strings.s(missing.size())+" ("+missing+"), "
                             + "because not found in persisted state (continuing)");
                 }
+                // bundles have to be supplied by ID, but if so they can be deleted along with the jars
                 bundles.keySet().removeAll(itemsToDelete);
+                for (String item: itemsToDelete) {
+                    bundleJars.remove(item+".jar");
+                }
                 break;
             case UNKNOWN:
                 break; // no-op
@@ -372,9 +377,12 @@ public class CompoundTransformer {
                         }
                         break;
                     case MANAGED_BUNDLE:
-                        for (Map.Entry<String, String> entry : bundles.entrySet()) {
-                            entry.setValue(transformer.transform(entry.getValue()));
-                        }
+                        // transform of bundles and JARs not supported - you can delete, that's all
+                        // TODO we should support a better way of adding/removing bundles,
+                        // e.g. start in management mode where you can edit brooklyn-managed bundles
+//                        for (Map.Entry<String, String> entry : bundles.entrySet()) {
+//                            entry.setValue(transformer.transform(entry.getValue()));
+//                        }
                         break;
                     case UNKNOWN:
                         break; // no-op
@@ -393,6 +401,7 @@ public class CompoundTransformer {
                 .feeds(feeds)
                 .catalogItems(catalogItems)
                 .bundles(bundles)
+                .bundleJars(bundleJars)
                 .build();
     }
     

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
index 4799c06..6c0fa35 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
@@ -185,5 +185,4 @@ public class BasicManagedBundle extends AbstractBrooklynObject implements Manage
     public static ManagedBundle of(CatalogBundle bundleUrl) {
         return new BasicManagedBundle(bundleUrl.getSymbolicName(), bundleUrl.getVersion(), bundleUrl.getUrl());
     }
-
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/test/java/org/apache/brooklyn/core/BrooklynVersionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/BrooklynVersionTest.java b/core/src/test/java/org/apache/brooklyn/core/BrooklynVersionTest.java
index ccaca98..049916c 100644
--- a/core/src/test/java/org/apache/brooklyn/core/BrooklynVersionTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/BrooklynVersionTest.java
@@ -29,9 +29,10 @@ import org.apache.brooklyn.core.catalog.internal.CatalogEntityItemDto;
 import org.apache.brooklyn.core.catalog.internal.CatalogItemBuilder;
 import org.apache.brooklyn.core.catalog.internal.CatalogItemDtoAbstract;
 import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
-import org.apache.brooklyn.util.osgi.OsgiTestResources;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
 import org.apache.brooklyn.test.support.TestResourceUnavailableException;
+import org.apache.brooklyn.util.core.osgi.OsgiTestBase;
+import org.apache.brooklyn.util.osgi.OsgiTestResources;
 import org.apache.brooklyn.util.text.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -101,6 +102,7 @@ public class BrooklynVersionTest {
         String version = "0.1.0";
         String type = "brooklyn.osgi.tests.SimpleEntity";
         List<String> libraries = Lists.newArrayList("classpath:" + OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+        OsgiTestBase.preinstallLibrariesLowLevelToPreventCatalogBomParsing(mgmt, libraries.toArray(new String[1]));
 
         CatalogEntityItemDto c1 = CatalogItemBuilder.newEntity(symName, version)
                 .javaType(type)

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java
index f19556e..d4cf6f5 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/osgi/OsgiVersionMoreEntityTest.java
@@ -46,6 +46,7 @@ import org.apache.brooklyn.test.support.TestResourceUnavailableException;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.core.osgi.OsgiTestBase;
 import org.apache.brooklyn.util.core.osgi.Osgis;
+import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.os.Os;
 import org.apache.brooklyn.util.osgi.OsgiTestResources;
@@ -128,9 +129,10 @@ public class OsgiVersionMoreEntityTest implements OsgiTestResources {
     protected RegisteredType addCatalogItemWithNameAndType(String symName, String version, String type, String ...libraries) {
         return addCatalogItemWithNameAndType(mgmt, symName, version, type, libraries);
     }
-
+    
     @SuppressWarnings("deprecation")
     static RegisteredType addCatalogItemWithNameAndType(ManagementContext mgmt, String symName, String version, String type, String ...libraries) {
+        OsgiTestBase.preinstallLibrariesLowLevelToPreventCatalogBomParsing(mgmt, libraries);
         CatalogEntityItemDto c1 = newCatalogItemWithNameAndType(symName, version, type, libraries);
         mgmt.getCatalog().addItem(c1);
         RegisteredType c2 = mgmt.getTypeRegistry().get(symName, version);

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/PersistenceStoreObjectAccessorWriterTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/PersistenceStoreObjectAccessorWriterTestFixture.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/PersistenceStoreObjectAccessorWriterTestFixture.java
index b4ac83f..47e4204 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/PersistenceStoreObjectAccessorWriterTestFixture.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/PersistenceStoreObjectAccessorWriterTestFixture.java
@@ -104,7 +104,7 @@ public abstract class PersistenceStoreObjectAccessorWriterTestFixture {
         Date write1 = accessor.getLastModifiedDate();
         Assert.assertNotNull(write1);
         
-        Time.sleep(getLastModifiedResolution().times(2));
+        Time.sleep(getLastModifiedResolution().multiply(2));
         accessor.put("abc");
         accessor.waitForCurrentWrites(TIMEOUT);
         Date write2 = accessor.getLastModifiedDate();

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
index 9b8ccae..59ea8f2 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializerTest.java
@@ -531,9 +531,7 @@ public class XmlMementoSerializerTest {
                 bundlePrefix + ":" + classname, bundlePrefix + ":" + oldClassname));
     }
 
-    // TODO This doesn't get the bundleName - should we expect it to? Is this because of 
-    // how we're using Felix? Would it also be true in Karaf?
-    @Test(groups="Broken")
+    @Test
     public void testOsgiBundleNamePrefixIncludedForDownstreamDependency() throws Exception {
         mgmt = LocalManagementContextForTests.builder(true).enableOsgiReusable().build();
         serializer.setLookupContext(newEmptyLookupManagementContext(mgmt, true));
@@ -546,9 +544,14 @@ public class XmlMementoSerializerTest {
         assertSerializeAndDeserialize(obj);
 
         // i.e. prepended with bundle name
-        String expectedForm = "<"+bundleName+":"+classname+">ALWAYS_TRUE</"+bundleName+":"+classname+">";
+        String expectedFormInFelix = "<"+classname+">ALWAYS_TRUE</"+classname+">";
+        String expectedFormInKaraf = "<"+bundleName+":"+classname+">ALWAYS_TRUE</"+bundleName+":"+classname+">";
         String serializedForm = serializer.toString(obj);
-        assertEquals(serializedForm.trim(), expectedForm.trim());
+        // TODO we don't currently have a way to test this with karaf or check if we are karaf or felix
+        // so this test isn't yet of much value, but other tests assert the full form for installed bundles
+        // so I think we're alright
+        Assert.assertTrue(serializedForm.trim().equals(expectedFormInFelix) || serializedForm.trim().equals(expectedFormInKaraf),
+            "Should have matched either the karaf or the felix form, but was "+serializedForm);
     }
     
     @Test

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerTest.java
index 9f8e582..05969ec 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformerTest.java
@@ -38,7 +38,6 @@ import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoRawData;
 import org.apache.brooklyn.api.objs.BrooklynObjectType;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.BasicConfigKey;
-import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.persist.BrooklynMementoPersisterToObjectStore;
 import org.apache.brooklyn.core.mgmt.persist.FileBasedObjectStore;
 import org.apache.brooklyn.core.mgmt.persist.PersistMode;

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/core/src/test/java/org/apache/brooklyn/util/core/osgi/OsgiTestBase.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/osgi/OsgiTestBase.java b/core/src/test/java/org/apache/brooklyn/util/core/osgi/OsgiTestBase.java
index db66c13..0e6d751 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/osgi/OsgiTestBase.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/osgi/OsgiTestBase.java
@@ -17,6 +17,10 @@ package org.apache.brooklyn.util.core.osgi;
 
 import java.io.File;
 import java.io.IOException;
+
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
+import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.os.Os;
 import org.apache.commons.io.FileUtils;
 import org.osgi.framework.BundleException;
@@ -53,4 +57,18 @@ public class OsgiTestBase {
         }
     }
 
+    public static void preinstallLibrariesLowLevelToPreventCatalogBomParsing(ManagementContext mgmt, String ...libraries) {
+        // catalog BOM CAMP syntax not available in core; need to pre-install
+        // to prevent Brooklyn from installing BOMs in those libraries
+        for (String lib: libraries) {
+            // install libs manually to prevent catalog BOM loading
+            // (could do OsgiManager.installDeferredStart also, then just ignore the start)
+            try {
+                Osgis.install(((ManagementContextInternal)mgmt).getOsgiManager().get().getFramework(), lib);
+            } catch (BundleException e) {
+                throw Exceptions.propagate(e);
+            }
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
----------------------------------------------------------------------
diff --git a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
index 7359e4d..c5a2b59 100644
--- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
+++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java
@@ -62,6 +62,7 @@ import org.apache.brooklyn.rest.domain.CatalogLocationSummary;
 import org.apache.brooklyn.rest.domain.CatalogPolicySummary;
 import org.apache.brooklyn.rest.filter.HaHotStateRequired;
 import org.apache.brooklyn.rest.transform.CatalogTransformer;
+import org.apache.brooklyn.rest.util.BrooklynRestResourceUtils;
 import org.apache.brooklyn.rest.util.WebResourceUtils;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
@@ -151,25 +152,35 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
     }
 
     public static class BundleInstallationRestResult {
+        // as Osgi result, but without bundle, and with maps of catalog items installed
+        
         String message;
         ManagedBundle metadata;
+        OsgiBundleInstallationResult.ResultCode code;
         
-        enum ResultCode { 
-            INSTALLED_NEW_BUNDLE,
-            UPDATED_EXISTING_BUNDLE, 
-            IGNORING_BUNDLE_AREADY_INSTALLED, 
-            ERROR_PREPARING_BUNDLE,
-            ERROR_INSTALLING_BUNDLE 
-        }
-        Map<String,Object> catalogItemsInstalled;
+        Map<String,Object> types;
         
         public String getMessage() {
             return message;
         }
         
-        public static BundleInstallationRestResult of(OsgiBundleInstallationResult result, ManagementContext mgmt) {
-            // TODO 
-            return null;
+        @SuppressWarnings("deprecation")
+        public static BundleInstallationRestResult of(OsgiBundleInstallationResult in, ManagementContext mgmt, BrooklynRestResourceUtils brooklynU, UriInfo ui) {
+            BundleInstallationRestResult result = new BundleInstallationRestResult();
+            result.message = in.getMessage();
+            result.metadata = in.getMetadata();
+            result.code = in.getCode();
+            if (in.getCatalogItemsInstalled()!=null) {
+                result.types = MutableMap.of();
+                for (String id: in.getCatalogItemsInstalled()) {
+                    // TODO prefer to use RegisteredType, but we need transformer for those in REST
+                    //RegisteredType ci = mgmt.getTypeRegistry().get(id);
+                    
+                    CatalogItem<?, ?> ci = CatalogUtils.getCatalogItemOptionalVersion(mgmt, id);
+                    CatalogTransformer.catalogItemSummary(brooklynU, ci, ui.getBaseUriBuilder());
+                }
+            }
+            return result;
         }
     }
     
@@ -186,10 +197,10 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat
         
         if (result.hasError()) {
             return ApiError.builder().errorCode(Status.BAD_REQUEST).message(result.getWithoutError().getMessage())
-                .data(result).build().asJsonResponse();
+                .data(BundleInstallationRestResult.of(result.getWithoutError(), mgmt(), brooklyn(), ui)).build().asJsonResponse();
         }
 
-        return Response.status(Status.CREATED).entity( BundleInstallationRestResult.of(result.get(), mgmt()) ).build();
+        return Response.status(Status.CREATED).entity( BundleInstallationRestResult.of(result.get(), mgmt(), brooklyn(), ui) ).build();
     }
 
     private Response buildCreateResponse(Iterable<? extends CatalogItem<?, ?>> catalogItems) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/062fdc4d/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java
----------------------------------------------------------------------
diff --git a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java
index 5cfcf4c..714dad4 100644
--- a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java
+++ b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/resources/CatalogResourceTest.java
@@ -59,6 +59,7 @@ import org.apache.brooklyn.rest.domain.CatalogItemSummary;
 import org.apache.brooklyn.rest.domain.CatalogLocationSummary;
 import org.apache.brooklyn.rest.domain.CatalogPolicySummary;
 import org.apache.brooklyn.rest.testing.BrooklynRestResourceTest;
+import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.test.support.TestResourceUnavailableException;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.ResourceUtils;
@@ -483,7 +484,7 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
                 .post(Streams.readFully(new FileInputStream(f)));
 
         assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
-        assertTrue(response.readEntity(String.class).contains("Invalid ZIP/JAR archive"));
+        Asserts.assertStringContainsIgnoreCase(response.readEntity(String.class), "zip file is empty");
     }
 
     @Test
@@ -495,7 +496,7 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
                 .post(Streams.readFully(new FileInputStream(f)));
 
         assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
-        assertTrue(response.readEntity(String.class).contains("Archive must contain a catalog.bom file in the root"));
+        Asserts.assertStringContainsIgnoreCase(response.readEntity(String.class), "Missing bundle symbolic name in BOM or MANIFEST");
     }
 
     @Test
@@ -514,7 +515,7 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
                 .post(Streams.readFully(new FileInputStream(f)));
 
         assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
-        assertTrue(response.readEntity(String.class).contains("Catalog BOM must define bundle and version"));
+        Asserts.assertStringContainsIgnoreCase(response.readEntity(String.class), "Missing bundle symbolic name in BOM or MANIFEST");
     }
 
     @Test
@@ -534,7 +535,8 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
                 .post(Streams.readFully(new FileInputStream(f)));
 
         assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
-        assertTrue(response.readEntity(String.class).contains("Catalog BOM must define bundle"));
+        Asserts.assertStringContainsIgnoreCase(response.readEntity(String.class), 
+            "Missing bundle symbolic name in BOM or MANIFEST");
     }
 
     @Test
@@ -554,7 +556,7 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
                 .post(Streams.readFully(new FileInputStream(f)));
 
         assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
-        assertTrue(response.readEntity(String.class).contains("Catalog BOM must define version"));
+        Asserts.assertStringContainsIgnoreCase(response.readEntity(String.class), "Catalog BOM must define version");
     }
 
     @Test
@@ -562,6 +564,7 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
         String name = "My Catalog App";
         String bundle = "org.apache.brooklyn.test";
         String version = "0.1.0";
+        String wrongBundleName = "org.apache.brooklyn.test2";
         File f = createJar(ImmutableMap.<String, String>of(
                 "catalog.bom", Joiner.on("\n").join(
                         "brooklyn.catalog:",
@@ -576,7 +579,7 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
                 "META-INF/MANIFEST.MF", Joiner.on("\n").join(
                         "Manifest-Version: 1.0",
                         "Bundle-Name: " + name,
-                        "Bundle-SymbolicName: org.apache.brooklyn.test2",
+                        "Bundle-SymbolicName: "+wrongBundleName,
                         "Bundle-Version: " + version,
                         "Bundle-ManifestVersion: " + version)));
 
@@ -585,7 +588,9 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
                 .post(Streams.readFully(new FileInputStream(f)));
 
         assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
-        assertTrue(response.readEntity(String.class).contains("JAR MANIFEST symbolic-name 'org.apache.brooklyn.test2' does not match '"+bundle+"' defined in BOM"));
+        Asserts.assertStringContainsIgnoreCase(response.readEntity(String.class), 
+            "symbolic name mismatch",
+            wrongBundleName, bundle);
     }
 
     @Test
@@ -593,6 +598,7 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
         String name = "My Catalog App";
         String bundle = "org.apache.brooklyn.test";
         String version = "0.1.0";
+        String wrongVersion = "0.3.0";
         File f = createJar(ImmutableMap.<String, String>of(
                 "catalog.bom", Joiner.on("\n").join(
                         "brooklyn.catalog:",
@@ -608,15 +614,17 @@ public class CatalogResourceTest extends BrooklynRestResourceTest {
                         "Manifest-Version: 1.0",
                         "Bundle-Name: " + name,
                         "Bundle-SymbolicName: " + bundle,
-                        "Bundle-Version: 0.3.0",
-                        "Bundle-ManifestVersion: 0.3.0")));
+                        "Bundle-Version: " + wrongVersion,
+                        "Bundle-ManifestVersion: " + wrongVersion)));
 
         Response response = client().path("/catalog")
                 .header(HttpHeaders.CONTENT_TYPE, "application/x-jar")
                 .post(Streams.readFully(new FileInputStream(f)));
 
         assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
-        assertTrue(response.readEntity(String.class).contains("JAR MANIFEST version '0.3.0' does not match '"+version+"' defined in BOM"));
+        Asserts.assertStringContainsIgnoreCase(response.readEntity(String.class), 
+            "version mismatch",
+            wrongVersion, version);
     }
 
     @Test