You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2014/11/04 15:29:55 UTC

[01/18] git commit: Fix rebinding to entities/policies living in OSGi bundles

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master d36f3483e -> d5636527a


Fix rebinding to entities/policies living in OSGi bundles

When an entity/policy is created from a catalog item we make a note of its related catalog item id. On rebind we use that information to get the class loading context from the corresponding catalog item so that classes from OSGi bundles referenced in the item config are accessible.


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

Branch: refs/heads/master
Commit: b454beb60e0f99a615c082ee3d1366b92b3e1ed7
Parents: e24d3cd
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Mon Oct 27 18:16:55 2014 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Mon Oct 27 22:55:11 2014 +0200

----------------------------------------------------------------------
 .../mementos/BrooklynMementoManifest.java       |  11 +-
 .../catalog/internal/BasicBrooklynCatalog.java  |  12 +-
 .../brooklyn/entity/basic/BrooklynTags.java     |   2 +
 .../entity/rebind/RebindManagerImpl.java        | 241 +++++++++++--------
 .../rebind/dto/BrooklynMementoManifestImpl.java |  53 +++-
 .../AbstractBrooklynMementoPersister.java       |  21 +-
 .../BrooklynMementoPersisterInMemory.java       |   2 +-
 .../BrooklynMementoPersisterToMultiFile.java    |   5 +-
 .../BrooklynMementoPersisterToObjectStore.java  |  21 +-
 .../BrooklynAssemblyTemplateInstantiator.java   |   6 +-
 10 files changed, 251 insertions(+), 123 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b454beb6/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java b/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java
index cff691b..f8a40a6 100644
--- a/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java
+++ b/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java
@@ -19,8 +19,11 @@
 package brooklyn.mementos;
 
 import java.io.Serializable;
+import java.util.Collection;
 import java.util.Map;
 
+import brooklyn.util.guava.Maybe;
+
 /**
  * Represents a manifest of the entities etc in the overall memento.
  * 
@@ -30,6 +33,8 @@ public interface BrooklynMementoManifest extends Serializable {
 
     public Map<String, String> getEntityIdToType();
 
+    public Map<String, Maybe<String>> getEntityIdToContextCatalogItemId();
+
     public Map<String, String> getLocationIdToType();
 
     public Map<String, String> getPolicyIdToType();
@@ -38,7 +43,11 @@ public interface BrooklynMementoManifest extends Serializable {
 
     public Map<String, String> getFeedIdToType();
     
-    public Map<String, String> getCatalogItemIdToType();
+    public CatalogItemMemento getCatalogItemMemento(String id);
+
+    public Collection<String> getCatalogItemIds();
+
+    public Map<String, CatalogItemMemento> getCatalogItemMementos();
 
     public boolean isEmpty();
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b454beb6/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
index 98e2222..18a77f7 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -42,6 +42,7 @@ import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogPredicates;
 import brooklyn.config.BrooklynServerConfig;
+import brooklyn.entity.basic.BrooklynTags;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.classloading.BrooklynClassLoadingContext;
@@ -241,22 +242,27 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         if (specType==null) return null;
 
         String yaml = loadedItem.getPlanYaml();
-        SpecT spec = null;
 
         if (yaml!=null) {
             DeploymentPlan plan = makePlanFromYaml(yaml);
             BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, item);
+            SpecT spec;
             switch (item.getCatalogItemType()) {
                 case TEMPLATE:
                 case ENTITY:
-                    return createEntitySpec(plan, loader);
+                    spec = createEntitySpec(plan, loader);
+                    break;
                 case POLICY:
-                    return createPolicySpec(plan, loader);
+                    spec = createPolicySpec(plan, loader);
+                    break;
                 default: throw new RuntimeException("Only entity & policy catalog items are supported. Unsupported catalog item type " + item.getCatalogItemType());
             }
+            ((AbstractBrooklynObjectSpec<?, ?>)spec).tag(BrooklynTags.newContextCatalogItemIdTag(item.getId()));
+            return spec;
         }
 
         // revert to legacy mechanism
+        SpecT spec = null;
         try {
             if (loadedItem.getJavaType()!=null) {
                 SpecT specT = (SpecT) Reflections.findMethod(specType, "create", Class.class).invoke(null, loadedItem.loadJavaClass(mgmt));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b454beb6/core/src/main/java/brooklyn/entity/basic/BrooklynTags.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/BrooklynTags.java b/core/src/main/java/brooklyn/entity/basic/BrooklynTags.java
index 01ac52e..67b4b42 100644
--- a/core/src/main/java/brooklyn/entity/basic/BrooklynTags.java
+++ b/core/src/main/java/brooklyn/entity/basic/BrooklynTags.java
@@ -29,6 +29,7 @@ import com.google.common.annotations.Beta;
 public class BrooklynTags {
 
     public static final String YAML_SPEC_KIND = "yaml_spec";
+    public static final String CONTEXT_CATALOG_ITEM_ID_KIND = "context_catalog_item_id";
     public static final String NOTES_KIND = "notes";
     
     public static class NamedStringTag implements Serializable {
@@ -53,6 +54,7 @@ public class BrooklynTags {
     }
     
     public static NamedStringTag newYamlSpecTag(String contents) { return new NamedStringTag(YAML_SPEC_KIND, contents); }
+    public static NamedStringTag newContextCatalogItemIdTag(String contents) { return new NamedStringTag(CONTEXT_CATALOG_ITEM_ID_KIND, contents); }
     public static NamedStringTag newNotesTag(String contents) { return new NamedStringTag(NOTES_KIND, contents); }
     
     public static NamedStringTag findFirst(String kind, Iterable<Object> tags) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b454beb6/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index d9ce494..8eee9eb 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -38,6 +38,7 @@ import brooklyn.basic.BrooklynObject;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogLoadMode;
 import brooklyn.catalog.internal.BasicBrooklynCatalog;
+import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.config.BrooklynServerConfig;
 import brooklyn.config.ConfigKey;
 import brooklyn.enricher.basic.AbstractEnricher;
@@ -46,6 +47,8 @@ import brooklyn.entity.Entity;
 import brooklyn.entity.Feed;
 import brooklyn.entity.basic.AbstractApplication;
 import brooklyn.entity.basic.AbstractEntity;
+import brooklyn.entity.basic.BrooklynTags;
+import brooklyn.entity.basic.BrooklynTags.NamedStringTag;
 import brooklyn.entity.basic.ConfigKeys;
 import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.proxying.InternalEntityFactory;
@@ -60,6 +63,8 @@ import brooklyn.location.basic.AbstractLocation;
 import brooklyn.location.basic.LocationInternal;
 import brooklyn.management.ExecutionContext;
 import brooklyn.management.Task;
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
+import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
 import brooklyn.management.ha.HighAvailabilityManagerImpl;
 import brooklyn.management.ha.ManagementNodeState;
 import brooklyn.management.internal.EntityManagerInternal;
@@ -85,6 +90,7 @@ import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.exceptions.RuntimeInterruptedException;
 import brooklyn.util.flags.FlagUtils;
+import brooklyn.util.guava.Maybe;
 import brooklyn.util.javalang.Reflections;
 import brooklyn.util.task.BasicExecutionContext;
 import brooklyn.util.task.ScheduledTask;
@@ -485,26 +491,30 @@ public class RebindManagerImpl implements RebindManager {
             LookupContext realLookupContext = new RebindContextLookupContext(managementContext, rebindContext, exceptionHandler);
             
             // Mutli-phase deserialization.
+            //
             //  1. deserialize just the "manifest" to find all instances (and their types).
-            //  2. instantiate entities+locations so that inter-entity references can subsequently be set during deserialize (and entity config/state is set).
-            //  3. deserialize the memento
-            //  4. instantiate policies+enrichers (could perhaps merge this with (2), depending how they are implemented)
-            //  5. reconstruct the entities etc (i.e. calling init on the already-instantiated instances).
-            //  6. add policies+enrichers to all the entities.
-            //  7. manage the entities
+            //  2. instantiate and reconstruct catalog items
+            //  3. instantiate entities+locations so that inter-entity references can subsequently be set during deserialize (and entity config/state is set).
+            //  4. deserialize the memento
+            //  5. instantiate policies+enricherss+feeds (could perhaps merge this with (3), depending how they are implemented)
+            //  6. reconstruct the entities etc (i.e. calling init on the already-instantiated instances).
+            //  7. add policies+enrichers+feeds to all the entities.
+            //  8. manage the entities
             
-            // TODO if underlying data-store is changed between first and second phase (e.g. to add an
+            // TODO if underlying data-store is changed between first and second manifest read (e.g. to add an
             // entity), then second phase might try to reconstitute an entity that has not been put in
             // the rebindContext. This should not affect normal production usage, because rebind is run
             // against a data-store that is not being written to by other brooklyn instance(s).
 
-            
             //
             // PHASE ONE
             //
-            
+
+            //The manifest contains full catalog items mementos. Reading them at this stage means that
+            //we don't support references to entities/locations withing tags.
+
             BrooklynMementoManifest mementoManifest = persistenceStoreAccess.loadMementoManifest(exceptionHandler);
-            
+
             boolean isEmpty = mementoManifest.isEmpty();
             if (!isEmpty) {
                 if (mode==ManagementNodeState.HOT_STANDBY)
@@ -518,11 +528,84 @@ public class RebindManagerImpl implements RebindManager {
                     LOG.info("Rebind check: no existing state; will persist new items to "+getPersister().getBackingStoreDescription());
             }
 
-            
             //
             // PHASE TWO
             //
             
+            // Instantiate catalog items
+            if (persistCatalogItemsEnabled) {
+                LOG.debug("RebindManager instantiating catalog items: {}", mementoManifest.getCatalogItemIds());
+                for (CatalogItemMemento catalogItemMemento : mementoManifest.getCatalogItemMementos().values()) {
+                    if (LOG.isDebugEnabled()) LOG.debug("RebindManager instantiating catalog item {}", catalogItemMemento);
+                    try {
+                        CatalogItem<?, ?> catalogItem = newCatalogItem(catalogItemMemento, reflections);
+                        rebindContext.registerCatalogItem(catalogItemMemento.getId(), catalogItem);
+                    } catch (Exception e) {
+                        exceptionHandler.onCreateFailed(BrooklynObjectType.CATALOG_ITEM, catalogItemMemento.getId(), catalogItemMemento.getType(), e);
+                    }
+                }
+            } else {
+                LOG.debug("Not rebinding catalog; feature disabled: {}", mementoManifest.getCatalogItemIds());
+            }
+
+            // Reconstruct catalog entries
+            if (persistCatalogItemsEnabled) {
+                LOG.debug("RebindManager reconstructing catalog items");
+                for (CatalogItemMemento catalogItemMemento : mementoManifest.getCatalogItemMementos().values()) {
+                    CatalogItem<?, ?> item = rebindContext.getCatalogItem(catalogItemMemento.getId());
+                    LOG.debug("RebindManager reconstructing catalog item {}", catalogItemMemento);
+                    if (item == null) {
+                        exceptionHandler.onNotFound(BrooklynObjectType.CATALOG_ITEM, catalogItemMemento.getId());
+                    } else {
+                        try {
+                            item.getRebindSupport().reconstruct(rebindContext, catalogItemMemento);
+                            if (item instanceof AbstractBrooklynObject) {
+                                AbstractBrooklynObject.class.cast(item).setManagementContext(managementContext);
+                            }
+                        } catch (Exception e) {
+                            exceptionHandler.onRebindFailed(BrooklynObjectType.CATALOG_ITEM, item, e);
+                        }
+                    }
+                }
+            }
+            
+            // Register catalogue items with the management context. Loads the bundles in the OSGi framework.
+            CatalogLoadMode catalogLoadMode = managementContext.getConfig().getConfig(BrooklynServerConfig.CATALOG_LOAD_MODE);
+            if (persistCatalogItemsEnabled) {
+                boolean shouldResetCatalog = catalogLoadMode == CatalogLoadMode.LOAD_PERSISTED_STATE
+                        || (!isEmpty && catalogLoadMode == CatalogLoadMode.LOAD_BROOKLYN_CATALOG_URL_IF_NO_PERSISTED_STATE);
+                boolean shouldLoadDefaultCatalog = catalogLoadMode == CatalogLoadMode.LOAD_BROOKLYN_CATALOG_URL
+                        || (isEmpty && catalogLoadMode == CatalogLoadMode.LOAD_BROOKLYN_CATALOG_URL_IF_NO_PERSISTED_STATE);
+                if (shouldResetCatalog) {
+                    // Reset catalog with previously persisted state
+                    LOG.debug("RebindManager resetting management context catalog to previously persisted state");
+                    managementContext.getCatalog().reset(rebindContext.getCatalogItems());
+                } else if (shouldLoadDefaultCatalog) {
+                    // Load catalogue as normal
+                    // TODO in read-only mode, should do this less frequently than entities etc
+                    LOG.debug("RebindManager loading default catalog");
+                    ((BasicBrooklynCatalog) managementContext.getCatalog()).resetCatalogToContentsAtConfiguredUrl();
+                } else {
+                    // Management context should have taken care of loading the catalogue
+                    Collection<CatalogItem<?, ?>> catalogItems = rebindContext.getCatalogItems();
+                    String message = "RebindManager not resetting catalog to persisted state. Catalog load mode is {}.";
+                    if (!catalogItems.isEmpty()) {
+                        LOG.info(message + " There {} {} item{} persisted.", new Object[]{
+                                catalogLoadMode, catalogItems.size() == 1 ? "was" : "were", catalogItems.size(), Strings.s(catalogItems)});
+                    } else if (LOG.isDebugEnabled()) {
+                        LOG.debug(message, catalogLoadMode);
+                    }
+                }
+                // TODO destroy old (as above)
+            } else {
+                LOG.debug("RebindManager not resetting catalog because catalog persistence is disabled");
+            }
+            
+            
+            //
+            // PHASE THREE
+            //
+            
             // Instantiate locations
             LOG.debug("RebindManager instantiating locations: {}", mementoManifest.getLocationIdToType().keySet());
             for (Map.Entry<String, String> entry : mementoManifest.getLocationIdToType().entrySet()) {
@@ -543,10 +626,11 @@ public class RebindManagerImpl implements RebindManager {
             for (Map.Entry<String, String> entry : mementoManifest.getEntityIdToType().entrySet()) {
                 String entityId = entry.getKey();
                 String entityType = entry.getValue();
+                Maybe<String> contextCatalogItemId = mementoManifest.getEntityIdToContextCatalogItemId().get(entityId);
                 if (LOG.isTraceEnabled()) LOG.trace("RebindManager instantiating entity {}", entityId);
                 
                 try {
-                    Entity entity = newEntity(entityId, entityType, reflections);
+                    Entity entity = newEntity(entityId, entityType, getEntityLoadingContext(entityId, contextCatalogItemId, classLoader, rebindContext));
                     rebindContext.registerEntity(entityId, entity);
                 } catch (Exception e) {
                     exceptionHandler.onCreateFailed(BrooklynObjectType.ENTITY, entityId, entityType, e);
@@ -555,14 +639,14 @@ public class RebindManagerImpl implements RebindManager {
             
             
             //
-            // PHASE THREE
+            // PHASE FOUR
             //
             
             BrooklynMemento memento = persistenceStoreAccess.loadMemento(realLookupContext, exceptionHandler);
-
+            
             
             //
-            // PHASE FOUR
+            // PHASE FIVE
             //
             
             // Instantiate policies
@@ -572,7 +656,7 @@ public class RebindManagerImpl implements RebindManager {
                     if (LOG.isDebugEnabled()) LOG.debug("RebindManager instantiating policy {}", policyMemento);
                     
                     try {
-                        Policy policy = newPolicy(policyMemento, reflections);
+                        Policy policy = newPolicy(policyMemento, getPolicyLoadingContext(policyMemento.getId(), memento, classLoader, rebindContext));
                         rebindContext.registerPolicy(policyMemento.getId(), policy);
                     } catch (Exception e) {
                         exceptionHandler.onCreateFailed(BrooklynObjectType.POLICY, policyMemento.getId(), policyMemento.getType(), e);
@@ -616,24 +700,8 @@ public class RebindManagerImpl implements RebindManager {
                 LOG.debug("Not rebinding feeds; feature disabled: {}", memento.getFeedIds());
             } 
 
-            // Instantiate catalog items
-            if (persistCatalogItemsEnabled) {
-                LOG.debug("RebindManager instantiating catalog items: {}", memento.getCatalogItemIds());
-                for (CatalogItemMemento catalogItemMemento : memento.getCatalogItemMementos().values()) {
-                    if (LOG.isDebugEnabled()) LOG.debug("RebindManager instantiating catalog item {}", catalogItemMemento);
-                    try {
-                        CatalogItem<?, ?> catalogItem = newCatalogItem(catalogItemMemento, reflections);
-                        rebindContext.registerCatalogItem(catalogItemMemento.getId(), catalogItem);
-                    } catch (Exception e) {
-                        exceptionHandler.onCreateFailed(BrooklynObjectType.CATALOG_ITEM, catalogItemMemento.getId(), catalogItemMemento.getType(), e);
-                    }
-                }
-            } else {
-                LOG.debug("Not rebinding catalog; feature disabled: {}", memento.getCatalogItemIds());
-            }
-
             //
-            // PHASE FIVE
+            // PHASE SIX
             //
             
             // Reconstruct locations
@@ -736,32 +804,11 @@ public class RebindManagerImpl implements RebindManager {
                 }
             }
 
-            // Reconstruct catalog entries
-            if (persistCatalogItemsEnabled) {
-                LOG.debug("RebindManager reconstructing catalog items");
-                for (CatalogItemMemento catalogItemMemento : memento.getCatalogItemMementos().values()) {
-                    CatalogItem<?, ?> item = rebindContext.getCatalogItem(catalogItemMemento.getId());
-                    LOG.debug("RebindManager reconstructing catalog item {}", catalogItemMemento);
-                    if (item == null) {
-                        exceptionHandler.onNotFound(BrooklynObjectType.CATALOG_ITEM, catalogItemMemento.getId());
-                    } else {
-                        try {
-                            item.getRebindSupport().reconstruct(rebindContext, catalogItemMemento);
-                            if (item instanceof AbstractBrooklynObject) {
-                                AbstractBrooklynObject.class.cast(item).setManagementContext(managementContext);
-                            }
-                        } catch (Exception e) {
-                            exceptionHandler.onRebindFailed(BrooklynObjectType.CATALOG_ITEM, item, e);
-                        }
-                    }
-                }
-            }
-
             //
-            // PHASE SIX
+            // PHASE SEVEN
             //
             
-            // Associate policies+enrichers with entities
+            // Associate policies+enrichers+feeds with entities
             LOG.debug("RebindManager reconstructing entities");
             for (EntityMemento entityMemento : sortParentFirst(memento.getEntityMementos()).values()) {
                 Entity entity = rebindContext.getEntity(entityMemento.getId());
@@ -786,7 +833,7 @@ public class RebindManagerImpl implements RebindManager {
             
             
             //
-            // PHASE SEVEN
+            // PHASE EIGHT
             //
 
             LOG.debug("RebindManager managing locations");
@@ -845,38 +892,6 @@ public class RebindManagerImpl implements RebindManager {
                entityManager.unmanage(entityManager.getEntity(oldEntityId), ManagementTransitionMode.REBINDING_DESTROYED); 
             }
 
-            // Register catalogue items with the management context.
-            CatalogLoadMode catalogLoadMode = managementContext.getConfig().getConfig(BrooklynServerConfig.CATALOG_LOAD_MODE);
-            if (persistCatalogItemsEnabled) {
-                boolean shouldResetCatalog = catalogLoadMode == CatalogLoadMode.LOAD_PERSISTED_STATE
-                        || (!isEmpty && catalogLoadMode == CatalogLoadMode.LOAD_BROOKLYN_CATALOG_URL_IF_NO_PERSISTED_STATE);
-                boolean shouldLoadDefaultCatalog = catalogLoadMode == CatalogLoadMode.LOAD_BROOKLYN_CATALOG_URL
-                        || (isEmpty && catalogLoadMode == CatalogLoadMode.LOAD_BROOKLYN_CATALOG_URL_IF_NO_PERSISTED_STATE);
-                if (shouldResetCatalog) {
-                    // Reset catalog with previously persisted state
-                    LOG.debug("RebindManager resetting management context catalog to previously persisted state");
-                    managementContext.getCatalog().reset(rebindContext.getCatalogItems());
-                } else if (shouldLoadDefaultCatalog) {
-                    // Load catalogue as normal
-                    // TODO in read-only mode, should do this less frequently than entities etc
-                    LOG.debug("RebindManager loading default catalog");
-                    ((BasicBrooklynCatalog) managementContext.getCatalog()).resetCatalogToContentsAtConfiguredUrl();
-                } else {
-                    // Management context should have taken care of loading the catalogue
-                    Collection<CatalogItem<?, ?>> catalogItems = rebindContext.getCatalogItems();
-                    String message = "RebindManager not resetting catalog to persisted state. Catalog load mode is {}.";
-                    if (!catalogItems.isEmpty()) {
-                        LOG.info(message + " There {} {} item{} persisted.", new Object[]{
-                                catalogLoadMode, catalogItems.size() == 1 ? "was" : "were", catalogItems.size(), Strings.s(catalogItems)});
-                    } else if (LOG.isDebugEnabled()) {
-                        LOG.debug(message, catalogLoadMode);
-                    }
-                }
-                // TODO destroy old (as above)
-            } else {
-                LOG.debug("RebindManager not resetting catalog because catalog persistence is disabled");
-            }
-
             exceptionHandler.onDone();
 
             if (!isEmpty && mode!=ManagementNodeState.HOT_STANDBY) {
@@ -903,6 +918,41 @@ public class RebindManagerImpl implements RebindManager {
         }
     }
     
+    private BrooklynClassLoadingContext getEntityLoadingContext(String entityId, Maybe<String> contextCatalogItemId, ClassLoader classLoader, RebindContextImpl rebindContext) {
+        return getLoadingContextFromCatalogItemId(contextCatalogItemId, classLoader, rebindContext);
+    }
+
+    private BrooklynClassLoadingContext getPolicyLoadingContext(String policyId, BrooklynMemento memento, ClassLoader classLoader, RebindContextImpl rebindContext) {
+        PolicyMemento policyMemento = memento.getPolicyMemento(policyId);
+        Maybe<String> contextCatalogItemId = getContextCatalogItemIdFromTags(policyMemento.getTags());
+        return getLoadingContextFromCatalogItemId(contextCatalogItemId, classLoader, rebindContext);
+    }
+
+    private Maybe<String> getContextCatalogItemIdFromTags(Collection<Object> tags) {
+        for (Object obj : tags) {
+            if (obj instanceof NamedStringTag) {
+                NamedStringTag tag = (NamedStringTag) obj;
+                if (BrooklynTags.CONTEXT_CATALOG_ITEM_ID_KIND.equals(tag.getKind())) {
+                    return Maybe.of(tag.getContents());
+                }
+            }
+        }
+        return Maybe.absent();
+    }
+
+    private BrooklynClassLoadingContext getLoadingContextFromCatalogItemId(Maybe<String> catalogItemId, ClassLoader classLoader, RebindContext rebindContext) {
+        if (catalogItemId.isPresent()) {
+            CatalogItem<?, ?> catalogItem = rebindContext.getCatalogItem(catalogItemId.get());
+            if (catalogItem != null) {
+                return CatalogUtils.newClassLoadingContext(managementContext, catalogItem);
+            } else {
+                throw new IllegalStateException("Failed to load catalog item " + catalogItemId + " required for rebinding.");
+            }
+        } else {
+            return new JavaBrooklynClassLoadingContext(managementContext, classLoader);
+        }
+    }
+
     static ManagementTransitionMode computeMode(BrooklynObject item, ManagementTransitionMode oldMode, boolean isNowReadOnly) {
         return computeMode(item, oldMode==null ? null : oldMode.wasReadOnly(), isNowReadOnly);
     }
@@ -953,8 +1003,8 @@ public class RebindManagerImpl implements RebindManager {
         return result;
     }
 
-    private Entity newEntity(String entityId, String entityType, Reflections reflections) {
-        Class<? extends Entity> entityClazz = reflections.loadClass(entityType, Entity.class);
+    private Entity newEntity(String entityId, String entityType, BrooklynClassLoadingContext loader) {
+        Class<? extends Entity> entityClazz = loader.loadClass(entityType, Entity.class);
         
         if (InternalFactory.isNewStyle(entityClazz)) {
             // Not using entityManager.createEntity(EntitySpec) because don't want init() to be called.
@@ -977,7 +1027,7 @@ public class RebindManagerImpl implements RebindManager {
 
             // TODO document the multiple sources of flags, and the reason for setting the mgmt context *and* supplying it as the flag
             // (NB: merge reported conflict as the two things were added separately)
-            Entity entity = (Entity) invokeConstructor(reflections, entityClazz, new Object[] {flags}, new Object[] {flags, null}, new Object[] {null}, new Object[0]);
+            Entity entity = (Entity) invokeConstructor(null, entityClazz, new Object[] {flags}, new Object[] {flags, null}, new Object[] {null}, new Object[0]);
             
             // In case the constructor didn't take the Map arg, then also set it here.
             // e.g. for top-level app instances such as WebClusterDatabaseExampleApp will (often?) not have
@@ -1029,11 +1079,10 @@ public class RebindManagerImpl implements RebindManager {
     /**
      * Constructs a new policy, passing to its constructor the policy id and all of memento.getConfig().
      */
