Changes to move to catalogItemId + search path. Restore catalogItemId; change getCatalogItemIdHierarchy to getCatalogItemIdSearchPath. Update "stackCatalogItemId" to work with catalogItemId + search path. Use catalogItemIdAndSearchPath when merging wrapper parent to child. Rebind changes for catalogItemId + search path. Update AbstractBrooklynObject[Spec] for catalogItemId + searchPath Do catalogItemIdAndSearchPath only if non-null Update "catalogItemIdHierarchy" -> "searchPath" in persistence
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/81815f94 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/81815f94 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/81815f94 Branch: refs/heads/master Commit: 81815f9424ba1987dbba5c3ee206deec4400babf Parents: b61f972 Author: Geoff Macartney <[email protected]> Authored: Fri Mar 10 17:10:33 2017 +0000 Committer: Geoff Macartney <[email protected]> Committed: Thu Apr 20 11:20:36 2017 +0100 ---------------------------------------------------------------------- .../internal/AbstractBrooklynObjectSpec.java | 90 ++++---- .../mementos/BrooklynMementoManifest.java | 10 +- .../api/mgmt/rebind/mementos/Memento.java | 6 +- .../brooklyn/api/objs/BrooklynObject.java | 9 +- .../catalog/CatalogOsgiYamlEntityTest.java | 8 +- .../catalog/CatalogOsgiYamlTemplateTest.java | 2 +- .../brooklyn/catalog/CatalogYamlEntityTest.java | 6 +- .../catalog/CatalogYamlLocationTest.java | 4 +- .../brooklyn/catalog/CatalogYamlRebindTest.java | 6 +- .../catalog/CatalogYamlTemplateTest.java | 4 +- .../core/catalog/internal/CatalogItemDo.java | 12 +- .../internal/CatalogItemDtoAbstract.java | 5 - .../core/catalog/internal/CatalogUtils.java | 14 +- .../internal/JavaCatalogToSpecTransformer.java | 4 +- .../access/PortForwardManagerClient.java | 4 +- .../core/mgmt/EntityManagementUtils.java | 6 +- .../internal/AbstractManagementContext.java | 30 ++- .../BrooklynMementoPersisterToObjectStore.java | 24 +- .../core/mgmt/persist/XmlMementoSerializer.java | 2 +- .../core/mgmt/rebind/RebindIteration.java | 227 ++++++++++++------- .../core/mgmt/rebind/dto/AbstractMemento.java | 48 +--- .../rebind/dto/BrooklynMementoManifestImpl.java | 4 +- .../rebind/dto/EntityMementoManifestImpl.java | 20 +- .../mgmt/rebind/dto/MementosGenerators.java | 3 +- .../rebind/transformer/CompoundTransformer.java | 23 +- .../core/objs/AbstractBrooklynObject.java | 38 ++-- .../core/objs/AbstractEntityAdjunct.java | 3 +- .../core/objs/BrooklynObjectInternal.java | 8 +- .../core/objs/proxy/InternalEntityFactory.java | 14 +- .../objs/proxy/InternalLocationFactory.java | 16 +- .../core/objs/proxy/InternalPolicyFactory.java | 30 +-- .../brooklyn/util/core/ClassLoaderUtils.java | 4 +- .../rebind/RebindConfigInheritanceTest.java | 3 +- .../util/core/ClassLoaderUtilsTest.java | 4 +- .../rest/transform/LocationTransformer.java | 4 +- 35 files changed, 374 insertions(+), 321 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java b/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java index 16b4175..10acfe4 100644 --- a/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java +++ b/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java @@ -68,7 +68,9 @@ public abstract class AbstractBrooklynObjectSpec<T, SpecT extends AbstractBrookl private final Class<? extends T> type; private String displayName; - private Deque<String> catalogItemIdStack; + private String catalogItemId; + private Deque<String> catalogItemIdSearchPath = new ArrayDeque<>(); + private Set<Object> tags = MutableSet.of(); private List<SpecParameter<?>> parameters = ImmutableList.of(); @@ -108,13 +110,16 @@ public abstract class AbstractBrooklynObjectSpec<T, SpecT extends AbstractBrookl * (or TODO we add a separate field to record other catalog item IDs that could be applied for searching, see below) */ public SpecT catalogItemId(String val) { - getCatalogItemIdStack().clear(); - return stackCatalogItemId(val); + catalogItemId = val; + return self(); } - protected SpecT catalogItemIdStack(Collection<String> catalogItemIdStack) { - this.catalogItemIdStack = null; - getCatalogItemIdStack().addAll(catalogItemIdStack); + public synchronized SpecT catalogItemIdAndSearchPath(String catalogItemId, Collection<String> searchPath) { + if (catalogItemId != null) { + catalogItemId(catalogItemId); + catalogItemIdSearchPath.clear(); + catalogItemIdSearchPath.addAll(searchPath); + } return self(); } @@ -125,30 +130,37 @@ public abstract class AbstractBrooklynObjectSpec<T, SpecT extends AbstractBrookl @Beta public SpecT catalogItemIdIfNotNull(String val) { if (val!=null) { - stackCatalogItemId(val); + catalogItemId(val); } return self(); } - private Deque<String> getCatalogItemIdStack() { - if (catalogItemIdStack == null) { - catalogItemIdStack = new ArrayDeque<>(); + protected Object readResolve() { + if (catalogItemIdSearchPath == null) { + catalogItemIdSearchPath = new ArrayDeque<>(); } - return catalogItemIdStack; + return this; } /** * Adds (stacks) the catalog item id of a wrapping specification. * Does nothing if the value is null. + * If the value is not null, and is not the same as the current + * catalogItemId, then the *current* catalogItemId will + * be moved to the start of the search path, and the value supplied + * as the parameter here will be set as the new catalogItemId. * <p> - * Used when we want to collect nested item ID's so that *all* can be searched. + * Used when we want to collect IDs of items that extend other items, so that *all* can be searched. * e.g. if R3 extends R2 which extends R1 any one of these might supply config keys * referencing resources or types in their local bundles. */ @Beta public SpecT stackCatalogItemId(String val) { - if (null != val && (getCatalogItemIdStack().isEmpty() || !getCatalogItemIdStack().element().equals(val))) { - getCatalogItemIdStack().addFirst(val); + if (null != val) { + if (null != catalogItemId && !catalogItemId.equals(val)) { + catalogItemIdSearchPath.addFirst(catalogItemId); + } + catalogItemId(val); } return self(); } @@ -239,35 +251,26 @@ public abstract class AbstractBrooklynObjectSpec<T, SpecT extends AbstractBrookl return displayName; } - /** - * @deprecated since 0.11.0, use getOuterCatalogItemId or getInnerCatalogItemIds as appropriate - */ - @Deprecated public final String getCatalogItemId() { - return getOuterCatalogItemId(); + return catalogItemId; } - public final String getOuterCatalogItemId() { - if (getCatalogItemIdStack().size() != 0) { - return getCatalogItemIdStack().getFirst(); - } - return null; - } - - - /** - * An immutable list of ids of this object's catalog item and its defining catalog items. - * Wrapping items are first in the list (i.e. wrapping items precede wrapped items), - * for example, if the catalog item is defined as - * <pre> - * items: - * - id: X - * item: Y - * </pre> - * then the list will contain X, Y. - */ - public final List<String> getCatalogItemIdHierarchy() { - return ImmutableList.copyOf(catalogItemIdStack); + /** + * An immutable list of ids of catalog items that define this item. + * Wrapping items are first in the list (i.e. wrapping items precede wrapped items), + * for example, for a spec of an item of type Z, where the catalog is: + * <pre> + * items: + * - id: X + * - id: Y + * item: X + * - id: Z + * item: Y + * </pre> + * then the spec will have getCatalogId() of Z and getCatalogItemIdSearchPath() of Y, X. + */ + public final List<String> getCatalogItemIdSearchPath() { + return ImmutableList.copyOf(catalogItemIdSearchPath); } public final Set<Object> getTags() { @@ -317,7 +320,7 @@ public abstract class AbstractBrooklynObjectSpec<T, SpecT extends AbstractBrookl .configure(otherSpec.getConfig()) .configure(otherSpec.getFlags()) .tags(otherSpec.getTags()) - .catalogItemIdStack(otherSpec.getCatalogItemIdHierarchy()) + .catalogItemIdAndSearchPath(otherSpec.getCatalogItemId(), otherSpec.getCatalogItemIdSearchPath()) .parameters(otherSpec.getParameters()); } @@ -327,7 +330,8 @@ public abstract class AbstractBrooklynObjectSpec<T, SpecT extends AbstractBrookl if (!obj.getClass().equals(getClass())) return false; AbstractBrooklynObjectSpec<?, ?> other = (AbstractBrooklynObjectSpec<?, ?>) obj; if (!Objects.equal(getDisplayName(), other.getDisplayName())) return false; - if (!Objects.equal(getCatalogItemIdHierarchy(), other.getCatalogItemIdHierarchy())) return false; + if (!Objects.equal(getCatalogItemId(), other.getCatalogItemId())) return false; + if (!Objects.equal(getCatalogItemIdSearchPath(), other.getCatalogItemIdSearchPath())) return false; if (!Objects.equal(getType(), other.getType())) return false; if (!Objects.equal(getTags(), other.getTags())) return false; if (!Objects.equal(getConfig(), other.getConfig())) return false; @@ -338,7 +342,7 @@ public abstract class AbstractBrooklynObjectSpec<T, SpecT extends AbstractBrookl @Override public int hashCode() { - return Objects.hashCode(getCatalogItemIdHierarchy(), getDisplayName(), getType(), getTags()); + return Objects.hashCode(getCatalogItemIdSearchPath(), getDisplayName(), getType(), getTags()); } /** http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoManifest.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoManifest.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoManifest.java index bcf246e..fa56d1d 100644 --- a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoManifest.java +++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/BrooklynMementoManifest.java @@ -36,14 +36,8 @@ public interface BrooklynMementoManifest extends Serializable { String getId(); String getType(); String getParent(); - - /** - * deprecated since 0.11.0, use {@link #getCatalogItemHierarchy()} instead - * @return - */ - @Deprecated String getCatalogItemId(); - - List<String> getCatalogItemHierarchy(); + String getCatalogItemId(); + List<String> getCatalogItemIdSearchPath(); } String getPlaneId(); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java index 4ca219d..71fc587 100644 --- a/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java +++ b/api/src/main/java/org/apache/brooklyn/api/mgmt/rebind/mementos/Memento.java @@ -48,15 +48,13 @@ public interface Memento extends Serializable { /** * The principal catalog item id. - * @deprecated since 0.11.0 - use {@link #getCatalogItemHierarchy()} instead */ - @Deprecated String getCatalogItemId(); /** - * Catalog Item Ids of all defining catalog items. + * Item Ids of all catalog items used to define this item. */ - List<String> getCatalogItemHierarchy(); + List<String> getCatalogItemIdSearchPath(); String getDisplayName(); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java index ff49e1b..d72fe6a 100644 --- a/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java +++ b/api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObject.java @@ -60,16 +60,19 @@ public interface BrooklynObject extends Identifiable, Configurable { String getCatalogItemId(); /** - * An immutable list of ids of this object's catalog item and its defining catalog items. - * e.g. if the catalog item is defined as + * An immutable list of ids of catalog items that define this item. + * e.g. if the catalog item is defined as a Z where * <pre> * items: * - id: X + * - id: Y + * item: X + * - id: Z * item: Y * </pre> * then the list will contain X, Y. */ - List<String> getCatalogItemHierarchy(); + List<String> getCatalogItemIdSearchPath(); /** * Tags are arbitrary objects which can be attached to an entity for subsequent reference. http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlEntityTest.java ---------------------------------------------------------------------- diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlEntityTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlEntityTest.java index dbf9445..b0bf747 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlEntityTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlEntityTest.java @@ -708,7 +708,7 @@ public class CatalogOsgiYamlEntityTest extends AbstractYamlTest { BrooklynTypeRegistry registry = mgmt().getTypeRegistry(); RegisteredType item = registry.get(symbolicName, TEST_VERSION); AbstractBrooklynObjectSpec<?, ?> spec = registry.createSpec(item, null, null); - assertEquals(spec.getOuterCatalogItemId(), ver(symbolicName)); + assertEquals(spec.getCatalogItemId(), ver(symbolicName)); deleteCatalogEntity(symbolicName); } @@ -813,9 +813,9 @@ public class CatalogOsgiYamlEntityTest extends AbstractYamlTest { Entity entity = app.getChildren().iterator().next(); assertEquals(entity.getCatalogItemId(), ver(symbolicNameOuter)); - assertEquals(entity.getCatalogItemHierarchy().size(), 2); - assertEquals(entity.getCatalogItemHierarchy().get(0), ver(symbolicNameOuter)); - assertEquals(entity.getCatalogItemHierarchy().get(1), ver(symbolicNameInner)); + assertEquals(entity.getCatalogItemIdSearchPath().size(), 1, "should have exactly one item in search path"); + assertEquals(entity.getCatalogItemIdSearchPath().get(0), ver(symbolicNameInner), + "should have " + symbolicNameInner + " in search path"); deleteCatalogEntity(symbolicNameInner); deleteCatalogEntity(symbolicNameOuter); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlTemplateTest.java ---------------------------------------------------------------------- diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlTemplateTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlTemplateTest.java index 4ecfcf2..8b2a561 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlTemplateTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogOsgiYamlTemplateTest.java @@ -87,7 +87,7 @@ public class CatalogOsgiYamlTemplateTest extends AbstractYamlTest { EntitySpec<?> child = Iterables.getOnlyElement( spec.getChildren() ); Assert.assertEquals(child.getType().getName(), SIMPLE_ENTITY_TYPE); - Assert.assertEquals(child.getOuterCatalogItemId(), "t1:"+TEST_VERSION); + Assert.assertEquals(child.getCatalogItemId(), "t1:"+TEST_VERSION); } private RegisteredType makeItem(String symbolicName, String templateType) { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java ---------------------------------------------------------------------- diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java index c40f7f8..b3264f7 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlEntityTest.java @@ -643,9 +643,9 @@ public class CatalogYamlEntityTest extends AbstractYamlTest { Entity entity = app.getChildren().iterator().next(); assertEquals(entity.getCatalogItemId(), ver(symbolicNameOuter)); - assertEquals(entity.getCatalogItemHierarchy().size(), 2); - assertEquals(entity.getCatalogItemHierarchy().get(0), ver(symbolicNameOuter)); - assertEquals(entity.getCatalogItemHierarchy().get(1), ver(symbolicNameInner)); + assertEquals(entity.getCatalogItemIdSearchPath().size(), 1, "should have exactly one item in search path"); + assertEquals(entity.getCatalogItemIdSearchPath().get(0), ver(symbolicNameInner), + "should have " + symbolicNameInner + " in search path"); deleteCatalogEntity(symbolicNameInner); deleteCatalogEntity(symbolicNameOuter); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java ---------------------------------------------------------------------- diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java index dc017d3..01fb484 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlLocationTest.java @@ -176,10 +176,10 @@ public class CatalogYamlLocationTest extends AbstractYamlTest { LocationSpec<? extends Location> spec1 = mgmt().getLocationRegistry().getLocationSpec(def1).get(); LocationSpec<? extends Location> spec2 = mgmt().getLocationRegistry().getLocationSpec(def2).get(); - assertEquals(spec1.getOuterCatalogItemId(), "loc1:0.1.2"); + assertEquals(spec1.getCatalogItemId(), "loc1:0.1.2"); assertEquals(spec1.getDisplayName(), "My Loc 1"); assertContainsAll(spec1.getFlags(), ImmutableMap.of("mykey1", "myval1", "mykey1b", "myval1b")); - assertEquals(spec2.getOuterCatalogItemId(), "loc2:0.1.2"); + assertEquals(spec2.getCatalogItemId(), "loc2:0.1.2"); assertEquals(spec2.getDisplayName(), "My Loc 2"); assertContainsAll(spec2.getFlags(), ImmutableMap.of("mykey1", "myvalOverridden", "mykey1b", "myval1b", "mykey2", "myval2")); } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java ---------------------------------------------------------------------- diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java index 08616fc..874e301 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlRebindTest.java @@ -170,13 +170,13 @@ public class CatalogYamlRebindTest extends AbstractYamlRebindTest { testRebindWithCatalogAndAppUsingOptions(mode, osgiMode, RebindOptions.create()); } - // Re-run the same tests as testRebindWithCatalogAndApp but with the XML updated to mimic state - // persisted before <catalogItemId> was replaced with <catalogItemHierarchy>. + // Re-run all the same tests as testRebindWithCatalogAndApp, but with the XML updated to mimic state + // persisted before <catalogItemIdSearchPath> was introduced. @Test(dataProvider = "dataProvider") public void testRebindWithCatalogAndAppRebindCatalogItemIds(RebindWithCatalogTestMode mode, OsgiMode osgiMode) throws Exception { final RebindOptions rebindOptions = RebindOptions.create(); applyCompoundStateTransformer(rebindOptions, CompoundTransformer.builder() - .xmlReplaceItem("//catalogItemHierarchy", "<catalogItemId><xsl:value-of select=\"string\"/></catalogItemId>") + .xmlDeleteItem("//catalogItemIdSearchPath") .build()); testRebindWithCatalogAndAppUsingOptions(mode, osgiMode, rebindOptions); } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java ---------------------------------------------------------------------- diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java index f128abc..cb585e0 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlTemplateTest.java @@ -208,7 +208,7 @@ public class CatalogYamlTemplateTest extends AbstractYamlTest { EntitySpec<?> child = Iterables.getOnlyElement( spec.getChildren() ); Assert.assertEquals(child.getType().getName(), TestEntity.class.getName()); - Assert.assertEquals(child.getOuterCatalogItemId(), "t1:"+TEST_VERSION); + Assert.assertEquals(child.getCatalogItemId(), "t1:"+TEST_VERSION); } @Test @@ -247,7 +247,7 @@ public class CatalogYamlTemplateTest extends AbstractYamlTest { Assert.assertEquals(spec.getChildren().size(), 0); Assert.assertEquals(spec.getType(), BasicApplication.class); Assert.assertEquals(ConfigBag.newInstance(spec.getConfig()).getStringKey("foo"), "boo"); - Assert.assertEquals(spec.getOuterCatalogItemId(), "app1r:1"); + Assert.assertEquals(spec.getCatalogItemId(), "app1r:1"); } private RegisteredType addCatalogItem(String symbolicName, String templateType) { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java index 42cdb42..36e1192 100644 --- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java +++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDo.java @@ -132,18 +132,18 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT>, BrooklynObj } @Override - public void setCatalogItemIdHierarchy(List<String> ids) { - itemDto.setCatalogItemIdHierarchy(ids); + public void setCatalogItemIdSearchPath(List<String> ids) { + itemDto.setCatalogItemIdSearchPath(ids); } @Override - public List<String> getCatalogItemHierarchy() { - return itemDto.getCatalogItemHierarchy(); + public List<String> getCatalogItemIdSearchPath() { + return itemDto.getCatalogItemIdSearchPath(); } @Override - public void nestCatalogItemId(String id) { - itemDto.nestCatalogItemId(id); + public void stackCatalogItemId(String id) { + itemDto.stackCatalogItemId(id); } @Override http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java index 539b8b1..0bae32d 100644 --- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java +++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogItemDtoAbstract.java @@ -104,11 +104,6 @@ public abstract class CatalogItemDtoAbstract<T, SpecT> extends AbstractBrooklynO } @Override - public List<String> getCatalogItemHierarchy() { - return ImmutableList.of(getCatalogItemId()); - } - - @Override public String getJavaType() { if (javaType != null) return javaType; return type; http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java index 4bb11fd..2f85db9 100644 --- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java +++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java @@ -142,12 +142,12 @@ public class CatalogUtils { } public static BrooklynClassLoadingContext newClassLoadingContextForCatalogItems( - ManagementContext managementContext, List<String> catalogItemIds) { + ManagementContext managementContext, String catalogItemId, List<String> searchPath) { - BrooklynClassLoadingContextSequential seqLoader = - new BrooklynClassLoadingContextSequential(managementContext); - for (String catalogItemId : catalogItemIds) { - addCatalogItemContext(managementContext, seqLoader, catalogItemId); + BrooklynClassLoadingContextSequential seqLoader = new BrooklynClassLoadingContextSequential(managementContext); + addCatalogItemContext(managementContext, seqLoader, catalogItemId); + for (String searchId : searchPath) { + addCatalogItemContext(managementContext, seqLoader, searchId); } return seqLoader; } @@ -195,7 +195,9 @@ public class CatalogUtils { if (log.isDebugEnabled()) BrooklynLogging.log(log, BrooklynLogging.levelDebugOrTraceIfReadOnly(entity), "Catalog item addition: "+entity+" from "+entity.getCatalogItemId()+" applying its catalog item ID to "+itemBeingAdded); - ((BrooklynObjectInternal)itemBeingAdded).setCatalogItemIdHierarchy(entity.getCatalogItemHierarchy()); + final BrooklynObjectInternal addInternal = (BrooklynObjectInternal) itemBeingAdded; + addInternal.setCatalogItemId(entity.getCatalogItemId()); + addInternal.setCatalogItemIdSearchPath(entity.getCatalogItemIdSearchPath()); } else { if (!itemBeingAdded.getCatalogItemId().equals(entity.getCatalogItemId())) { // not a problem, but something to watch out for http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/catalog/internal/JavaCatalogToSpecTransformer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/JavaCatalogToSpecTransformer.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/JavaCatalogToSpecTransformer.java index bf698e8..f9c4131 100644 --- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/JavaCatalogToSpecTransformer.java +++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/JavaCatalogToSpecTransformer.java @@ -26,7 +26,6 @@ import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.entity.EntitySpec; import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec; import org.apache.brooklyn.api.mgmt.ManagementContext; -import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; import org.apache.brooklyn.api.policy.Policy; import org.apache.brooklyn.api.policy.PolicySpec; import org.apache.brooklyn.api.typereg.RegisteredType; @@ -84,7 +83,8 @@ public class JavaCatalogToSpecTransformer implements PlanToSpecTransformer { // but it doesn't hurt (and if we re-instate a class+bundle approach for RegisteredType // we will want to do this) final BrooklynClassLoadingContextSequential ctx = new BrooklynClassLoadingContextSequential(mgmt); - ctx.add(CatalogUtils.newClassLoadingContextForCatalogItems(mgmt, item.getCatalogItemHierarchy())); + ctx.add(CatalogUtils.newClassLoadingContextForCatalogItems(mgmt, item.getCatalogItemId(), + item.getCatalogItemIdSearchPath())); type = ctx.loadClass(javaType); } catch (Exception e) { Exceptions.propagateIfFatal(e); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/location/access/PortForwardManagerClient.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/location/access/PortForwardManagerClient.java b/core/src/main/java/org/apache/brooklyn/core/location/access/PortForwardManagerClient.java index d5781cd..92091fc 100644 --- a/core/src/main/java/org/apache/brooklyn/core/location/access/PortForwardManagerClient.java +++ b/core/src/main/java/org/apache/brooklyn/core/location/access/PortForwardManagerClient.java @@ -388,8 +388,8 @@ public class PortForwardManagerClient implements PortForwardManager { } @Override - public List<String> getCatalogItemHierarchy() { - return getDelegate().getCatalogItemHierarchy(); + public List<String> getCatalogItemIdSearchPath() { + return getDelegate().getCatalogItemIdSearchPath(); } @Override http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java index d222151..8fb6345 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java @@ -259,12 +259,14 @@ public class EntityManagementUtils { wrappedChild.parametersAdd(wrapperParent.getParameters()); } - wrappedChild.stackCatalogItemId(wrapperParent.getOuterCatalogItemId()); + wrappedChild.catalogItemIdAndSearchPath(wrapperParent.getCatalogItemId(), wrapperParent.getCatalogItemIdSearchPath()); // NB: this clobber's child config wherever they conflict; might prefer to deeply merge maps etc // (or maybe even prevent the merge in these cases; // not sure there is a compelling reason to have config on a pure-wrapper parent) - Map<ConfigKey<?>, Object> configWithoutWrapperMarker = Maps.filterKeys(wrapperParent.getConfig(), Predicates.not(Predicates.<ConfigKey<?>>equalTo(EntityManagementUtils.WRAPPER_APP_MARKER))); + Map<ConfigKey<?>, Object> configWithoutWrapperMarker = + Maps.filterKeys(wrapperParent.getConfig(), + Predicates.not(Predicates.<ConfigKey<?>>equalTo(EntityManagementUtils.WRAPPER_APP_MARKER))); wrappedChild.configure(configWithoutWrapperMarker); wrappedChild.configure(wrapperParent.getFlags()); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java index 16bb3de..6d81626 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java @@ -51,6 +51,7 @@ import org.apache.brooklyn.api.mgmt.ha.HighAvailabilityManager; import org.apache.brooklyn.api.mgmt.rebind.RebindManager; import org.apache.brooklyn.api.objs.BrooklynObject; import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry; +import org.apache.brooklyn.api.typereg.RegisteredType; import org.apache.brooklyn.config.StringConfigMap; import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog; import org.apache.brooklyn.core.catalog.internal.CatalogInitialization; @@ -130,16 +131,25 @@ public abstract class AbstractManagementContext implements ManagementContextInte public BrooklynClassLoadingContext apply(@Nullable Object input) { if (input instanceof EntityInternal) { EntityInternal internal = (EntityInternal)input; - final List<String> catalogItemHierarchy = internal.getCatalogItemHierarchy(); - if (catalogItemHierarchy.size() > 0) { - final ManagementContext managementContext = internal.getManagementContext(); - BrooklynClassLoadingContextSequential seqLoader = - new BrooklynClassLoadingContextSequential(managementContext); - seqLoader.add(newClassLoadingContextForCatalogItems(managementContext, catalogItemHierarchy)); - JavaBrooklynClassLoadingContext entityLoader = - JavaBrooklynClassLoadingContext.create(input.getClass().getClassLoader()); - seqLoader.add(entityLoader); - return seqLoader; + String inputCatalogItemId = internal.getCatalogItemId(); + if(inputCatalogItemId != null) { + RegisteredType item = internal.getManagementContext().getTypeRegistry().get(internal.getCatalogItemId()); + + if (item != null) { + final List<String> searchPath = internal.getCatalogItemIdSearchPath(); + final ManagementContext managementContext = internal.getManagementContext(); + BrooklynClassLoadingContextSequential seqLoader = + new BrooklynClassLoadingContextSequential(managementContext); + seqLoader.add(newClassLoadingContextForCatalogItems(managementContext, inputCatalogItemId, searchPath)); + JavaBrooklynClassLoadingContext entityLoader = + JavaBrooklynClassLoadingContext.create(input.getClass().getClassLoader()); + seqLoader.add(entityLoader); + return seqLoader; + } else { + log.error("Can't find catalog item " + internal.getCatalogItemId() + + " used for instantiating entity " + internal + + ". Falling back to application classpath."); + } } return apply(internal.getManagementSupport()); } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java index a716151..5aace6d 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/BrooklynMementoPersisterToObjectStore.java @@ -37,8 +37,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.annotation.Nullable; import javax.xml.xpath.XPathConstants; -import com.google.common.collect.ImmutableList; - import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.api.mgmt.rebind.PersistenceExceptionHandler; import org.apache.brooklyn.api.mgmt.rebind.RebindExceptionHandler; @@ -195,8 +193,8 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer return null; } else { final BrooklynClassLoadingContextSequential ctx = new BrooklynClassLoadingContextSequential(managementContext); - ctx.add( - CatalogUtils.newClassLoadingContextForCatalogItems(managementContext, item.getCatalogItemHierarchy())); + ctx.add(CatalogUtils.newClassLoadingContextForCatalogItems(managementContext, + item.getCatalogItemId(), item.getCatalogItemIdSearchPath())); return ClassLoaderFromBrooklynClassLoadingContext.of(ctx); } } @@ -360,20 +358,6 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer } } - // We must be able to cope with XML serialized with either a single "catalogItemId" - // or a list "catalogItemHierarchy" of catalog item ids. Only one should be encountered - // but in any case prefer the list of ids. - private ImmutableList<String> getCatalogItemIds(XPathHelper x) { - final MutableList<String> list = MutableList.of(); - final List<String> catalogItemHierarchy = x.getStringList("catalogItemHierarchy"); - final String catalogItemId = Strings.emptyToNull(x.get("catalogItemId")); - if (!catalogItemHierarchy.isEmpty()) { - list.addAll(catalogItemHierarchy); - } else if (catalogItemId != null) { - list.add(catalogItemId); - } - return ImmutableList.copyOf(list); - } @Override public BrooklynMementoManifest loadMementoManifest(BrooklynMementoRawData mementoData, @@ -391,7 +375,9 @@ public class BrooklynMementoPersisterToObjectStore implements BrooklynMementoPer XPathHelper x = new XPathHelper(contents, "/"+type.toCamelCase()+"/"); switch (type) { case ENTITY: - builder.entity(x.get("id"), x.get("type"), Strings.emptyToNull(x.get("parent")), getCatalogItemIds(x)); + builder.entity(x.get("id"), x.get("type"), Strings.emptyToNull(x.get("parent")), + Strings.emptyToNull(x.get("catalogItemId")), + x.getStringList("searchPath")); break; case LOCATION: case POLICY: http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java index 12b2c3a..16beb4e 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/persist/XmlMementoSerializer.java @@ -455,7 +455,7 @@ public class XmlMementoSerializer<T> extends XmlSerializer<T> implements Memento public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { if (source == null) return; AbstractBrooklynObjectSpec<?, ?> spec = (AbstractBrooklynObjectSpec<?, ?>) source; - String catalogItemId = spec.getOuterCatalogItemId(); + String catalogItemId = spec.getCatalogItemId(); if (Strings.isNonBlank(catalogItemId)) { // write this field first, so we can peek at it when we read writer.startNode("catalogItemId"); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java index 80c5eb2..a12bd7e 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java @@ -19,6 +19,8 @@ package org.apache.brooklyn.core.mgmt.rebind; import static com.google.common.base.Preconditions.checkNotNull; +import static org.apache.brooklyn.core.BrooklynFeatureEnablement.FEATURE_AUTO_FIX_CATALOG_REF_ON_REBIND; +import static org.apache.brooklyn.core.BrooklynFeatureEnablement.FEATURE_BACKWARDS_COMPATIBILITY_INFER_CATALOG_ITEM_ON_REBIND; import static org.apache.brooklyn.core.catalog.internal.CatalogUtils.newClassLoadingContextForCatalogItems; import java.io.IOException; @@ -32,7 +34,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; + import org.apache.brooklyn.api.catalog.BrooklynCatalog; import org.apache.brooklyn.api.catalog.CatalogItem; import org.apache.brooklyn.api.entity.Application; @@ -771,7 +773,7 @@ public abstract class RebindIteration { if (!isEmpty) { BrooklynLogging.log(LOG, shouldLogRebinding() ? LoggingLevel.INFO : LoggingLevel.DEBUG, "Rebind complete " + "("+mode+(readOnlyRebindCount.get()>=0 ? ", iteration "+readOnlyRebindCount : "")+")" + - " in {}: {} app{}, {} entit{}, {} location{}, {} polic{}, {} enricher{}, {} feed{}, {} catalog item{}", new Object[]{ + " in {}: {} app{}, {} entit{}, {} location{}, {} polic{}, {} enricher{}, {} feed{}, {} catalog item{}", Time.makeTimeStringRounded(timer), applications.size(), Strings.s(applications), rebindContext.getEntities().size(), Strings.ies(rebindContext.getEntities()), rebindContext.getLocations().size(), Strings.s(rebindContext.getLocations()), @@ -779,7 +781,7 @@ public abstract class RebindIteration { rebindContext.getEnrichers().size(), Strings.s(rebindContext.getEnrichers()), rebindContext.getFeeds().size(), Strings.s(rebindContext.getFeeds()), rebindContext.getCatalogItems().size(), Strings.s(rebindContext.getCatalogItems()) - }); + ); } // Return the top-level applications @@ -797,30 +799,51 @@ public abstract class RebindIteration { rebindMetrics.noteError(messages); } } - - protected List<String> findCatalogItemIds(ClassLoader cl, Map<String, EntityMementoManifest> entityIdToManifest, EntityMementoManifest entityManifest) { - if (!entityManifest.getCatalogItemHierarchy().isEmpty()) { - return entityManifest.getCatalogItemHierarchy(); + + protected class CatalogItemIdAndSearchPath { + private String catalogItemId; + private List<String> searchPath; + + public CatalogItemIdAndSearchPath(String catalogItemId, List<String> searchPath) { + this.catalogItemId = catalogItemId; + this.searchPath = searchPath; + } + public String getCatalogItemId() { return catalogItemId; } + public List<String> getSearchPath() { return searchPath; } + } + + protected CatalogItemIdAndSearchPath findCatalogItemIds(ClassLoader cl, Map<String, + EntityMementoManifest> entityIdToManifest, EntityMementoManifest entityManifest) { + + if (entityManifest.getCatalogItemId() != null) { + return new CatalogItemIdAndSearchPath(entityManifest.getCatalogItemId(), + entityManifest.getCatalogItemIdSearchPath()); } - if (BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_BACKWARDS_COMPATIBILITY_INFER_CATALOG_ITEM_ON_REBIND)) { + if (BrooklynFeatureEnablement.isEnabled(FEATURE_BACKWARDS_COMPATIBILITY_INFER_CATALOG_ITEM_ON_REBIND)) { + String typeId = null; + List<String> searchPath = MutableList.of(); //First check if any of the parent entities has a catalogItemId set. EntityMementoManifest ptr = entityManifest; while (ptr != null) { - if (ptr.getCatalogItemHierarchy() != null) { - List<String> ids = MutableList.of(); - for (String id : ptr.getCatalogItemHierarchy()) { - RegisteredType type = managementContext.getTypeRegistry().get(id); + final String pId = ptr.getCatalogItemId(); + if (pId != null) { + RegisteredType type = managementContext.getTypeRegistry().get(pId); + if (type != null) { + typeId = type.getId(); + } + for (String id : ptr.getCatalogItemIdSearchPath()) { + type = managementContext.getTypeRegistry().get(id); if (type != null) { - ids.add(type.getId()); + searchPath.add(type.getId()); } else { - //Couldn't find a catalog item with this id, but return it anyway and + //Couldn't find a catalog item with this id, but add it anyway and //let the caller deal with the error. //TODO under what circumstances is this permitted? - ids.add(id); + searchPath.add(id); } } - return ids; + return new CatalogItemIdAndSearchPath(typeId, searchPath); } if (ptr.getParent() != null) { ptr = entityIdToManifest.get(ptr.getParent()); @@ -839,7 +862,7 @@ public abstract class RebindIteration { RegisteredType t = types.get(ptr.getType(), BrooklynCatalog.DEFAULT_VERSION); if (t != null) { LOG.debug("Inferred catalog item ID "+t.getId()+" for "+entityManifest+" from ancestor "+ptr); - return ImmutableList.of(t.getId()); + return new CatalogItemIdAndSearchPath(t.getId(), ImmutableList.<String>of()); } if (ptr.getParent() != null) { ptr = entityIdToManifest.get(ptr.getParent()); @@ -851,7 +874,7 @@ public abstract class RebindIteration { //As a last resort go through all catalog items trying to load the type and use the first that succeeds. //But first check if can be loaded from the default classpath if (JavaBrooklynClassLoadingContext.create(managementContext).tryLoadClass(entityManifest.getType()).isPresent()) { - return ImmutableList.of(); + return new CatalogItemIdAndSearchPath(null, ImmutableList.<String>of()); } // TODO get to the point when we can deprecate this behaviour!: @@ -859,21 +882,24 @@ public abstract class RebindIteration { BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(managementContext, item); boolean canLoadClass = loader.tryLoadClass(entityManifest.getType()).isPresent(); if (canLoadClass) { - LOG.warn("Missing catalog item for "+entityManifest.getId()+" ("+entityManifest.getType()+"), inferring as "+item.getId()+" because that is able to load the item"); - return ImmutableList.of(item.getId()); + LOG.warn("Missing catalog item for " + entityManifest.getId() + " (" + entityManifest.getType() + + "), inferring as " + item.getId() + " because that is able to load the item"); + return new CatalogItemIdAndSearchPath(item.getId(), ImmutableList.<String>of()); } } } - return ImmutableList.of(); + return new CatalogItemIdAndSearchPath(null, ImmutableList.<String>of()); } protected static class LoadedClass<T extends BrooklynObject> { protected final Class<? extends T> clazz; - protected final List<String> catalogItemIds; - - protected LoadedClass(Class<? extends T> clazz, List<String> catalogItemIds) { + protected final String catalogItemId; + protected final List<String> searchPath; + + protected LoadedClass(Class<? extends T> clazz, String catalogItemId, List<String> searchPath) { this.clazz = clazz; - this.catalogItemIds = catalogItemIds; + this.catalogItemId = catalogItemId; + this.searchPath = searchPath; } } @@ -891,10 +917,12 @@ public abstract class RebindIteration { protected Entity newEntity(EntityMementoManifest entityManifest) { String entityId = entityManifest.getId(); - List<String> catalogItemIds = findCatalogItemIds(classLoader, mementoManifest.getEntityIdToManifest(), entityManifest); + CatalogItemIdAndSearchPath idPath = + findCatalogItemIds(classLoader, mementoManifest.getEntityIdToManifest(), entityManifest); String entityType = entityManifest.getType(); - LoadedClass<? extends Entity> loaded = load(Entity.class, entityType, catalogItemIds, entityId); + LoadedClass<? extends Entity> loaded = + load(Entity.class, entityType, idPath.getCatalogItemId(), idPath.getSearchPath(), entityId); Class<? extends Entity> entityClazz = loaded.clazz; Entity entity; @@ -906,7 +934,8 @@ public abstract class RebindIteration { entity = entityFactory.constructEntity(entityClazz, Reflections.getAllInterfaces(entityClazz), entityId); } else { - LOG.warn("Deprecated rebind of entity without no-arg constructor; this may not be supported in future versions: id="+entityId+"; type="+entityType); + LOG.warn("Deprecated rebind of entity without no-arg constructor; " + + "this may not be supported in future versions: id=" + entityId+"; type=" + entityType); // There are several possibilities for the constructor; find one that works. // Prefer passing in the flags because required for Application to set the management context @@ -916,9 +945,11 @@ public abstract class RebindIteration { flags.put("id", entityId); if (AbstractApplication.class.isAssignableFrom(entityClazz)) flags.put("mgmt", managementContext); - // TODO document the multiple sources of flags, and the reason for setting the mgmt context *and* supplying it as the flag + // 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 = invokeConstructor(null, entityClazz, new Object[] {flags}, new Object[] {flags, null}, new Object[] {null}, new Object[0]); + 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 @@ -933,90 +964,110 @@ public abstract class RebindIteration { managementContext.prePreManage(entity); } - setCatalogItemIds(entity, loaded.catalogItemIds); + setCatalogItemIds(entity, loaded.catalogItemId, loaded.searchPath); return entity; } - protected void setCatalogItemIds(BrooklynObject object, List<String> idHierarchy) { - ((BrooklynObjectInternal)object).setCatalogItemIdHierarchy(idHierarchy); + protected void setCatalogItemIds(BrooklynObject object, String catalogItemId, List<String> searchPath) { + final BrooklynObjectInternal internal = (BrooklynObjectInternal) object; + internal.setCatalogItemId(catalogItemId); + internal.setCatalogItemIdSearchPath(searchPath); } protected <T extends BrooklynObject> LoadedClass<? extends T> load(Class<T> bType, Memento memento) { - return load(bType, memento.getType(), memento.getCatalogItemHierarchy(), memento.getId()); + return load(bType, memento.getType(), memento.getCatalogItemId(), memento.getCatalogItemIdSearchPath(), + memento.getId()); } @SuppressWarnings("unchecked") - protected <T extends BrooklynObject> LoadedClass<? extends T> load(Class<T> bType, String jType, List<String> catalogItemIds, String contextSuchAsId) { + protected <T extends BrooklynObject> LoadedClass<? extends T> load(Class<T> bType, String jType, + String catalogItemId, List<String> searchPath, String contextSuchAsId) { checkNotNull(jType, "Type of %s (%s) must not be null", contextSuchAsId, bType.getSimpleName()); - List<String> idsFromReboundCatalog = MutableList.of(); - if (catalogItemIds != null && !catalogItemIds.isEmpty()) { - findCatalogIdsInReboundCatalog(bType, catalogItemIds, contextSuchAsId, idsFromReboundCatalog); - if (idsFromReboundCatalog.size() != catalogItemIds.size()) { - LOG.warn("Unable to load all catalog items "+ Iterables.toString(catalogItemIds) - +" for "+contextSuchAsId + " (" + bType.getSimpleName()+"); attempting load nevertheless"); + List<String> reboundSearchPath = MutableList.of(); + if (searchPath != null && !searchPath.isEmpty()) { + for (String searchItemId : searchPath) { + CatalogItem<?, ?> searchItem = findCatalogItemInReboundCatalog(bType, searchItemId, contextSuchAsId); + if (searchItem != null) { + reboundSearchPath.add(searchItem.getCatalogItemId()); + } else { + LOG.warn("Unable to load catalog item "+ searchItemId + +" for "+contextSuchAsId + " (" + bType.getSimpleName()+"); attempting load nevertheless"); + } } - try { - BrooklynClassLoadingContextSequential loader = new BrooklynClassLoadingContextSequential(managementContext); - loader.add(newClassLoadingContextForCatalogItems(managementContext, idsFromReboundCatalog)); - return new LoadedClass<T>(loader.loadClass(jType, bType), idsFromReboundCatalog); - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - LOG.warn("Unable to load "+jType+" using loader; will try reflections"); + } + + if (catalogItemId != null) { + CatalogItem<?, ?> catalogItem = findCatalogItemInReboundCatalog(bType, catalogItemId, contextSuchAsId); + if (catalogItem != null) { + String transformedCatalogItemId = catalogItem.getCatalogItemId(); + try { + BrooklynClassLoadingContextSequential loader = + new BrooklynClassLoadingContextSequential(managementContext); + loader.add(newClassLoadingContextForCatalogItems(managementContext, transformedCatalogItemId, + reboundSearchPath)); + return new LoadedClass<T>(loader.loadClass(jType, bType), transformedCatalogItemId, reboundSearchPath); + } catch (Exception e) { + Exceptions.propagateIfFatal(e); + LOG.warn("Unable to load "+jType+" using loader; will try reflections"); + } + } else { + LOG.warn("Unable to load catalog item "+catalogItemId+" for " + contextSuchAsId + + " ("+bType.getSimpleName()+"); will try reflection"); } } - + try { - return new LoadedClass<T>((Class<T>)loadClass(jType), catalogItemIds); + return new LoadedClass<T>((Class<T>)loadClass(jType), catalogItemId, reboundSearchPath); } catch (Exception e) { Exceptions.propagateIfFatal(e); LOG.warn("Unable to load "+jType+" using reflections; will try standard context"); } - if (catalogItemIds != null && !catalogItemIds.isEmpty()) { - throw new IllegalStateException("Unable to load catalog items " + Iterables.toString(catalogItemIds) - + " for "+contextSuchAsId+", or load class from classpath"); - } else if (BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_BACKWARDS_COMPATIBILITY_INFER_CATALOG_ITEM_ON_REBIND)) { + if (catalogItemId != null) { + throw new IllegalStateException("Unable to load catalog item " + catalogItemId + " for " + + contextSuchAsId + ", or load class from classpath"); + } else if (BrooklynFeatureEnablement.isEnabled(FEATURE_BACKWARDS_COMPATIBILITY_INFER_CATALOG_ITEM_ON_REBIND)) { //Try loading from whichever catalog bundle succeeds. BrooklynCatalog catalog = managementContext.getCatalog(); for (CatalogItem<?, ?> item : catalog.getCatalogItems()) { BrooklynClassLoadingContext catalogLoader = CatalogUtils.newClassLoadingContext(managementContext, item); Maybe<Class<?>> catalogClass = catalogLoader.tryLoadClass(jType); if (catalogClass.isPresent()) { - return new LoadedClass<T>((Class<? extends T>) catalogClass.get(), catalogItemIds); + return new LoadedClass<T>((Class<? extends T>) catalogClass.get(), catalogItemId, reboundSearchPath); } } - throw new IllegalStateException("No catalogItemId specified for "+contextSuchAsId+" and can't load class (" + jType + ") from either classpath or catalog items"); + throw new IllegalStateException("No catalogItemId specified for " + contextSuchAsId + + " and can't load class (" + jType + ") from either classpath or catalog items"); } else { - throw new IllegalStateException("No catalogItemId specified for "+contextSuchAsId+" and can't load class (" + jType + ") from classpath"); + throw new IllegalStateException("No catalogItemId specified for " + contextSuchAsId + + " and can't load class (" + jType + ") from classpath"); } } - private <T extends BrooklynObject> void findCatalogIdsInReboundCatalog(Class<T> bType, List<String> catalogItemIds, String contextSuchAsId, List<String> idsToUse) { - for (String catalogItemId : catalogItemIds) { - CatalogItem<?, ?> catalogItem = rebindContext.lookup().lookupCatalogItem(catalogItemId); - if (catalogItem == null) { - if (BrooklynFeatureEnablement.isEnabled(BrooklynFeatureEnablement.FEATURE_AUTO_FIX_CATALOG_REF_ON_REBIND)) { - // See https://issues.apache.org/jira/browse/BROOKLYN-149 - // This is a dangling reference to the catalog item (which will have been logged by lookupCatalogItem). - // Try loading as any version. - if (CatalogUtils.looksLikeVersionedId(catalogItemId)) { - String symbolicName = CatalogUtils.getSymbolicNameFromVersionedId(catalogItemId); - catalogItem = rebindContext.lookup().lookupCatalogItem(symbolicName); - - if (catalogItem != null) { - LOG.warn("Unable to load catalog item "+ catalogItemIds +" for "+contextSuchAsId - +" ("+bType.getSimpleName()+"); will auto-upgrade to "+catalogItem.getCatalogItemId()); - idsToUse.add(catalogItem.getCatalogItemId()); - } + private <T extends BrooklynObject> CatalogItem<?, ?> findCatalogItemInReboundCatalog(Class<T> bType, + String catalogItemId, String contextSuchAsId) { + CatalogItem<?, ?> catalogItem = rebindContext.lookup().lookupCatalogItem(catalogItemId); + if (catalogItem == null) { + if (BrooklynFeatureEnablement.isEnabled(FEATURE_AUTO_FIX_CATALOG_REF_ON_REBIND)) { + // See https://issues.apache.org/jira/browse/BROOKLYN-149 + // This is a dangling reference to the catalog item (which will have been logged by lookupCatalogItem). + // Try loading as any version. + if (CatalogUtils.looksLikeVersionedId(catalogItemId)) { + String symbolicName = CatalogUtils.getSymbolicNameFromVersionedId(catalogItemId); + catalogItem = rebindContext.lookup().lookupCatalogItem(symbolicName); + + if (catalogItem != null) { + LOG.warn("Unable to load catalog item " + catalogItemId + " for " + contextSuchAsId + + " (" + bType.getSimpleName() + "); will auto-upgrade to " + + catalogItem.getCatalogItemId() + ":" + catalogItem.getVersion()); } } - } else { - idsToUse.add(catalogItemId); } } + return catalogItem; } protected Class<?> loadClass(String jType) throws ClassNotFoundException { @@ -1056,7 +1107,8 @@ public abstract class RebindIteration { return location; } else { - LOG.warn("Deprecated rebind of location without no-arg constructor; this may not be supported in future versions: id="+locationId+"; type="+locationType); + LOG.warn("Deprecated rebind of location without no-arg constructor; " + + "this may not be supported in future versions: id=" + locationId + "; type="+locationType); // There are several possibilities for the constructor; find one that works. // Prefer passing in the flags because required for Application to set the management context @@ -1073,7 +1125,8 @@ public abstract class RebindIteration { */ protected Policy newPolicy(PolicyMemento memento) { String id = memento.getId(); - LoadedClass<? extends Policy> loaded = load(Policy.class, memento.getType(), memento.getCatalogItemHierarchy(), id); + LoadedClass<? extends Policy> loaded = load(Policy.class, memento.getType(), memento.getCatalogItemId(), + memento.getCatalogItemIdSearchPath(), id); Class<? extends Policy> policyClazz = loaded.clazz; Policy policy; @@ -1084,7 +1137,8 @@ public abstract class RebindIteration { ((AbstractPolicy)policy).setManagementContext(managementContext); } else { - LOG.warn("Deprecated rebind of policy without no-arg constructor; this may not be supported in future versions: id="+id+"; type="+policyClazz); + LOG.warn("Deprecated rebind of policy without no-arg constructor; " + + "this may not be supported in future versions: id=" + id + "; type="+policyClazz); // There are several possibilities for the constructor; find one that works. // Prefer passing in the flags because required for Application to set the management context @@ -1098,7 +1152,7 @@ public abstract class RebindIteration { policy = invokeConstructor(null, policyClazz, new Object[] {flags}); } - setCatalogItemIds(policy, memento.getCatalogItemHierarchy()); + setCatalogItemIds(policy, memento.getCatalogItemId(), memento.getCatalogItemIdSearchPath()); return policy; } @@ -1118,7 +1172,8 @@ public abstract class RebindIteration { ((AbstractEnricher)enricher).setManagementContext(managementContext); } else { - LOG.warn("Deprecated rebind of enricher without no-arg constructor; this may not be supported in future versions: id="+id+"; type="+enricherClazz); + LOG.warn("Deprecated rebind of enricher without no-arg constructor; " + + "this may not be supported in future versions: id=" + id + "; type="+enricherClazz); // There are several possibilities for the constructor; find one that works. // Prefer passing in the flags because required for Application to set the management context @@ -1132,7 +1187,7 @@ public abstract class RebindIteration { enricher = invokeConstructor(reflections, enricherClazz, new Object[] {flags}); } - setCatalogItemIds(enricher, memento.getCatalogItemHierarchy()); + setCatalogItemIds(enricher, memento.getCatalogItemId(), memento.getCatalogItemIdSearchPath()); return enricher; } @@ -1152,10 +1207,11 @@ public abstract class RebindIteration { ((AbstractFeed)feed).setManagementContext(managementContext); } else { - throw new IllegalStateException("rebind of feed without no-arg constructor unsupported: id="+id+"; type="+feedClazz); + throw new IllegalStateException("rebind of feed without no-arg constructor unsupported: id=" + id + + "; type="+feedClazz); } - setCatalogItemIds(feed, memento.getCatalogItemHierarchy()); + setCatalogItemIds(feed, memento.getCatalogItemId(), memento.getCatalogItemIdSearchPath()); return feed; } @@ -1189,7 +1245,8 @@ public abstract class RebindIteration { args.append(Arrays.asList(possibleArgs[i])); } } - throw new IllegalStateException("Cannot instantiate instance of type "+clazz+"; expected constructor signature not found ("+args+")"); + throw new IllegalStateException("Cannot instantiate instance of type " + clazz + + "; expected constructor signature not found ("+args+")"); } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java index 876ab24..6e2a0f2 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/AbstractMemento.java @@ -24,7 +24,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import com.google.common.collect.Iterables; import org.apache.brooklyn.api.mgmt.rebind.mementos.Memento; import org.apache.brooklyn.core.BrooklynVersion; import org.apache.brooklyn.core.config.Sanitizer; @@ -47,9 +46,8 @@ public abstract class AbstractMemento implements Memento, Serializable { protected String type; protected Class<?> typeClass; protected String displayName; - // catalogItemId is retained to support rebind of previously persisted state (prior to catalogItemHierarchy) protected String catalogItemId; - protected List<String> catalogItemHierarchy; + protected List<String> searchPath; protected Map<String, Object> customFields = Maps.newLinkedHashMap(); protected List<Object> tags = Lists.newArrayList(); protected Map<String,Set<String>> relations = Maps.newLinkedHashMap(); @@ -68,7 +66,9 @@ public abstract class AbstractMemento implements Memento, Serializable { type = other.getType(); typeClass = other.getTypeClass(); displayName = other.getDisplayName(); - setCatalogItemIdHierarchy(other.getCatalogItemHierarchy(), other.getCatalogItemId()); + catalogItemId = other.getCatalogItemId(); + searchPath = isEmpty(other.getCatalogItemIdSearchPath()) ? + MutableList.<String>of() : MutableList.copyOf(other.getCatalogItemIdSearchPath()); customFields.putAll(other.getCustomFields()); tags.addAll(other.getTags()); relations.putAll(other.getRelations()); @@ -76,16 +76,6 @@ public abstract class AbstractMemento implements Memento, Serializable { return self(); } - private void setCatalogItemIdHierarchy(List<String> otherItemIdHierarchy, String otherItemId) { - if (isEmpty(otherItemIdHierarchy) && otherItemId == null) { - catalogItemHierarchy = MutableList.of(); - } else if (isEmpty(otherItemIdHierarchy) && otherItemId != null) { - catalogItemHierarchy = MutableList.of(otherItemId); - } else { - catalogItemHierarchy = MutableList.copyOf(otherItemIdHierarchy); - } - } - private boolean isEmpty(List<String> ids) { return ids == null || ids.isEmpty(); } @@ -103,14 +93,8 @@ public abstract class AbstractMemento implements Memento, Serializable { private String type; private String id; private String displayName; - - @Deprecated - /** - @deprecated since 0.11.0; retained to support rebind of previously persisted state (prior to catalogItemHierarchy) - */ protected String catalogItemId; - - private List<String> catalogItemHierarchy; + private List<String> searchPath; private List<Object> tags; private Map<String,Set<String>> relations; @@ -130,7 +114,8 @@ public abstract class AbstractMemento implements Memento, Serializable { type = builder.type; typeClass = builder.typeClass; displayName = builder.displayName; - catalogItemHierarchy = builder.catalogItemHierarchy; + catalogItemId = builder.catalogItemId; + searchPath = builder.searchPath; setCustomFields(builder.customFields); tags = toPersistedList(builder.tags); relations = toPersistedMap(builder.relations); @@ -141,17 +126,6 @@ public abstract class AbstractMemento implements Memento, Serializable { // but the method declared here simplifies how it is connected in via builder etc protected abstract void setCustomFields(Map<String, Object> fields); - // deals with value created by deserialization of state persisted with <catalogItemId> - private void normalizeCatalogItemIds() { - if (catalogItemHierarchy == null) { - catalogItemHierarchy = MutableList.of(); - } - if (catalogItemHierarchy.isEmpty() && catalogItemId != null) { - catalogItemHierarchy = MutableList.of(catalogItemId); - catalogItemId = null; - } - } - @Override public void injectTypeClass(Class<?> clazz) { this.typeClass = clazz; @@ -184,14 +158,12 @@ public abstract class AbstractMemento implements Memento, Serializable { @Override public String getCatalogItemId() { - normalizeCatalogItemIds(); - return Iterables.getFirst(getCatalogItemHierarchy(), null); + return catalogItemId; } @Override - public List<String> getCatalogItemHierarchy() { - normalizeCatalogItemIds(); - return catalogItemHierarchy; + public List<String> getCatalogItemIdSearchPath() { + return searchPath; } @Override http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BrooklynMementoManifestImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BrooklynMementoManifestImpl.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BrooklynMementoManifestImpl.java index a4a7ecc..9e7d5da 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BrooklynMementoManifestImpl.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/BrooklynMementoManifestImpl.java @@ -56,8 +56,8 @@ public class BrooklynMementoManifestImpl implements BrooklynMementoManifest, Ser public Builder brooklynVersion(String val) { brooklynVersion = val; return this; } - public Builder entity(String id, String type, String parent, List<String> catalogItemIds) { - entityIdToManifest.put(id, new EntityMementoManifestImpl(id, type, parent, catalogItemIds)); + public Builder entity(String id, String type, String parent, String catalogItemId, List<String> searchPath) { + entityIdToManifest.put(id, new EntityMementoManifestImpl(id, type, parent, catalogItemId, searchPath)); return this; } public Builder location(String id, String type) { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/EntityMementoManifestImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/EntityMementoManifestImpl.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/EntityMementoManifestImpl.java index 28c2a7e..439db61 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/EntityMementoManifestImpl.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/EntityMementoManifestImpl.java @@ -19,7 +19,7 @@ package org.apache.brooklyn.core.mgmt.rebind.dto; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; + import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoManifest.EntityMementoManifest; import java.util.List; @@ -28,13 +28,15 @@ public class EntityMementoManifestImpl implements EntityMementoManifest { private String id; private String type; private String parentId; - private List<String> catalogItemIds; + private String catalogItemId; + private List<String> searchPath; - public EntityMementoManifestImpl(String id, String type, String parentId, List<String> catalogItemIds) { + public EntityMementoManifestImpl(String id, String type, String parentId, String catalogItemId, List<String> searchPath) { this.id = id; this.type = type; this.parentId = parentId; - this.catalogItemIds = ImmutableList.copyOf(catalogItemIds); + this.catalogItemId = catalogItemId; + this.searchPath = ImmutableList.copyOf(searchPath); } @Override @@ -52,18 +54,14 @@ public class EntityMementoManifestImpl implements EntityMementoManifest { return parentId; } - /** - * @deprecated since 0.11.0, use {@link #getCatalogItemHierarchy()} instead - */ - @Deprecated @Override public String getCatalogItemId() { - return Iterables.getFirst(catalogItemIds, null); + return catalogItemId; } @Override - public List<String> getCatalogItemHierarchy() { - return catalogItemIds; + public List<String> getCatalogItemIdSearchPath() { + return searchPath; } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java index 06f567c..c998de7 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/dto/MementosGenerators.java @@ -451,7 +451,8 @@ public class MementosGenerators { builder.id = instance.getId(); builder.displayName = instance.getDisplayName(); - builder.catalogItemHierarchy = instance.getCatalogItemHierarchy(); + builder.catalogItemId = instance.getCatalogItemId(); + builder.searchPath = instance.getCatalogItemIdSearchPath(); builder.type = (typePrefix.isPresent() ? typePrefix.get() : "") + instance.getClass().getName(); builder.typeClass = instance.getClass(); if (instance instanceof EntityAdjunct) { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformer.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformer.java index ece0cdf..a793183 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformer.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/transformer/CompoundTransformer.java @@ -102,7 +102,8 @@ public class CompoundTransformer { return xsltTransformer(xslt); } - /** Discards and replaces the item at the given XPath. + /** + * Discards and replaces the item at the given XPath. * <p> * For example to replace all occurrences * of text "foo" inside a tag "Tag1", you can use <code>TagName/text()[.='foo']</code>; @@ -119,7 +120,15 @@ public class CompoundTransformer { + newValue + "</xsl:template>"); } - + + /** + * Discards the item at the given XPath. + */ + public Builder xmlDeleteItem(String xpathToMatch) { + return xsltTransformerRecursiveCopyWithExtraRules( + "<xsl:template match=\"" + xpathToMatch + "\"></xsl:template>"); + } + /** * Replaces a tag, but while continuing to recurse. */ @@ -182,12 +191,12 @@ public class CompoundTransformer { * old text matches oldSymbolicName and optionally oldVersion * to have newSymbolicName and newVersion. * <p> - * Also changes contents of elements within a list of 'catalogItemHierarchy' e.g. + * Also changes contents of elements within a list of 'catalogItemIdSearchPath' e.g. * <pre> - * <catalogItemHierarchy> + * <catalogItemIdSearchPath> * <string>one</string> * <string>two</string> - * </catalogItemHierarchy> + * </catalogItemIdSearchPath> * </pre> * </p> * This provides a programmatic way to change the catalogItemID. */ @@ -196,13 +205,13 @@ public class CompoundTransformer { if (oldVersion==null) return changeCatalogItemId(oldSymbolicName, newSymbolicName, newVersion); // warnings use underscore notation because that's what CompoundTransformerLoader uses - return xmlReplaceItem("*[self::catalogItemId|parent::catalogItemHierarchy]/text()[.='"+ + return xmlReplaceItem("*[self::catalogItemId|parent::catalogItemIdSearchPath]/text()[.='"+ Preconditions.checkNotNull(oldSymbolicName, "old_symbolic_name")+":"+Preconditions.checkNotNull(oldVersion, "old_version")+"']", Preconditions.checkNotNull(newSymbolicName, "new_symbolic_name")+":"+Preconditions.checkNotNull(newVersion, "new_version")); } /** As {@link #changeCatalogItemId(String, String, String, String)} matching any old version. */ public Builder changeCatalogItemId(String oldSymbolicName, String newSymbolicName, String newVersion) { - return xmlReplaceItem("*[self::catalogItemId|parent::catalogItemHierarchy]/text()[starts-with(.,'"+Preconditions.checkNotNull(oldSymbolicName, "old_symbolic_name")+":')]", + return xmlReplaceItem("*[self::catalogItemId|parent::catalogItemIdSearchPath]/text()[starts-with(.,'"+Preconditions.checkNotNull(oldSymbolicName, "old_symbolic_name")+":')]", Preconditions.checkNotNull(newSymbolicName, "new_symbolic_name")+":"+Preconditions.checkNotNull(newVersion, "new_version")); } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java index 9ba131c..cadeab8 100644 --- a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java +++ b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractBrooklynObject.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Set; import com.google.common.collect.ImmutableList; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,7 +63,8 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal { @SetFromFlag("id") private String id = Identifiers.makeRandomLowercaseId(10); - private Deque<String> catalogItemIdStack = new ArrayDeque<>(); + private String catalogItemId; + private Deque<String> searchPath = new ArrayDeque<>(); /** callers (only in TagSupport) should synchronize on this for all access */ @SetFromFlag("tags") @@ -100,6 +102,13 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal { // rely on sub-class to call configure(properties), because otherwise its fields will not have been initialised } + protected Object readResolve() { + if (searchPath == null) { + searchPath = new ArrayDeque<>(); + } + return this; + } + /** * See {@link #configure(Map)} * @@ -202,33 +211,32 @@ public abstract class AbstractBrooklynObject implements BrooklynObjectInternal { @Override public void setCatalogItemId(String id) { - catalogItemIdStack.clear(); - nestCatalogItemId(id); + catalogItemId = id; } @Override - public void setCatalogItemIdHierarchy(List<String> ids) { - catalogItemIdStack.clear(); - catalogItemIdStack.addAll(ids); + public void setCatalogItemIdSearchPath(List<String> ids) { + searchPath.clear(); + searchPath.addAll(ids); } - @Override - public void nestCatalogItemId(String id) { + @Override + public void stackCatalogItemId(String id) { if (null != id) { - catalogItemIdStack.addFirst(id); + if (null != catalogItemId && !catalogItemId.equals(id)) { + searchPath.addFirst(catalogItemId); + } + setCatalogItemId(id); } } - public List<String> getCatalogItemHierarchy() { - return ImmutableList.copyOf(catalogItemIdStack); + public List<String> getCatalogItemIdSearchPath() { + return ImmutableList.copyOf(searchPath); } @Override public String getCatalogItemId() { - if (catalogItemIdStack.size() != 0) { - return catalogItemIdStack.getFirst(); - } - return null; + return catalogItemId; } protected void onTagsChanged() { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java index 260c210..ea02877 100644 --- a/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java +++ b/core/src/main/java/org/apache/brooklyn/core/objs/AbstractEntityAdjunct.java @@ -379,7 +379,8 @@ public abstract class AbstractEntityAdjunct extends AbstractBrooklynObject imple this.entity = entity; this.execution = ((EntityInternal) entity).getExecutionContext(); if (entity!=null && getCatalogItemId() == null) { - setCatalogItemIdHierarchy(entity.getCatalogItemHierarchy()); + setCatalogItemId(entity.getCatalogItemId()); + setCatalogItemIdSearchPath(entity.getCatalogItemIdSearchPath()); } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/81815f94/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java index 4c05ed6..6cec5ab 100644 --- a/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java +++ b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java @@ -38,9 +38,13 @@ import com.google.common.annotations.Beta; public interface BrooklynObjectInternal extends BrooklynObject, Rebindable { void setCatalogItemId(String id); - void setCatalogItemIdHierarchy(List<String> id); + void setCatalogItemIdSearchPath(List<String> id); - void nestCatalogItemId(String id); + /** + * Moves the current catalog item id onto the start of the search path, + * then sets the catalog item id to the supplied value. + */ + void stackCatalogItemId(String id); // subclasses typically apply stronger typing @Override