-    @SuppressWarnings("unchecked")
-    private Policy newPolicy(PolicyMemento memento, Reflections reflections) {
+    private Policy newPolicy(PolicyMemento memento, BrooklynClassLoadingContext loader) {
         String id = memento.getId();
         String policyType = checkNotNull(memento.getType(), "policy type of %s must not be null in memento", id);
-        Class<? extends Policy> policyClazz = (Class<? extends Policy>) reflections.loadClass(policyType);
+        Class<? extends Policy> policyClazz = loader.loadClass(policyType, Policy.class);
 
         if (InternalFactory.isNewStyle(policyClazz)) {
             InternalPolicyFactory policyFactory = managementContext.getPolicyFactory();
@@ -1055,7 +1104,7 @@ public class RebindManagerImpl implements RebindManager {
                     "noConstructionInit", true);
             flags.putAll(memento.getConfig());
 
-            return (Policy) invokeConstructor(reflections, policyClazz, new Object[] {flags});
+            return (Policy) invokeConstructor(null, policyClazz, new Object[] {flags});
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b454beb6/core/src/main/java/brooklyn/entity/rebind/dto/BrooklynMementoManifestImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/BrooklynMementoManifestImpl.java b/core/src/main/java/brooklyn/entity/rebind/dto/BrooklynMementoManifestImpl.java
index 4d1339b..6c0fb4e 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/BrooklynMementoManifestImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/BrooklynMementoManifestImpl.java
@@ -19,10 +19,13 @@
 package brooklyn.entity.rebind.dto;
 
 import java.io.Serializable;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
 
 import brooklyn.mementos.BrooklynMementoManifest;
+import brooklyn.mementos.CatalogItemMemento;
+import brooklyn.util.guava.Maybe;
 
 import com.google.common.collect.Maps;
 
@@ -37,17 +40,26 @@ public class BrooklynMementoManifestImpl implements BrooklynMementoManifest, Ser
     public static class Builder {
         protected String brooklynVersion;
         protected final Map<String, String> entityIdToType = Maps.newConcurrentMap();
+        protected final Map<String, Maybe<String>> entityIdToContextCatalogItemId = Maps.newConcurrentMap();
         protected final Map<String, String> locationIdToType = Maps.newConcurrentMap();
         protected final Map<String, String> policyIdToType = Maps.newConcurrentMap();
         protected final Map<String, String> enricherIdToType = Maps.newConcurrentMap();
         protected final Map<String, String> feedIdToType = Maps.newConcurrentMap();
-        protected final Map<String, String> catalogItemIdToType = Maps.newConcurrentMap();
+        protected final Map<String, CatalogItemMemento> catalogItems = Maps.newConcurrentMap();
         
         public Builder brooklynVersion(String val) {
             brooklynVersion = val; return this;
         }
-        public Builder entity(String id, String type) {
-            entityIdToType.put(id, type); return this;
+        public Builder entity(String id, String type, String catalogItemId) {
+            entityIdToType.put(id, type);
+            Maybe<String> catalogItemIdOption;
+            if (catalogItemId != null) {
+                catalogItemIdOption = Maybe.of(catalogItemId);
+            } else {
+                catalogItemIdOption = Maybe.absent();
+            }
+            entityIdToContextCatalogItemId.put(id, catalogItemIdOption);
+            return this;
         }
         public Builder entities(Map<String, String> vals) {
             entityIdToType.putAll(vals); return this;
@@ -76,11 +88,11 @@ public class BrooklynMementoManifestImpl implements BrooklynMementoManifest, Ser
         public Builder feed(Map<String, String> vals) {
             feedIdToType.putAll(vals); return this;
         }
-        public Builder catalogItem(String id, String type) {
-            catalogItemIdToType.put(id, type); return this;
+        public Builder catalogItems(Map<String, CatalogItemMemento> vals) {
+            catalogItems.putAll(vals); return this;
         }
-        public Builder catalogItems(Map<String, String> vals) {
-            catalogItemIdToType.putAll(vals); return this;
+        public Builder catalogItem(CatalogItemMemento val) {
+            catalogItems.put(val.getId(), val); return this;
         }
 
         public BrooklynMementoManifest build() {
@@ -89,19 +101,21 @@ public class BrooklynMementoManifestImpl implements BrooklynMementoManifest, Ser
     }
 
     private final Map<String, String> entityIdToType;
+    private final Map<String, Maybe<String>> entityIdToContextCatalogItemId;
     private final Map<String, String> locationIdToType;
     private final Map<String, String> policyIdToType;
     private final Map<String, String> enricherIdToType;
     private final Map<String, String> feedIdToType;
-    private final Map<String, String> catalogItemIdToType;
+    private Map<String, CatalogItemMemento> catalogItems;
     
     private BrooklynMementoManifestImpl(Builder builder) {
         entityIdToType = builder.entityIdToType;
+        entityIdToContextCatalogItemId = builder.entityIdToContextCatalogItemId;
         locationIdToType = builder.locationIdToType;
         policyIdToType = builder.policyIdToType;
         enricherIdToType = builder.enricherIdToType;
         feedIdToType = builder.feedIdToType;
-        catalogItemIdToType = builder.catalogItemIdToType;
+        catalogItems = builder.catalogItems;
     }
 
     @Override
@@ -110,6 +124,11 @@ public class BrooklynMementoManifestImpl implements BrooklynMementoManifest, Ser
     }
 
     @Override
+    public Map<String, Maybe<String>> getEntityIdToContextCatalogItemId() {
+        return Collections.unmodifiableMap(entityIdToContextCatalogItemId);
+    }
+
+    @Override
     public Map<String, String> getLocationIdToType() {
         return Collections.unmodifiableMap(locationIdToType);
     }
@@ -130,8 +149,18 @@ public class BrooklynMementoManifestImpl implements BrooklynMementoManifest, Ser
     }
     
     @Override
-    public Map<String, String> getCatalogItemIdToType() {
-        return Collections.unmodifiableMap(catalogItemIdToType);
+    public CatalogItemMemento getCatalogItemMemento(String id) {
+        return catalogItems.get(id);
+    }
+
+    @Override
+    public Collection<String> getCatalogItemIds() {
+        return Collections.unmodifiableSet(catalogItems.keySet());
+    }
+
+    @Override
+    public Map<String, CatalogItemMemento> getCatalogItemMementos() {
+        return Collections.unmodifiableMap(catalogItems);
     }
 
     @Override
@@ -141,7 +170,7 @@ public class BrooklynMementoManifestImpl implements BrooklynMementoManifest, Ser
                 policyIdToType.isEmpty() &&
                 enricherIdToType.isEmpty() &&
                 feedIdToType.isEmpty() &&
-                catalogItemIdToType.isEmpty();
+                catalogItems.isEmpty();
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b454beb6/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java b/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
index c230e9e..ff75aa9 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
@@ -19,6 +19,11 @@
 package brooklyn.entity.rebind.persister;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Collection;
+
+import brooklyn.entity.basic.BrooklynTags;
+import brooklyn.entity.basic.BrooklynTags.NamedStringTag;
 import brooklyn.entity.rebind.PersistenceExceptionHandler;
 import brooklyn.entity.rebind.RebindExceptionHandler;
 import brooklyn.entity.rebind.dto.BrooklynMementoManifestImpl;
@@ -51,7 +56,7 @@ public abstract class AbstractBrooklynMementoPersister implements BrooklynMement
     public BrooklynMementoManifest loadMementoManifest(RebindExceptionHandler exceptionHandler) {
         BrooklynMementoManifestImpl.Builder builder = BrooklynMementoManifestImpl.builder();
         for (EntityMemento entity : memento.getEntityMementos().values()) {
-            builder.entity(entity.getId(), entity.getType());
+            builder.entity(entity.getId(), entity.getType(), getContextCatalogItemId(entity.getTags()));
         }
         for (LocationMemento entity : memento.getLocationMementos().values()) {
             builder.location(entity.getId(), entity.getType());
@@ -63,11 +68,23 @@ public abstract class AbstractBrooklynMementoPersister implements BrooklynMement
             builder.enricher(entity.getId(), entity.getType());
         }
         for (CatalogItemMemento entity : memento.getCatalogItemMementos().values()) {
-            builder.catalogItem(entity.getId(), entity.getType());
+            builder.catalogItem(entity);
         }
         return builder.build();
     }
 
+    private String getContextCatalogItemId(Collection<Object> tags) {
+        for (Object obj : tags) {
+            if (obj instanceof NamedStringTag) {
+                NamedStringTag tag = (NamedStringTag) obj;
+                if (BrooklynTags.CONTEXT_CATALOG_ITEM_ID_KIND.equals(tag.getKind())) {
+                    return tag.getContents();
+                }
+            }
+        }
+        return null;
+    }
+
     @Override public void enableWriteAccess() {}
     @Override public void disableWriteAccess(boolean graceful) {}
     @Override public void stop(boolean graceful) {}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b454beb6/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java
index f9ddc1c..0fdd64b 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java
@@ -152,7 +152,7 @@ public class BrooklynMementoPersisterInMemory extends AbstractBrooklynMementoPer
                         return (Feed) invokeConstructor(clazz, new Object[0], new Object[] {MutableMap.of()});
                     }
                     @Override public CatalogItem<?, ?> lookupCatalogItem(String id) {
-                        Class<?> clazz = loadClass(manifest.getCatalogItemIdToType().get(id));
+                        Class<?> clazz = loadClass(manifest.getCatalogItemMemento(id).getType());
                         return (CatalogItem<?,?>) invokeConstructor(clazz, new Object[0]);
                     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b454beb6/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
index b58aea5..eb67ee7 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
@@ -32,6 +32,8 @@ import java.util.concurrent.TimeoutException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.entity.basic.BrooklynTags;
+import brooklyn.entity.basic.BrooklynTags.NamedStringTag;
 import brooklyn.entity.rebind.BrooklynObjectType;
 import brooklyn.entity.rebind.PersistenceExceptionHandler;
 import brooklyn.entity.rebind.RebindExceptionHandler;
@@ -192,7 +194,8 @@ public class BrooklynMementoPersisterToMultiFile implements BrooklynMementoPersi
                     String contents = readFile(file);
                     String id = (String) XmlUtil.xpath(contents, "/entity/id");
                     String type = (String) XmlUtil.xpath(contents, "/entity/type");
-                    builder.entity(id, type);
+                    String contextCatalogItemId = (String) XmlUtil.xpath(contents, "/entity/tags/" + NamedStringTag.class.getName().replace("$", "_-") + "[kind='" + BrooklynTags.CONTEXT_CATALOG_ITEM_ID_KIND + "']/contents");
+                    builder.entity(id, type, contextCatalogItemId);
                 } catch (Exception e) {
                     exceptionHandler.onLoadMementoFailed(BrooklynObjectType.ENTITY, "File "+file, e);
                 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b454beb6/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
index 98fff36..6d86a35 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
@@ -37,7 +37,9 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.config.BrooklynProperties;
 import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.BrooklynTags;
 import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.BrooklynTags.NamedStringTag;
 import brooklyn.entity.rebind.BrooklynObjectType;
 import brooklyn.entity.rebind.PeriodicDeltaChangeListener;
 import brooklyn.entity.rebind.PersistenceExceptionHandler;
@@ -60,6 +62,7 @@ import brooklyn.mementos.Memento;
 import brooklyn.mementos.PolicyMemento;
 import brooklyn.util.exceptions.CompoundRuntimeException;
 import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.text.Strings;
 import brooklyn.util.time.Duration;
 import brooklyn.util.time.Time;
 import brooklyn.util.xstream.XmlUtil;
@@ -251,7 +254,8 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
                     case ENTITY:
                         String id = (String) XmlUtil.xpath(contents, "/entity/id");
                         String objType = (String) XmlUtil.xpath(contents, "/entity/type");
-                        builder.entity(id, objType);
+                        String contextCatalogItemId = (String) XmlUtil.xpath(contents, "/entity/tags/" + NamedStringTag.class.getName().replace("$", "_-") + "[kind='" + BrooklynTags.CONTEXT_CATALOG_ITEM_ID_KIND + "']/contents");
+                        builder.entity(id, objType, Strings.isEmpty(contextCatalogItemId) ? null : contextCatalogItemId);
                         break;
                     case LOCATION:
                         id = (String) XmlUtil.xpath(contents, "/location/id");
@@ -274,9 +278,16 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
                         builder.feed(id, objType);
                         break;
                     case CATALOG_ITEM:
-                        id = (String) XmlUtil.xpath(contents, "/catalogItem/id");
-                        objType = (String) XmlUtil.xpath(contents, "/catalogItem/type");
-                        builder.catalogItem(id, objType);
+                        try {
+                            CatalogItemMemento memento = (CatalogItemMemento) serializer.fromString(contents);
+                            if (memento == null) {
+                                LOG.warn("No "+type.toString().toLowerCase()+"-memento deserialized from " + subPath + "; ignoring and continuing");
+                            } else {
+                                builder.catalogItem(memento);
+                            }
+                        } catch (Exception e) {
+                            exceptionHandler.onLoadMementoFailed(type, "Memento "+subPath, e);
+                        }
                         break;
                     default:
                         throw new IllegalStateException("Unexpected brooklyn type: "+type);
@@ -294,7 +305,7 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
             LOG.debug("Loaded memento manifest; took {}; {} entities, {} locations, {} policies, {} enrichers, {} feeds, {} catalog items, from {}", new Object[]{
                      Time.makeTimeStringRounded(stopwatch.elapsed(TimeUnit.MILLISECONDS)), result.getEntityIdToType().size(), 
                      result.getLocationIdToType().size(), result.getPolicyIdToType().size(), result.getEnricherIdToType().size(), 
-                     result.getFeedIdToType().size(), result.getCatalogItemIdToType().size(),
+                     result.getFeedIdToType().size(), result.getCatalogItemMementos().size(),
                      objectStore.getSummaryName() });
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b454beb6/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index 5f594c4..1d05811 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -32,7 +32,6 @@ import java.io.InputStreamReader;
 import java.io.Reader;
 import java.io.StringReader;
 import java.util.List;
-import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
@@ -42,12 +41,13 @@ import org.slf4j.LoggerFactory;
 import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
 import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
 import brooklyn.catalog.CatalogItem;
-import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
+import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.config.BrooklynServerConfig;
 import brooklyn.entity.Application;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.BasicApplicationImpl;
+import brooklyn.entity.basic.BrooklynTags;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.classloading.BrooklynClassLoadingContext;
@@ -201,7 +201,9 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
                 }
                 spec = entityResolver.resolveSpec();
             } else {
+                //TODO migrate to catalog.createSpec
                 spec = resolveCatalogYamlReferenceSpec(mgmt, item, encounteredCatalogTypes);
+                spec.tag(BrooklynTags.newContextCatalogItemIdTag(item.getId()));
                 entityResolver.populateSpec(spec);
             }
         }


[17/18] git commit: code review, and fixing failing test and rat checks

Posted by he...@apache.org.
code review, and fixing failing test and rat checks


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

Branch: refs/heads/master
Commit: 32f2bd79121b2f39e7b27efa60f78da7d1263d56
Parents: 0b89adc
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Nov 4 13:18:15 2014 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 4 13:20:16 2014 +0000

----------------------------------------------------------------------
 .../brooklyn/osgi/tests/more/MoreEntity.java     |  3 ++-
 .../osgi/OsgiVersionMoreEntityTest.java          |  4 ++--
 .../more-entity-v1-called-v1-osgi-catalog.yaml   | 19 ++++++++++++++++++-
 .../catalog/more-entity-v1-osgi-catalog.yaml     | 19 ++++++++++++++++++-
 .../more-entity-v1-with-policy-osgi-catalog.yaml | 19 ++++++++++++++++++-
 .../catalog/more-entity-v2-osgi-catalog.yaml     | 19 ++++++++++++++++++-
 .../catalog/simple-policy-osgi-catalog.yaml      | 19 ++++++++++++++++++-
 7 files changed, 94 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/32f2bd79/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java b/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
index f26f1f1..955388c 100644
--- a/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
+++ b/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
@@ -32,7 +32,8 @@ public interface MoreEntity extends Entity {
         .parameter(String.class, "name")
         .buildAbstract();
 
-    /** Makes a string saying hi to the given name, in uppercase, for testing. */
+    /** Makes a string saying hi to the given name, in uppercase, for testing. 
+     * In contrast to v1, impl here returns HI not Hi. */
     String sayHI(String name);
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/32f2bd79/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
index 4175639..c5df30d 100644
--- a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
@@ -207,8 +207,8 @@ public class OsgiVersionMoreEntityTest {
         String catalogItemId = Iterables.getOnlyElement( me.getPolicies() ).getCatalogItemId();
         Assert.assertNotNull(catalogItemId);
         // must be the actual source bundle
-        Assert.assertFalse(catalogItemId.equals(me.getCatalogItemId()));
-        Assert.assertTrue(catalogItemId.startsWith("brooklyn-test-osgi-entities"));
+        Assert.assertFalse(catalogItemId.equals(me.getCatalogItemId()), "catalog item id is: "+catalogItemId);
+        Assert.assertTrue(catalogItemId.equals(OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_POLICY), "catalog item id is: "+catalogItemId);
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/32f2bd79/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-called-v1-osgi-catalog.yaml
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-called-v1-osgi-catalog.yaml b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-called-v1-osgi-catalog.yaml
index 058dc33..0bc4997 100644
--- a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-called-v1-osgi-catalog.yaml
+++ b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-called-v1-osgi-catalog.yaml
@@ -1,4 +1,21 @@
-
+#
+# 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.
+#
 services:
 - type: brooklyn.osgi.tests.more.MoreEntity
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/32f2bd79/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-osgi-catalog.yaml
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-osgi-catalog.yaml b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-osgi-catalog.yaml
index 574a35e..940053d 100644
--- a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-osgi-catalog.yaml
+++ b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-osgi-catalog.yaml
@@ -1,4 +1,21 @@
-
+#
+# 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.
+#
 services:
 - type: brooklyn.osgi.tests.more.MoreEntity
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/32f2bd79/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-with-policy-osgi-catalog.yaml
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-with-policy-osgi-catalog.yaml b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-with-policy-osgi-catalog.yaml
index c1ab77d..79657d8 100644
--- a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-with-policy-osgi-catalog.yaml
+++ b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-with-policy-osgi-catalog.yaml
@@ -1,4 +1,21 @@
-
+#
+# 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.
+#
 services:
 - type: brooklyn.osgi.tests.more.MoreEntity
   brooklyn.policies:

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/32f2bd79/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v2-osgi-catalog.yaml
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v2-osgi-catalog.yaml b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v2-osgi-catalog.yaml
index 4f102b5..7b29439 100644
--- a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v2-osgi-catalog.yaml
+++ b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v2-osgi-catalog.yaml
@@ -1,4 +1,21 @@
-
+#
+# 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.
+#
 services:
 - type: brooklyn.osgi.tests.more.MoreEntity
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/32f2bd79/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/simple-policy-osgi-catalog.yaml
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/simple-policy-osgi-catalog.yaml b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/simple-policy-osgi-catalog.yaml
index b3f407c..0004513 100644
--- a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/simple-policy-osgi-catalog.yaml
+++ b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/simple-policy-osgi-catalog.yaml
@@ -1,4 +1,21 @@
-
+#
+# 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.
+#
 brooklyn.policies:
 - type: brooklyn.osgi.tests.SimplePolicy
 


[06/18] git commit: Fix compile warnings

Posted by he...@apache.org.
Fix compile warnings


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

Branch: refs/heads/master
Commit: 246c29d33cc859d160864d46a7385fb929459ae8
Parents: d2d4e61
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Thu Oct 30 14:33:25 2014 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Thu Oct 30 14:33:25 2014 +0200

----------------------------------------------------------------------
 .../brooklyn/catalog/internal/BasicBrooklynCatalog.java   |  7 +++----
 .../creation/BrooklynAssemblyTemplateInstantiator.java    |  1 -
 .../spi/creation/BrooklynComponentTemplateResolver.java   | 10 +++++++---
 .../spi/lookup/AbstractTemplateBrooklynLookup.java        |  2 +-
 .../spi/lookup/AssemblyTemplateBrooklynLookup.java        |  2 +-
 .../lookup/PlatformComponentTemplateBrooklynLookup.java   |  2 +-
 6 files changed, 13 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/246c29d3/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
index f8bd2c8..bdb73d7 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -42,7 +42,6 @@ import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogPredicates;
 import brooklyn.config.BrooklynServerConfig;
-import brooklyn.entity.basic.BrooklynTags;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.classloading.BrooklynClassLoadingContext;
@@ -117,7 +116,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     
     public void reset(CatalogDto dto) {
         // Unregister all existing persisted items.
-        for (CatalogItem toRemove : getCatalogItems()) {
+        for (CatalogItem<?, ?> toRemove : getCatalogItems()) {
             if (log.isTraceEnabled()) {
                 log.trace("Scheduling item for persistence removal: {}", toRemove.getId());
             }
@@ -133,9 +132,9 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
         for (CatalogItem<?, ?> entry : getCatalogItems()) {
             boolean setManagementContext = false;
             if (entry instanceof CatalogItemDo) {
-                CatalogItemDo cid = CatalogItemDo.class.cast(entry);
+                CatalogItemDo<?, ?> cid = CatalogItemDo.class.cast(entry);
                 if (cid.getDto() instanceof CatalogItemDtoAbstract) {
-                    CatalogItemDtoAbstract cdto = CatalogItemDtoAbstract.class.cast(cid.getDto());
+                    CatalogItemDtoAbstract<?, ?> cdto = CatalogItemDtoAbstract.class.cast(cid.getDto());
                     if (cdto.getManagementContext() == null) {
                         cdto.setManagementContext((ManagementContextInternal) mgmt);
                     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/246c29d3/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index 346b19c..8bd1073 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -47,7 +47,6 @@ import brooklyn.config.BrooklynServerConfig;
 import brooklyn.entity.Application;
 import brooklyn.entity.Entity;
 import brooklyn.entity.basic.BasicApplicationImpl;
-import brooklyn.entity.basic.BrooklynTags;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.classloading.BrooklynClassLoadingContext;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/246c29d3/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index d4192b4..14a932d 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -277,10 +277,14 @@ public class BrooklynComponentTemplateResolver {
         if (planId==null)
             planId = (String) attrs.getStringKey(BrooklynCampConstants.PLAN_ID_FLAG);
 
-        Object children = attrs.getStringKey("brooklyn.children");
-        if (children != null) {
+        Object childrenObj = attrs.getStringKey("brooklyn.children");
+        if (childrenObj != null) {
             Set<String> encounteredCatalogTypes = MutableSet.of();
-            for (Map<String,?> childAttrs : (Iterable<Map<String,?>>)children) {
+
+            @SuppressWarnings("unchecked")
+            Iterable<Map<String,?>> children = (Iterable<Map<String,?>>)childrenObj;
+
+            for (Map<String,?> childAttrs : children) {
                 BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(loader, childAttrs);
                 BrooklynAssemblyTemplateInstantiator instantiator = new BrooklynAssemblyTemplateInstantiator();
                 // TODO: Creating a new set of encounteredCatalogTypes prevents the recursive definition check in

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/246c29d3/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
index 9aac6ec..8d815ee 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
@@ -51,7 +51,7 @@ public abstract class AbstractTemplateBrooklynLookup<T extends AbstractResource>
     public abstract T adapt(CatalogItem<?,?> item);
 
     protected ResolvableLink<T> newLink(CatalogItem<? extends Entity,EntitySpec<?>> li) {
-        return newLink(li.getId(), li.getName());
+        return newLink(li.getId(), li.getDisplayName());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/246c29d3/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
index 19baee6..adf9f70 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
@@ -42,7 +42,7 @@ public class AssemblyTemplateBrooklynLookup extends AbstractTemplateBrooklynLook
     @Override
     public AssemblyTemplate adapt(CatalogItem<?,?> item) {
         return AssemblyTemplate.builder().
-                name(item.getName()).
+                name(item.getDisplayName()).
                 id(item.getId()).
                 description(item.getDescription()).
                 created(root.getCreated()).

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/246c29d3/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
index e9d415d..9cabc33 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
@@ -40,7 +40,7 @@ public class PlatformComponentTemplateBrooklynLookup extends AbstractTemplateBro
     @Override
     public PlatformComponentTemplate adapt(CatalogItem<?,?> item) {
         return PlatformComponentTemplate.builder().
-                name(item.getName()).
+                name(item.getDisplayName()).
                 id(item.getId()).
                 description(item.getDescription()).
                 created(root.getCreated()).


[13/18] OSGi catalog item test (see full msg for details)

Posted by he...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
new file mode 100644
index 0000000..83cd46d
--- /dev/null
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java
@@ -0,0 +1,187 @@
+/*
+ * 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 io.brooklyn.camp.brooklyn.catalog;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+import io.brooklyn.camp.brooklyn.AbstractYamlTest;
+
+import java.util.Collection;
+
+import org.testng.annotations.Test;
+
+import brooklyn.catalog.CatalogItem;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.BasicEntity;
+import brooklyn.management.osgi.OsgiStandaloneTest;
+import brooklyn.management.osgi.OsgiTestResources;
+
+import com.google.common.collect.Iterables;
+
+
+public class CatalogYamlEntityTest extends AbstractYamlTest {
+    
+    private static final String SIMPLE_ENTITY_TYPE = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_ENTITY;
+
+    @Test
+    public void testAddCatalogItem() throws Exception {
+        String registeredTypeName = "my.catalog.app.id.load";
+        addCatalogOSGiEntity(registeredTypeName);
+
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(registeredTypeName);
+        assertEquals(item.getRegisteredTypeName(), registeredTypeName);
+
+        deleteCatalogEntity(registeredTypeName);
+    }
+
+    @Test
+    public void testLaunchApplicationReferencingCatalog() throws Exception {
+        String registeredTypeName = "my.catalog.app.id.launch";
+        registerAndLaunchAndAssertSimpleEntity(registeredTypeName, SIMPLE_ENTITY_TYPE);
+    }
+
+    @Test
+    public void testLaunchApplicationWithCatalogReferencingOtherCatalog() throws Exception {
+        String referencedRegisteredTypeName = "my.catalog.app.id.referenced";
+        String referrerRegisteredTypeName = "my.catalog.app.id.referring";
+        addCatalogOSGiEntity(referencedRegisteredTypeName, SIMPLE_ENTITY_TYPE);
+        addCatalogOSGiEntity(referrerRegisteredTypeName, referencedRegisteredTypeName);
+
+        String yaml = "name: simple-app-yaml\n" +
+                      "location: localhost\n" +
+                      "services: \n" +
+                      "  - serviceType: "+referrerRegisteredTypeName;
+        Entity app = createAndStartApplication(yaml);
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(simpleEntity.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
+
+        deleteCatalogEntity(referencedRegisteredTypeName);
+        deleteCatalogEntity(referrerRegisteredTypeName);
+    }
+
+    @Test
+    public void testLaunchApplicationChildWithCatalogReferencingOtherCatalog() throws Exception {
+        String referencedRegisteredTypeName = "my.catalog.app.id.child.referenced";
+        String referrerRegisteredTypeName = "my.catalog.app.id.child.referring";
+        addCatalogOSGiEntity(referencedRegisteredTypeName, SIMPLE_ENTITY_TYPE);
+        addCatalogChildOSGiEntity(referrerRegisteredTypeName, referencedRegisteredTypeName);
+
+        Entity app = createAndStartApplication(
+            "name: simple-app-yaml",
+            "location: localhost",
+            "services:",
+            "- serviceType: "+BasicEntity.class.getName(),
+            "  brooklyn.children:",
+            "  - type: " + referrerRegisteredTypeName);
+
+        Collection<Entity> children = app.getChildren();
+        assertEquals(children.size(), 1);
+        Entity child = Iterables.getOnlyElement(children);
+        assertEquals(child.getEntityType().getName(), BasicEntity.class.getName());
+        Collection<Entity> grandChildren = child.getChildren();
+        assertEquals(grandChildren.size(), 1);
+        Entity grandChild = Iterables.getOnlyElement(grandChildren);
+        assertEquals(grandChild.getEntityType().getName(), BasicEntity.class.getName());
+        Collection<Entity> grandGrandChildren = grandChild.getChildren();
+        assertEquals(grandGrandChildren.size(), 1);
+        Entity grandGrandChild = Iterables.getOnlyElement(grandGrandChildren);
+        assertEquals(grandGrandChild.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
+
+        deleteCatalogEntity(referencedRegisteredTypeName);
+        deleteCatalogEntity(referrerRegisteredTypeName);
+    }
+
+    @Test
+    public void testLaunchApplicationWithTypeUsingJavaColonPrefix() throws Exception {
+        String registeredTypeName = SIMPLE_ENTITY_TYPE;
+        String serviceName = "java:"+SIMPLE_ENTITY_TYPE;
+        registerAndLaunchAndAssertSimpleEntity(registeredTypeName, serviceName);
+    }
+
+    @Test
+    public void testLaunchApplicationLoopWithJavaTypeName() throws Exception {
+        String registeredTypeName = SIMPLE_ENTITY_TYPE;
+        String serviceName = SIMPLE_ENTITY_TYPE;
+        registerAndLaunchAndAssertSimpleEntity(registeredTypeName, serviceName);
+    }
+
+    @Test
+    public void testLaunchApplicationChildLoopCatalogIdFails() throws Exception {
+        String referrerRegisteredTypeName = "my.catalog.app.id.child.referring";
+        try {
+            addCatalogChildOSGiEntity(referrerRegisteredTypeName, referrerRegisteredTypeName);
+            fail("Expected to throw IllegalStateException");
+        } catch (IllegalStateException e) {
+            assertTrue(e.getMessage().contains("Could not find "+referrerRegisteredTypeName));
+        }
+    }
+
+    private void registerAndLaunchAndAssertSimpleEntity(String registeredTypeName, String serviceType) throws Exception {
+        addCatalogOSGiEntity(registeredTypeName, serviceType);
+        String yaml = "name: simple-app-yaml\n" +
+                      "location: localhost\n" +
+                      "services: \n" +
+                      "  - serviceType: "+registeredTypeName;
+        Entity app = createAndStartApplication(yaml);
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        assertEquals(simpleEntity.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
+
+        deleteCatalogEntity(registeredTypeName);
+    }
+
+    private void addCatalogOSGiEntity(String registeredTypeName) {
+        addCatalogOSGiEntity(registeredTypeName, SIMPLE_ENTITY_TYPE);
+    }
+
+    private void addCatalogOSGiEntity(String registeredTypeName, String serviceType) {
+        addCatalogItem(
+            "brooklyn.catalog:",
+            "  id: " + registeredTypeName,
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: 0.1.2",
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "services:",
+            "- type: " + serviceType);
+    }
+
+    private void addCatalogChildOSGiEntity(String registeredTypeName, String serviceType) {
+        addCatalogItem(
+            "brooklyn.catalog:",
+            "  id: " + registeredTypeName,
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: 0.1.2",
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "services:",
+            "- type: " + BasicEntity.class.getName(),
+            "  brooklyn.children:",
+            "  - type: " + serviceType);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
new file mode 100644
index 0000000..0d5c44d
--- /dev/null
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogYamlPolicyTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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 io.brooklyn.camp.brooklyn.catalog;
+
+import static org.testng.Assert.assertEquals;
+import io.brooklyn.camp.brooklyn.AbstractYamlTest;
+
+import org.testng.annotations.Test;
+
+import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.CatalogPredicates;
+import brooklyn.entity.Entity;
+import brooklyn.event.basic.BasicConfigKey;
+import brooklyn.management.osgi.OsgiStandaloneTest;
+import brooklyn.policy.Policy;
+
+import com.google.common.collect.Iterables;
+
+public class CatalogYamlPolicyTest extends AbstractYamlTest {
+    private static final String SIMPLE_POLICY_TYPE = "brooklyn.osgi.tests.SimplePolicy";
+    private static final String SIMPLE_ENTITY_TYPE = "brooklyn.osgi.tests.SimpleEntity";
+
+    @Test
+    public void testAddCatalogItem() throws Exception {
+        assertEquals(countCatalogPolicies(), 0);
+
+        String registeredTypeName = "my.catalog.policy.id.load";
+        addCatalogOSGiPolicy(registeredTypeName, SIMPLE_POLICY_TYPE);
+
+        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(registeredTypeName);
+        assertEquals(item.getRegisteredTypeName(), registeredTypeName);
+        assertEquals(countCatalogPolicies(), 1);
+
+        deleteCatalogEntity(registeredTypeName);
+    }
+
+    @Test
+    public void testLaunchApplicationReferencingPolicy() throws Exception {
+        String registeredTypeName = "my.catalog.policy.id.launch";
+        addCatalogOSGiPolicy(registeredTypeName, SIMPLE_POLICY_TYPE);
+        Entity app = createAndStartApplication(
+            "name: simple-app-yaml",
+            "location: localhost",
+            "services: ",
+            "  - type: brooklyn.entity.basic.BasicEntity\n" +
+            "    brooklyn.policies:\n" +
+            "    - type: " + registeredTypeName,
+            "      brooklyn.config:",
+            "        config2: config2 override",
+            "        config3: config3");
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        Policy policy = Iterables.getOnlyElement(simpleEntity.getPolicies());
+        assertEquals(policy.getPolicyType().getName(), SIMPLE_POLICY_TYPE);
+        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config1")), "config1");
+        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config2")), "config2 override");
+        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config3")), "config3");
+
+        deleteCatalogEntity(registeredTypeName);
+    }
+
+    @Test
+    public void testLaunchApplicationWithCatalogReferencingOtherCatalog() throws Exception {
+        String referencedRegisteredTypeName = "my.catalog.policy.id.referenced";
+        String referrerRegisteredTypeName = "my.catalog.policy.id.referring";
+        addCatalogOSGiPolicy(referencedRegisteredTypeName, SIMPLE_POLICY_TYPE);
+
+        addCatalogItem(
+            "brooklyn.catalog:",
+            "  id: " + referrerRegisteredTypeName,
+            "  name: My Catalog App",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: 0.1.2",
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "services:",
+            "- type: " + SIMPLE_ENTITY_TYPE,
+            "  brooklyn.policies:",
+            "  - type: " + referencedRegisteredTypeName);
+
+        String yaml = "name: simple-app-yaml\n" +
+                      "location: localhost\n" +
+                      "services: \n" +
+                      "  - serviceType: "+referrerRegisteredTypeName;
+
+        Entity app = createAndStartApplication(yaml);
+
+        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
+        Policy policy = Iterables.getOnlyElement(simpleEntity.getPolicies());
+        assertEquals(policy.getPolicyType().getName(), SIMPLE_POLICY_TYPE);
+
+        deleteCatalogEntity(referencedRegisteredTypeName);
+    }
+
+    private void addCatalogOSGiPolicy(String registeredTypeName, String serviceType) {
+        addCatalogItem(
+            "brooklyn.catalog:",
+            "  id: " + registeredTypeName,
+            "  name: My Catalog Policy",
+            "  description: My description",
+            "  icon_url: classpath://path/to/myicon.jpg",
+            "  version: 0.1.2",
+            "  libraries:",
+            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
+            "",
+            "brooklyn.policies:",
+            "- type: " + serviceType,
+            "  brooklyn.config:",
+            "    config1: config1",
+            "    config2: config2");
+    }
+
+    private int countCatalogPolicies() {
+        return Iterables.size(mgmt().getCatalog().getCatalogItems(CatalogPredicates.IS_POLICY));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-called-v1-osgi-catalog.yaml
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-called-v1-osgi-catalog.yaml b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-called-v1-osgi-catalog.yaml
new file mode 100644
index 0000000..058dc33
--- /dev/null
+++ b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-called-v1-osgi-catalog.yaml
@@ -0,0 +1,10 @@
+
+services:
+- type: brooklyn.osgi.tests.more.MoreEntity
+
+brooklyn.catalog:
+  id: more-entity-v1
+  version: 1.0
+  # see OsgiTestResources
+  libraries:
+  - classpath:/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-osgi-catalog.yaml
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-osgi-catalog.yaml b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-osgi-catalog.yaml
new file mode 100644
index 0000000..574a35e
--- /dev/null
+++ b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-osgi-catalog.yaml
@@ -0,0 +1,10 @@
+
+services:
+- type: brooklyn.osgi.tests.more.MoreEntity
+
+brooklyn.catalog:
+  id: more-entity
+  version: 1.0
+  # see OsgiTestResources
+  libraries:
+  - classpath:/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-with-policy-osgi-catalog.yaml
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-with-policy-osgi-catalog.yaml b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-with-policy-osgi-catalog.yaml
new file mode 100644
index 0000000..c1ab77d
--- /dev/null
+++ b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v1-with-policy-osgi-catalog.yaml
@@ -0,0 +1,12 @@
+
+services:
+- type: brooklyn.osgi.tests.more.MoreEntity
+  brooklyn.policies:
+  - type: simple-policy
+
+brooklyn.catalog:
+  id: more-entity
+  version: 1.0
+  # see OsgiTestResources
+  libraries:
+  - classpath:/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v2-osgi-catalog.yaml
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v2-osgi-catalog.yaml b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v2-osgi-catalog.yaml
new file mode 100644
index 0000000..4f102b5
--- /dev/null
+++ b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/more-entity-v2-osgi-catalog.yaml
@@ -0,0 +1,11 @@
+
+services:
+- type: brooklyn.osgi.tests.more.MoreEntity
+
+brooklyn.catalog:
+  id: more-entity
+  version: 2.0
+  # see OsgiTestResources
+  libraries:
+  - classpath:/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
+  - classpath:/brooklyn/osgi/brooklyn-test-osgi-entities.jar

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/simple-policy-osgi-catalog.yaml
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/simple-policy-osgi-catalog.yaml b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/simple-policy-osgi-catalog.yaml
new file mode 100644
index 0000000..b3f407c
--- /dev/null
+++ b/usage/camp/src/test/resources/io/brooklyn/camp/brooklyn/catalog/simple-policy-osgi-catalog.yaml
@@ -0,0 +1,10 @@
+
+brooklyn.policies:
+- type: brooklyn.osgi.tests.SimplePolicy
+
+brooklyn.catalog:
+  id: simple-policy
+  version: 1.0
+  # see OsgiTestResources
+  libraries:
+  - classpath:/brooklyn/osgi/brooklyn-test-osgi-entities.jar

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/utils/common/src/main/java/brooklyn/util/exceptions/Exceptions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/exceptions/Exceptions.java b/utils/common/src/main/java/brooklyn/util/exceptions/Exceptions.java
index d7282d1..10126e3 100644
--- a/utils/common/src/main/java/brooklyn/util/exceptions/Exceptions.java
+++ b/utils/common/src/main/java/brooklyn/util/exceptions/Exceptions.java
@@ -126,22 +126,36 @@ public class Exceptions {
         return collapse(source, true);
     }
     
+    /** as {@link #collapse(Throwable)} but includes causal messages in the message as per {@link #collapseTextIncludingAllCausalMessages(Throwable)};
+     * use with care (limit once) as repeated usage can result in multiple copies of the same message */ 
+    public static Throwable collapseIncludingAllCausalMessages(Throwable source) {
+        return collapse(source, true, true);
+    }
+    
     /** creates (but does not throw) a new {@link PropagatedRuntimeException} whose 
      * message is taken from the first _interesting_ element in the source,
      * and optionally also the causal chain */
     public static Throwable collapse(Throwable source, boolean collapseCausalChain) {
+        return collapse(source, collapseCausalChain, false);
+    }
+    
+    private static Throwable collapse(Throwable source, boolean collapseCausalChain, boolean includeAllCausalMessages) {
         String message = "";
         Throwable collapsed = source;
         int collapseCount = 0;
+        boolean messageIsFinal = false;
         // remove boring stack traces at the head
-        while (isBoring(collapsed)) {
+        while (isBoring(collapsed)  && !messageIsFinal) {
             collapseCount++;
             Throwable cause = collapsed.getCause();
             if (cause==null)
                 // everything in the tree is boring...
                 return source;
             String collapsedS = collapsed.getMessage();
-            if (Strings.isNonBlank(collapsedS)) {
+            if (collapsed instanceof PropagatedRuntimeException && ((PropagatedRuntimeException)collapsed).isCauseEmbeddedInMessage()) {
+                message = collapsed.getMessage();
+                messageIsFinal = true;
+            } else if (Strings.isNonBlank(collapsedS)) {
                 collapsedS = Strings.removeFromEnd(collapsedS, cause.toString(), stripBoringPrefixes(cause.toString()), cause.getMessage());
                 collapsedS = stripBoringPrefixes(collapsedS);
                 if (Strings.isNonBlank(collapsedS))
@@ -161,14 +175,19 @@ public class Exceptions {
             messagesCause = messagesCause.getCause();
         }
         
-        if (collapseCount==0)
+        if (collapseCount==0 && !includeAllCausalMessages)
             return source;
         
+        if (collapseCount==0) {
+            message = messagesCause.toString();
+            messagesCause = messagesCause.getCause();
+        }
+        
         if (Strings.isBlank(message)) {
             return new PropagatedRuntimeException(collapseCausalChain ? collapsed : source);
         } else {
-            if (messagesCause!=null) {
-                String extraMessage = collapseText(messagesCause);
+            if (messagesCause!=null && !messageIsFinal) {
+                String extraMessage = collapseText(messagesCause, includeAllCausalMessages);
                 message = appendSeparator(message, extraMessage);
             }
             return new PropagatedRuntimeException(message, collapseCausalChain ? collapsed : source, true);
@@ -195,8 +214,19 @@ public class Exceptions {
 
     /** like {@link #collapse(Throwable)} but returning a one-line message suitable for logging without traces */
     public static String collapseText(Throwable t) {
+        return collapseText(t, false);
+    }
+
+    /** normally {@link #collapseText(Throwable)} will stop following causal chains when encountering an interesting exception
+     * with a message; this variant will continue to follow such causal chains, showing all messages. 
+     * for use e.g. when verbose is desired in the single-line message. */
+    public static String collapseTextIncludingAllCausalMessages(Throwable t) {
+        return collapseText(t, true);
+    }
+    
+    private static String collapseText(Throwable t, boolean includeAllCausalMessages) {
         if (t == null) return null;
-        Throwable t2 = collapse(t);
+        Throwable t2 = collapse(t, true, includeAllCausalMessages);
         if (t2 instanceof PropagatedRuntimeException) {
             if (((PropagatedRuntimeException)t2).isCauseEmbeddedInMessage())
                 // normally
@@ -205,10 +235,20 @@ public class Exceptions {
                 return ""+t2.getCause();
             return ""+t2.getClass();
         }
-        return t2.toString();
+        String result = t2.toString();
+        if (!includeAllCausalMessages) {
+            return result;
+        }
+        Throwable cause = t2.getCause();
+        if (cause != null) {
+            String causeResult = collapseText(new PropagatedRuntimeException(cause));
+            if (result.indexOf(causeResult)>=0)
+                return result;
+            return result + "; caused by "+causeResult;
+        }
+        return result;
     }
 
-
     public static RuntimeException propagate(Collection<? extends Throwable> exceptions) {
         throw propagate(create(exceptions));
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/utils/common/src/main/java/brooklyn/util/guava/Functionals.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/guava/Functionals.java b/utils/common/src/main/java/brooklyn/util/guava/Functionals.java
index e24c475..dcbd9da 100644
--- a/utils/common/src/main/java/brooklyn/util/guava/Functionals.java
+++ b/utils/common/src/main/java/brooklyn/util/guava/Functionals.java
@@ -21,7 +21,6 @@ package brooklyn.util.guava;
 import java.util.concurrent.Callable;
 
 import brooklyn.util.guava.IfFunctions.IfFunctionBuilderApplyingFirst;
-import brooklyn.util.javalang.Enums;
 
 import com.google.common.base.Function;
 import com.google.common.base.Functions;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/utils/common/src/main/java/brooklyn/util/guava/IllegalStateExceptionSupplier.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/guava/IllegalStateExceptionSupplier.java b/utils/common/src/main/java/brooklyn/util/guava/IllegalStateExceptionSupplier.java
index 14ee639..b75bca2 100644
--- a/utils/common/src/main/java/brooklyn/util/guava/IllegalStateExceptionSupplier.java
+++ b/utils/common/src/main/java/brooklyn/util/guava/IllegalStateExceptionSupplier.java
@@ -29,7 +29,7 @@ public class IllegalStateExceptionSupplier implements Supplier<RuntimeException>
     
     public IllegalStateExceptionSupplier() { this(null, null); }
     public IllegalStateExceptionSupplier(String message) { this(message, null); }
-    public IllegalStateExceptionSupplier(Throwable cause) { this(null, cause); }
+    public IllegalStateExceptionSupplier(Throwable cause) { this(cause!=null ? cause.getMessage() : null, cause); }
     public IllegalStateExceptionSupplier(String message, Throwable cause) { 
         this.message = message;
         this.cause = cause;


[12/18] git commit: tidy up osgi test bundles, in prep for writing more bundles and more tests

Posted by he...@apache.org.
tidy up osgi test bundles, in prep for writing more bundles and more tests


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

Branch: refs/heads/master
Commit: a76208af1fe0eaa287430515beb0a750f7bfaa2b
Parents: 642c7ff
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Sat Nov 1 11:41:07 2014 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Nov 3 18:57:20 2014 +0000

----------------------------------------------------------------------
 .../src/test/dependencies/osgi/entities/pom.xml |   2 +
 .../management/osgi/OsgiEntitiesTest.java       |  92 +++++++++++++++++++
 .../management/osgi/OsgiStandaloneTest.java     |  61 +++---------
 .../management/osgi/OsgiTestResources.java      |  43 +++++++++
 core/src/test/resources/brooklyn/osgi/README.md |   8 +-
 .../osgi/brooklyn-test-osgi-entities.jar        | Bin 14663 -> 12378 bytes
 6 files changed, 156 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76208af/core/src/test/dependencies/osgi/entities/pom.xml
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/entities/pom.xml b/core/src/test/dependencies/osgi/entities/pom.xml
index 7818229..41551f4 100644
--- a/core/src/test/dependencies/osgi/entities/pom.xml
+++ b/core/src/test/dependencies/osgi/entities/pom.xml
@@ -22,7 +22,9 @@
     <modelVersion>4.0.0</modelVersion>
     <packaging>jar</packaging>
 
+    <groupId>org.apache.brooklyn.test.resources.osgi</groupId>
     <artifactId>brooklyn-test-osgi-entities</artifactId>
+    <version>0.1.0</version>
 
     <name>OSGi bundled test entities</name>
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76208af/core/src/test/java/brooklyn/management/osgi/OsgiEntitiesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiEntitiesTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiEntitiesTest.java
new file mode 100644
index 0000000..9b92b0c
--- /dev/null
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiEntitiesTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.management.osgi;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.launch.Framework;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.proxying.InternalEntityFactory;
+import brooklyn.entity.proxying.InternalPolicyFactory;
+import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.util.os.Os;
+import brooklyn.util.osgi.Osgis;
+
+
+/** 
+ * Tests that OSGi entities load correctly and have the right catalog information set.
+ *     
+ */
+public class OsgiEntitiesTest {
+   
+    public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
+    public static final String BROOKLYN_TEST_OSGI_ENTITIES_URL = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_URL;
+
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+    }
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws BundleException, IOException, InterruptedException {
+    }
+    
+    /**
+     * Test fix for
+     * java.lang.NoClassDefFoundError: brooklyn.event.AttributeSensor not found by io.brooklyn.brooklyn-test-osgi-entities [41]
+     */
+    @Test
+    public void testEntityProxy() throws Exception {
+        File storageTempDir = Os.newTempDir("osgi-standalone");
+        Framework framework = Osgis.newFrameworkStarted(storageTempDir.getAbsolutePath(), true, null);
+        
+        try {
+        ManagementContextInternal managementContext;
+        InternalEntityFactory factory;
+
+        managementContext = new LocalManagementContextForTests();
+        InternalPolicyFactory policyFactory = new InternalPolicyFactory(managementContext);
+        factory = new InternalEntityFactory(managementContext, managementContext.getEntityManager().getEntityTypeRegistry(), policyFactory);
+
+        Bundle bundle = Osgis.install(framework, BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+        @SuppressWarnings("unchecked")
+        Class<? extends Entity> bundleCls = (Class<? extends Entity>) bundle.loadClass("brooklyn.osgi.tests.SimpleEntityImpl");
+        @SuppressWarnings("unchecked")
+        Class<? extends Entity> bundleInterface = (Class<? extends Entity>) bundle.loadClass("brooklyn.osgi.tests.SimpleEntity");
+
+        @SuppressWarnings("unchecked")
+        EntitySpec<Entity> spec = (EntitySpec<Entity>) (((EntitySpec<Entity>)EntitySpec.create(bundleInterface))).impl(bundleCls);
+        Entity entity = bundleCls.newInstance();
+        factory.createEntityProxy(spec, entity);
+
+        if (managementContext != null) Entities.destroyAll(managementContext);
+        } finally {
+            OsgiStandaloneTest.tearDownOsgiFramework(framework, storageTempDir);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76208af/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
index 87320f6..c2f9d51 100644
--- a/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
@@ -39,12 +39,6 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import brooklyn.entity.Entity;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.entity.proxying.InternalEntityFactory;
-import brooklyn.entity.proxying.InternalPolicyFactory;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.test.entity.LocalManagementContextForTests;
 import brooklyn.util.ResourceUtils;
 import brooklyn.util.collections.MutableSet;
 import brooklyn.util.maven.MavenArtifact;
@@ -55,24 +49,19 @@ import brooklyn.util.osgi.Osgis;
 import brooklyn.util.osgi.Osgis.ManifestHelper;
 import brooklyn.util.stream.Streams;
 
-/** tests some assumptions about OSGi behaviour, in standalone mode (not part of brooklyn).
- * 
- * relies on the following bundles, which exist in the classpath (and contain their sources):
- * 
- * <li>brooklyn-osgi-test-a_0.1.0 -
- *     defines TestA which has a "times" method and a static multiplier field;
- *     we set the multiplier to determine when we are sharing versions and when not
- *     
- *  */
+/** 
+ * Tests some assumptions about OSGi behaviour, in standalone mode (not part of brooklyn).
+ * See {@link OsgiTestResources} for description of test resources.
+ */
 public class OsgiStandaloneTest {
 
     private static final Logger log = LoggerFactory.getLogger(OsgiStandaloneTest.class);
 
-    public static final String BROOKLYN_OSGI_TEST_A_0_1_0_URL = "classpath:/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar";
-    
-    public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = "/brooklyn/osgi/brooklyn-test-osgi-entities.jar";
-    public static final String BROOKLYN_TEST_OSGI_ENTITIES_URL = "classpath:"+BROOKLYN_TEST_OSGI_ENTITIES_PATH;
-    
+    public static final String BROOKLYN_OSGI_TEST_A_0_1_0_URL = OsgiTestResources.BROOKLYN_OSGI_TEST_A_0_1_0_URL;
+
+    public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
+    public static final String BROOKLYN_TEST_OSGI_ENTITIES_URL = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_URL;
+
     protected Framework framework = null;
     private File storageTempDir;
 
@@ -84,6 +73,10 @@ public class OsgiStandaloneTest {
 
     @AfterMethod(alwaysRun=true)
     public void tearDown() throws BundleException, IOException, InterruptedException {
+        tearDownOsgiFramework(framework, storageTempDir);
+    }
+
+    public static void tearDownOsgiFramework(Framework framework, File storageTempDir) throws BundleException, InterruptedException, IOException {
         if (framework!=null) {
             framework.stop();
             Assert.assertEquals(framework.waitForStop(1000).getType(), FrameworkEvent.STOPPED);
@@ -141,34 +134,6 @@ public class OsgiStandaloneTest {
         Assert.assertTrue(Osgis.isExtensionBundle(bundle));
     }
 
-
-    /**
-     * Test fix for
-     * java.lang.NoClassDefFoundError: brooklyn.event.AttributeSensor not found by io.brooklyn.brooklyn-test-osgi-entities [41]
-     */
-    @Test
-    public void testEntityProxy() throws Exception {
-        ManagementContextInternal managementContext;
-        InternalEntityFactory factory;
-
-        managementContext = new LocalManagementContextForTests();
-        InternalPolicyFactory policyFactory = new InternalPolicyFactory(managementContext);
-        factory = new InternalEntityFactory(managementContext, managementContext.getEntityManager().getEntityTypeRegistry(), policyFactory);
-
-        Bundle bundle = install(BROOKLYN_TEST_OSGI_ENTITIES_PATH);
-        @SuppressWarnings("unchecked")
-        Class<? extends Entity> bundleCls = (Class<? extends Entity>) bundle.loadClass("brooklyn.osgi.tests.SimpleEntityImpl");
-        @SuppressWarnings("unchecked")
-        Class<? extends Entity> bundleInterface = (Class<? extends Entity>) bundle.loadClass("brooklyn.osgi.tests.SimpleEntity");
-
-        @SuppressWarnings("unchecked")
-        EntitySpec<Entity> spec = (EntitySpec<Entity>) (((EntitySpec<Entity>)EntitySpec.create(bundleInterface))).impl(bundleCls);
-        Entity entity = bundleCls.newInstance();
-        factory.createEntityProxy(spec, entity);
-
-        if (managementContext != null) Entities.destroyAll(managementContext);
-    }
-
     @Test
     public void testAMultiplier() throws Exception {
         Bundle bundle = install(BROOKLYN_OSGI_TEST_A_0_1_0_URL);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76208af/core/src/test/java/brooklyn/management/osgi/OsgiTestResources.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiTestResources.java b/core/src/test/java/brooklyn/management/osgi/OsgiTestResources.java
new file mode 100644
index 0000000..3ab2055
--- /dev/null
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiTestResources.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.management.osgi;
+
+/**
+* Many OSGi tests require OSGi bundles (of course). Test bundles have been collected here
+* for convenience and clarity. Available bundles (on the classpath, with source code
+* either embedded or in /src/dependencies) are:
+* <p>
+* <li>brooklyn-osgi-test-a_0.1.0 -
+*     defines TestA which has a "times" method and a static multiplier field;
+*     we set the multiplier to determine when we are sharing versions and when not
+*     
+* <li>brooklyn-test-osgi-entities (also version 0.1.0) -
+*     defines an entity and an application, to confirm it can be read and used by brooklyn
+* <p>
+* Some of these bundles are also used in REST API tests, as that stretches catalog further
+* (using CAMP) and that is one area where OSGi is heavily used. 
+*/
+public class OsgiTestResources {
+
+    public static final String BROOKLYN_OSGI_TEST_A_0_1_0_URL = "classpath:/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar";
+
+    public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = "/brooklyn/osgi/brooklyn-test-osgi-entities.jar";
+    public static final String BROOKLYN_TEST_OSGI_ENTITIES_URL = "classpath:"+BROOKLYN_TEST_OSGI_ENTITIES_PATH;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76208af/core/src/test/resources/brooklyn/osgi/README.md
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/README.md b/core/src/test/resources/brooklyn/osgi/README.md
index 7225e90..4109080 100644
--- a/core/src/test/resources/brooklyn/osgi/README.md
+++ b/core/src/test/resources/brooklyn/osgi/README.md
@@ -1,4 +1,7 @@
-Sample OSGi bundle files included here, either are built from /src/dependencies in this project, or contain their sources, or both.
+This directory contains OSGi bundle files used for testing.
+
+Source code including pom.xml is contained in the bundles,
+or in /src/dependencies, or both.
 
 ----
 Licensed to the Apache Software Foundation (ASF) under one
@@ -16,4 +19,5 @@ 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.
\ No newline at end of file
+under the License.
+

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76208af/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar
index 42d842c..494de30 100644
Binary files a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar and b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar differ


[18/18] git commit: This closes #294

Posted by he...@apache.org.
This closes #294


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

Branch: refs/heads/master
Commit: d5636527ada64aabf1e0f122f56a2aa5968ca463
Parents: d36f348 32f2bd7
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Nov 4 14:29:30 2014 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 4 14:29:30 2014 +0000

----------------------------------------------------------------------
 .../basic/AbstractBrooklynObjectSpec.java       |  12 +
 .../java/brooklyn/basic/BrooklynObject.java     |  13 +
 .../basic/internal/ApiObjectsFactory.java       |  60 ++++
 .../internal/ApiObjectsFactoryInterface.java    |  29 ++
 .../main/java/brooklyn/catalog/CatalogItem.java |   9 +-
 .../mementos/BrooklynMementoManifest.java       |  17 +-
 .../main/java/brooklyn/mementos/Memento.java    |   2 +
 .../brooklyn/basic/AbstractBrooklynObject.java  |  15 +
 .../brooklyn/basic/BrooklynObjectInternal.java  |   3 +
 .../basic/internal/ApiObjectsFactoryImpl.java   |  41 +++
 .../catalog/internal/BasicBrooklynCatalog.java  |  31 +-
 .../brooklyn/catalog/internal/CatalogDo.java    |   2 +-
 .../catalog/internal/CatalogItemDo.java         |   7 +-
 .../internal/CatalogItemDtoAbstract.java        |  13 +
 .../brooklyn/catalog/internal/CatalogUtils.java |  38 ++-
 .../brooklyn/entity/basic/AbstractEntity.java   |   6 +
 .../basic/EntityTransientCopyInternal.java      |   2 +
 .../entity/proxying/InternalEntityFactory.java  |   4 +
 .../proxying/InternalLocationFactory.java       |   5 +
 .../entity/proxying/InternalPolicyFactory.java  |   9 +
 .../AbstractBrooklynObjectRebindSupport.java    |   1 +
 .../entity/rebind/RebindManagerImpl.java        | 257 +++++++++------
 .../entity/rebind/dto/AbstractMemento.java      |  13 +
 .../rebind/dto/BrooklynMementoManifestImpl.java |  52 +--
 .../rebind/dto/EntityMementoManifestImpl.java   |  56 ++++
 .../entity/rebind/dto/MementosGenerators.java   |   1 +
 .../AbstractBrooklynMementoPersister.java       |   4 +-
 .../BrooklynMementoPersisterInMemory.java       |   6 +-
 .../BrooklynMementoPersisterToMultiFile.java    |   5 +-
 .../BrooklynMementoPersisterToObjectStore.java  |  22 +-
 .../BrooklynClassLoadingContextSequential.java  |  12 +-
 .../OsgiBrooklynClassLoadingContext.java        |  16 +-
 .../brooklyn/management/ha/OsgiManager.java     |  26 +-
 .../policy/basic/AbstractEntityAdjunct.java     |   3 +
 ...yn.basic.internal.ApiObjectsFactoryInterface |  19 ++
 core/src/test/dependencies/osgi/README.md       |  29 ++
 .../src/test/dependencies/osgi/entities/pom.xml |   7 +-
 .../dependencies/osgi/more-entities-v1/pom.xml  |  82 +++++
 .../brooklyn/osgi/tests/more/MoreEntity.java    |  38 +++
 .../osgi/tests/more/MoreEntityImpl.java         |  44 +++
 .../dependencies/osgi/more-entities-v2/pom.xml  |  87 +++++
 .../brooklyn/osgi/tests/more/MoreEntity.java    |  39 +++
 .../osgi/tests/more/MoreEntityImpl.java         |  47 +++
 .../brooklyn/catalog/internal/CatalogItems.java |   4 +-
 .../entity/rebind/RebindPolicyTest.java         |   2 +-
 .../management/osgi/OsgiStandaloneTest.java     |  60 +---
 .../management/osgi/OsgiTestResources.java      |  61 ++++
 .../osgi/OsgiVersionMoreEntityTest.java         | 318 +++++++++++++++++++
 .../entity/TestEntityTransientCopyImpl.java     |  28 ++
 core/src/test/resources/brooklyn/osgi/README.md |  10 +-
 .../osgi/brooklyn-test-osgi-entities.jar        | Bin 14663 -> 12406 bytes
 .../brooklyn-test-osgi-more-entities_0.1.0.jar  | Bin 0 -> 12452 bytes
 .../brooklyn-test-osgi-more-entities_0.2.0.jar  | Bin 0 -> 12615 bytes
 .../autoscaling/AutoScalerPolicyMetricTest.java |   8 +-
 .../BrooklynAssemblyTemplateInstantiator.java   |   2 +
 .../BrooklynComponentTemplateResolver.java      |   9 +-
 .../spi/creation/BrooklynEntityMatcher.java     |  11 +-
 .../lookup/AbstractTemplateBrooklynLookup.java  |   2 +-
 .../lookup/AssemblyTemplateBrooklynLookup.java  |   2 +-
 ...PlatformComponentTemplateBrooklynLookup.java |   2 +-
 .../camp/brooklyn/CatalogYamlEntityTest.java    | 184 -----------
 .../camp/brooklyn/CatalogYamlPolicyTest.java    | 136 --------
 .../CatalogOsgiVersionMoreEntityTest.java       | 130 ++++++++
 .../brooklyn/catalog/CatalogYamlEntityTest.java | 187 +++++++++++
 .../brooklyn/catalog/CatalogYamlPolicyTest.java | 135 ++++++++
 .../more-entity-v1-called-v1-osgi-catalog.yaml  |  27 ++
 .../catalog/more-entity-v1-osgi-catalog.yaml    |  27 ++
 ...more-entity-v1-with-policy-osgi-catalog.yaml |  29 ++
 .../catalog/more-entity-v2-osgi-catalog.yaml    |  28 ++
 .../catalog/simple-policy-osgi-catalog.yaml     |  27 ++
 .../brooklyn/util/exceptions/Exceptions.java    |  56 +++-
 .../java/brooklyn/util/guava/Functionals.java   |   1 -
 .../guava/IllegalStateExceptionSupplier.java    |   2 +-
 .../main/java/brooklyn/util/text/Strings.java   |  10 +
 74 files changed, 2122 insertions(+), 560 deletions(-)
----------------------------------------------------------------------



[16/18] git commit: mark some policy tests as integration, lower the invocation count for one quite slow one

Posted by he...@apache.org.
mark some policy tests as integration, lower the invocation count for one quite slow one


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

Branch: refs/heads/master
Commit: 0b89adc0566f02e205800f222093029f5a7e82bb
Parents: e771265
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Nov 4 13:17:54 2014 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 4 13:20:16 2014 +0000

----------------------------------------------------------------------
 .../policy/autoscaling/AutoScalerPolicyMetricTest.java       | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0b89adc0/policy/src/test/java/brooklyn/policy/autoscaling/AutoScalerPolicyMetricTest.java
----------------------------------------------------------------------
diff --git a/policy/src/test/java/brooklyn/policy/autoscaling/AutoScalerPolicyMetricTest.java b/policy/src/test/java/brooklyn/policy/autoscaling/AutoScalerPolicyMetricTest.java
index 7c5ee75..4120614 100644
--- a/policy/src/test/java/brooklyn/policy/autoscaling/AutoScalerPolicyMetricTest.java
+++ b/policy/src/test/java/brooklyn/policy/autoscaling/AutoScalerPolicyMetricTest.java
@@ -93,7 +93,7 @@ public class AutoScalerPolicyMetricTest {
         Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 1));
     }
     
-    @Test
+    @Test(groups="Integration")
     public void testIncrementsSizeInProportionToMetric() {
         tc.resize(5);
         
@@ -109,7 +109,7 @@ public class AutoScalerPolicyMetricTest {
         Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 11));
     }
     
-    @Test
+    @Test(groups="Integration")
     public void testDecrementsSizeInProportionToMetric() {
         tc.resize(5);
         
@@ -128,7 +128,7 @@ public class AutoScalerPolicyMetricTest {
         Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 0));
     }
     
-    @Test
+    @Test(groups="Integration")
     public void testObeysMinAndMaxSize() {
         tc.resize(4);
         
@@ -147,7 +147,7 @@ public class AutoScalerPolicyMetricTest {
         Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT_MS), currentSizeAsserter(tc, 6));
     }
     
-    @Test(invocationCount=100)
+    @Test(groups="Integration",invocationCount=20)
     public void testWarnsWhenMaxCapReached() {
         final List<MaxPoolSizeReachedEvent> maxReachedEvents = Lists.newCopyOnWriteArrayList();
         tc.resize(1);


[09/18] git commit: Merge remote-tracking branch 'apache-gh/pr/274' into misc4

Posted by he...@apache.org.
Merge remote-tracking branch 'apache-gh/pr/274' into misc4

Conflicts:
	utils/common/src/main/java/brooklyn/util/text/Strings.java - unambiguous new methods added at end


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

Branch: refs/heads/master
Commit: e832ee462c981ed2b056c0aaa9e39a64e99cc73b
Parents: 83011fe 0eb6763
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Nov 3 18:56:16 2014 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Nov 3 18:56:16 2014 +0000

----------------------------------------------------------------------
 .../basic/AbstractBrooklynObjectSpec.java       |  11 +
 .../java/brooklyn/basic/ApiObjectsFactory.java  |  41 +++
 .../java/brooklyn/basic/BrooklynObject.java     |   5 +
 .../mementos/BrooklynMementoManifest.java       |  17 +-
 .../main/java/brooklyn/mementos/Memento.java    |   2 +
 .../brooklyn/basic/AbstractBrooklynObject.java  |  13 +
 .../brooklyn/basic/ApiObjectsFactoryImpl.java   |  41 +++
 .../catalog/internal/BasicBrooklynCatalog.java  |  19 +-
 .../catalog/internal/CatalogItemDo.java         |   7 +-
 .../brooklyn/catalog/internal/CatalogUtils.java |  18 +-
 .../brooklyn/entity/basic/AbstractEntity.java   |   4 +
 .../entity/proxying/InternalEntityFactory.java  |   4 +
 .../proxying/InternalLocationFactory.java       |   5 +
 .../entity/proxying/InternalPolicyFactory.java  |   9 +
 .../AbstractBrooklynObjectRebindSupport.java    |   1 +
 .../entity/rebind/RebindManagerImpl.java        | 257 +++++++++++--------
 .../entity/rebind/dto/AbstractMemento.java      |  13 +
 .../rebind/dto/BrooklynMementoManifestImpl.java |  52 ++--
 .../rebind/dto/EntityMementoManifestImpl.java   |  56 ++++
 .../entity/rebind/dto/MementosGenerators.java   |   1 +
 .../AbstractBrooklynMementoPersister.java       |   4 +-
 .../BrooklynMementoPersisterInMemory.java       |   6 +-
 .../BrooklynMementoPersisterToMultiFile.java    |   5 +-
 .../BrooklynMementoPersisterToObjectStore.java  |  22 +-
 .../OsgiBrooklynClassLoadingContext.java        |  15 +-
 .../policy/basic/AbstractEntityAdjunct.java     |   3 +
 ...ApiObjectsFactory$ApiObjectsFactoryInterface |  19 ++
 .../entity/rebind/RebindPolicyTest.java         |   2 +-
 .../BrooklynAssemblyTemplateInstantiator.java   |   2 +
 .../BrooklynComponentTemplateResolver.java      |  11 +-
 .../lookup/AbstractTemplateBrooklynLookup.java  |   2 +-
 .../lookup/AssemblyTemplateBrooklynLookup.java  |   2 +-
 ...PlatformComponentTemplateBrooklynLookup.java |   2 +-
 .../main/java/brooklyn/util/text/Strings.java   |  10 +
 34 files changed, 522 insertions(+), 159 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e832ee46/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e832ee46/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e832ee46/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e832ee46/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e832ee46/utils/common/src/main/java/brooklyn/util/text/Strings.java
----------------------------------------------------------------------
diff --cc utils/common/src/main/java/brooklyn/util/text/Strings.java
index a52dcc9,6e3ec06..03b7c67
--- a/utils/common/src/main/java/brooklyn/util/text/Strings.java
+++ b/utils/common/src/main/java/brooklyn/util/text/Strings.java
@@@ -833,9 -833,14 +833,19 @@@ public class Strings 
          return replaceAllRegex(x, "\\s+", whitespaceReplacement);
      }
  
 +    public static String toLowerCase(String value) {
 +        if (value==null || value.length()==0) return value;
 +        return value.toLowerCase(Locale.ENGLISH);
 +    }
 +
+     /**
+      * @return null if var is null or empty string, otherwise return var
+      */
+     public static String emptyToNull(String var) {
+         if (isNonEmpty(var)) {
+             return var;
+         } else {
+             return null;
+         }
+     }
  }


[15/18] git commit: Merge branch 'master' into misc6

Posted by he...@apache.org.
Merge branch 'master' into misc6


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

Branch: refs/heads/master
Commit: e7712656b8504bb3ae736dc3e55b8ffc8d102728
Parents: 35fd634 b18b189
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Tue Nov 4 11:11:31 2014 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 4 11:11:31 2014 +0000

----------------------------------------------------------------------
 .../brooklyn/catalog/internal/CatalogDo.java    | 14 ++++----
 .../brooklyn/catalog/internal/CatalogDto.java   | 34 +++++++++++++++++++-
 .../catalog/internal/CatalogLoadTest.java       |  4 +--
 3 files changed, 41 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e7712656/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
----------------------------------------------------------------------


[05/18] git commit: Set the catalog item id used when creating BOSpecs

Posted by he...@apache.org.
Set the catalog item id used when creating BOSpecs


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

Branch: refs/heads/master
Commit: d2d4e617f34ac52ae9e8103ed18478aa7335fa0f
Parents: b496958
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Thu Oct 30 13:15:45 2014 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Thu Oct 30 13:15:45 2014 +0200

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java    |  2 +-
 .../brooklyn/catalog/internal/CatalogItemDo.java  |  2 +-
 .../brooklyn/catalog/internal/CatalogUtils.java   | 18 +++++++++++-------
 .../OsgiBrooklynClassLoadingContext.java          | 15 ++++++++++++---
 .../BrooklynComponentTemplateResolver.java        |  1 +
 5 files changed, 26 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2d4e617/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
index a0a8375..f8bd2c8 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -407,7 +407,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
 
         CatalogUtils.installLibraries(mgmt, libraries);
 
-        AbstractBrooklynObjectSpec<?, ?> spec = createSpec(plan, CatalogUtils.newClassLoadingContext(mgmt, libraries));
+        AbstractBrooklynObjectSpec<?, ?> spec = createSpec(plan, CatalogUtils.newClassLoadingContext(mgmt, "<not created yet>", libraries, getRootClassLoader()));
 
         CatalogItemBuilder<?> builder = createItemBuilder(spec, registeredTypeName)
             .libraries(libraries)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2d4e617/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index 178ef90..cb409fa 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -127,7 +127,7 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
     @SuppressWarnings("unchecked")
     Class<? extends T> loadJavaClass(final ManagementContext mgmt) {
         if (javaClass!=null) return javaClass;
-        javaClass = (Class<T>)CatalogUtils.newClassLoadingContext(mgmt, getLibraries(), catalog.getRootClassLoader()).loadClass(getJavaType());
+        javaClass = (Class<T>)CatalogUtils.newClassLoadingContext(mgmt, getId(), getLibraries(), catalog.getRootClassLoader()).loadClass(getJavaType());
         return javaClass;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2d4e617/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
index 31a519e..c0ad54f 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
@@ -51,20 +51,16 @@ public class CatalogUtils {
         if (libraries == null) {
             log.debug("CatalogItemDtoAbstract.getLibraries() is null.", new Exception("Trace for null CatalogItemDtoAbstract.getLibraries()"));
         }
-        return newClassLoadingContext(mgmt, libraries);
+        return newClassLoadingContext(mgmt, item.getId(), libraries, mgmt.getCatalog().getRootClassLoader());
     }
 
-    public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, CatalogItemLibraries libraries) {
-        return newClassLoadingContext(mgmt, libraries, mgmt.getCatalog().getRootClassLoader());
-    }
-
-    public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, CatalogItemLibraries libraries, ClassLoader classLoader) {
+    public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, String catalogItemId, CatalogItemLibraries libraries, ClassLoader classLoader) {
         BrooklynClassLoadingContextSequential result = new BrooklynClassLoadingContextSequential(mgmt);
 
         if (libraries!=null) {
             List<String> bundles = libraries.getBundles();
             if (bundles!=null && !bundles.isEmpty()) {
-                result.add(new OsgiBrooklynClassLoadingContext(mgmt, bundles));
+                result.add(new OsgiBrooklynClassLoadingContext(mgmt, catalogItemId, bundles));
             }
         }
 
@@ -101,4 +97,12 @@ public class CatalogUtils {
         }
     }
 
+    public static String getContextCatalogItemIdFromLoader(BrooklynClassLoadingContext loader) {
+        if (loader instanceof OsgiBrooklynClassLoadingContext) {
+            return ((OsgiBrooklynClassLoadingContext)loader).getContextCatalogId();
+        } else {
+            return null;
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2d4e617/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java b/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
index 2b9058a..498d440 100644
--- a/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
+++ b/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
@@ -31,10 +31,12 @@ import com.google.common.base.Objects;
 public class OsgiBrooklynClassLoadingContext extends AbstractBrooklynClassLoadingContext {
 
     private final List<String> bundles;
+    private final String contextCatalogId;
 
-    public OsgiBrooklynClassLoadingContext(ManagementContext mgmt, List<String> bundles) {
+    public OsgiBrooklynClassLoadingContext(ManagementContext mgmt, String catalogItemId, List<String> bundles) {
         super(mgmt);
         this.bundles = bundles;
+        this.contextCatalogId = catalogItemId;
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
@@ -69,14 +71,17 @@ public class OsgiBrooklynClassLoadingContext extends AbstractBrooklynClassLoadin
     
     @Override
     public int hashCode() {
-        return Objects.hashCode(super.hashCode(), bundles);
+        return Objects.hashCode(super.hashCode(), bundles, contextCatalogId);
     }
     
     @Override
     public boolean equals(Object obj) {
         if (!super.equals(obj)) return false;
         if (!(obj instanceof OsgiBrooklynClassLoadingContext)) return false;
-        if (!Objects.equal(bundles, ((OsgiBrooklynClassLoadingContext)obj).bundles)) return false;
+
+        OsgiBrooklynClassLoadingContext other = (OsgiBrooklynClassLoadingContext)obj;
+        if (!contextCatalogId.equals(other.contextCatalogId)) return false;
+        if (!Objects.equal(bundles, other.bundles)) return false;
         return true;
     }
 
@@ -91,4 +96,8 @@ public class OsgiBrooklynClassLoadingContext extends AbstractBrooklynClassLoadin
         return null;
     }
     
+    public String getContextCatalogId() {
+        return contextCatalogId;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d2d4e617/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index 98149fd..d4192b4 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -257,6 +257,7 @@ public class BrooklynComponentTemplateResolver {
             List<Class<?>> additionalInterfaceClazzes = Reflections.getAllInterfaces(type);
             spec = EntitySpec.create(interfaceclazz).impl(type).additionalInterfaces(additionalInterfaceClazzes);
         }
+        spec.contextCatalogItemId(CatalogUtils.getContextCatalogItemIdFromLoader(loader));
         if (template.isPresent() && template.get().getSourceCode()!=null)
             spec.tag(BrooklynTags.newYamlSpecTag(template.get().getSourceCode()));
 


[04/18] git commit: Make a note of the remaining steps needed for reliable rebind + OSGi bundles.

Posted by he...@apache.org.
Make a note of the remaining steps needed for reliable rebind + OSGi bundles.


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

Branch: refs/heads/master
Commit: b496958d91567abb3a17ceaa84de645cbeeffd85
Parents: d716e2f
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Thu Oct 30 11:56:50 2014 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Thu Oct 30 11:56:50 2014 +0200

----------------------------------------------------------------------
 .../main/java/brooklyn/entity/rebind/RebindManagerImpl.java | 9 +++++++++
 1 file changed, 9 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/b496958d/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index 9f620d6..807e6fb 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -504,6 +504,15 @@ public class RebindManagerImpl implements RebindManager {
             // the rebindContext. This should not affect normal production usage, because rebind is run
             // against a data-store that is not being written to by other brooklyn instance(s).
 
+            // TODO Rebinding to code in OSGi bundles:
+            // Inferring the catalog item id context:
+            //   * most of the time the creator will be passing "my catalog item id" 
+            //     (or API could also take "BrooklynObject me" as a creation context and the 
+            //     receiver query the creator's catalog item id)
+            //   * propagate the catalog item id when doing setEntity, addChild
+            //   * fall back to the context entity of Tasks.current() (if set)
+            //   * when none of the above work let the user specify the catalog item
+            
             //
             // PHASE ONE
             //


[07/18] git commit: Initialize the context catalog item id when adding items to the BO hierarchy.

Posted by he...@apache.org.
Initialize the context catalog item id when adding items to the BO hierarchy.


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

Branch: refs/heads/master
Commit: 36ee1e0fcb944fa2a3b6265cdad54de3afb8b889
Parents: 246c29d
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Thu Oct 30 15:18:38 2014 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Fri Oct 31 14:44:41 2014 +0200

----------------------------------------------------------------------
 .../src/main/java/brooklyn/entity/basic/AbstractEntity.java | 4 ++++
 .../brooklyn/entity/proxying/InternalLocationFactory.java   | 5 +++++
 .../brooklyn/entity/proxying/InternalPolicyFactory.java     | 9 +++++++++
 .../java/brooklyn/policy/basic/AbstractEntityAdjunct.java   | 3 +++
 4 files changed, 21 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/36ee1e0f/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
index 00b58b7..f26ee64 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
@@ -555,6 +555,10 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         
         getApplication();
         
+        if (getContextCatalogItemId() == null) {
+            setContextCatalogItemId(entity.getContextCatalogItemId());
+        }
+        
         return this;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/36ee1e0f/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
index a5fa6c5..14ea05f 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
@@ -23,6 +23,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 
 import brooklyn.config.ConfigKey;
+import brooklyn.entity.basic.AbstractEntity;
 import brooklyn.location.Location;
 import brooklyn.location.LocationSpec;
 import brooklyn.location.basic.AbstractLocation;
@@ -104,6 +105,10 @@ public class InternalLocationFactory extends InternalFactory {
             if (spec.getDisplayName()!=null)
                 ((AbstractLocation)loc).setDisplayName(spec.getDisplayName());
             
+            if (spec.getContextCatalogItemId()!=null) {
+                ((AbstractLocation)loc).setContextCatalogItemId(spec.getContextCatalogItemId());
+            }
+            
             loc.tags().addTags(spec.getTags());
             
             if (isNewStyle(clazz)) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/36ee1e0f/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
index 10bc83b..c5785ca 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
@@ -23,6 +23,7 @@ import java.util.Map;
 import brooklyn.config.ConfigKey;
 import brooklyn.enricher.basic.AbstractEnricher;
 import brooklyn.entity.Feed;
+import brooklyn.entity.basic.AbstractEntity;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.policy.Enricher;
@@ -106,6 +107,10 @@ public class InternalPolicyFactory extends InternalFactory {
             if (spec.getDisplayName()!=null)
                 ((AbstractPolicy)pol).setDisplayName(spec.getDisplayName());
             
+            if (spec.getContextCatalogItemId()!=null) {
+                ((AbstractPolicy)pol).setContextCatalogItemId(spec.getContextCatalogItemId());
+            }
+            
             pol.tags().addTags(spec.getTags());
             
             if (isNewStyle(clazz)) {
@@ -143,6 +148,10 @@ public class InternalPolicyFactory extends InternalFactory {
             if (spec.getDisplayName()!=null)
                 ((AbstractEnricher)enricher).setDisplayName(spec.getDisplayName());
             
+            if (spec.getContextCatalogItemId()!=null) {
+                ((AbstractEnricher)enricher).setContextCatalogItemId(spec.getContextCatalogItemId());
+            }
+            
             enricher.tags().addTags(spec.getTags());
             
             if (isNewStyle(clazz)) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/36ee1e0f/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
index 9dd3e9a..a7d8892 100644
--- a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
+++ b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
@@ -238,6 +238,9 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
     public void setEntity(EntityLocal entity) {
         if (destroyed.get()) throw new IllegalStateException("Cannot set entity on a destroyed entity adjunct");
         this.entity = entity;
+        if (getContextCatalogItemId() == null) {
+            setContextCatalogItemId(entity.getContextCatalogItemId());
+        }
     }
     
     /** @deprecated since 0.7.0 only {@link AbstractEnricher} has emit convenience */


[08/18] git commit: Initialize the context catalog item id from the current task's context entity.

Posted by he...@apache.org.
Initialize the context catalog item id from the current task's context entity.


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

Branch: refs/heads/master
Commit: 0eb67633c168237154134af3028ba4048845efa5
Parents: 36ee1e0
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Fri Oct 31 14:41:50 2014 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Fri Oct 31 14:44:45 2014 +0200

----------------------------------------------------------------------
 .../basic/AbstractBrooklynObjectSpec.java       |  1 +
 .../java/brooklyn/basic/ApiObjectsFactory.java  | 41 ++++++++++++++++++++
 .../brooklyn/basic/AbstractBrooklynObject.java  |  2 +
 .../brooklyn/basic/ApiObjectsFactoryImpl.java   | 41 ++++++++++++++++++++
 .../entity/rebind/RebindManagerImpl.java        | 10 ++++-
 ...ApiObjectsFactory$ApiObjectsFactoryInterface | 19 +++++++++
 6 files changed, 113 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0eb67633/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java b/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
index 2ef4d67..867b509 100644
--- a/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
+++ b/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
@@ -41,6 +41,7 @@ public abstract class AbstractBrooklynObjectSpec<T,K extends AbstractBrooklynObj
     protected AbstractBrooklynObjectSpec(Class<? extends T> type) {
         checkValidType(type);
         this.type = type;
+        this.contextCatalogItemId = ApiObjectsFactory.get().getContextCatalogItemId();
     }
     
     @SuppressWarnings("unchecked")

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0eb67633/api/src/main/java/brooklyn/basic/ApiObjectsFactory.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/basic/ApiObjectsFactory.java b/api/src/main/java/brooklyn/basic/ApiObjectsFactory.java
new file mode 100644
index 0000000..f85e9c7
--- /dev/null
+++ b/api/src/main/java/brooklyn/basic/ApiObjectsFactory.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.basic;
+
+import java.util.ServiceLoader;
+
+public class ApiObjectsFactory {
+    public interface ApiObjectsFactoryInterface {
+        public String getContextCatalogItemId();
+    }
+
+    private static ApiObjectsFactoryInterface INSTANCE = getFactoryInstance();
+
+    private static ApiObjectsFactoryInterface getFactoryInstance() {
+        ServiceLoader<ApiObjectsFactoryInterface> LOADER = ServiceLoader.load(ApiObjectsFactoryInterface.class);
+        for (ApiObjectsFactoryInterface item : LOADER) {
+            return item;
+        }
+        throw new IllegalStateException("Implementation of " + ApiObjectsFactoryInterface.class + " not found on classpath");
+    }
+
+    public static ApiObjectsFactoryInterface get() {
+        return INSTANCE;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0eb67633/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java b/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
index 8c2608d..8ff8776 100644
--- a/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
+++ b/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
@@ -74,6 +74,8 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
             _legacyConstruction = true;
         }
 
+        contextCatalogItemId = ApiObjectsFactory.get().getContextCatalogItemId();
+
         // rely on sub-class to call configure(properties), because otherwise its fields will not have been initialised
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0eb67633/core/src/main/java/brooklyn/basic/ApiObjectsFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/ApiObjectsFactoryImpl.java b/core/src/main/java/brooklyn/basic/ApiObjectsFactoryImpl.java
new file mode 100644
index 0000000..8c95442
--- /dev/null
+++ b/core/src/main/java/brooklyn/basic/ApiObjectsFactoryImpl.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.basic;
+
+import brooklyn.basic.ApiObjectsFactory.ApiObjectsFactoryInterface;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.management.Task;
+import brooklyn.util.task.Tasks;
+
+public class ApiObjectsFactoryImpl implements ApiObjectsFactoryInterface {
+
+    @Override
+    public String getContextCatalogItemId() {
+        Task<?> currentTask = Tasks.current();
+        if (currentTask != null) {
+            Entity contextEntity = BrooklynTaskTags.getContextEntity(currentTask);
+            if (contextEntity != null) {
+                return contextEntity.getContextCatalogItemId();
+            }
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0eb67633/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index 807e6fb..6d6d6a1 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -512,7 +512,15 @@ public class RebindManagerImpl implements RebindManager {
             //   * propagate the catalog item id when doing setEntity, addChild
             //   * fall back to the context entity of Tasks.current() (if set)
             //   * when none of the above work let the user specify the catalog item
-            
+            //
+            //  Precedence of setting the catalog item ID:
+            //   1. User-supplied catalog item ID.
+            //   2. Creating from a catalog item - all items resolved during the creation of a spec
+            //      from a catalog item receive the catalog item's ID as context.
+            //   3. When using the Java API for creating specs get the catalog item ID from the
+            //      context entity of the Tasks.current() task.
+            //   4. Propagate the context catalog item ID to children, adjuncts if they don't have one already.
+
             //
             // PHASE ONE
             //

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/0eb67633/core/src/main/resources/META-INF/services/brooklyn.basic.ApiObjectsFactory$ApiObjectsFactoryInterface
----------------------------------------------------------------------
diff --git a/core/src/main/resources/META-INF/services/brooklyn.basic.ApiObjectsFactory$ApiObjectsFactoryInterface b/core/src/main/resources/META-INF/services/brooklyn.basic.ApiObjectsFactory$ApiObjectsFactoryInterface
new file mode 100644
index 0000000..007e088
--- /dev/null
+++ b/core/src/main/resources/META-INF/services/brooklyn.basic.ApiObjectsFactory$ApiObjectsFactoryInterface
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+brooklyn.basic.ApiObjectsFactoryImpl


[10/18] git commit: minor tweaks to catalog item id setting

Posted by he...@apache.org.
minor tweaks to catalog item id setting

move catalog-item inferencing based on entity proximity to a helper method with a bit of logging
(did this mainly because i didn't see it in addChild/addEnricher/etc but then i realized you'd
done it in setParent/setEntity ... now it's in both which is superfluous but harmless)

only change of note is putting {get,set}CatalogItemId in the EntityTransientCopyInternal so that
on hot-standby rebind we are allowed to set these. (not sure if that was a problem or not.)

next will test this, but need to grab some osgi items to do that!


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

Branch: refs/heads/master
Commit: 642c7ffdd3794ca88dba2e0e8e512881547f948d
Parents: 72ac129
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Oct 31 18:58:39 2014 -0500
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Nov 3 18:57:19 2014 +0000

----------------------------------------------------------------------
 .../brooklyn/basic/AbstractBrooklynObject.java  |  1 +
 .../brooklyn/basic/BrooklynObjectInternal.java  |  3 +++
 .../brooklyn/catalog/internal/CatalogUtils.java | 19 +++++++++++++
 .../brooklyn/entity/basic/AbstractEntity.java   | 10 ++++---
 .../basic/EntityTransientCopyInternal.java      |  2 ++
 .../entity/rebind/RebindManagerImpl.java        |  4 +--
 .../entity/TestEntityTransientCopyImpl.java     | 28 ++++++++++++++++++++
 7 files changed, 61 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/642c7ffd/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java b/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
index 9d1cd88..ff1bbd8 100644
--- a/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
+++ b/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
@@ -172,6 +172,7 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
         return id;
     }
 
+    @Override
     public void setCatalogItemId(String id) {
         this.catalogItemId = id;
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/642c7ffd/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java b/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java
index 76033dc..84a0a58 100644
--- a/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java
+++ b/core/src/main/java/brooklyn/basic/BrooklynObjectInternal.java
@@ -21,4 +21,7 @@ package brooklyn.basic;
 import brooklyn.entity.rebind.Rebindable;
 
 public interface BrooklynObjectInternal extends BrooklynObject, Rebindable {
+    
+    public void setCatalogItemId(String id);
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/642c7ffd/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
index f5bf6bc..5b6b81d 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
@@ -28,9 +28,12 @@ import org.slf4j.LoggerFactory;
 import com.google.common.base.Joiner;
 import com.google.common.base.Stopwatch;
 
+import brooklyn.basic.BrooklynObject;
+import brooklyn.basic.BrooklynObjectInternal;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.catalog.CatalogItem.CatalogItemLibraries;
 import brooklyn.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
+import brooklyn.entity.Entity;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.classloading.BrooklynClassLoadingContext;
 import brooklyn.management.classloading.BrooklynClassLoadingContextSequential;
@@ -106,4 +109,20 @@ public class CatalogUtils {
         }
     }
 
+    public static void setCatalogItemIdOnAddition(Entity entity, BrooklynObject itemBeingAdded) {
+        if (entity.getCatalogItemId()!=null) {
+            if (itemBeingAdded.getCatalogItemId()==null) {
+                log.debug("Catalog item addition: "+entity+" from "+entity.getCatalogItemId()+" applying its catalog item ID to "+itemBeingAdded);
+                ((BrooklynObjectInternal)itemBeingAdded).setCatalogItemId(entity.getCatalogItemId());
+            } else {
+                if (!itemBeingAdded.getCatalogItemId().equals(entity.getCatalogItemId())) {
+                    // not a problem, but something to watch out for
+                    log.debug("Cross-catalog item detected: "+entity+" from "+entity.getCatalogItemId()+" has "+itemBeingAdded+" from "+itemBeingAdded.getCatalogItemId());
+                }
+            }
+        } else if (itemBeingAdded.getCatalogItemId()==null) {
+            log.debug("Catalog item addition: "+entity+" without catalog item ID has "+itemBeingAdded+" from "+itemBeingAdded.getCatalogItemId());
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/642c7ffd/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
index d97255b..034bea7 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
@@ -32,6 +32,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import brooklyn.basic.AbstractBrooklynObject;
+import brooklyn.catalog.internal.CatalogUtils;
 import brooklyn.config.ConfigKey;
 import brooklyn.config.ConfigKey.HasConfigKey;
 import brooklyn.config.render.RendererHints;
@@ -556,10 +557,6 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         
         getApplication();
         
-        if (getCatalogItemId() == null) {
-            setCatalogItemId(entity.getCatalogItemId());
-        }
-        
         return this;
     }
 
@@ -586,6 +583,8 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
     @Override
     public <T extends Entity> T addChild(T child) {
         checkNotNull(child, "child must not be null (for entity %s)", this);
+        CatalogUtils.setCatalogItemIdOnAddition(this, child);
+        
         boolean changed;
         synchronized (children) {
             if (Entities.isAncestor(this, child)) throw new IllegalStateException("loop detected trying to add child "+child+" to "+this+"; it is already an ancestor");
@@ -1139,6 +1138,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
             removePolicy(old);
         }
         
+        CatalogUtils.setCatalogItemIdOnAddition(this, policy);
         policies.add((AbstractPolicy)policy);
         ((AbstractPolicy)policy).setEntity(this);
         
@@ -1195,6 +1195,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
             removeEnricher(old);
         }
         
+        CatalogUtils.setCatalogItemIdOnAddition(this, enricher);
         enrichers.add((AbstractEnricher) enricher);
         ((AbstractEnricher)enricher).setEntity(this);
         
@@ -1309,6 +1310,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
                 removeFeed(old);
             }
             
+            CatalogUtils.setCatalogItemIdOnAddition(AbstractEntity.this, feed);
             feeds.add(feed);
             if (!AbstractEntity.this.equals(((AbstractFeed)feed).getEntity()))
                 ((AbstractFeed)feed).setEntity(AbstractEntity.this);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/642c7ffd/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java b/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java
index 9ce3815..0082768 100644
--- a/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java
+++ b/core/src/main/java/brooklyn/entity/basic/EntityTransientCopyInternal.java
@@ -82,6 +82,7 @@ public interface EntityTransientCopyInternal {
     Maybe<Object> getConfigRaw(HasConfigKey<?> key, boolean includeInherited);
     @Deprecated Set<Object> getTags();
     @Deprecated boolean containsTag(@Nonnull Object tag);
+    String getCatalogItemId();
 
     
     // from entity local
@@ -107,5 +108,6 @@ public interface EntityTransientCopyInternal {
     RebindSupport<EntityMemento> getRebindSupport();
     // for REST calls on read-only entities which want to resolve values
     ExecutionContext getExecutionContext();
+    void setCatalogItemId(String id);
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/642c7ffd/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index 9f15404..24076f9 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -509,9 +509,9 @@ public class RebindManagerImpl implements RebindManager {
             //   * most of the time the creator will be passing "my catalog item id" 
             //     (or API could also take "BrooklynObject me" as a creation context and the 
             //     receiver query the creator's catalog item id)
+            //   * look at the context entity of Tasks.current() (if set)
             //   * propagate the catalog item id when doing setEntity, addChild
-            //   * fall back to the context entity of Tasks.current() (if set)
-            //   * when none of the above work let the user specify the catalog item
+            //   * when none of the above work (or they are wrong) let the user specify the catalog item
             //
             //  Precedence of setting the catalog item ID:
             //   1. User-supplied catalog item ID.

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/642c7ffd/core/src/test/java/brooklyn/test/entity/TestEntityTransientCopyImpl.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/test/entity/TestEntityTransientCopyImpl.java b/core/src/test/java/brooklyn/test/entity/TestEntityTransientCopyImpl.java
new file mode 100644
index 0000000..a5987ee
--- /dev/null
+++ b/core/src/test/java/brooklyn/test/entity/TestEntityTransientCopyImpl.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.test.entity;
+
+import brooklyn.entity.basic.EntityTransientCopyInternal;
+
+/**
+ * Entity to give compilation errors if {@link EntityTransientCopyInternal} methods are not aligned
+ * with Entity methods. (Everything in that interface should be on EntityInternal, and if not, we want to know!)
+ */
+public class TestEntityTransientCopyImpl extends TestEntityImpl implements EntityTransientCopyInternal {
+}


[02/18] git commit: Look in parent entities when looking for a context catalog id to load classes from.

Posted by he...@apache.org.
Look in parent entities when looking for a context catalog id to load classes from.


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

Branch: refs/heads/master
Commit: 405842d20aa11d83fe91734ba61b80106f1383bd
Parents: b454beb
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Wed Oct 29 17:34:00 2014 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Wed Oct 29 17:34:00 2014 +0200

----------------------------------------------------------------------
 .../mementos/BrooklynMementoManifest.java       | 14 +++--
 .../entity/rebind/RebindManagerImpl.java        | 39 ++++++++------
 .../rebind/dto/BrooklynMementoManifestImpl.java | 35 +++---------
 .../rebind/dto/EntityMementoManifestImpl.java   | 56 ++++++++++++++++++++
 .../AbstractBrooklynMementoPersister.java       |  2 +-
 .../BrooklynMementoPersisterInMemory.java       |  4 +-
 .../BrooklynMementoPersisterToMultiFile.java    |  4 +-
 .../BrooklynMementoPersisterToObjectStore.java  |  5 +-
 .../entity/rebind/RebindPolicyTest.java         |  2 +-
 .../main/java/brooklyn/util/text/Strings.java   | 10 ++++
 10 files changed, 117 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/405842d2/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java b/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java
index f8a40a6..418c59b 100644
--- a/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java
+++ b/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java
@@ -22,7 +22,7 @@ import java.io.Serializable;
 import java.util.Collection;
 import java.util.Map;
 
-import brooklyn.util.guava.Maybe;
+import brooklyn.entity.trait.Identifiable;
 
 /**
  * Represents a manifest of the entities etc in the overall memento.
@@ -30,10 +30,14 @@ import brooklyn.util.guava.Maybe;
  * @author aled
  */
 public interface BrooklynMementoManifest extends Serializable {
-
-    public Map<String, String> getEntityIdToType();
-
-    public Map<String, Maybe<String>> getEntityIdToContextCatalogItemId();
+    public interface EntityMementoManifest extends Identifiable{
+        public String getId();
+        public String getType();
+        public String getParent();
+        public String getContextCatalogItemId();
+    }
+
+    public Map<String, EntityMementoManifest> getEntityIdToManifest();
 
     public Map<String, String> getLocationIdToType();
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/405842d2/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index 8eee9eb..2691a5b 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -73,6 +73,7 @@ import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.management.internal.ManagementTransitionInfo.ManagementTransitionMode;
 import brooklyn.mementos.BrooklynMemento;
 import brooklyn.mementos.BrooklynMementoManifest;
+import brooklyn.mementos.BrooklynMementoManifest.EntityMementoManifest;
 import brooklyn.mementos.BrooklynMementoPersister;
 import brooklyn.mementos.BrooklynMementoPersister.LookupContext;
 import brooklyn.mementos.BrooklynMementoRawData;
@@ -90,7 +91,6 @@ import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.exceptions.RuntimeInterruptedException;
 import brooklyn.util.flags.FlagUtils;
-import brooklyn.util.guava.Maybe;
 import brooklyn.util.javalang.Reflections;
 import brooklyn.util.task.BasicExecutionContext;
 import brooklyn.util.task.ScheduledTask;
@@ -622,18 +622,18 @@ public class RebindManagerImpl implements RebindManager {
             }
             
             // Instantiate entities
-            LOG.debug("RebindManager instantiating entities: {}", mementoManifest.getEntityIdToType().keySet());
-            for (Map.Entry<String, String> entry : mementoManifest.getEntityIdToType().entrySet()) {
+            LOG.debug("RebindManager instantiating entities: {}", mementoManifest.getEntityIdToManifest().keySet());
+            for (Map.Entry<String, EntityMementoManifest> entry : mementoManifest.getEntityIdToManifest().entrySet()) {
                 String entityId = entry.getKey();
-                String entityType = entry.getValue();
-                Maybe<String> contextCatalogItemId = mementoManifest.getEntityIdToContextCatalogItemId().get(entityId);
+                EntityMementoManifest entityManifest = entry.getValue();
+                String contextCatalogItemId = findContextCatalogItemId(mementoManifest.getEntityIdToManifest(), entityManifest);
                 if (LOG.isTraceEnabled()) LOG.trace("RebindManager instantiating entity {}", entityId);
                 
                 try {
-                    Entity entity = newEntity(entityId, entityType, getEntityLoadingContext(entityId, contextCatalogItemId, classLoader, rebindContext));
+                    Entity entity = newEntity(entityId, entityManifest.getType(), getLoadingContextFromCatalogItemId(contextCatalogItemId, classLoader, rebindContext));
                     rebindContext.registerEntity(entityId, entity);
                 } catch (Exception e) {
-                    exceptionHandler.onCreateFailed(BrooklynObjectType.ENTITY, entityId, entityType, e);
+                    exceptionHandler.onCreateFailed(BrooklynObjectType.ENTITY, entityId, entityManifest.getType(), e);
                 }
             }
             
@@ -918,31 +918,38 @@ public class RebindManagerImpl implements RebindManager {
         }
     }
     
-    private BrooklynClassLoadingContext getEntityLoadingContext(String entityId, Maybe<String> contextCatalogItemId, ClassLoader classLoader, RebindContextImpl rebindContext) {
-        return getLoadingContextFromCatalogItemId(contextCatalogItemId, classLoader, rebindContext);
+    private String findContextCatalogItemId(Map<String, EntityMementoManifest> entityIdToManifest, EntityMementoManifest entityManifest) {
+        EntityMementoManifest ptr = entityManifest;
+        while (ptr != null) {
+            if (ptr.getContextCatalogItemId() != null) {
+                return ptr.getContextCatalogItemId();
+            }
+            ptr = entityIdToManifest.get(ptr.getParent());
+        }
+        return null;
     }
 
     private BrooklynClassLoadingContext getPolicyLoadingContext(String policyId, BrooklynMemento memento, ClassLoader classLoader, RebindContextImpl rebindContext) {
         PolicyMemento policyMemento = memento.getPolicyMemento(policyId);
-        Maybe<String> contextCatalogItemId = getContextCatalogItemIdFromTags(policyMemento.getTags());
+        String contextCatalogItemId = getContextCatalogItemIdFromTags(policyMemento.getTags());
         return getLoadingContextFromCatalogItemId(contextCatalogItemId, classLoader, rebindContext);
     }
 
-    private Maybe<String> getContextCatalogItemIdFromTags(Collection<Object> tags) {
+    private String getContextCatalogItemIdFromTags(Collection<Object> tags) {
         for (Object obj : tags) {
             if (obj instanceof NamedStringTag) {
                 NamedStringTag tag = (NamedStringTag) obj;
                 if (BrooklynTags.CONTEXT_CATALOG_ITEM_ID_KIND.equals(tag.getKind())) {
-                    return Maybe.of(tag.getContents());
+                    return tag.getContents();
                 }
             }
         }
-        return Maybe.absent();
+        return null;
     }
 
-    private BrooklynClassLoadingContext getLoadingContextFromCatalogItemId(Maybe<String> catalogItemId, ClassLoader classLoader, RebindContext rebindContext) {
-        if (catalogItemId.isPresent()) {
-            CatalogItem<?, ?> catalogItem = rebindContext.getCatalogItem(catalogItemId.get());
+    private BrooklynClassLoadingContext getLoadingContextFromCatalogItemId(String catalogItemId, ClassLoader classLoader, RebindContext rebindContext) {
+        if (catalogItemId != null) {
+            CatalogItem<?, ?> catalogItem = rebindContext.getCatalogItem(catalogItemId);
             if (catalogItem != null) {
                 return CatalogUtils.newClassLoadingContext(managementContext, catalogItem);
             } else {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/405842d2/core/src/main/java/brooklyn/entity/rebind/dto/BrooklynMementoManifestImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/BrooklynMementoManifestImpl.java b/core/src/main/java/brooklyn/entity/rebind/dto/BrooklynMementoManifestImpl.java
index 6c0fb4e..2b52003 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/BrooklynMementoManifestImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/BrooklynMementoManifestImpl.java
@@ -25,7 +25,6 @@ import java.util.Map;
 
 import brooklyn.mementos.BrooklynMementoManifest;
 import brooklyn.mementos.CatalogItemMemento;
-import brooklyn.util.guava.Maybe;
 
 import com.google.common.collect.Maps;
 
@@ -39,8 +38,7 @@ public class BrooklynMementoManifestImpl implements BrooklynMementoManifest, Ser
     
     public static class Builder {
         protected String brooklynVersion;
-        protected final Map<String, String> entityIdToType = Maps.newConcurrentMap();
-        protected final Map<String, Maybe<String>> entityIdToContextCatalogItemId = Maps.newConcurrentMap();
+        protected final Map<String, EntityMementoManifest> entityIdToManifest = Maps.newConcurrentMap();
         protected final Map<String, String> locationIdToType = Maps.newConcurrentMap();
         protected final Map<String, String> policyIdToType = Maps.newConcurrentMap();
         protected final Map<String, String> enricherIdToType = Maps.newConcurrentMap();
@@ -50,20 +48,10 @@ public class BrooklynMementoManifestImpl implements BrooklynMementoManifest, Ser
         public Builder brooklynVersion(String val) {
             brooklynVersion = val; return this;
         }
-        public Builder entity(String id, String type, String catalogItemId) {
-            entityIdToType.put(id, type);
-            Maybe<String> catalogItemIdOption;
-            if (catalogItemId != null) {
-                catalogItemIdOption = Maybe.of(catalogItemId);
-            } else {
-                catalogItemIdOption = Maybe.absent();
-            }
-            entityIdToContextCatalogItemId.put(id, catalogItemIdOption);
+        public Builder entity(String id, String type, String parent, String catalogItemId) {
+            entityIdToManifest.put(id, new EntityMementoManifestImpl(id, type, parent, catalogItemId));
             return this;
         }
-        public Builder entities(Map<String, String> vals) {
-            entityIdToType.putAll(vals); return this;
-        }
         public Builder location(String id, String type) {
             locationIdToType.put(id, type); return this;
         }
@@ -100,8 +88,7 @@ public class BrooklynMementoManifestImpl implements BrooklynMementoManifest, Ser
         }
     }
 
-    private final Map<String, String> entityIdToType;
-    private final Map<String, Maybe<String>> entityIdToContextCatalogItemId;
+    private final Map<String, EntityMementoManifest> entityIdToManifest;
     private final Map<String, String> locationIdToType;
     private final Map<String, String> policyIdToType;
     private final Map<String, String> enricherIdToType;
@@ -109,8 +96,7 @@ public class BrooklynMementoManifestImpl implements BrooklynMementoManifest, Ser
     private Map<String, CatalogItemMemento> catalogItems;
     
     private BrooklynMementoManifestImpl(Builder builder) {
-        entityIdToType = builder.entityIdToType;
-        entityIdToContextCatalogItemId = builder.entityIdToContextCatalogItemId;
+        entityIdToManifest = builder.entityIdToManifest;
         locationIdToType = builder.locationIdToType;
         policyIdToType = builder.policyIdToType;
         enricherIdToType = builder.enricherIdToType;
@@ -119,13 +105,8 @@ public class BrooklynMementoManifestImpl implements BrooklynMementoManifest, Ser
     }
 
     @Override
-    public Map<String, String> getEntityIdToType() {
-        return Collections.unmodifiableMap(entityIdToType);
-    }
-
-    @Override
-    public Map<String, Maybe<String>> getEntityIdToContextCatalogItemId() {
-        return Collections.unmodifiableMap(entityIdToContextCatalogItemId);
+    public Map<String, EntityMementoManifest> getEntityIdToManifest() {
+        return Collections.unmodifiableMap(entityIdToManifest);
     }
 
     @Override
@@ -165,7 +146,7 @@ public class BrooklynMementoManifestImpl implements BrooklynMementoManifest, Ser
 
     @Override
     public boolean isEmpty() {
-        return entityIdToType.isEmpty() &&
+        return entityIdToManifest.isEmpty() &&
                 locationIdToType.isEmpty() &&
                 policyIdToType.isEmpty() &&
                 enricherIdToType.isEmpty() &&

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/405842d2/core/src/main/java/brooklyn/entity/rebind/dto/EntityMementoManifestImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/EntityMementoManifestImpl.java b/core/src/main/java/brooklyn/entity/rebind/dto/EntityMementoManifestImpl.java
new file mode 100644
index 0000000..bfec2ca
--- /dev/null
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/EntityMementoManifestImpl.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.entity.rebind.dto;
+
+import brooklyn.mementos.BrooklynMementoManifest.EntityMementoManifest;
+
+public class EntityMementoManifestImpl implements EntityMementoManifest {
+    private String id;
+    private String type;
+    private String parentId;
+    private String contextCatalogItemId;
+
+    public EntityMementoManifestImpl(String id, String type, String parentId, String contextCatalogItemId) {
+        this.id = id;
+        this.type = type;
+        this.parentId = parentId;
+        this.contextCatalogItemId = contextCatalogItemId;
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public String getType() {
+        return type;
+    }
+
+    @Override
+    public String getParent() {
+        return parentId;
+    }
+
+    @Override
+    public String getContextCatalogItemId() {
+        return contextCatalogItemId;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/405842d2/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java b/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
index ff75aa9..9758213 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
@@ -56,7 +56,7 @@ public abstract class AbstractBrooklynMementoPersister implements BrooklynMement
     public BrooklynMementoManifest loadMementoManifest(RebindExceptionHandler exceptionHandler) {
         BrooklynMementoManifestImpl.Builder builder = BrooklynMementoManifestImpl.builder();
         for (EntityMemento entity : memento.getEntityMementos().values()) {
-            builder.entity(entity.getId(), entity.getType(), getContextCatalogItemId(entity.getTags()));
+            builder.entity(entity.getId(), entity.getType(), entity.getParent(), getContextCatalogItemId(entity.getTags()));
         }
         for (LocationMemento entity : memento.getLocationMementos().values()) {
             builder.location(entity.getId(), entity.getType());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/405842d2/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java
index 0fdd64b..847dfa7 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterInMemory.java
@@ -42,6 +42,7 @@ import brooklyn.location.Location;
 import brooklyn.management.ManagementContext;
 import brooklyn.mementos.BrooklynMemento;
 import brooklyn.mementos.BrooklynMementoManifest;
+import brooklyn.mementos.BrooklynMementoManifest.EntityMementoManifest;
 import brooklyn.policy.Enricher;
 import brooklyn.policy.Policy;
 import brooklyn.util.collections.MutableList;
@@ -124,7 +125,8 @@ public class BrooklynMementoPersisterInMemory extends AbstractBrooklynMementoPer
                     @Override public Entity lookupEntity(String id) {
                         List<Class<?>> types = MutableList.<Class<?>>builder()
                                 .add(Entity.class, EntityInternal.class, EntityProxy.class)
-                                .add(loadClass(manifest.getEntityIdToType().get(id)))
+                                //TODO Doesn't support loading from catalog item osgi bundles
+                                .add(loadClass(manifest.getEntityIdToManifest().get(id).getType()))
                                 .build();
                         return (Entity) java.lang.reflect.Proxy.newProxyInstance(
                                 classLoader,

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/405842d2/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
index eb67ee7..cdd87b8 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
@@ -48,6 +48,7 @@ import brooklyn.mementos.EntityMemento;
 import brooklyn.mementos.LocationMemento;
 import brooklyn.mementos.PolicyMemento;
 import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.text.Strings;
 import brooklyn.util.time.Duration;
 import brooklyn.util.time.Time;
 import brooklyn.util.xstream.XmlUtil;
@@ -194,8 +195,9 @@ public class BrooklynMementoPersisterToMultiFile implements BrooklynMementoPersi
                     String contents = readFile(file);
                     String id = (String) XmlUtil.xpath(contents, "/entity/id");
                     String type = (String) XmlUtil.xpath(contents, "/entity/type");
+                    String parentId = (String) XmlUtil.xpath(contents, "/entity/parent");
                     String contextCatalogItemId = (String) XmlUtil.xpath(contents, "/entity/tags/" + NamedStringTag.class.getName().replace("$", "_-") + "[kind='" + BrooklynTags.CONTEXT_CATALOG_ITEM_ID_KIND + "']/contents");
-                    builder.entity(id, type, contextCatalogItemId);
+                    builder.entity(id, type, Strings.emptyToNull(parentId), Strings.emptyToNull(contextCatalogItemId));
                 } catch (Exception e) {
                     exceptionHandler.onLoadMementoFailed(BrooklynObjectType.ENTITY, "File "+file, e);
                 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/405842d2/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
index 6d86a35..09f58b7 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
@@ -254,8 +254,9 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
                     case ENTITY:
                         String id = (String) XmlUtil.xpath(contents, "/entity/id");
                         String objType = (String) XmlUtil.xpath(contents, "/entity/type");
+                        String parentId = (String) XmlUtil.xpath(contents, "/entity/parent");
                         String contextCatalogItemId = (String) XmlUtil.xpath(contents, "/entity/tags/" + NamedStringTag.class.getName().replace("$", "_-") + "[kind='" + BrooklynTags.CONTEXT_CATALOG_ITEM_ID_KIND + "']/contents");
-                        builder.entity(id, objType, Strings.isEmpty(contextCatalogItemId) ? null : contextCatalogItemId);
+                        builder.entity(id, objType, Strings.emptyToNull(parentId), Strings.emptyToNull(contextCatalogItemId));
                         break;
                     case LOCATION:
                         id = (String) XmlUtil.xpath(contents, "/location/id");
@@ -303,7 +304,7 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
 
         if (LOG.isDebugEnabled()) {
             LOG.debug("Loaded memento manifest; took {}; {} entities, {} locations, {} policies, {} enrichers, {} feeds, {} catalog items, from {}", new Object[]{
-                     Time.makeTimeStringRounded(stopwatch.elapsed(TimeUnit.MILLISECONDS)), result.getEntityIdToType().size(), 
+                     Time.makeTimeStringRounded(stopwatch.elapsed(TimeUnit.MILLISECONDS)), result.getEntityIdToManifest().size(), 
                      result.getLocationIdToType().size(), result.getPolicyIdToType().size(), result.getEnricherIdToType().size(), 
                      result.getFeedIdToType().size(), result.getCatalogItemMementos().size(),
                      objectStore.getSummaryName() });

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/405842d2/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java b/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
index 9e550ed..ef27a94 100644
--- a/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
+++ b/core/src/test/java/brooklyn/entity/rebind/RebindPolicyTest.java
@@ -141,7 +141,7 @@ public class RebindPolicyTest extends RebindTestFixtureWithApp {
         RebindTestUtils.waitForPersisted(origApp);
         
         BrooklynMementoManifest manifest = loadMementoManifest();
-        assertFalse(manifest.getEntityIdToType().containsKey(entity.getId()));
+        assertFalse(manifest.getEntityIdToManifest().containsKey(entity.getId()));
         assertFalse(manifest.getPolicyIdToType().containsKey(policy.getId()));
         assertFalse(manifest.getEnricherIdToType().containsKey(enricher.getId()));
         assertFalse(manifest.getLocationIdToType().containsKey(loc.getId()));

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/405842d2/utils/common/src/main/java/brooklyn/util/text/Strings.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/text/Strings.java b/utils/common/src/main/java/brooklyn/util/text/Strings.java
index 4c275c9..6e3ec06 100644
--- a/utils/common/src/main/java/brooklyn/util/text/Strings.java
+++ b/utils/common/src/main/java/brooklyn/util/text/Strings.java
@@ -833,4 +833,14 @@ public class Strings {
         return replaceAllRegex(x, "\\s+", whitespaceReplacement);
     }
 
+    /**
+     * @return null if var is null or empty string, otherwise return var
+     */
+    public static String emptyToNull(String var) {
+        if (isNonEmpty(var)) {
+            return var;
+        } else {
+            return null;
+        }
+    }
 }


[11/18] git commit: Catalog Item ID field renaming and ApiObjectsFactory tweaks

Posted by he...@apache.org.
Catalog Item ID field renaming and ApiObjectsFactory tweaks

* catalogItemId rather than contextCatalogItemId
* ApiObjectsFactory moved to internal package, inner class promoted so services file is nicer
* safer initialization of ApiObjectsFactory


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

Branch: refs/heads/master
Commit: 72ac1296dde17d5a80a5496d8f81273e07bd3bf1
Parents: e832ee4
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Fri Oct 31 10:19:57 2014 -0500
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Mon Nov 3 18:57:19 2014 +0000

----------------------------------------------------------------------
 .../basic/AbstractBrooklynObjectSpec.java       | 13 +++--
 .../java/brooklyn/basic/ApiObjectsFactory.java  | 41 -------------
 .../java/brooklyn/basic/BrooklynObject.java     | 10 +++-
 .../basic/internal/ApiObjectsFactory.java       | 60 ++++++++++++++++++++
 .../internal/ApiObjectsFactoryInterface.java    | 29 ++++++++++
 .../main/java/brooklyn/catalog/CatalogItem.java |  9 ++-
 .../mementos/BrooklynMementoManifest.java       |  2 +-
 .../main/java/brooklyn/mementos/Memento.java    |  2 +-
 .../brooklyn/basic/AbstractBrooklynObject.java  | 13 +++--
 .../brooklyn/basic/ApiObjectsFactoryImpl.java   | 41 -------------
 .../basic/internal/ApiObjectsFactoryImpl.java   | 41 +++++++++++++
 .../catalog/internal/BasicBrooklynCatalog.java  |  2 +-
 .../brooklyn/catalog/internal/CatalogDo.java    |  3 +-
 .../catalog/internal/CatalogItemDo.java         |  2 +-
 .../brooklyn/catalog/internal/CatalogUtils.java |  5 +-
 .../brooklyn/entity/basic/AbstractEntity.java   |  4 +-
 .../entity/proxying/InternalEntityFactory.java  |  4 +-
 .../proxying/InternalLocationFactory.java       |  4 +-
 .../entity/proxying/InternalPolicyFactory.java  |  8 +--
 .../AbstractBrooklynObjectRebindSupport.java    |  2 +-
 .../entity/rebind/RebindManagerImpl.java        | 14 ++---
 .../entity/rebind/dto/AbstractMemento.java      | 16 +++---
 .../rebind/dto/EntityMementoManifestImpl.java   | 10 ++--
 .../entity/rebind/dto/MementosGenerators.java   |  2 +-
 .../AbstractBrooklynMementoPersister.java       |  2 +-
 .../BrooklynMementoPersisterToMultiFile.java    |  4 +-
 .../BrooklynMementoPersisterToObjectStore.java  |  4 +-
 .../OsgiBrooklynClassLoadingContext.java        | 12 ++--
 .../policy/basic/AbstractEntityAdjunct.java     |  4 +-
 ...ApiObjectsFactory$ApiObjectsFactoryInterface | 19 -------
 ...yn.basic.internal.ApiObjectsFactoryInterface | 19 +++++++
 .../BrooklynAssemblyTemplateInstantiator.java   |  2 +-
 .../BrooklynComponentTemplateResolver.java      |  4 +-
 33 files changed, 236 insertions(+), 171 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java b/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
index 867b509..c0a4ccc 100644
--- a/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
+++ b/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
@@ -22,6 +22,7 @@ import java.io.Serializable;
 import java.lang.reflect.Modifier;
 import java.util.Set;
 
+import brooklyn.basic.internal.ApiObjectsFactory;
 import brooklyn.util.collections.MutableSet;
 import brooklyn.util.exceptions.Exceptions;
 
@@ -35,13 +36,13 @@ public abstract class AbstractBrooklynObjectSpec<T,K extends AbstractBrooklynObj
     
     private final Class<? extends T> type;
     private String displayName;
-    private String contextCatalogItemId;
+    private String catalogItemId;
     private Set<Object> tags = MutableSet.of();
 
     protected AbstractBrooklynObjectSpec(Class<? extends T> type) {
         checkValidType(type);
         this.type = type;
-        this.contextCatalogItemId = ApiObjectsFactory.get().getContextCatalogItemId();
+        this.catalogItemId = ApiObjectsFactory.get().getCatalogItemIdFromContext();
     }
     
     @SuppressWarnings("unchecked")
@@ -61,8 +62,8 @@ public abstract class AbstractBrooklynObjectSpec<T,K extends AbstractBrooklynObj
         return self();
     }
     
-    public K contextCatalogItemId(String val) {
-        contextCatalogItemId = val;
+    public K catalogItemId(String val) {
+        catalogItemId = val;
         return self();
     }
     
@@ -91,8 +92,8 @@ public abstract class AbstractBrooklynObjectSpec<T,K extends AbstractBrooklynObj
         return displayName;
     }
     
-    public final String getContextCatalogItemId() {
-        return contextCatalogItemId;
+    public final String getCatalogItemId() {
+        return catalogItemId;
     }
 
     public final Set<Object> getTags() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/api/src/main/java/brooklyn/basic/ApiObjectsFactory.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/basic/ApiObjectsFactory.java b/api/src/main/java/brooklyn/basic/ApiObjectsFactory.java
deleted file mode 100644
index f85e9c7..0000000
--- a/api/src/main/java/brooklyn/basic/ApiObjectsFactory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.basic;
-
-import java.util.ServiceLoader;
-
-public class ApiObjectsFactory {
-    public interface ApiObjectsFactoryInterface {
-        public String getContextCatalogItemId();
-    }
-
-    private static ApiObjectsFactoryInterface INSTANCE = getFactoryInstance();
-
-    private static ApiObjectsFactoryInterface getFactoryInstance() {
-        ServiceLoader<ApiObjectsFactoryInterface> LOADER = ServiceLoader.load(ApiObjectsFactoryInterface.class);
-        for (ApiObjectsFactoryInterface item : LOADER) {
-            return item;
-        }
-        throw new IllegalStateException("Implementation of " + ApiObjectsFactoryInterface.class + " not found on classpath");
-    }
-
-    public static ApiObjectsFactoryInterface get() {
-        return INSTANCE;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/api/src/main/java/brooklyn/basic/BrooklynObject.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/basic/BrooklynObject.java b/api/src/main/java/brooklyn/basic/BrooklynObject.java
index a31fbf8..4698780 100644
--- a/api/src/main/java/brooklyn/basic/BrooklynObject.java
+++ b/api/src/main/java/brooklyn/basic/BrooklynObject.java
@@ -38,8 +38,16 @@ public interface BrooklynObject extends Identifiable {
 
     /**
      * The catalog item ID this object was loaded from.
+     * <p>
+     * This can be used to understand the appropriate classloading context,
+     * such as for versioning purposes, as well as meta-information such as 
+     * branding (maybe you can even get an icon) and 
+     * potentially things like resource lifecycle (if a software version is being sunsetted).
+     * <p>
+     * In some cases this may be set heuristically from context and so may not be accurate.
+     * Callers can set an explicit catalog item ID if inferencing is not correct.
      */
-    String getContextCatalogItemId();
+    String getCatalogItemId();
     
     /** 
      * Tags are arbitrary objects which can be attached to an entity for subsequent reference.

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/api/src/main/java/brooklyn/basic/internal/ApiObjectsFactory.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/basic/internal/ApiObjectsFactory.java b/api/src/main/java/brooklyn/basic/internal/ApiObjectsFactory.java
new file mode 100644
index 0000000..ecbb7fb
--- /dev/null
+++ b/api/src/main/java/brooklyn/basic/internal/ApiObjectsFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.basic.internal;
+
+import java.util.ServiceLoader;
+
+import brooklyn.util.guava.Maybe;
+
+import com.google.common.annotations.Beta;
+
+/** 
+ * This class grants access to implementations in core for operations needed in API classes.
+ * The majority of the API classes are interfaces or have minimal behaviour, but there are a
+ * few instances where more complex behaviour from core is desired.
+ * <p>
+ * This class acts as a bridge for those instances. See the concrete implementation of the
+ * {@link ApiObjectsFactoryInterface} in brooklyn-core class ApiObjectsFactoryImpl.
+ */
+@Beta
+public class ApiObjectsFactory {
+    
+    private static Maybe<ApiObjectsFactoryInterface> INSTANCE;
+
+    private static synchronized ApiObjectsFactoryInterface getFactoryInstance() {
+        // defer initialization to allow any other static initialization to complete,
+        // and use maybe so we (1) don't check multiple times, but (2) do throw error in the caller's stack
+        if (INSTANCE!=null) return INSTANCE.get();
+        
+        ServiceLoader<ApiObjectsFactoryInterface> LOADER = ServiceLoader.load(ApiObjectsFactoryInterface.class);
+        for (ApiObjectsFactoryInterface item : LOADER) {
+            INSTANCE = Maybe.of(item);
+            return INSTANCE.get();
+        }
+        INSTANCE = Maybe.absent("Implementation of " + ApiObjectsFactoryInterface.class + " not found on classpath");
+        return INSTANCE.get();
+    }
+
+    /**
+     * Create (if necessary) and return the concrete implementation from core for the
+     * methods exposed here. */
+    public static ApiObjectsFactoryInterface get() {
+        return getFactoryInstance();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/api/src/main/java/brooklyn/basic/internal/ApiObjectsFactoryInterface.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/basic/internal/ApiObjectsFactoryInterface.java b/api/src/main/java/brooklyn/basic/internal/ApiObjectsFactoryInterface.java
new file mode 100644
index 0000000..275e102
--- /dev/null
+++ b/api/src/main/java/brooklyn/basic/internal/ApiObjectsFactoryInterface.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.basic.internal;
+
+/** 
+ * Methods from downstream projects used in API classes at runtime. 
+ * See {@link ApiObjectsFactory}. 
+ */
+public interface ApiObjectsFactoryInterface {
+    
+    public String getCatalogItemIdFromContext();
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/api/src/main/java/brooklyn/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/CatalogItem.java b/api/src/main/java/brooklyn/catalog/CatalogItem.java
index 3a6c2fb..409bd7e 100644
--- a/api/src/main/java/brooklyn/catalog/CatalogItem.java
+++ b/api/src/main/java/brooklyn/catalog/CatalogItem.java
@@ -77,5 +77,12 @@ public interface CatalogItem<T,SpecT> extends BrooklynObject, Rebindable {
 
     @Override
     RebindSupport<CatalogItemMemento> getRebindSupport();
-}
+    
+    /** Built up from {@link #getId()} and {@link #getVersion()}.
+     * 
+     * (It is a bit self-referential having this method on this type of {@link BrooklynObject},
+     * but it is easier this than making the interface hierarchy more complicated.) */
+    @Override
+    public String getCatalogItemId();
 
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java b/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java
index 418c59b..6187e29 100644
--- a/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java
+++ b/api/src/main/java/brooklyn/mementos/BrooklynMementoManifest.java
@@ -34,7 +34,7 @@ public interface BrooklynMementoManifest extends Serializable {
         public String getId();
         public String getType();
         public String getParent();
-        public String getContextCatalogItemId();
+        public String getCatalogItemId();
     }
 
     public Map<String, EntityMementoManifest> getEntityIdToManifest();

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/api/src/main/java/brooklyn/mementos/Memento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/mementos/Memento.java b/api/src/main/java/brooklyn/mementos/Memento.java
index 6ab36b0..bb6f8b1 100644
--- a/api/src/main/java/brooklyn/mementos/Memento.java
+++ b/api/src/main/java/brooklyn/mementos/Memento.java
@@ -42,7 +42,7 @@ public interface Memento extends Serializable {
     
     public String getType();
     
-    public String getContextCatalogItemId();
+    public String getCatalogItemId();
     
     public String getDisplayName();
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java b/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
index 8ff8776..9d1cd88 100644
--- a/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
+++ b/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
@@ -25,6 +25,7 @@ import java.util.Set;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import brooklyn.basic.internal.ApiObjectsFactory;
 import brooklyn.entity.proxying.InternalFactory;
 import brooklyn.entity.rebind.RebindManagerImpl;
 import brooklyn.management.ManagementContext;
@@ -48,7 +49,7 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
     @SetFromFlag(value = "id")
     private String id = Identifiers.makeRandomId(8);
 
-    private String contextCatalogItemId;
+    private String catalogItemId;
 
     /** subclasses should synchronize on this for all access */
     @SetFromFlag(value = "tags")
@@ -74,7 +75,7 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
             _legacyConstruction = true;
         }
 
-        contextCatalogItemId = ApiObjectsFactory.get().getContextCatalogItemId();
+        catalogItemId = ApiObjectsFactory.get().getCatalogItemIdFromContext();
 
         // rely on sub-class to call configure(properties), because otherwise its fields will not have been initialised
     }
@@ -171,13 +172,13 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
         return id;
     }
 
-    public void setContextCatalogItemId(String id) {
-        this.contextCatalogItemId = id;
+    public void setCatalogItemId(String id) {
+        this.catalogItemId = id;
     }
 
     @Override
-    public String getContextCatalogItemId() {
-        return contextCatalogItemId;
+    public String getCatalogItemId() {
+        return catalogItemId;
     }
 
     protected void onTagsChanged() {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/basic/ApiObjectsFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/ApiObjectsFactoryImpl.java b/core/src/main/java/brooklyn/basic/ApiObjectsFactoryImpl.java
deleted file mode 100644
index 8c95442..0000000
--- a/core/src/main/java/brooklyn/basic/ApiObjectsFactoryImpl.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.basic;
-
-import brooklyn.basic.ApiObjectsFactory.ApiObjectsFactoryInterface;
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.management.Task;
-import brooklyn.util.task.Tasks;
-
-public class ApiObjectsFactoryImpl implements ApiObjectsFactoryInterface {
-
-    @Override
-    public String getContextCatalogItemId() {
-        Task<?> currentTask = Tasks.current();
-        if (currentTask != null) {
-            Entity contextEntity = BrooklynTaskTags.getContextEntity(currentTask);
-            if (contextEntity != null) {
-                return contextEntity.getContextCatalogItemId();
-            }
-        }
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/basic/internal/ApiObjectsFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/internal/ApiObjectsFactoryImpl.java b/core/src/main/java/brooklyn/basic/internal/ApiObjectsFactoryImpl.java
new file mode 100644
index 0000000..f705494
--- /dev/null
+++ b/core/src/main/java/brooklyn/basic/internal/ApiObjectsFactoryImpl.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.basic.internal;
+
+import brooklyn.basic.internal.ApiObjectsFactoryInterface;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.management.Task;
+import brooklyn.util.task.Tasks;
+
+public class ApiObjectsFactoryImpl implements ApiObjectsFactoryInterface {
+
+    @Override
+    public String getCatalogItemIdFromContext() {
+        Task<?> currentTask = Tasks.current();
+        if (currentTask != null) {
+            Entity contextEntity = BrooklynTaskTags.getContextEntity(currentTask);
+            if (contextEntity != null) {
+                return contextEntity.getCatalogItemId();
+            }
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
index bdb73d7..53cb2de 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -256,7 +256,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
                     break;
                 default: throw new RuntimeException("Only entity & policy catalog items are supported. Unsupported catalog item type " + item.getCatalogItemType());
             }
-            ((AbstractBrooklynObjectSpec<?, ?>)spec).contextCatalogItemId(item.getId());
+            ((AbstractBrooklynObjectSpec<?, ?>)spec).catalogItemId(item.getId());
             return spec;
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
index cb40839..749c275 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
@@ -20,6 +20,7 @@ package brooklyn.catalog.internal;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -233,7 +234,7 @@ public class CatalogDo {
             mgmt.getRebindManager().getChangeListener().onManaged(entry);
         }
    }
-
+    
     /**
      * Removes the given entry from the catalog.
      */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index cb409fa..7bcf9ec 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -59,7 +59,7 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
     }
 
     @Override
-    public String getContextCatalogItemId() {
+    public String getCatalogItemId() {
         return null;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
index c32d913..f5bf6bc 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogUtils.java
@@ -97,9 +97,10 @@ public class CatalogUtils {
         }
     }
 
-    public static String getContextCatalogItemIdFromLoader(BrooklynClassLoadingContext loader) {
+    /** Scans the given {@link BrooklynClassLoadingContext} to detect what catalog item id is in effect. */
+    public static String getCatalogItemIdFromLoader(BrooklynClassLoadingContext loader) {
         if (loader instanceof OsgiBrooklynClassLoadingContext) {
-            return ((OsgiBrooklynClassLoadingContext)loader).getContextCatalogId();
+            return ((OsgiBrooklynClassLoadingContext)loader).getCatalogItemId();
         } else {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
index 1474c1b..d97255b 100644
--- a/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
+++ b/core/src/main/java/brooklyn/entity/basic/AbstractEntity.java
@@ -556,8 +556,8 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
         
         getApplication();
         
-        if (getContextCatalogItemId() == null) {
-            setContextCatalogItemId(entity.getContextCatalogItemId());
+        if (getCatalogItemId() == null) {
+            setCatalogItemId(entity.getCatalogItemId());
         }
         
         return this;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
index b831651..50e15e6 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
@@ -241,8 +241,8 @@ public class InternalEntityFactory extends InternalFactory {
             if (spec.getDisplayName()!=null)
                 ((AbstractEntity)entity).setDisplayName(spec.getDisplayName());
             
-            if (spec.getContextCatalogItemId()!=null) {
-                ((AbstractEntity)entity).setContextCatalogItemId(spec.getContextCatalogItemId());
+            if (spec.getCatalogItemId()!=null) {
+                ((AbstractEntity)entity).setCatalogItemId(spec.getCatalogItemId());
             }
             
             entity.tags().addTags(spec.getTags());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
index 14ea05f..4e6c0d7 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalLocationFactory.java
@@ -105,8 +105,8 @@ public class InternalLocationFactory extends InternalFactory {
             if (spec.getDisplayName()!=null)
                 ((AbstractLocation)loc).setDisplayName(spec.getDisplayName());
             
-            if (spec.getContextCatalogItemId()!=null) {
-                ((AbstractLocation)loc).setContextCatalogItemId(spec.getContextCatalogItemId());
+            if (spec.getCatalogItemId()!=null) {
+                ((AbstractLocation)loc).setCatalogItemId(spec.getCatalogItemId());
             }
             
             loc.tags().addTags(spec.getTags());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
index c5785ca..618a691 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalPolicyFactory.java
@@ -107,8 +107,8 @@ public class InternalPolicyFactory extends InternalFactory {
             if (spec.getDisplayName()!=null)
                 ((AbstractPolicy)pol).setDisplayName(spec.getDisplayName());
             
-            if (spec.getContextCatalogItemId()!=null) {
-                ((AbstractPolicy)pol).setContextCatalogItemId(spec.getContextCatalogItemId());
+            if (spec.getCatalogItemId()!=null) {
+                ((AbstractPolicy)pol).setCatalogItemId(spec.getCatalogItemId());
             }
             
             pol.tags().addTags(spec.getTags());
@@ -148,8 +148,8 @@ public class InternalPolicyFactory extends InternalFactory {
             if (spec.getDisplayName()!=null)
                 ((AbstractEnricher)enricher).setDisplayName(spec.getDisplayName());
             
-            if (spec.getContextCatalogItemId()!=null) {
-                ((AbstractEnricher)enricher).setContextCatalogItemId(spec.getContextCatalogItemId());
+            if (spec.getCatalogItemId()!=null) {
+                ((AbstractEnricher)enricher).setCatalogItemId(spec.getCatalogItemId());
             }
             
             enricher.tags().addTags(spec.getTags());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java
index 3eb6c96..5d8bcd6 100644
--- a/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java
@@ -48,7 +48,7 @@ public abstract class AbstractBrooklynObjectRebindSupport<T extends Memento> imp
         if (LOG.isTraceEnabled()) LOG.trace("Reconstructing: {}", memento.toVerboseString());
 
         instance.setDisplayName(memento.getDisplayName());
-        instance.setContextCatalogItemId(memento.getContextCatalogItemId());
+        instance.setCatalogItemId(memento.getCatalogItemId());
         addConfig(rebindContext, memento);
         addTags(rebindContext, memento);
         addCustoms(rebindContext, memento);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index 6d6d6a1..9f15404 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -641,11 +641,11 @@ public class RebindManagerImpl implements RebindManager {
             for (Map.Entry<String, EntityMementoManifest> entry : mementoManifest.getEntityIdToManifest().entrySet()) {
                 String entityId = entry.getKey();
                 EntityMementoManifest entityManifest = entry.getValue();
-                String contextCatalogItemId = findContextCatalogItemId(mementoManifest.getEntityIdToManifest(), entityManifest);
+                String catalogItemId = findCatalogItemId(mementoManifest.getEntityIdToManifest(), entityManifest);
                 if (LOG.isTraceEnabled()) LOG.trace("RebindManager instantiating entity {}", entityId);
                 
                 try {
-                    Entity entity = newEntity(entityId, entityManifest.getType(), getLoadingContextFromCatalogItemId(contextCatalogItemId, classLoader, rebindContext));
+                    Entity entity = newEntity(entityId, entityManifest.getType(), getLoadingContextFromCatalogItemId(catalogItemId, classLoader, rebindContext));
                     rebindContext.registerEntity(entityId, entity);
                 } catch (Exception e) {
                     exceptionHandler.onCreateFailed(BrooklynObjectType.ENTITY, entityId, entityManifest.getType(), e);
@@ -671,7 +671,7 @@ public class RebindManagerImpl implements RebindManager {
                     if (LOG.isDebugEnabled()) LOG.debug("RebindManager instantiating policy {}", policyMemento);
                     
                     try {
-                        Policy policy = newPolicy(policyMemento, getLoadingContextFromCatalogItemId(policyMemento.getContextCatalogItemId(), classLoader, rebindContext));
+                        Policy policy = newPolicy(policyMemento, getLoadingContextFromCatalogItemId(policyMemento.getCatalogItemId(), classLoader, rebindContext));
                         rebindContext.registerPolicy(policyMemento.getId(), policy);
                     } catch (Exception e) {
                         exceptionHandler.onCreateFailed(BrooklynObjectType.POLICY, policyMemento.getId(), policyMemento.getType(), e);
@@ -933,11 +933,11 @@ public class RebindManagerImpl implements RebindManager {
         }
     }
     
-    private String findContextCatalogItemId(Map<String, EntityMementoManifest> entityIdToManifest, EntityMementoManifest entityManifest) {
+    private String findCatalogItemId(Map<String, EntityMementoManifest> entityIdToManifest, EntityMementoManifest entityManifest) {
         EntityMementoManifest ptr = entityManifest;
         while (ptr != null) {
-            if (ptr.getContextCatalogItemId() != null) {
-                return ptr.getContextCatalogItemId();
+            if (ptr.getCatalogItemId() != null) {
+                return ptr.getCatalogItemId();
             }
             if (ptr.getParent() != null) {
                 ptr = entityIdToManifest.get(ptr.getParent());
@@ -957,7 +957,7 @@ public class RebindManagerImpl implements RebindManager {
                 throw new IllegalStateException("Failed to load catalog item " + catalogItemId + " required for rebinding.");
             }
         } else {
-            return new JavaBrooklynClassLoadingContext(managementContext, classLoader);
+            return JavaBrooklynClassLoadingContext.create(managementContext, classLoader);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java b/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java
index c07b991..c7ec1d9 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java
@@ -43,7 +43,7 @@ public abstract class AbstractMemento implements Memento, Serializable {
         protected String type;
         protected Class<?> typeClass;
         protected String displayName;
-        protected String contextCatalogItemId;
+        protected String catalogItemId;
         protected Map<String, Object> fields = Maps.newLinkedHashMap();
         protected List<Object> tags = Lists.newArrayList();
 
@@ -57,7 +57,7 @@ public abstract class AbstractMemento implements Memento, Serializable {
             type = other.getType();
             typeClass = other.getTypeClass();
             displayName = other.getDisplayName();
-            contextCatalogItemId = other.getContextCatalogItemId();
+            catalogItemId = other.getCatalogItemId();
             fields.putAll(other.getCustomFields());
             tags.addAll(other.getTags());
             return self();
@@ -77,8 +77,8 @@ public abstract class AbstractMemento implements Memento, Serializable {
         public B displayName(String val) {
             displayName = val; return self();
         }
-        public B contextCatalogItemId(String val) {
-            contextCatalogItemId = val; return self();
+        public B catalogItemId(String val) {
+            catalogItemId = val; return self();
         }
         /**
          * @deprecated since 0.7.0; use config/attributes so generic persistence will work, rather than requiring "custom fields"
@@ -93,7 +93,7 @@ public abstract class AbstractMemento implements Memento, Serializable {
     private String type;
     private String id;
     private String displayName;
-    private String contextCatalogItemId;
+    private String catalogItemId;
     private List<Object> tags;
 
     private transient Class<?> typeClass;
@@ -109,7 +109,7 @@ public abstract class AbstractMemento implements Memento, Serializable {
         type = builder.type;
         typeClass = builder.typeClass;
         displayName = builder.displayName;
-        contextCatalogItemId = builder.contextCatalogItemId;
+        catalogItemId = builder.catalogItemId;
         setCustomFields(builder.fields);
         tags = toPersistedList(builder.tags);
     }
@@ -149,8 +149,8 @@ public abstract class AbstractMemento implements Memento, Serializable {
     }
 
     @Override
-    public String getContextCatalogItemId() {
-        return contextCatalogItemId;
+    public String getCatalogItemId() {
+        return catalogItemId;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/entity/rebind/dto/EntityMementoManifestImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/EntityMementoManifestImpl.java b/core/src/main/java/brooklyn/entity/rebind/dto/EntityMementoManifestImpl.java
index bfec2ca..05b1dd7 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/EntityMementoManifestImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/EntityMementoManifestImpl.java
@@ -24,13 +24,13 @@ public class EntityMementoManifestImpl implements EntityMementoManifest {
     private String id;
     private String type;
     private String parentId;
-    private String contextCatalogItemId;
+    private String catalogItemId;
 
-    public EntityMementoManifestImpl(String id, String type, String parentId, String contextCatalogItemId) {
+    public EntityMementoManifestImpl(String id, String type, String parentId, String catalogItemId) {
         this.id = id;
         this.type = type;
         this.parentId = parentId;
-        this.contextCatalogItemId = contextCatalogItemId;
+        this.catalogItemId = catalogItemId;
     }
 
     @Override
@@ -49,8 +49,8 @@ public class EntityMementoManifestImpl implements EntityMementoManifest {
     }
 
     @Override
-    public String getContextCatalogItemId() {
-        return contextCatalogItemId;
+    public String getCatalogItemId() {
+        return catalogItemId;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java b/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
index 8888f5c..d5a5172 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
@@ -378,7 +378,7 @@ public class MementosGenerators {
     private static void populateBrooklynObjectMementoBuilder(BrooklynObject instance, AbstractMemento.Builder<?> builder) {
         builder.id = instance.getId();
         builder.displayName = instance.getDisplayName();
-        builder.contextCatalogItemId = instance.getContextCatalogItemId();
+        builder.catalogItemId = instance.getCatalogItemId();
         builder.type = instance.getClass().getName();
         builder.typeClass = instance.getClass();
         

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java b/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
index d185ab5..91baa26 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
@@ -51,7 +51,7 @@ public abstract class AbstractBrooklynMementoPersister implements BrooklynMement
     public BrooklynMementoManifest loadMementoManifest(RebindExceptionHandler exceptionHandler) {
         BrooklynMementoManifestImpl.Builder builder = BrooklynMementoManifestImpl.builder();
         for (EntityMemento entity : memento.getEntityMementos().values()) {
-            builder.entity(entity.getId(), entity.getType(), entity.getParent(), entity.getContextCatalogItemId());
+            builder.entity(entity.getId(), entity.getType(), entity.getParent(), entity.getCatalogItemId());
         }
         for (LocationMemento entity : memento.getLocationMementos().values()) {
             builder.location(entity.getId(), entity.getType());

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
index 7e13d62..2d0fe99 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
@@ -194,8 +194,8 @@ public class BrooklynMementoPersisterToMultiFile implements BrooklynMementoPersi
                     String id = (String) XmlUtil.xpath(contents, "/entity/id");
                     String type = (String) XmlUtil.xpath(contents, "/entity/type");
                     String parentId = (String) XmlUtil.xpath(contents, "/entity/parent");
-                    String contextCatalogItemId = (String) XmlUtil.xpath(contents, "/entity/contextCatalogItemId");
-                    builder.entity(id, type, Strings.emptyToNull(parentId), Strings.emptyToNull(contextCatalogItemId));
+                    String catalogItemId = (String) XmlUtil.xpath(contents, "/entity/catalogItemId");
+                    builder.entity(id, type, Strings.emptyToNull(parentId), Strings.emptyToNull(catalogItemId));
                 } catch (Exception e) {
                     exceptionHandler.onLoadMementoFailed(BrooklynObjectType.ENTITY, "File "+file, e);
                 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
index cf03958..6ab8a7c 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
@@ -253,8 +253,8 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
                         String id = (String) XmlUtil.xpath(contents, "/entity/id");
                         String objType = (String) XmlUtil.xpath(contents, "/entity/type");
                         String parentId = (String) XmlUtil.xpath(contents, "/entity/parent");
-                        String contextCatalogItemId = (String) XmlUtil.xpath(contents, "/entity/contextCatalogItemId");
-                        builder.entity(id, objType, Strings.emptyToNull(parentId), Strings.emptyToNull(contextCatalogItemId));
+                        String catalogItemId = (String) XmlUtil.xpath(contents, "/entity/catalogItemId");
+                        builder.entity(id, objType, Strings.emptyToNull(parentId), Strings.emptyToNull(catalogItemId));
                         break;
                     case LOCATION:
                         id = (String) XmlUtil.xpath(contents, "/location/id");

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java b/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
index 498d440..7dbc037 100644
--- a/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
+++ b/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
@@ -31,12 +31,12 @@ import com.google.common.base.Objects;
 public class OsgiBrooklynClassLoadingContext extends AbstractBrooklynClassLoadingContext {
 
     private final List<String> bundles;
-    private final String contextCatalogId;
+    private final String catalogItemId;
 
     public OsgiBrooklynClassLoadingContext(ManagementContext mgmt, String catalogItemId, List<String> bundles) {
         super(mgmt);
         this.bundles = bundles;
-        this.contextCatalogId = catalogItemId;
+        this.catalogItemId = catalogItemId;
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
@@ -71,7 +71,7 @@ public class OsgiBrooklynClassLoadingContext extends AbstractBrooklynClassLoadin
     
     @Override
     public int hashCode() {
-        return Objects.hashCode(super.hashCode(), bundles, contextCatalogId);
+        return Objects.hashCode(super.hashCode(), bundles, catalogItemId);
     }
     
     @Override
@@ -80,7 +80,7 @@ public class OsgiBrooklynClassLoadingContext extends AbstractBrooklynClassLoadin
         if (!(obj instanceof OsgiBrooklynClassLoadingContext)) return false;
 
         OsgiBrooklynClassLoadingContext other = (OsgiBrooklynClassLoadingContext)obj;
-        if (!contextCatalogId.equals(other.contextCatalogId)) return false;
+        if (!catalogItemId.equals(other.catalogItemId)) return false;
         if (!Objects.equal(bundles, other.bundles)) return false;
         return true;
     }
@@ -96,8 +96,8 @@ public class OsgiBrooklynClassLoadingContext extends AbstractBrooklynClassLoadin
         return null;
     }
     
-    public String getContextCatalogId() {
-        return contextCatalogId;
+    public String getCatalogItemId() {
+        return catalogItemId;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
index a7d8892..60597b5 100644
--- a/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
+++ b/core/src/main/java/brooklyn/policy/basic/AbstractEntityAdjunct.java
@@ -238,8 +238,8 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple
     public void setEntity(EntityLocal entity) {
         if (destroyed.get()) throw new IllegalStateException("Cannot set entity on a destroyed entity adjunct");
         this.entity = entity;
-        if (getContextCatalogItemId() == null) {
-            setContextCatalogItemId(entity.getContextCatalogItemId());
+        if (entity!=null && getCatalogItemId() == null) {
+            setCatalogItemId(entity.getCatalogItemId());
         }
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/resources/META-INF/services/brooklyn.basic.ApiObjectsFactory$ApiObjectsFactoryInterface
----------------------------------------------------------------------
diff --git a/core/src/main/resources/META-INF/services/brooklyn.basic.ApiObjectsFactory$ApiObjectsFactoryInterface b/core/src/main/resources/META-INF/services/brooklyn.basic.ApiObjectsFactory$ApiObjectsFactoryInterface
deleted file mode 100644
index 007e088..0000000
--- a/core/src/main/resources/META-INF/services/brooklyn.basic.ApiObjectsFactory$ApiObjectsFactoryInterface
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#  http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
-brooklyn.basic.ApiObjectsFactoryImpl

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/core/src/main/resources/META-INF/services/brooklyn.basic.internal.ApiObjectsFactoryInterface
----------------------------------------------------------------------
diff --git a/core/src/main/resources/META-INF/services/brooklyn.basic.internal.ApiObjectsFactoryInterface b/core/src/main/resources/META-INF/services/brooklyn.basic.internal.ApiObjectsFactoryInterface
new file mode 100644
index 0000000..4af251f
--- /dev/null
+++ b/core/src/main/resources/META-INF/services/brooklyn.basic.internal.ApiObjectsFactoryInterface
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+brooklyn.basic.internal.ApiObjectsFactoryImpl

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index 8bd1073..d03502e 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -202,7 +202,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
             } else {
                 //TODO migrate to catalog.createSpec
                 spec = resolveCatalogYamlReferenceSpec(mgmt, item, encounteredCatalogTypes);
-                spec.contextCatalogItemId(item.getId());
+                spec.catalogItemId(item.getId());
                 entityResolver.populateSpec(spec);
             }
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/72ac1296/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index 2dfb581..2adad06 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -257,7 +257,7 @@ public class BrooklynComponentTemplateResolver {
             List<Class<?>> additionalInterfaceClazzes = Reflections.getAllInterfaces(type);
             spec = EntitySpec.create(interfaceclazz).impl(type).additionalInterfaces(additionalInterfaceClazzes);
         }
-        spec.contextCatalogItemId(CatalogUtils.getContextCatalogItemIdFromLoader(loader));
+        spec.catalogItemId(CatalogUtils.getCatalogItemIdFromLoader(loader));
         if (template.isPresent() && template.get().getSourceCode()!=null)
             spec.tag(BrooklynTags.newYamlSpecTag(template.get().getSourceCode()));
 
@@ -282,9 +282,7 @@ public class BrooklynComponentTemplateResolver {
         if (childrenObj != null) {
             Set<String> encounteredCatalogTypes = MutableSet.of();
 
-            @SuppressWarnings("unchecked")
             Iterable<Map<String,?>> children = (Iterable<Map<String,?>>)childrenObj;
-
             for (Map<String,?> childAttrs : children) {
                 BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(loader, childAttrs);
                 BrooklynAssemblyTemplateInstantiator instantiator = new BrooklynAssemblyTemplateInstantiator();


[14/18] git commit: OSGi catalog item test (see full msg for details)

Posted by he...@apache.org.
OSGi catalog item test (see full msg for details)

Add some more OSGi test bundles - see OsgiTestResources.
Write lots more tests of OSGi loading and item ID - in OsgiEntitiesTest, and in camp project using YAML e.g. Catalog*Osgi*Test.java .
Also load OSGi on addItem(CatalogItem), and improve OSGi loading error messages when OSGi loading fails.
Better error messages on OSGi failures.


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

Branch: refs/heads/master
Commit: 35fd634154c0248f16ea3f5f09e4229b13f902e2
Parents: a76208a
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Mon Nov 3 09:57:13 2014 +0000
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 4 11:10:55 2014 +0000

----------------------------------------------------------------------
 .../catalog/internal/BasicBrooklynCatalog.java  |  12 +-
 .../brooklyn/catalog/internal/CatalogDo.java    |   1 -
 .../internal/CatalogItemDtoAbstract.java        |  13 +
 .../BrooklynClassLoadingContextSequential.java  |  12 +-
 .../OsgiBrooklynClassLoadingContext.java        |   1 +
 .../brooklyn/management/ha/OsgiManager.java     |  26 +-
 core/src/test/dependencies/osgi/README.md       |  29 ++
 .../src/test/dependencies/osgi/entities/pom.xml |   5 +-
 .../dependencies/osgi/more-entities-v1/pom.xml  |  82 +++++
 .../brooklyn/osgi/tests/more/MoreEntity.java    |  38 +++
 .../osgi/tests/more/MoreEntityImpl.java         |  44 +++
 .../dependencies/osgi/more-entities-v2/pom.xml  |  87 +++++
 .../brooklyn/osgi/tests/more/MoreEntity.java    |  38 +++
 .../osgi/tests/more/MoreEntityImpl.java         |  47 +++
 .../brooklyn/catalog/internal/CatalogItems.java |   4 +-
 .../management/osgi/OsgiEntitiesTest.java       |  92 ------
 .../management/osgi/OsgiStandaloneTest.java     |   5 +-
 .../management/osgi/OsgiTestResources.java      |  50 ++-
 .../osgi/OsgiVersionMoreEntityTest.java         | 318 +++++++++++++++++++
 core/src/test/resources/brooklyn/osgi/README.md |   2 +
 .../osgi/brooklyn-test-osgi-entities.jar        | Bin 12378 -> 12406 bytes
 .../brooklyn-test-osgi-more-entities_0.1.0.jar  | Bin 0 -> 12452 bytes
 .../brooklyn-test-osgi-more-entities_0.2.0.jar  | Bin 0 -> 12615 bytes
 .../spi/creation/BrooklynEntityMatcher.java     |  11 +-
 .../camp/brooklyn/CatalogYamlEntityTest.java    | 184 -----------
 .../camp/brooklyn/CatalogYamlPolicyTest.java    | 136 --------
 .../CatalogOsgiVersionMoreEntityTest.java       | 130 ++++++++
 .../brooklyn/catalog/CatalogYamlEntityTest.java | 187 +++++++++++
 .../brooklyn/catalog/CatalogYamlPolicyTest.java | 135 ++++++++
 .../more-entity-v1-called-v1-osgi-catalog.yaml  |  10 +
 .../catalog/more-entity-v1-osgi-catalog.yaml    |  10 +
 ...more-entity-v1-with-policy-osgi-catalog.yaml |  12 +
 .../catalog/more-entity-v2-osgi-catalog.yaml    |  11 +
 .../catalog/simple-policy-osgi-catalog.yaml     |  10 +
 .../brooklyn/util/exceptions/Exceptions.java    |  56 +++-
 .../java/brooklyn/util/guava/Functionals.java   |   1 -
 .../guava/IllegalStateExceptionSupplier.java    |   2 +-
 37 files changed, 1344 insertions(+), 457 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
index 53cb2de..0236999 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -167,10 +167,13 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     }
 
     protected CatalogItemDo<?,?> getCatalogItemDo(String idOrRegisteredTypeName) {
-        CatalogItemDo<?, ?> item = catalog.getIdCache().get(idOrRegisteredTypeName);
-        if (item == null) {
-            item = catalog.getRegisteredTypeNameCache().get(idOrRegisteredTypeName);
-        }
+        CatalogItemDo<?, ?> item = null;
+        // TODO really need to remove redundancy of id v registered type;
+        // should also remove "manual additions" bucket; just have one map a la osgi
+        if (manualAdditionsCatalog!=null) item = manualAdditionsCatalog.getIdCache().get(idOrRegisteredTypeName);
+        if (item == null) item = catalog.getIdCache().get(idOrRegisteredTypeName);
+        if (item == null && manualAdditionsCatalog!=null) item = manualAdditionsCatalog.getRegisteredTypeNameCache().get(idOrRegisteredTypeName);
+        if (item == null) item = catalog.getRegisteredTypeNameCache().get(idOrRegisteredTypeName);
         return item;
     }
     
@@ -498,6 +501,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
     public void addItem(CatalogItem<?,?> item) {
         log.debug("Adding manual catalog item to "+mgmt+": "+item);
         checkNotNull(item, "item");
+        CatalogUtils.installLibraries(mgmt, item.getLibraries());
         if (manualAdditionsCatalog==null) loadManualAdditionsCatalog();
         manualAdditionsCatalog.addEntry(getAbstractCatalogItem(item));
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
index 749c275..a4ba086 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
@@ -20,7 +20,6 @@ package brooklyn.catalog.internal;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index 6507ba7..704976b 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -24,6 +24,9 @@ import java.util.Set;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import brooklyn.basic.AbstractBrooklynObject;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.entity.rebind.BasicCatalogItemRebindSupport;
@@ -38,6 +41,8 @@ import com.google.common.collect.Sets;
 
 public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynObject implements CatalogItem<T, SpecT> {
 
+    private static final Logger log = LoggerFactory.getLogger(CatalogItemDtoAbstract.class);
+    
     // TODO are ID and registeredType the same?
     @SetFromFlag Set<Object> tags = Sets.newLinkedHashSet();
     @SetFromFlag String registeredType;
@@ -229,4 +234,12 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO
         }
     }
 
+    /** Use of this method is discouraged unless it is assigning the same (final) ID that this object already has. */
+    @Override
+    public void setCatalogItemId(String id) {
+        if (id!=null && !id.equals(getRegisteredTypeName())) {
+            log.warn("Setting 'catalog-item ID' of catalog item "+getId()+"/"+getRegisteredTypeName()+" to "+id+"; if set, catalog-item ID should match the registered type name.");
+        }
+        super.setCatalogItemId(id);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContextSequential.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContextSequential.java b/core/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContextSequential.java
index 5012dc0..551168b 100644
--- a/core/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContextSequential.java
+++ b/core/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContextSequential.java
@@ -25,13 +25,14 @@ import java.util.Set;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Objects;
-
 import brooklyn.management.ManagementContext;
 import brooklyn.util.collections.MutableList;
 import brooklyn.util.collections.MutableSet;
+import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.guava.Maybe;
 
+import com.google.common.base.Objects;
+
 public final class BrooklynClassLoadingContextSequential extends AbstractBrooklynClassLoadingContext {
 
     private static final Logger log = LoggerFactory.getLogger(BrooklynClassLoadingContextSequential.class);
@@ -66,18 +67,23 @@ public final class BrooklynClassLoadingContextSequential extends AbstractBrookly
     }
     
     public Maybe<Class<?>> tryLoadClass(String className) {
+        List<Throwable> errors = MutableList.of();
         for (BrooklynClassLoadingContext target: primaries) {
             Maybe<Class<?>> clazz = target.tryLoadClass(className);
             if (clazz.isPresent())
                 return clazz;
+            errors.add( ((Maybe.Absent<?>)clazz).getException() );
         }
+        boolean noPrimaryErrors = errors.isEmpty();
         for (BrooklynClassLoadingContext target: secondaries) {
             Maybe<Class<?>> clazz = target.tryLoadClass(className);
             if (clazz.isPresent())
                 return clazz;
+            if (noPrimaryErrors)
+                errors.add( ((Maybe.Absent<?>)clazz).getException() );
         }
 
-        return Maybe.absent("Unable to load "+className+" from "+primaries);
+        return Maybe.absent(Exceptions.create("Unable to load "+className+" from "+primaries, errors));
     }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java b/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
index 7dbc037..74cc6cf 100644
--- a/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
+++ b/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
@@ -24,6 +24,7 @@ import java.util.List;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.ha.OsgiManager;
 import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.guava.Maybe;
 
 import com.google.common.base.Objects;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/main/java/brooklyn/management/ha/OsgiManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/ha/OsgiManager.java b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
index bde7360..7f6ca52 100644
--- a/core/src/main/java/brooklyn/management/ha/OsgiManager.java
+++ b/core/src/main/java/brooklyn/management/ha/OsgiManager.java
@@ -38,6 +38,7 @@ import brooklyn.util.os.Os;
 import brooklyn.util.osgi.Osgis;
 
 import com.google.common.base.Throwables;
+import com.google.common.collect.Iterables;
 
 public class OsgiManager {
 
@@ -91,7 +92,7 @@ public class OsgiManager {
             Bundle b = Osgis.install(framework, bundleUrl);
             nv = b.getSymbolicName()+":"+b.getVersion().toString();
             bundleUrlToNameVersionString.put(bundleUrl, nv);
-            log.debug("Bundle from "+bundleUrl+" successfully installed as " + nv);
+            log.debug("Bundle from "+bundleUrl+" successfully installed as " + nv + " ("+b+")");
         } catch (BundleException e) {
             log.debug("Bundle from "+bundleUrl+" failed to install (rethrowing): "+e);
             throw Throwables.propagate(e);
@@ -104,9 +105,11 @@ public class OsgiManager {
     public <T> Maybe<Class<T>> tryResolveClass(String type, Iterable<String> bundleUrlsOrNameVersionString) {
         Map<String,Throwable> bundleProblems = MutableMap.of();
         for (String bundleUrlOrNameVersionString: bundleUrlsOrNameVersionString) {
+            boolean noVersionInstalled = false;
             try {
                 String bundleNameVersion = bundleUrlToNameVersionString.get(bundleUrlOrNameVersionString);
                 if (bundleNameVersion==null) {
+                    noVersionInstalled = true;
                     bundleNameVersion = bundleUrlOrNameVersionString;
                 }
 
@@ -131,7 +134,16 @@ public class OsgiManager {
                 }
             } catch (Exception e) {
                 Exceptions.propagateIfFatal(e);
-                bundleProblems.put(bundleUrlOrNameVersionString, e);
+                if (noVersionInstalled) {
+                    if (bundleUrlOrNameVersionString.contains("/")) {
+                        // suppress misleading nested trace if the input string looked like a URL
+                        bundleProblems.put(bundleUrlOrNameVersionString, new IllegalStateException("Bundle does not appear to be installed"));
+                    } else {
+                        bundleProblems.put(bundleUrlOrNameVersionString, new IllegalStateException("Bundle does not appear to be installed", e));
+                    }
+                } else {
+                    bundleProblems.put(bundleUrlOrNameVersionString, e);
+                }
 
                 Throwable cause = e.getCause();
                 if (cause != null && cause.getMessage().contains("Unresolved constraint in bundle")) {
@@ -140,7 +152,15 @@ public class OsgiManager {
                 }
             }
         }
-        return Maybe.absent("Unable to resolve class "+type+": "+bundleProblems);
+        if (bundleProblems.size()==1) {
+            Throwable error = Iterables.getOnlyElement(bundleProblems.values());
+            if (error instanceof ClassNotFoundException && error.getCause()!=null && error.getCause().getMessage()!=null) {
+                error = Exceptions.collapseIncludingAllCausalMessages(error);
+            }
+            return Maybe.absent("Unable to resolve class "+type+" in "+Iterables.getOnlyElement(bundleProblems.keySet()), error);
+        } else {
+            return Maybe.absent(Exceptions.create("Unable to resolve class "+type+": "+bundleProblems, bundleProblems.values()));
+        }
     }
 
     public URL getResource(String name, Iterable<String> bundleUrlsOrNameVersionString) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/dependencies/osgi/README.md
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/README.md b/core/src/test/dependencies/osgi/README.md
new file mode 100644
index 0000000..ee8539b
--- /dev/null
+++ b/core/src/test/dependencies/osgi/README.md
@@ -0,0 +1,29 @@
+This directory contains source code for OSGi bundle files 
+used for testing.
+
+Binaries are included under src/test/resources.  They are
+copied there when these projects are built, and the binaries
+are included in source control to speed up build times
+(as these projects do not change much).  These projects are
+NOT built as part of the normal brooklyn build.
+
+See OsgiTestResources.java for information on the bundles.
+
+----
+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.
+

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/dependencies/osgi/entities/pom.xml
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/entities/pom.xml b/core/src/test/dependencies/osgi/entities/pom.xml
index 41551f4..d143ea2 100644
--- a/core/src/test/dependencies/osgi/entities/pom.xml
+++ b/core/src/test/dependencies/osgi/entities/pom.xml
@@ -70,11 +70,10 @@
             <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
-                <version>1.4.0</version>
-                <extensions>true</extensions>
+                <version>2.5.3</version>
                 <configuration>
                     <instructions>
-                        <Bundle-Version>0.1.0</Bundle-Version>
+                        <Bundle-Version>${project.version}</Bundle-Version>
                     </instructions>
                 </configuration>
             </plugin>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/dependencies/osgi/more-entities-v1/pom.xml
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/more-entities-v1/pom.xml b/core/src/test/dependencies/osgi/more-entities-v1/pom.xml
new file mode 100644
index 0000000..aab4774
--- /dev/null
+++ b/core/src/test/dependencies/osgi/more-entities-v1/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>jar</packaging>
+
+    <groupId>org.apache.brooklyn.test.resources.osgi</groupId>
+    <artifactId>brooklyn-test-osgi-more-entities</artifactId>
+    <version>0.1.0</version>
+
+    <name>OSGi bundled test entities</name>
+
+    <description>
+        Simple entities for testing the OSGi functionality
+    </description>
+
+    <parent>
+        <groupId>org.apache.brooklyn</groupId>
+        <artifactId>brooklyn-parent</artifactId>
+        <version>0.7.0-SNAPSHOT</version><!-- BROOKLYN_VERSION -->
+        <relativePath>../../../../../../pom.xml</relativePath>
+    </parent>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.brooklyn</groupId>
+            <artifactId>brooklyn-core</artifactId>
+            <version>${brooklyn.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.brooklyn</groupId>
+            <artifactId>brooklyn-api</artifactId>
+            <version>${brooklyn.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.brooklyn</groupId>
+            <artifactId>brooklyn-utils-common</artifactId>
+            <version>${brooklyn.version}</version>
+        </dependency>
+    </dependencies>
+    
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.3.2</version>
+                <configuration>
+                    <outputDirectory>../../../resources/brooklyn/osgi</outputDirectory>
+                    <finalName>brooklyn-test-osgi-more-entities_${version}</finalName>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>2.5.3</version>
+                <configuration>
+                    <instructions>
+                        <Bundle-Version>${project.version}</Bundle-Version>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/dependencies/osgi/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java b/core/src/test/dependencies/osgi/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
new file mode 100644
index 0000000..f26f1f1
--- /dev/null
+++ b/core/src/test/dependencies/osgi/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.osgi.tests.more;
+
+
+import brooklyn.entity.Effector;
+import brooklyn.entity.Entity;
+import brooklyn.entity.effector.Effectors;
+import brooklyn.entity.proxying.ImplementedBy;
+
+@ImplementedBy(MoreEntityImpl.class)
+public interface MoreEntity extends Entity {
+
+    public static final Effector<String> SAY_HI = Effectors.effector(String.class, "sayHI")
+        .description("says HI to an uppercased name")
+        .parameter(String.class, "name")
+        .buildAbstract();
+
+    /** Makes a string saying hi to the given name, in uppercase, for testing. */
+    String sayHI(String name);
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/dependencies/osgi/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java b/core/src/test/dependencies/osgi/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
new file mode 100644
index 0000000..5eb1de5
--- /dev/null
+++ b/core/src/test/dependencies/osgi/more-entities-v1/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.osgi.tests.more;
+
+import brooklyn.entity.basic.AbstractEntity;
+import brooklyn.entity.effector.EffectorBody;
+import brooklyn.util.config.ConfigBag;
+
+
+public class MoreEntityImpl extends AbstractEntity implements MoreEntity {
+
+    @Override
+    public void init() {
+        super.init();
+        getMutableEntityType().addEffector(SAY_HI, new EffectorBody<String>() {
+            @Override
+            public String call(ConfigBag parameters) {
+                return sayHI((String)parameters.getStringKey("name"));
+            }
+        });
+    }
+    
+    @Override
+    public String sayHI(String name) {
+        return "Hi "+name.toUpperCase();
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/dependencies/osgi/more-entities-v2/pom.xml
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/more-entities-v2/pom.xml b/core/src/test/dependencies/osgi/more-entities-v2/pom.xml
new file mode 100644
index 0000000..a29247d
--- /dev/null
+++ b/core/src/test/dependencies/osgi/more-entities-v2/pom.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>jar</packaging>
+
+    <groupId>org.apache.brooklyn.test.resources.osgi</groupId>
+    <artifactId>brooklyn-test-osgi-more-entities</artifactId>
+    <version>0.2.0</version>
+
+    <name>OSGi bundled test entities</name>
+
+    <description>
+        Simple entities for testing the OSGi functionality
+    </description>
+
+    <parent>
+        <groupId>org.apache.brooklyn</groupId>
+        <artifactId>brooklyn-parent</artifactId>
+        <version>0.7.0-SNAPSHOT</version><!-- BROOKLYN_VERSION -->
+        <relativePath>../../../../../../pom.xml</relativePath>
+    </parent>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.brooklyn</groupId>
+            <artifactId>brooklyn-core</artifactId>
+            <version>${brooklyn.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.brooklyn</groupId>
+            <artifactId>brooklyn-api</artifactId>
+            <version>${brooklyn.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.brooklyn</groupId>
+            <artifactId>brooklyn-utils-common</artifactId>
+            <version>${brooklyn.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.brooklyn.test.resources.osgi</groupId>
+            <artifactId>brooklyn-test-osgi-entities</artifactId>
+            <version>0.1.0</version>
+        </dependency>
+    </dependencies>
+    
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.3.2</version>
+                <configuration>
+                    <outputDirectory>../../../resources/brooklyn/osgi</outputDirectory>
+                    <finalName>brooklyn-test-osgi-more-entities_${version}</finalName>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <version>2.5.3</version>
+                <configuration>
+                    <instructions>
+                        <Bundle-Version>${project.version}</Bundle-Version>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java b/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
new file mode 100644
index 0000000..f26f1f1
--- /dev/null
+++ b/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntity.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.osgi.tests.more;
+
+
+import brooklyn.entity.Effector;
+import brooklyn.entity.Entity;
+import brooklyn.entity.effector.Effectors;
+import brooklyn.entity.proxying.ImplementedBy;
+
+@ImplementedBy(MoreEntityImpl.class)
+public interface MoreEntity extends Entity {
+
+    public static final Effector<String> SAY_HI = Effectors.effector(String.class, "sayHI")
+        .description("says HI to an uppercased name")
+        .parameter(String.class, "name")
+        .buildAbstract();
+
+    /** Makes a string saying hi to the given name, in uppercase, for testing. */
+    String sayHI(String name);
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
----------------------------------------------------------------------
diff --git a/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java b/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
new file mode 100644
index 0000000..355c43a
--- /dev/null
+++ b/core/src/test/dependencies/osgi/more-entities-v2/src/main/java/brooklyn/osgi/tests/more/MoreEntityImpl.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.osgi.tests.more;
+
+import brooklyn.entity.basic.AbstractEntity;
+import brooklyn.entity.effector.EffectorBody;
+import brooklyn.policy.PolicySpec;
+import brooklyn.util.config.ConfigBag;
+
+
+public class MoreEntityImpl extends AbstractEntity implements MoreEntity {
+
+    /** Unlike v1, this declares an explicit dependency on SimplePolicy */
+    @Override
+    public void init() {
+        super.init();
+        getMutableEntityType().addEffector(SAY_HI, new EffectorBody<String>() {
+            @Override
+            public String call(ConfigBag parameters) {
+                return sayHI((String)parameters.getStringKey("name"));
+            }
+        });
+        addPolicy(PolicySpec.create(brooklyn.osgi.tests.SimplePolicy.class));
+    }
+    
+    /** Unlike v1, this returns "HI " rather than "Hi " */
+    public String sayHI(String name) {
+        return "HI "+name.toUpperCase();
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/java/brooklyn/catalog/internal/CatalogItems.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/catalog/internal/CatalogItems.java b/core/src/test/java/brooklyn/catalog/internal/CatalogItems.java
index 44bb9d5..dcefbcc 100644
--- a/core/src/test/java/brooklyn/catalog/internal/CatalogItems.java
+++ b/core/src/test/java/brooklyn/catalog/internal/CatalogItems.java
@@ -20,8 +20,8 @@ package brooklyn.catalog.internal;
 
 import io.brooklyn.camp.spi.pdp.DeploymentPlan;
 
-/** Deliberately package-private. Only for internal use. */
-class CatalogItems {
+/** Only for internal use / use in tests. */
+public class CatalogItems {
 
     public static CatalogTemplateItemDto newTemplateFromJava(String javaType, String name) {
         return newTemplateFromJava(javaType, name, null, null);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/java/brooklyn/management/osgi/OsgiEntitiesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiEntitiesTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiEntitiesTest.java
deleted file mode 100644
index 9b92b0c..0000000
--- a/core/src/test/java/brooklyn/management/osgi/OsgiEntitiesTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package brooklyn.management.osgi;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.launch.Framework;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.entity.proxying.InternalEntityFactory;
-import brooklyn.entity.proxying.InternalPolicyFactory;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.test.entity.LocalManagementContextForTests;
-import brooklyn.util.os.Os;
-import brooklyn.util.osgi.Osgis;
-
-
-/** 
- * Tests that OSGi entities load correctly and have the right catalog information set.
- *     
- */
-public class OsgiEntitiesTest {
-   
-    public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
-    public static final String BROOKLYN_TEST_OSGI_ENTITIES_URL = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_URL;
-
-    @BeforeMethod(alwaysRun=true)
-    public void setUp() throws Exception {
-    }
-
-    @AfterMethod(alwaysRun=true)
-    public void tearDown() throws BundleException, IOException, InterruptedException {
-    }
-    
-    /**
-     * Test fix for
-     * java.lang.NoClassDefFoundError: brooklyn.event.AttributeSensor not found by io.brooklyn.brooklyn-test-osgi-entities [41]
-     */
-    @Test
-    public void testEntityProxy() throws Exception {
-        File storageTempDir = Os.newTempDir("osgi-standalone");
-        Framework framework = Osgis.newFrameworkStarted(storageTempDir.getAbsolutePath(), true, null);
-        
-        try {
-        ManagementContextInternal managementContext;
-        InternalEntityFactory factory;
-
-        managementContext = new LocalManagementContextForTests();
-        InternalPolicyFactory policyFactory = new InternalPolicyFactory(managementContext);
-        factory = new InternalEntityFactory(managementContext, managementContext.getEntityManager().getEntityTypeRegistry(), policyFactory);
-
-        Bundle bundle = Osgis.install(framework, BROOKLYN_TEST_OSGI_ENTITIES_PATH);
-        @SuppressWarnings("unchecked")
-        Class<? extends Entity> bundleCls = (Class<? extends Entity>) bundle.loadClass("brooklyn.osgi.tests.SimpleEntityImpl");
-        @SuppressWarnings("unchecked")
-        Class<? extends Entity> bundleInterface = (Class<? extends Entity>) bundle.loadClass("brooklyn.osgi.tests.SimpleEntity");
-
-        @SuppressWarnings("unchecked")
-        EntitySpec<Entity> spec = (EntitySpec<Entity>) (((EntitySpec<Entity>)EntitySpec.create(bundleInterface))).impl(bundleCls);
-        Entity entity = bundleCls.newInstance();
-        factory.createEntityProxy(spec, entity);
-
-        if (managementContext != null) Entities.destroyAll(managementContext);
-        } finally {
-            OsgiStandaloneTest.tearDownOsgiFramework(framework, storageTempDir);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
index c2f9d51..94b9e9e 100644
--- a/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiStandaloneTest.java
@@ -57,10 +57,11 @@ public class OsgiStandaloneTest {
 
     private static final Logger log = LoggerFactory.getLogger(OsgiStandaloneTest.class);
 
-    public static final String BROOKLYN_OSGI_TEST_A_0_1_0_URL = OsgiTestResources.BROOKLYN_OSGI_TEST_A_0_1_0_URL;
+    public static final String BROOKLYN_OSGI_TEST_A_0_1_0_PATH = OsgiTestResources.BROOKLYN_OSGI_TEST_A_0_1_0_PATH;
+    public static final String BROOKLYN_OSGI_TEST_A_0_1_0_URL = "classpath:"+BROOKLYN_OSGI_TEST_A_0_1_0_PATH;
 
     public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
-    public static final String BROOKLYN_TEST_OSGI_ENTITIES_URL = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_URL;
+    public static final String BROOKLYN_TEST_OSGI_ENTITIES_URL = "classpath:"+BROOKLYN_TEST_OSGI_ENTITIES_PATH;
 
     protected Framework framework = null;
     private File storageTempDir;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/java/brooklyn/management/osgi/OsgiTestResources.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiTestResources.java b/core/src/test/java/brooklyn/management/osgi/OsgiTestResources.java
index 3ab2055..de889be 100644
--- a/core/src/test/java/brooklyn/management/osgi/OsgiTestResources.java
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiTestResources.java
@@ -19,25 +19,43 @@
 package brooklyn.management.osgi;
 
 /**
-* Many OSGi tests require OSGi bundles (of course). Test bundles have been collected here
-* for convenience and clarity. Available bundles (on the classpath, with source code
-* either embedded or in /src/dependencies) are:
-* <p>
-* <li>brooklyn-osgi-test-a_0.1.0 -
-*     defines TestA which has a "times" method and a static multiplier field;
-*     we set the multiplier to determine when we are sharing versions and when not
-*     
-* <li>brooklyn-test-osgi-entities (also version 0.1.0) -
-*     defines an entity and an application, to confirm it can be read and used by brooklyn
-* <p>
-* Some of these bundles are also used in REST API tests, as that stretches catalog further
-* (using CAMP) and that is one area where OSGi is heavily used. 
-*/
+ * Many OSGi tests require OSGi bundles (of course). Test bundles have been collected here
+ * for convenience and clarity. Available bundles (on the classpath, with source code
+ * either embedded or in /src/dependencies) are described by the constants in this class.
+ * <p>
+ * Some of these bundles are also used in REST API tests, as that stretches catalog further
+ * (using CAMP) and that is one area where OSGi is heavily used. 
+ */
 public class OsgiTestResources {
 
-    public static final String BROOKLYN_OSGI_TEST_A_0_1_0_URL = "classpath:/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar";
+    /**
+     * brooklyn-osgi-test-a_0.1.0 -
+     * defines TestA which has a "times" method and a static multiplier field;
+     * we set the multiplier to determine when we are sharing versions and when not
+     */
+    public static final String BROOKLYN_OSGI_TEST_A_0_1_0_PATH = "/brooklyn/osgi/brooklyn-osgi-test-a_0.1.0.jar";
 
+    /**
+     * brooklyn-test-osgi-entities (v 0.1.0) -
+     * defines an entity and an application, to confirm it can be read and used by brooklyn
+     */
     public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = "/brooklyn/osgi/brooklyn-test-osgi-entities.jar";
-    public static final String BROOKLYN_TEST_OSGI_ENTITIES_URL = "classpath:"+BROOKLYN_TEST_OSGI_ENTITIES_PATH;
+    public static final String BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_ENTITY = "brooklyn.osgi.tests.SimpleEntity";
+    public static final String BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_POLICY = "brooklyn.osgi.tests.SimplePolicy";
 
+    /**
+     * brooklyn-test-osgi-more-entities_0.1.0 -
+     * another bundle with a minimal sayHi effector, used to test versioning and dependencies
+     * (this one has no dependencies, but see also {@value #BROOKLYN_TEST_MORE_ENTITIES_V2_PATH})
+     */
+    public static final String BROOKLYN_TEST_MORE_ENTITIES_V1_PATH = "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar";
+    public static final String BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY = "brooklyn.osgi.tests.more.MoreEntity";
+    
+    /**
+     * brooklyn-test-osgi-more-entities_0.2.0 -
+     * similar to {@link #BROOKLYN_TEST_MORE_ENTITIES_V1_PATH} but saying "HI NAME" rather than "Hi NAME",
+     * and declaring an explicit dependency on SimplePolicy from {@link #BROOKLYN_TEST_OSGI_ENTITIES_PATH}
+     */
+    public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_PATH = "/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar";
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
new file mode 100644
index 0000000..4175639
--- /dev/null
+++ b/core/src/test/java/brooklyn/management/osgi/OsgiVersionMoreEntityTest.java
@@ -0,0 +1,318 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package brooklyn.management.osgi;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.launch.Framework;
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.internal.CatalogEntityItemDto;
+import brooklyn.catalog.internal.CatalogItems;
+import brooklyn.catalog.internal.CatalogUtils;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.effector.Effectors;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.entity.proxying.InternalEntityFactory;
+import brooklyn.entity.proxying.InternalPolicyFactory;
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
+import brooklyn.management.internal.LocalManagementContext;
+import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.policy.PolicySpec;
+import brooklyn.test.entity.LocalManagementContextForTests;
+import brooklyn.test.entity.TestApplication;
+import brooklyn.util.os.Os;
+import brooklyn.util.osgi.Osgis;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+
+/** 
+ * Tests that OSGi entities load correctly and have the right catalog information set.
+ * Note further tests done elsewhere using CAMP YAML (referring to methods in this class).
+ */
+public class OsgiVersionMoreEntityTest {
+   
+    public static final String BROOKLYN_TEST_OSGI_ENTITIES_PATH = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
+    public static final String BROOKLYN_TEST_OSGI_ENTITIES_URL = "classpath:"+OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
+
+    public static final String BROOKLYN_TEST_MORE_ENTITIES_V1_PATH = OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_V1_PATH;
+    public static final String BROOKLYN_TEST_MORE_ENTITIES_V1_URL = "classpath:"+BROOKLYN_TEST_MORE_ENTITIES_V1_PATH;
+    public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_PATH = OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_V2_PATH;
+    public static final String BROOKLYN_TEST_MORE_ENTITIES_V2_URL = "classpath:"+BROOKLYN_TEST_MORE_ENTITIES_V2_PATH;
+    
+    protected LocalManagementContext mgmt;
+    protected TestApplication app;
+
+    @BeforeMethod(alwaysRun=true)
+    public void setUp() throws Exception {
+        mgmt = LocalManagementContextForTests.builder(true).disableOsgi(false).build();
+        app = TestApplication.Factory.newManagedInstanceForTests(mgmt);
+    }
+
+    @AfterMethod(alwaysRun=true)
+    public void tearDown() throws BundleException, IOException, InterruptedException {
+        Entities.destroyAll(mgmt);
+    }
+    
+    /**
+     * Test fix for
+     * java.lang.NoClassDefFoundError: brooklyn.event.AttributeSensor not found by io.brooklyn.brooklyn-test-osgi-entities [41]
+     */
+    @Test
+    public void testEntityProxy() throws Exception {
+        File storageTempDir = Os.newTempDir("osgi-standalone");
+        Framework framework = Osgis.newFrameworkStarted(storageTempDir.getAbsolutePath(), true, null);
+        
+        try {
+            ManagementContextInternal managementContext;
+            InternalEntityFactory factory;
+
+            managementContext = new LocalManagementContextForTests();
+            InternalPolicyFactory policyFactory = new InternalPolicyFactory(managementContext);
+            factory = new InternalEntityFactory(managementContext, managementContext.getEntityManager().getEntityTypeRegistry(), policyFactory);
+
+            Bundle bundle = Osgis.install(framework, BROOKLYN_TEST_OSGI_ENTITIES_PATH);
+            @SuppressWarnings("unchecked")
+            Class<? extends Entity> bundleCls = (Class<? extends Entity>) bundle.loadClass("brooklyn.osgi.tests.SimpleEntityImpl");
+            @SuppressWarnings("unchecked")
+            Class<? extends Entity> bundleInterface = (Class<? extends Entity>) bundle.loadClass("brooklyn.osgi.tests.SimpleEntity");
+
+            @SuppressWarnings("unchecked")
+            EntitySpec<Entity> spec = (EntitySpec<Entity>) (((EntitySpec<Entity>)EntitySpec.create(bundleInterface))).impl(bundleCls);
+            Entity entity = bundleCls.newInstance();
+            factory.createEntityProxy(spec, entity);
+
+            if (managementContext != null) Entities.destroyAll(managementContext);
+        } finally {
+            OsgiStandaloneTest.tearDownOsgiFramework(framework, storageTempDir);
+        }
+    }
+    
+    @SuppressWarnings("deprecation")
+    protected CatalogItem<?, ?> addCatalogItem(String type, String ...libraries) {
+        CatalogEntityItemDto c1 = newCatalogItem(type, libraries);
+        mgmt.getCatalog().addItem(c1);
+        CatalogItem<?, ?> c2 = mgmt.getCatalog().getCatalogItem(type);
+        return c2;
+    }
+
+    static CatalogEntityItemDto newCatalogItem(String type, String ...libraries) {
+        CatalogEntityItemDto c1 = CatalogItems.newEntityFromJava(type, type);
+        c1.setCatalogItemId(type);
+        for (String library: libraries)
+            c1.getLibrariesDto().addBundle(library);
+        return c1;
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    protected Entity addItemFromCatalog(CatalogItem<?, ?> c2) {
+        BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, c2);
+        EntitySpec spec = EntitySpec.create( (Class)loader.loadClass(c2.getJavaType()) );
+        // not a great test as we set the ID here; but:
+        // YAML test will do better;
+        // and we can check that downstream items are loaded correctly
+        spec.catalogItemId(c2.getRegisteredTypeName());
+        Entity me = app.createAndManageChild(spec);
+        return me;
+    }
+
+    public static void assertV1MethodCall(Entity me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+        Assert.assertEquals(doMethodCallBrooklyn(me), "Hi BROOKLYN");
+    }
+    public static void assertV2MethodCall(Entity me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+        Assert.assertEquals(doMethodCallBrooklyn(me), "HI BROOKLYN");
+    }
+
+    public static Object doMethodCallBrooklyn(Entity me) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+        return me.getClass().getMethod("sayHI", String.class).invoke(me, "Brooklyn");
+    }
+
+    public static void assertV1EffectorCall(Entity me) {
+        Assert.assertEquals(doEffectorCallBrooklyn(me), "Hi BROOKLYN");
+    }
+    public static void assertV2EffectorCall(Entity me) {
+        Assert.assertEquals(doEffectorCallBrooklyn(me), "HI BROOKLYN");
+    }
+
+    public static String doEffectorCallBrooklyn(Entity me) {
+        return me.invoke(Effectors.effector(String.class, "sayHI").buildAbstract(), ImmutableMap.of("name", "brooklyn")).getUnchecked();
+    }
+
+    @Test
+    public void testMoreEntitiesV1() throws Exception {
+        CatalogItem<?, ?> c2 = addCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+        
+        // test load and instantiate
+        Entity me = addItemFromCatalog(c2);
+        Assert.assertEquals(me.getCatalogItemId(), OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
+        
+        assertV1MethodCall(me);
+        assertV1EffectorCall(me);
+        
+        // test adding a child gets the right type; this time by entity parent hierarchy
+        BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, c2);
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        Entity me2 = me.addChild(EntitySpec.create( (Class)loader.loadClass(c2.getJavaType()) ));
+        Assert.assertEquals(me2.getCatalogItemId(), OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    protected PolicySpec<?> getPolicySpec(CatalogItem<?, ?> cp) {
+        BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, cp);
+        PolicySpec spec = PolicySpec.create( (Class)loader.loadClass(cp.getJavaType()) );
+        spec.catalogItemId(cp.getRegisteredTypeName());
+        return spec;
+    }
+
+    @Test
+    public void testMoreEntitiesV1Policy() throws Exception {
+        CatalogItem<?, ?> c2 = addCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+        
+        // test load and instantiate
+        Entity me = addItemFromCatalog(c2);
+
+        CatalogItem<?, ?> cp = addCatalogItem(OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_POLICY, 
+            BROOKLYN_TEST_OSGI_ENTITIES_URL);
+        me.addPolicy(getPolicySpec(cp));
+        
+        Assert.assertEquals(me.getPolicies().size(), 1, "Wrong number of policies: "+me.getPolicies());
+        
+        String catalogItemId = Iterables.getOnlyElement( me.getPolicies() ).getCatalogItemId();
+        Assert.assertNotNull(catalogItemId);
+        // must be the actual source bundle
+        Assert.assertFalse(catalogItemId.equals(me.getCatalogItemId()));
+        Assert.assertTrue(catalogItemId.startsWith("brooklyn-test-osgi-entities"));
+    }
+
+    @Test
+    public void testMoreEntitiesV2FailsWithoutBasicTestOsgiEntitiesBundle() throws Exception {
+        CatalogItem<?, ?> c2 = addCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, 
+            BROOKLYN_TEST_MORE_ENTITIES_V2_URL);
+        
+        // test load and instantiate
+        try {
+            Entity me = addItemFromCatalog(c2);
+            Assert.fail("Should have failed, with unresolved dependency; instead got "+me);
+        } catch (Exception e) {
+            Assert.assertTrue(e.toString().toLowerCase().contains("unresolved constraint"), "Missing expected text in error: "+e);
+            Assert.assertTrue(e.toString().toLowerCase().contains("wiring.package"), "Missing expected text in error: "+e);
+            Assert.assertTrue(e.toString().toLowerCase().contains("brooklyn.osgi.tests"), "Missing expected text in error: "+e);
+        }
+    }
+    
+    // V2 works with dependency declared, and can load
+    // and has policy, with policy item catalog ID is reasonable
+    @Test
+    public void testMoreEntitiesV2() throws Exception {
+        CatalogItem<?, ?> c2 = addCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, 
+            BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
+        
+        // test load and instantiate
+        Entity me = addItemFromCatalog(c2);
+        Assert.assertEquals(me.getCatalogItemId(), OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY);
+        
+        assertV2MethodCall(me);
+        assertV2EffectorCall(me);
+        Assert.assertEquals(me.getPolicies().size(), 1, "Wrong number of policies: "+me.getPolicies());
+        
+        String catalogItemId = Iterables.getOnlyElement( me.getPolicies() ).getCatalogItemId();
+        Assert.assertNotNull(catalogItemId);
+        // allow either me's bundle (more) or the actual source bundle
+        Assert.assertTrue(catalogItemId.equals(me.getCatalogItemId()) || catalogItemId.startsWith("brooklyn-test-osgi-entities"));
+    }
+
+    @Test
+    public void testMoreEntitiesV1ThenV2GivesV2() throws Exception {
+        addCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, 
+            BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+        addCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, 
+            BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
+        
+        // test load and instantiate
+        Entity me = addItemFromCatalog( mgmt.getCatalog().getCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY) );
+        
+        assertV2MethodCall(me);
+        assertV2EffectorCall(me);
+        Assert.assertEquals(me.getPolicies().size(), 1, "Wrong number of policies: "+me.getPolicies());
+    }
+
+    @Test
+    public void testMoreEntitiesV2ThenV1GivesV1() throws Exception {
+        addCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, 
+            BROOKLYN_TEST_MORE_ENTITIES_V2_URL, BROOKLYN_TEST_OSGI_ENTITIES_URL);
+        addCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY, 
+            BROOKLYN_TEST_MORE_ENTITIES_V1_URL);
+        
+        // test load and instantiate
+        Entity me = addItemFromCatalog( mgmt.getCatalog().getCatalogItem(OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY) );
+        /*
+         * WARNING - Weird maven-bundle-plugin and OSGi behaviour.  Some caveats:
+         * <p>
+         * (1) When "import-package" declares a version, that is the *minimum* version;
+         *     it may be that semantic versioning is applied, so 1.3.1 = [1.3.1,4.0.0);
+         *     or it may be just a minimum 1.3.1 = [1.3.1,) ... i can't find good docs
+         *     [but see http://www.christianposta.com/blog/?p=241]
+         * <p>
+         * (2) Different versions of maven-bundle-plugin do wildly different things.
+         *     * v1.4.0 attaches the version to import-package (so you get the minimum
+         *       which can cause this test to fail);
+         *     * v2.x does not seem to declare the exported package at all in import-package
+         *       (violating the so-called best practice, see
+         *       http://blog.osgi.org/2007/04/importance-of-exporting-nd-importing.html )
+         *     * v2.4.0 gives a huge list in import/export package, with semver ranges;
+         *       but the other versions seem not to list much and they do NOT have versions
+         * <p>
+         * The tests are all working with 2.5.3 but if version dependencies become any
+         * more intertwined maven-bundle-plugin will almost certainly NOT do the wrong
+         * thing because packages do not have versions. (Ironically, 1.4.0 seems the
+         * best behaved, but for the minimum/semver package version behaviour, and
+         * even that wouldn't be so bad if you're doing semver, or if you figure out
+         * how to override with a _versionpolicy tag!)
+         */
+        assertV1MethodCall(me);
+        assertV1EffectorCall(me);
+        Assert.assertEquals(me.getPolicies().size(), 0, "Wrong number of policies: "+me.getPolicies());
+    }
+
+    // TODO test YAML for many of the above (in the camp project CAMP, using other code below)
+    
+    // TODO versioning (WIP until #92), install both V1 and V2 with version number, and test that both work
+    
+    // TODO other code which might be useful - but requires CAMP:
+//        mgmt.getCatalog().addItem(Strings.lines(
+//            "brooklyn.catalog:",
+//            "  id: my-entity",
+//            "brooklyn.library:",
+//            "- url: "+BROOKLYN_TEST_MORE_ENTITIES_V1_URL,
+//            "services:",
+//            "- type: "+OsgiTestResources.BROOKLYN_TEST_MORE_ENTITIES_MORE_ENTITY
+//        ));
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/resources/brooklyn/osgi/README.md
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/README.md b/core/src/test/resources/brooklyn/osgi/README.md
index 4109080..1d78ddb 100644
--- a/core/src/test/resources/brooklyn/osgi/README.md
+++ b/core/src/test/resources/brooklyn/osgi/README.md
@@ -3,6 +3,8 @@ This directory contains OSGi bundle files used for testing.
 Source code including pom.xml is contained in the bundles,
 or in /src/dependencies, or both.
 
+See OsgiTestResources.java for information on the bundles.
+
 ----
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar
index 494de30..5dad391 100644
Binary files a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar and b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-entities.jar differ

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar
new file mode 100644
index 0000000..a71f428
Binary files /dev/null and b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.1.0.jar differ

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
----------------------------------------------------------------------
diff --git a/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar
new file mode 100644
index 0000000..c75c092
Binary files /dev/null and b/core/src/test/resources/brooklyn/osgi/brooklyn-test-osgi-more-entities_0.2.0.jar differ

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
index 1e4a877..54bd4a6 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
@@ -215,6 +215,8 @@ public class BrooklynEntityMatcher implements PdpMatcher {
         if (attrs==null || attrs.isEmpty())
             return null;
         try {
+            // TODO don't use the mgmt loader, but instead use something like catalog.createSpec
+            // currently we get warnings and are unable to retrieve flags for items which come from catalog 
             Class<? extends Entity> type = BrooklynComponentTemplateResolver.Factory.newInstance(JavaBrooklynClassLoadingContext.newDefault(mgmt), typeName).loadEntityClass();
             ConfigBag bag = ConfigBag.newInstance(attrs);
             List<FlagConfigKeyAndValueRecord> values = FlagUtils.findAllFlagsAndConfigKeys(null, type, bag);
@@ -231,7 +233,14 @@ public class BrooklynEntityMatcher implements PdpMatcher {
             return values;
         } catch (Exception e) {
             Exceptions.propagateIfFatal(e);
-            log.warn("Ignoring configuration attributes on "+typeName+" due to "+e, e);
+            if (e.toString().contains("Could not find")) {
+                // TODO currently we get this error if a catalog item is passed, giving stack trace is too scary;
+                // when we are doing catalog.createSpec let's remove this block
+                log.warn("Ignoring configuration attributes on "+typeName+", item probably loaded from catalog and flags are not yet supported here");
+                log.debug("Ignoring configuration attributes on "+typeName+", details: "+e);
+            } else {
+                log.warn("Ignoring configuration attributes on "+typeName+" due to "+e, e);
+            }
             return null;
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlEntityTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlEntityTest.java
deleted file mode 100644
index 249e2f5..0000000
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlEntityTest.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package io.brooklyn.camp.brooklyn;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
-
-import java.util.Collection;
-
-import org.testng.annotations.Test;
-
-import brooklyn.catalog.CatalogItem;
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.BasicEntity;
-import brooklyn.management.osgi.OsgiStandaloneTest;
-
-import com.google.common.collect.Iterables;
-
-
-public class CatalogYamlEntityTest extends AbstractYamlTest {
-    private static final String SIMPLE_ENTITY_TYPE = "brooklyn.osgi.tests.SimpleEntity";
-
-    @Test
-    public void testAddCatalogItem() throws Exception {
-        String registeredTypeName = "my.catalog.app.id.load";
-        addCatalogOSGiEntity(registeredTypeName);
-
-        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(registeredTypeName);
-        assertEquals(item.getRegisteredTypeName(), registeredTypeName);
-
-        deleteCatalogEntity(registeredTypeName);
-    }
-
-    @Test
-    public void testLaunchApplicationReferencingCatalog() throws Exception {
-        String registeredTypeName = "my.catalog.app.id.launch";
-        registerAndLaunchAndAssertSimpleEntity(registeredTypeName, SIMPLE_ENTITY_TYPE);
-    }
-
-    @Test
-    public void testLaunchApplicationWithCatalogReferencingOtherCatalog() throws Exception {
-        String referencedRegisteredTypeName = "my.catalog.app.id.referenced";
-        String referrerRegisteredTypeName = "my.catalog.app.id.referring";
-        addCatalogOSGiEntity(referencedRegisteredTypeName, SIMPLE_ENTITY_TYPE);
-        addCatalogOSGiEntity(referrerRegisteredTypeName, referencedRegisteredTypeName);
-
-        String yaml = "name: simple-app-yaml\n" +
-                      "location: localhost\n" +
-                      "services: \n" +
-                      "  - serviceType: "+referrerRegisteredTypeName;
-        Entity app = createAndStartApplication(yaml);
-
-        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
-        assertEquals(simpleEntity.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
-
-        deleteCatalogEntity(referencedRegisteredTypeName);
-        deleteCatalogEntity(referrerRegisteredTypeName);
-    }
-
-    @Test
-    public void testLaunchApplicationChildWithCatalogReferencingOtherCatalog() throws Exception {
-        String referencedRegisteredTypeName = "my.catalog.app.id.child.referenced";
-        String referrerRegisteredTypeName = "my.catalog.app.id.child.referring";
-        addCatalogOSGiEntity(referencedRegisteredTypeName, SIMPLE_ENTITY_TYPE);
-        addCatalogChildOSGiEntity(referrerRegisteredTypeName, referencedRegisteredTypeName);
-
-        Entity app = createAndStartApplication(
-            "name: simple-app-yaml",
-            "location: localhost",
-            "services:",
-            "- serviceType: "+BasicEntity.class.getName(),
-            "  brooklyn.children:",
-            "  - type: " + referrerRegisteredTypeName);
-
-        Collection<Entity> children = app.getChildren();
-        assertEquals(children.size(), 1);
-        Entity child = Iterables.getOnlyElement(children);
-        assertEquals(child.getEntityType().getName(), BasicEntity.class.getName());
-        Collection<Entity> grandChildren = child.getChildren();
-        assertEquals(grandChildren.size(), 1);
-        Entity grandChild = Iterables.getOnlyElement(grandChildren);
-        assertEquals(grandChild.getEntityType().getName(), BasicEntity.class.getName());
-        Collection<Entity> grandGrandChildren = grandChild.getChildren();
-        assertEquals(grandGrandChildren.size(), 1);
-        Entity grandGrandChild = Iterables.getOnlyElement(grandGrandChildren);
-        assertEquals(grandGrandChild.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
-
-        deleteCatalogEntity(referencedRegisteredTypeName);
-        deleteCatalogEntity(referrerRegisteredTypeName);
-    }
-
-    @Test
-    public void testLaunchApplicationWithTypeUsingJavaColonPrefix() throws Exception {
-        String registeredTypeName = SIMPLE_ENTITY_TYPE;
-        String serviceName = "java:"+SIMPLE_ENTITY_TYPE;
-        registerAndLaunchAndAssertSimpleEntity(registeredTypeName, serviceName);
-    }
-
-    @Test
-    public void testLaunchApplicationLoopWithJavaTypeName() throws Exception {
-        String registeredTypeName = SIMPLE_ENTITY_TYPE;
-        String serviceName = SIMPLE_ENTITY_TYPE;
-        registerAndLaunchAndAssertSimpleEntity(registeredTypeName, serviceName);
-    }
-
-    @Test
-    public void testLaunchApplicationChildLoopCatalogIdFails() throws Exception {
-        String referrerRegisteredTypeName = "my.catalog.app.id.child.referring";
-        try {
-            addCatalogChildOSGiEntity(referrerRegisteredTypeName, referrerRegisteredTypeName);
-            fail("Expected to throw IllegalStateException");
-        } catch (IllegalStateException e) {
-            assertTrue(e.getMessage().contains("Could not find "+referrerRegisteredTypeName));
-        }
-    }
-
-    private void registerAndLaunchAndAssertSimpleEntity(String registeredTypeName, String serviceType) throws Exception {
-        addCatalogOSGiEntity(registeredTypeName, serviceType);
-        String yaml = "name: simple-app-yaml\n" +
-                      "location: localhost\n" +
-                      "services: \n" +
-                      "  - serviceType: "+registeredTypeName;
-        Entity app = createAndStartApplication(yaml);
-
-        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
-        assertEquals(simpleEntity.getEntityType().getName(), SIMPLE_ENTITY_TYPE);
-
-        deleteCatalogEntity(registeredTypeName);
-    }
-
-    private void addCatalogOSGiEntity(String registeredTypeName) {
-        addCatalogOSGiEntity(registeredTypeName, SIMPLE_ENTITY_TYPE);
-    }
-
-    private void addCatalogOSGiEntity(String registeredTypeName, String serviceType) {
-        addCatalogItem(
-            "brooklyn.catalog:",
-            "  id: " + registeredTypeName,
-            "  name: My Catalog App",
-            "  description: My description",
-            "  icon_url: classpath://path/to/myicon.jpg",
-            "  version: 0.1.2",
-            "  libraries:",
-            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
-            "",
-            "services:",
-            "- type: " + serviceType);
-    }
-
-    private void addCatalogChildOSGiEntity(String registeredTypeName, String serviceType) {
-        addCatalogItem(
-            "brooklyn.catalog:",
-            "  id: " + registeredTypeName,
-            "  name: My Catalog App",
-            "  description: My description",
-            "  icon_url: classpath://path/to/myicon.jpg",
-            "  version: 0.1.2",
-            "  libraries:",
-            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
-            "",
-            "services:",
-            "- type: " + BasicEntity.class.getName(),
-            "  brooklyn.children:",
-            "  - type: " + serviceType);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlPolicyTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlPolicyTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlPolicyTest.java
deleted file mode 100644
index 88545c8..0000000
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/CatalogYamlPolicyTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package io.brooklyn.camp.brooklyn;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
-import org.testng.annotations.Test;
-
-import brooklyn.catalog.CatalogItem;
-import brooklyn.catalog.CatalogPredicates;
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.BasicEntity;
-import brooklyn.event.basic.BasicConfigKey;
-import brooklyn.management.osgi.OsgiStandaloneTest;
-import brooklyn.policy.Policy;
-
-import com.google.common.collect.Iterables;
-
-public class CatalogYamlPolicyTest extends AbstractYamlTest {
-    private static final String SIMPLE_POLICY_TYPE = "brooklyn.osgi.tests.SimplePolicy";
-    private static final String SIMPLE_ENTITY_TYPE = "brooklyn.osgi.tests.SimpleEntity";
-
-    @Test
-    public void testAddCatalogItem() throws Exception {
-        assertEquals(countCatalogPolicies(), 0);
-
-        String registeredTypeName = "my.catalog.policy.id.load";
-        addCatalogOSGiPolicy(registeredTypeName, SIMPLE_POLICY_TYPE);
-
-        CatalogItem<?, ?> item = mgmt().getCatalog().getCatalogItem(registeredTypeName);
-        assertEquals(item.getRegisteredTypeName(), registeredTypeName);
-        assertEquals(countCatalogPolicies(), 1);
-
-        deleteCatalogEntity(registeredTypeName);
-    }
-
-    @Test
-    public void testLaunchApplicationReferencingPolicy() throws Exception {
-        String registeredTypeName = "my.catalog.policy.id.launch";
-        addCatalogOSGiPolicy(registeredTypeName, SIMPLE_POLICY_TYPE);
-        Entity app = createAndStartApplication(
-            "name: simple-app-yaml",
-            "location: localhost",
-            "services: ",
-            "  - type: brooklyn.entity.basic.BasicEntity\n" +
-            "    brooklyn.policies:\n" +
-            "    - type: " + registeredTypeName,
-            "      brooklyn.config:",
-            "        config2: config2 override",
-            "        config3: config3");
-
-        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
-        Policy policy = Iterables.getOnlyElement(simpleEntity.getPolicies());
-        assertEquals(policy.getPolicyType().getName(), SIMPLE_POLICY_TYPE);
-        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config1")), "config1");
-        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config2")), "config2 override");
-        assertEquals(policy.getConfig(new BasicConfigKey<String>(String.class, "config3")), "config3");
-
-        deleteCatalogEntity(registeredTypeName);
-    }
-
-    @Test
-    public void testLaunchApplicationWithCatalogReferencingOtherCatalog() throws Exception {
-        String referencedRegisteredTypeName = "my.catalog.policy.id.referenced";
-        String referrerRegisteredTypeName = "my.catalog.policy.id.referring";
-        addCatalogOSGiPolicy(referencedRegisteredTypeName, SIMPLE_POLICY_TYPE);
-
-        addCatalogItem(
-            "brooklyn.catalog:",
-            "  id: " + referrerRegisteredTypeName,
-            "  name: My Catalog App",
-            "  description: My description",
-            "  icon_url: classpath://path/to/myicon.jpg",
-            "  version: 0.1.2",
-            "  libraries:",
-            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
-            "",
-            "services:",
-            "- type: " + SIMPLE_ENTITY_TYPE,
-            "  brooklyn.policies:",
-            "  - type: " + referencedRegisteredTypeName);
-
-        String yaml = "name: simple-app-yaml\n" +
-                      "location: localhost\n" +
-                      "services: \n" +
-                      "  - serviceType: "+referrerRegisteredTypeName;
-
-        Entity app = createAndStartApplication(yaml);
-
-        Entity simpleEntity = Iterables.getOnlyElement(app.getChildren());
-        Policy policy = Iterables.getOnlyElement(simpleEntity.getPolicies());
-        assertEquals(policy.getPolicyType().getName(), SIMPLE_POLICY_TYPE);
-
-        deleteCatalogEntity(referencedRegisteredTypeName);
-    }
-
-    private void addCatalogOSGiPolicy(String registeredTypeName, String serviceType) {
-        addCatalogItem(
-            "brooklyn.catalog:",
-            "  id: " + registeredTypeName,
-            "  name: My Catalog Policy",
-            "  description: My description",
-            "  icon_url: classpath://path/to/myicon.jpg",
-            "  version: 0.1.2",
-            "  libraries:",
-            "  - url: " + OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL,
-            "",
-            "brooklyn.policies:",
-            "- type: " + serviceType,
-            "  brooklyn.config:",
-            "    config1: config1",
-            "    config2: config2");
-    }
-
-    private int countCatalogPolicies() {
-        return Iterables.size(mgmt().getCatalog().getCatalogItems(CatalogPredicates.IS_POLICY));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/35fd6341/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
new file mode 100644
index 0000000..9281e61
--- /dev/null
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/catalog/CatalogOsgiVersionMoreEntityTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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 io.brooklyn.camp.brooklyn.catalog;
+
+import io.brooklyn.camp.brooklyn.AbstractYamlTest;
+import io.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityMatcher;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.entity.Entity;
+import brooklyn.management.osgi.OsgiVersionMoreEntityTest;
+import brooklyn.policy.Policy;
+import brooklyn.util.ResourceUtils;
+
+import com.google.common.collect.Iterables;
+
+/** Many of the same tests as per {@link OsgiVersionMoreEntityTest} but using YAML for catalog and entities, so catalog item ID is set automatically */
+public class CatalogOsgiVersionMoreEntityTest extends AbstractYamlTest {
+    
+    private static String getLocalResource(String filename) {
+        return ResourceUtils.create(CatalogOsgiVersionMoreEntityTest.class).getResourceAsString(
+            "classpath:/"+CatalogOsgiVersionMoreEntityTest.class.getPackage().getName().replace('.', '/')+"/"+filename);
+    }
+    
+    @Test
+    public void testMoreEntityV1() throws Exception {
+        addCatalogItem(getLocalResource("more-entity-v1-osgi-catalog.yaml"));
+        Entity app = createAndStartApplication("services: [ { type: more-entity } ]");
+        Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
+        
+        Assert.assertEquals(moreEntity.getCatalogItemId(), "more-entity");
+        OsgiVersionMoreEntityTest.assertV1EffectorCall(moreEntity);
+        OsgiVersionMoreEntityTest.assertV1MethodCall(moreEntity);
+    }
+
+    /** TODO we get warnings from {@link BrooklynEntityMatcher#extractValidConfigFlagsOrKeys};
+     * if we passed the correct loader at that point we could avoid those warnings. */ 
+    @Test
+    public void testMoreEntityV1WithPolicy() throws Exception {
+        addCatalogItem(getLocalResource("simple-policy-osgi-catalog.yaml"));
+        addCatalogItem(getLocalResource("more-entity-v1-with-policy-osgi-catalog.yaml"));
+        Entity app = createAndStartApplication("services: [ { type: more-entity } ]");
+        Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
+        
+        Assert.assertEquals(moreEntity.getCatalogItemId(), "more-entity");
+        
+        Assert.assertEquals(moreEntity.getPolicies().size(), 1, "wrong policies: "+moreEntity.getPolicies());
+        Policy policy = Iterables.getOnlyElement(moreEntity.getPolicies());
+        // it was loaded by yaml w ref to catalog, so should have the simple-policy catalog-id
+        Assert.assertEquals(policy.getCatalogItemId(), "simple-policy");
+    }
+
+    @Test
+    public void testMoreEntityV2() throws Exception {
+        addCatalogItem(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
+        Entity app = createAndStartApplication("services: [ { type: more-entity } ]");
+        Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
+        
+        Assert.assertEquals(moreEntity.getCatalogItemId(), "more-entity");
+        OsgiVersionMoreEntityTest.assertV2EffectorCall(moreEntity);
+        OsgiVersionMoreEntityTest.assertV2MethodCall(moreEntity);
+        
+        Assert.assertEquals(moreEntity.getPolicies().size(), 1, "wrong policies: "+moreEntity.getPolicies());
+        Policy policy = Iterables.getOnlyElement(moreEntity.getPolicies());
+        // it was loaded from the java so should have the base more-entity catalog id
+        Assert.assertEquals(policy.getCatalogItemId(), "more-entity");
+    }
+
+    @Test
+    /** TODO this test works if we assume most recent version wins, but semantics TBC */
+    public void testMoreEntityV2ThenV1GivesV1() throws Exception {
+        addCatalogItem(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
+        addCatalogItem(getLocalResource("more-entity-v1-osgi-catalog.yaml"));
+        Entity app = createAndStartApplication("services: [ { type: more-entity } ]");
+        Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
+        
+        OsgiVersionMoreEntityTest.assertV1EffectorCall(moreEntity);
+        OsgiVersionMoreEntityTest.assertV1MethodCall(moreEntity);
+    }
+
+    /** unlike {@link #testMoreEntityV2ThenV1GivesV1()} this test should always work,
+     * because default should probably be either most-recent version or highest version,
+     * in either case this works */
+    @Test
+    public void testMoreEntityV1ThenV2GivesV2() throws Exception {
+        addCatalogItem(getLocalResource("more-entity-v1-osgi-catalog.yaml"));
+        addCatalogItem(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
+        Entity app = createAndStartApplication("services: [ { type: more-entity } ]");
+        Entity moreEntity = Iterables.getOnlyElement(app.getChildren());
+        
+        OsgiVersionMoreEntityTest.assertV2EffectorCall(moreEntity);
+        OsgiVersionMoreEntityTest.assertV2MethodCall(moreEntity);
+    }
+
+    @Test
+    public void testMoreEntityBothV1AndV2() throws Exception {
+        addCatalogItem(getLocalResource("more-entity-v1-called-v1-osgi-catalog.yaml"));
+        addCatalogItem(getLocalResource("more-entity-v2-osgi-catalog.yaml"));
+        Entity v1 = createAndStartApplication("services: [ { type: more-entity-v1 } ]");
+        Entity v2 = createAndStartApplication("services: [ { type: more-entity } ]");
+        
+        Entity moreEntityV1 = Iterables.getOnlyElement(v1.getChildren());
+        Entity moreEntityV2 = Iterables.getOnlyElement(v2.getChildren());
+        
+        OsgiVersionMoreEntityTest.assertV1EffectorCall(moreEntityV1);
+        OsgiVersionMoreEntityTest.assertV1MethodCall(moreEntityV1);
+        
+        OsgiVersionMoreEntityTest.assertV2EffectorCall(moreEntityV2);
+        OsgiVersionMoreEntityTest.assertV2MethodCall(moreEntityV2);
+    }
+
+
+}


[03/18] git commit: Use explicit property for context catalog id bookkeeping

Posted by he...@apache.org.
Use explicit property for context catalog id bookkeeping

Move from using tags to set the context catalog id to explicit properties.


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

Branch: refs/heads/master
Commit: d716e2fa37ffd4444b304ffcacdcf87be29666a2
Parents: 405842d
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Wed Oct 29 18:27:17 2014 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Wed Oct 29 18:56:21 2014 +0200

----------------------------------------------------------------------
 .../basic/AbstractBrooklynObjectSpec.java       | 10 ++++++++
 .../java/brooklyn/basic/BrooklynObject.java     |  5 ++++
 .../main/java/brooklyn/mementos/Memento.java    |  2 ++
 .../brooklyn/basic/AbstractBrooklynObject.java  | 11 +++++++++
 .../catalog/internal/BasicBrooklynCatalog.java  |  2 +-
 .../catalog/internal/CatalogItemDo.java         |  5 ++++
 .../brooklyn/entity/basic/BrooklynTags.java     |  2 --
 .../entity/proxying/InternalEntityFactory.java  |  4 +++
 .../AbstractBrooklynObjectRebindSupport.java    |  1 +
 .../entity/rebind/RebindManagerImpl.java        | 26 ++++----------------
 .../entity/rebind/dto/AbstractMemento.java      | 13 ++++++++++
 .../entity/rebind/dto/MementosGenerators.java   |  1 +
 .../AbstractBrooklynMementoPersister.java       | 19 +-------------
 .../BrooklynMementoPersisterToMultiFile.java    |  4 +--
 .../BrooklynMementoPersisterToObjectStore.java  |  4 +--
 .../BrooklynAssemblyTemplateInstantiator.java   |  2 +-
 16 files changed, 62 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java b/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
index 0efb0a6..2ef4d67 100644
--- a/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
+++ b/api/src/main/java/brooklyn/basic/AbstractBrooklynObjectSpec.java
@@ -35,6 +35,7 @@ public abstract class AbstractBrooklynObjectSpec<T,K extends AbstractBrooklynObj
     
     private final Class<? extends T> type;
     private String displayName;
+    private String contextCatalogItemId;
     private Set<Object> tags = MutableSet.of();
 
     protected AbstractBrooklynObjectSpec(Class<? extends T> type) {
@@ -59,6 +60,11 @@ public abstract class AbstractBrooklynObjectSpec<T,K extends AbstractBrooklynObj
         return self();
     }
     
+    public K contextCatalogItemId(String val) {
+        contextCatalogItemId = val;
+        return self();
+    }
+    
     public K tag(Object tag) {
         tags.add(tag);
         return self();
@@ -83,6 +89,10 @@ public abstract class AbstractBrooklynObjectSpec<T,K extends AbstractBrooklynObj
     public final String getDisplayName() {
         return displayName;
     }
+    
+    public final String getContextCatalogItemId() {
+        return contextCatalogItemId;
+    }
 
     public final Set<Object> getTags() {
         return ImmutableSet.copyOf(tags);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/api/src/main/java/brooklyn/basic/BrooklynObject.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/basic/BrooklynObject.java b/api/src/main/java/brooklyn/basic/BrooklynObject.java
index 600bcad..a31fbf8 100644
--- a/api/src/main/java/brooklyn/basic/BrooklynObject.java
+++ b/api/src/main/java/brooklyn/basic/BrooklynObject.java
@@ -35,6 +35,11 @@ public interface BrooklynObject extends Identifiable {
      * A display name; recommended to be a concise single-line description.
      */
     String getDisplayName();
+
+    /**
+     * The catalog item ID this object was loaded from.
+     */
+    String getContextCatalogItemId();
     
     /** 
      * Tags are arbitrary objects which can be attached to an entity for subsequent reference.

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/api/src/main/java/brooklyn/mementos/Memento.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/mementos/Memento.java b/api/src/main/java/brooklyn/mementos/Memento.java
index be8b629..6ab36b0 100644
--- a/api/src/main/java/brooklyn/mementos/Memento.java
+++ b/api/src/main/java/brooklyn/mementos/Memento.java
@@ -42,6 +42,8 @@ public interface Memento extends Serializable {
     
     public String getType();
     
+    public String getContextCatalogItemId();
+    
     public String getDisplayName();
     
     /**

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java b/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
index a32afaf..8c2608d 100644
--- a/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
+++ b/core/src/main/java/brooklyn/basic/AbstractBrooklynObject.java
@@ -48,6 +48,8 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
     @SetFromFlag(value = "id")
     private String id = Identifiers.makeRandomId(8);
 
+    private String contextCatalogItemId;
+
     /** subclasses should synchronize on this for all access */
     @SetFromFlag(value = "tags")
     private final Set<Object> tags = Sets.newLinkedHashSet();
@@ -167,6 +169,15 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal {
         return id;
     }
 
+    public void setContextCatalogItemId(String id) {
+        this.contextCatalogItemId = id;
+    }
+
+    @Override
+    public String getContextCatalogItemId() {
+        return contextCatalogItemId;
+    }
+
     protected void onTagsChanged() {
         requestPersist();
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
index 18a77f7..a0a8375 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -257,7 +257,7 @@ public class BasicBrooklynCatalog implements BrooklynCatalog {
                     break;
                 default: throw new RuntimeException("Only entity & policy catalog items are supported. Unsupported catalog item type " + item.getCatalogItemType());
             }
-            ((AbstractBrooklynObjectSpec<?, ?>)spec).tag(BrooklynTags.newContextCatalogItemIdTag(item.getId()));
+            ((AbstractBrooklynObjectSpec<?, ?>)spec).contextCatalogItemId(item.getId());
             return spec;
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index 136a466..178ef90 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -59,6 +59,11 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
     }
 
     @Override
+    public String getContextCatalogItemId() {
+        return null;
+    }
+
+    @Override
     public String getRegisteredTypeName() {
         return itemDto.getRegisteredTypeName();
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/core/src/main/java/brooklyn/entity/basic/BrooklynTags.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/basic/BrooklynTags.java b/core/src/main/java/brooklyn/entity/basic/BrooklynTags.java
index 67b4b42..01ac52e 100644
--- a/core/src/main/java/brooklyn/entity/basic/BrooklynTags.java
+++ b/core/src/main/java/brooklyn/entity/basic/BrooklynTags.java
@@ -29,7 +29,6 @@ import com.google.common.annotations.Beta;
 public class BrooklynTags {
 
     public static final String YAML_SPEC_KIND = "yaml_spec";
-    public static final String CONTEXT_CATALOG_ITEM_ID_KIND = "context_catalog_item_id";
     public static final String NOTES_KIND = "notes";
     
     public static class NamedStringTag implements Serializable {
@@ -54,7 +53,6 @@ public class BrooklynTags {
     }
     
     public static NamedStringTag newYamlSpecTag(String contents) { return new NamedStringTag(YAML_SPEC_KIND, contents); }
-    public static NamedStringTag newContextCatalogItemIdTag(String contents) { return new NamedStringTag(CONTEXT_CATALOG_ITEM_ID_KIND, contents); }
     public static NamedStringTag newNotesTag(String contents) { return new NamedStringTag(NOTES_KIND, contents); }
     
     public static NamedStringTag findFirst(String kind, Iterable<Object> tags) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
index b292827..f4e18cf 100644
--- a/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
+++ b/core/src/main/java/brooklyn/entity/proxying/InternalEntityFactory.java
@@ -241,6 +241,10 @@ public class InternalEntityFactory extends InternalFactory {
             if (spec.getDisplayName()!=null)
                 ((AbstractEntity)entity).setDisplayName(spec.getDisplayName());
             
+            if (spec.getContextCatalogItemId()!=null) {
+                ((AbstractEntity)entity).setContextCatalogItemId(spec.getContextCatalogItemId());
+            }
+            
             entity.tags().addTags(spec.getTags());
             ((AbstractEntity)entity).configure(MutableMap.copyOf(spec.getFlags()));
             

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java b/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java
index 9dc9645..3eb6c96 100644
--- a/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java
+++ b/core/src/main/java/brooklyn/entity/rebind/AbstractBrooklynObjectRebindSupport.java
@@ -48,6 +48,7 @@ public abstract class AbstractBrooklynObjectRebindSupport<T extends Memento> imp
         if (LOG.isTraceEnabled()) LOG.trace("Reconstructing: {}", memento.toVerboseString());
 
         instance.setDisplayName(memento.getDisplayName());
+        instance.setContextCatalogItemId(memento.getContextCatalogItemId());
         addConfig(rebindContext, memento);
         addTags(rebindContext, memento);
         addCustoms(rebindContext, memento);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index 2691a5b..9f620d6 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -47,8 +47,6 @@ import brooklyn.entity.Entity;
 import brooklyn.entity.Feed;
 import brooklyn.entity.basic.AbstractApplication;
 import brooklyn.entity.basic.AbstractEntity;
-import brooklyn.entity.basic.BrooklynTags;
-import brooklyn.entity.basic.BrooklynTags.NamedStringTag;
 import brooklyn.entity.basic.ConfigKeys;
 import brooklyn.entity.basic.EntityInternal;
 import brooklyn.entity.proxying.InternalEntityFactory;
@@ -656,7 +654,7 @@ public class RebindManagerImpl implements RebindManager {
                     if (LOG.isDebugEnabled()) LOG.debug("RebindManager instantiating policy {}", policyMemento);
                     
                     try {
-                        Policy policy = newPolicy(policyMemento, getPolicyLoadingContext(policyMemento.getId(), memento, classLoader, rebindContext));
+                        Policy policy = newPolicy(policyMemento, getLoadingContextFromCatalogItemId(policyMemento.getContextCatalogItemId(), classLoader, rebindContext));
                         rebindContext.registerPolicy(policyMemento.getId(), policy);
                     } catch (Exception e) {
                         exceptionHandler.onCreateFailed(BrooklynObjectType.POLICY, policyMemento.getId(), policyMemento.getType(), e);
@@ -924,24 +922,10 @@ public class RebindManagerImpl implements RebindManager {
             if (ptr.getContextCatalogItemId() != null) {
                 return ptr.getContextCatalogItemId();
             }
-            ptr = entityIdToManifest.get(ptr.getParent());
-        }
-        return null;
-    }
-
-    private BrooklynClassLoadingContext getPolicyLoadingContext(String policyId, BrooklynMemento memento, ClassLoader classLoader, RebindContextImpl rebindContext) {
-        PolicyMemento policyMemento = memento.getPolicyMemento(policyId);
-        String contextCatalogItemId = getContextCatalogItemIdFromTags(policyMemento.getTags());
-        return getLoadingContextFromCatalogItemId(contextCatalogItemId, classLoader, rebindContext);
-    }
-
-    private String getContextCatalogItemIdFromTags(Collection<Object> tags) {
-        for (Object obj : tags) {
-            if (obj instanceof NamedStringTag) {
-                NamedStringTag tag = (NamedStringTag) obj;
-                if (BrooklynTags.CONTEXT_CATALOG_ITEM_ID_KIND.equals(tag.getKind())) {
-                    return tag.getContents();
-                }
+            if (ptr.getParent() != null) {
+                ptr = entityIdToManifest.get(ptr.getParent());
+            } else {
+                ptr = null;
             }
         }
         return null;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java b/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java
index 67e35da..c07b991 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/AbstractMemento.java
@@ -43,6 +43,7 @@ public abstract class AbstractMemento implements Memento, Serializable {
         protected String type;
         protected Class<?> typeClass;
         protected String displayName;
+        protected String contextCatalogItemId;
         protected Map<String, Object> fields = Maps.newLinkedHashMap();
         protected List<Object> tags = Lists.newArrayList();
 
@@ -56,6 +57,7 @@ public abstract class AbstractMemento implements Memento, Serializable {
             type = other.getType();
             typeClass = other.getTypeClass();
             displayName = other.getDisplayName();
+            contextCatalogItemId = other.getContextCatalogItemId();
             fields.putAll(other.getCustomFields());
             tags.addAll(other.getTags());
             return self();
@@ -75,6 +77,9 @@ public abstract class AbstractMemento implements Memento, Serializable {
         public B displayName(String val) {
             displayName = val; return self();
         }
+        public B contextCatalogItemId(String val) {
+            contextCatalogItemId = val; return self();
+        }
         /**
          * @deprecated since 0.7.0; use config/attributes so generic persistence will work, rather than requiring "custom fields"
          */
@@ -88,6 +93,7 @@ public abstract class AbstractMemento implements Memento, Serializable {
     private String type;
     private String id;
     private String displayName;
+    private String contextCatalogItemId;
     private List<Object> tags;
 
     private transient Class<?> typeClass;
@@ -103,6 +109,7 @@ public abstract class AbstractMemento implements Memento, Serializable {
         type = builder.type;
         typeClass = builder.typeClass;
         displayName = builder.displayName;
+        contextCatalogItemId = builder.contextCatalogItemId;
         setCustomFields(builder.fields);
         tags = toPersistedList(builder.tags);
     }
@@ -141,6 +148,12 @@ public abstract class AbstractMemento implements Memento, Serializable {
         return displayName;
     }
 
+    @Override
+    public String getContextCatalogItemId() {
+        return contextCatalogItemId;
+    }
+
+    @Override
     public List<Object> getTags() {
         return fromPersistedList(tags);
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java b/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
index d5e6724..8888f5c 100644
--- a/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
+++ b/core/src/main/java/brooklyn/entity/rebind/dto/MementosGenerators.java
@@ -378,6 +378,7 @@ public class MementosGenerators {
     private static void populateBrooklynObjectMementoBuilder(BrooklynObject instance, AbstractMemento.Builder<?> builder) {
         builder.id = instance.getId();
         builder.displayName = instance.getDisplayName();
+        builder.contextCatalogItemId = instance.getContextCatalogItemId();
         builder.type = instance.getClass().getName();
         builder.typeClass = instance.getClass();
         

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java b/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
index 9758213..d185ab5 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/AbstractBrooklynMementoPersister.java
@@ -19,11 +19,6 @@
 package brooklyn.entity.rebind.persister;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Collection;
-
-import brooklyn.entity.basic.BrooklynTags;
-import brooklyn.entity.basic.BrooklynTags.NamedStringTag;
 import brooklyn.entity.rebind.PersistenceExceptionHandler;
 import brooklyn.entity.rebind.RebindExceptionHandler;
 import brooklyn.entity.rebind.dto.BrooklynMementoManifestImpl;
@@ -56,7 +51,7 @@ public abstract class AbstractBrooklynMementoPersister implements BrooklynMement
     public BrooklynMementoManifest loadMementoManifest(RebindExceptionHandler exceptionHandler) {
         BrooklynMementoManifestImpl.Builder builder = BrooklynMementoManifestImpl.builder();
         for (EntityMemento entity : memento.getEntityMementos().values()) {
-            builder.entity(entity.getId(), entity.getType(), entity.getParent(), getContextCatalogItemId(entity.getTags()));
+            builder.entity(entity.getId(), entity.getType(), entity.getParent(), entity.getContextCatalogItemId());
         }
         for (LocationMemento entity : memento.getLocationMementos().values()) {
             builder.location(entity.getId(), entity.getType());
@@ -73,18 +68,6 @@ public abstract class AbstractBrooklynMementoPersister implements BrooklynMement
         return builder.build();
     }
 
-    private String getContextCatalogItemId(Collection<Object> tags) {
-        for (Object obj : tags) {
-            if (obj instanceof NamedStringTag) {
-                NamedStringTag tag = (NamedStringTag) obj;
-                if (BrooklynTags.CONTEXT_CATALOG_ITEM_ID_KIND.equals(tag.getKind())) {
-                    return tag.getContents();
-                }
-            }
-        }
-        return null;
-    }
-
     @Override public void enableWriteAccess() {}
     @Override public void disableWriteAccess(boolean graceful) {}
     @Override public void stop(boolean graceful) {}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
index cdd87b8..7e13d62 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToMultiFile.java
@@ -32,8 +32,6 @@ import java.util.concurrent.TimeoutException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import brooklyn.entity.basic.BrooklynTags;
-import brooklyn.entity.basic.BrooklynTags.NamedStringTag;
 import brooklyn.entity.rebind.BrooklynObjectType;
 import brooklyn.entity.rebind.PersistenceExceptionHandler;
 import brooklyn.entity.rebind.RebindExceptionHandler;
@@ -196,7 +194,7 @@ public class BrooklynMementoPersisterToMultiFile implements BrooklynMementoPersi
                     String id = (String) XmlUtil.xpath(contents, "/entity/id");
                     String type = (String) XmlUtil.xpath(contents, "/entity/type");
                     String parentId = (String) XmlUtil.xpath(contents, "/entity/parent");
-                    String contextCatalogItemId = (String) XmlUtil.xpath(contents, "/entity/tags/" + NamedStringTag.class.getName().replace("$", "_-") + "[kind='" + BrooklynTags.CONTEXT_CATALOG_ITEM_ID_KIND + "']/contents");
+                    String contextCatalogItemId = (String) XmlUtil.xpath(contents, "/entity/contextCatalogItemId");
                     builder.entity(id, type, Strings.emptyToNull(parentId), Strings.emptyToNull(contextCatalogItemId));
                 } catch (Exception e) {
                     exceptionHandler.onLoadMementoFailed(BrooklynObjectType.ENTITY, "File "+file, e);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
index 09f58b7..cf03958 100644
--- a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
+++ b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynMementoPersisterToObjectStore.java
@@ -37,9 +37,7 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.config.BrooklynProperties;
 import brooklyn.config.ConfigKey;
-import brooklyn.entity.basic.BrooklynTags;
 import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.BrooklynTags.NamedStringTag;
 import brooklyn.entity.rebind.BrooklynObjectType;
 import brooklyn.entity.rebind.PeriodicDeltaChangeListener;
 import brooklyn.entity.rebind.PersistenceExceptionHandler;
@@ -255,7 +253,7 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer
                         String id = (String) XmlUtil.xpath(contents, "/entity/id");
                         String objType = (String) XmlUtil.xpath(contents, "/entity/type");
                         String parentId = (String) XmlUtil.xpath(contents, "/entity/parent");
-                        String contextCatalogItemId = (String) XmlUtil.xpath(contents, "/entity/tags/" + NamedStringTag.class.getName().replace("$", "_-") + "[kind='" + BrooklynTags.CONTEXT_CATALOG_ITEM_ID_KIND + "']/contents");
+                        String contextCatalogItemId = (String) XmlUtil.xpath(contents, "/entity/contextCatalogItemId");
                         builder.entity(id, objType, Strings.emptyToNull(parentId), Strings.emptyToNull(contextCatalogItemId));
                         break;
                     case LOCATION:

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d716e2fa/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index 1d05811..346b19c 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -203,7 +203,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
             } else {
                 //TODO migrate to catalog.createSpec
                 spec = resolveCatalogYamlReferenceSpec(mgmt, item, encounteredCatalogTypes);
-                spec.tag(BrooklynTags.newContextCatalogItemIdTag(item.getId()));
+                spec.contextCatalogItemId(item.getId());
                 entityResolver.populateSpec(spec);
             }
         }