cleaner config / config-map api understanding inheritance * Config is now resolved against the ancestor where it is defined, e.g. attributeWhenReady; (but do we need a way to specify that config should be resolved against the resolver?) * submap is no longer supported for entity config; findKeys has been introduced * many methods tidied and deprecated
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/0d655e05 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/0d655e05 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/0d655e05 Branch: refs/heads/master Commit: 0d655e0503ae1cdf7ad4f95b5321118041bd0592 Parents: 914982e Author: Alex Heneveld <alex.henev...@cloudsoftcorp.com> Authored: Tue Sep 20 16:43:43 2016 +0100 Committer: Alex Heneveld <alex.henev...@cloudsoftcorp.com> Committed: Wed Sep 21 16:06:07 2016 +0100 ---------------------------------------------------------------------- .../apache/brooklyn/api/objs/Configurable.java | 5 + .../BrooklynComponentTemplateResolver.java | 46 ++- .../brooklyn/ConfigInheritanceYamlTest.java | 22 +- .../brooklyn/camp/brooklyn/ObjectsYamlTest.java | 9 + .../core/config/BasicConfigInheritance.java | 185 ++++------ .../apache/brooklyn/core/config/ConfigKeys.java | 37 -- .../config/internal/AbstractConfigMapImpl.java | 367 ++++++++++++++----- .../AncestorContainerAndKeyValueIterator.java | 12 +- .../internal/BasicConfigValueAtContainer.java | 54 --- .../internal/LazyContainerAndKeyValue.java | 27 +- .../core/effector/ssh/SshEffectorTasks.java | 67 ++-- .../brooklyn/core/entity/AbstractEntity.java | 8 +- .../internal/ConfigMapViewWithStringKeys.java | 10 +- .../core/entity/internal/EntityConfigMap.java | 69 +--- .../core/internal/BrooklynPropertiesImpl.java | 23 +- .../core/location/AbstractLocation.java | 13 +- .../core/location/BasicLocationRegistry.java | 4 +- .../location/internal/LocationConfigMap.java | 92 ++--- .../entitlement/PerUserEntitlementManager.java | 11 +- .../BasicExternalConfigSupplierRegistry.java | 2 +- .../internal/DeferredBrooklynProperties.java | 11 +- .../mgmt/rebind/BasicEntityRebindSupport.java | 2 +- .../mgmt/rebind/BasicLocationRebindSupport.java | 4 +- .../mgmt/rebind/dto/MementosGenerators.java | 6 +- .../AbstractConfigurationSupportInternal.java | 35 +- .../core/objs/AbstractEntityAdjunct.java | 11 +- .../brooklyn/core/objs/AdjunctConfigMap.java | 55 +-- .../core/objs/BasicConfigurableObject.java | 13 +- .../core/objs/BrooklynObjectInternal.java | 19 +- .../core/server/BrooklynServerPaths.java | 4 +- .../FixedListMachineProvisioningLocation.java | 4 +- .../brooklyn/util/core/ClassLoaderUtils.java | 2 +- .../brooklyn/util/core/task/ssh/SshTasks.java | 30 +- .../brooklyn/core/entity/EntityConfigTest.java | 13 +- .../core/mgmt/rebind/RebindFailuresTest.java | 30 +- .../util/core/internal/FlagUtilsTest.java | 7 + .../jclouds/JcloudsByonLocationResolver.java | 2 +- .../location/jclouds/JcloudsLocation.java | 2 +- .../AbstractPortableTemplateBuilder.java | 2 +- .../apache/brooklyn/rest/BrooklynWebConfig.java | 4 +- .../rest/resources/EntityConfigResource.java | 7 +- .../rest/resources/PolicyConfigResource.java | 4 +- .../rest/transform/LocationTransformer.java | 17 +- .../rest/resources/LocationResourceTest.java | 23 +- .../rest/util/EntityLocationUtilsTest.java | 2 +- .../BrooklynNodeUpgradeEffectorBody.java | 2 +- .../base/VanillaSoftwareProcessTest.java | 3 +- .../brooklyn/config/ConfigInheritance.java | 180 ++++----- .../brooklyn/config/ConfigInheritances.java | 185 ++++++++++ .../org/apache/brooklyn/config/ConfigKey.java | 8 +- .../org/apache/brooklyn/config/ConfigMap.java | 103 ++++-- .../brooklyn/config/ConfigValueAtContainer.java | 17 +- .../apache/brooklyn/config/StringConfigMap.java | 10 + .../util/exceptions/ReferenceWithError.java | 14 +- 54 files changed, 1097 insertions(+), 797 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java b/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java index 02eee54..ea36c4d 100644 --- a/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java +++ b/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java @@ -18,11 +18,14 @@ */ package org.apache.brooklyn.api.objs; +import java.util.Set; + import org.apache.brooklyn.api.mgmt.Task; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.config.ConfigKey.HasConfigKey; import com.google.common.annotations.Beta; +import com.google.common.base.Predicate; /** * Something that has mutable config, such as an entity or policy. @@ -94,5 +97,7 @@ public interface Configurable { * @see {@link #setConfig(ConfigKey, Task)} */ <T> T set(HasConfigKey<T> key, Task<T> val); + + Set<ConfigKey<?>> findKeys(Predicate<ConfigKey<?>> predicate); } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java ---------------------------------------------------------------------- diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java index 2f7c643..ccf18c0 100644 --- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java +++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java @@ -46,6 +46,7 @@ import org.apache.brooklyn.camp.spi.ApplicationComponentTemplate; import org.apache.brooklyn.camp.spi.AssemblyTemplate; import org.apache.brooklyn.camp.spi.PlatformComponentTemplate; import org.apache.brooklyn.config.ConfigInheritance; +import org.apache.brooklyn.config.ConfigInheritances; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.config.ConfigValueAtContainer; import org.apache.brooklyn.core.catalog.internal.CatalogUtils; @@ -73,6 +74,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Function; +import com.google.common.base.Functions; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; @@ -289,25 +291,27 @@ public class BrooklynComponentTemplateResolver { Collection<FlagConfigKeyAndValueRecord> records = findAllFlagsAndConfigKeyValues(spec, bag); Set<String> keyNamesUsed = new LinkedHashSet<String>(); for (FlagConfigKeyAndValueRecord r: records) { - // run through flags *and* config keys (may be overkill, but...) + // flags and config keys tracked separately, look at each (may be overkill but it's what we've always done) + Function<Maybe<Object>, Maybe<Object>> rawConvFn = Functions.identity(); if (r.getFlagMaybeValue().isPresent()) { final String flag = r.getFlagName(); final ConfigKey<Object> key = (ConfigKey<Object>) r.getConfigKey(); if (key==null) ConfigKeys.newConfigKey(Object.class, flag); final Object ownValueF = new SpecialFlagsTransformer(loader, encounteredRegisteredTypeIds).apply(r.getFlagMaybeValue().get()); + Function<EntitySpec<?>, Maybe<Object>> rawEvalFn = new Function<EntitySpec<?>,Maybe<Object>>() { + @Override + public Maybe<Object> apply(EntitySpec<?> input) { + return spec.getFlags().containsKey(flag) ? Maybe.of((Object)spec.getFlags().get(flag)) : Maybe.absent(); + } + }; Iterable<? extends ConfigValueAtContainer<EntitySpec<?>,Object>> ckvi = MutableList.of( - new LazyContainerAndKeyValue<EntitySpec<?>,Object>(key, null, new Function<EntitySpec<?>,Maybe<Object>>() { - @Override - public Maybe<Object> apply(EntitySpec<?> input) { - return spec.getFlags().containsKey(flag) ? Maybe.of((Object)spec.getFlags().get(flag)) : Maybe.absent(); - } - })); + new LazyContainerAndKeyValue<EntitySpec<?>,Object>(key, null, rawEvalFn, rawConvFn)); - ConfigValueAtContainer<EntitySpec<?>,Object> combinedVal = getDefaultConfigInheritance().resolveInheriting( - key, Maybe.ofAllowingNull(ownValueF), null, - ckvi.iterator(), InheritanceContext.TYPE_DEFINITION); + ConfigValueAtContainer<EntitySpec<?>,Object> combinedVal = ConfigInheritances.resolveInheriting( + null, key, Maybe.ofAllowingNull(ownValueF), Maybe.<Object>absent(), + ckvi.iterator(), InheritanceContext.TYPE_DEFINITION, getDefaultConfigInheritance()).getWithoutError(); spec.configure(flag, combinedVal.get()); keyNamesUsed.add(flag); @@ -316,17 +320,19 @@ public class BrooklynComponentTemplateResolver { if (r.getConfigKeyMaybeValue().isPresent()) { final ConfigKey<Object> key = (ConfigKey<Object>) r.getConfigKey(); final Object ownValueF = new SpecialFlagsTransformer(loader, encounteredRegisteredTypeIds).apply(r.getConfigKeyMaybeValue().get()); + + Function<EntitySpec<?>, Maybe<Object>> rawEvalFn = new Function<EntitySpec<?>,Maybe<Object>>() { + @Override + public Maybe<Object> apply(EntitySpec<?> input) { + return spec.getConfig().containsKey(key) ? Maybe.of(spec.getConfig().get(key)) : Maybe.absent(); + } + }; Iterable<? extends ConfigValueAtContainer<EntitySpec<?>,Object>> ckvi = MutableList.of( - new LazyContainerAndKeyValue<EntitySpec<?>,Object>(key, null, new Function<EntitySpec<?>,Maybe<Object>>() { - @Override - public Maybe<Object> apply(EntitySpec<?> input) { - return spec.getConfig().containsKey(key) ? Maybe.of(spec.getConfig().get(key)) : Maybe.absent(); - } - })); + new LazyContainerAndKeyValue<EntitySpec<?>,Object>(key, null, rawEvalFn, rawConvFn)); - ConfigValueAtContainer<EntitySpec<?>,Object> combinedVal = getDefaultConfigInheritance().resolveInheriting( - key, Maybe.ofAllowingNull(ownValueF), null, - ckvi.iterator(), InheritanceContext.TYPE_DEFINITION); + ConfigValueAtContainer<EntitySpec<?>,Object> combinedVal = ConfigInheritances.resolveInheriting( + null, key, Maybe.ofAllowingNull(ownValueF), Maybe.<Object>absent(), + ckvi.iterator(), InheritanceContext.TYPE_DEFINITION, getDefaultConfigInheritance()).getWithoutError(); spec.configure(key, combinedVal.get()); keyNamesUsed.add(key.getName()); @@ -341,7 +347,7 @@ public class BrooklynComponentTemplateResolver { continue; } ConfigKey<?> key = entry.getValue(); - if (!ConfigKeys.isKeyReinheritable(key, InheritanceContext.TYPE_DEFINITION)) { + if (!ConfigInheritances.isKeyReinheritable(key, InheritanceContext.TYPE_DEFINITION)) { spec.removeConfig(key); spec.removeFlag(key.getName()); } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java ---------------------------------------------------------------------- diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java index 349adae..9a71aed 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java @@ -32,7 +32,6 @@ import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.core.config.MapConfigKey; import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.entity.EntityAsserts; -import org.apache.brooklyn.core.entity.internal.EntityConfigMap; import org.apache.brooklyn.core.sensor.Sensors; import org.apache.brooklyn.core.test.entity.TestEntity; import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess; @@ -221,16 +220,9 @@ public class ConfigInheritanceYamlTest extends AbstractYamlTest { ImmutableMap.of("mykey", "myval", "templateOptions", ImmutableMap.of("myOptionsKey", "myOptionsVal"))); } - /** - * TODO This hangs because the attributeWhenReady self-reference is resolved against the entity - * looking up the config value (i.e. the child). Therefore it waits for the TestEntity to have - * a value for that sensor, but this never happens. The way to avoid this is to explicitly set - * the component that the attributeWhenReady should apply to (e.g. see {@link #testInheritsParentConfigTask()}. - * - * Do we want to just exclude this test? Or do we want to "fix" it? Which entity should the - * attributeWhenReady apply to? - */ - @Test(groups={"Broken", "WIP"}, enabled=false) + // Fixed Sept 2016, attributeWhenReady self-reference is now resolved against the entity defining the config value. + // Prior to this it was resolved against the caller's scope. + @Test public void testInheritsParentConfigTaskWithSelfScope() throws Exception { String yaml = Joiner.on("\n").join( "services:", @@ -758,12 +750,8 @@ public class ConfigInheritanceYamlTest extends AbstractYamlTest { ImmutableMap.of("mykey1", "myval1", "mykey2", "myval2", "mykey3", "myval3")); } - /** - * TODO Has always failed, and probably hard to fix?! This is due to the way - * {@link EntityConfigMap#setInheritedConfig(Map, org.apache.brooklyn.util.core.config.ConfigBag)} works: - * the parent overrides the grandparent's config. So we only get mykey2+mykey3. - */ - @Test(groups={"Broken", "WIP"}) + // Fixed Sept 2016, inheritance is now computed with respect to defined keys and propagated upwards when traversing ancestors + @Test public void testExtendsParentMultipleLevels() throws Exception { addCatalogItems( "brooklyn.catalog:", http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java ---------------------------------------------------------------------- diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java index c372a72..f1ea8eb 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java @@ -21,6 +21,7 @@ package org.apache.brooklyn.camp.brooklyn; import static org.testng.Assert.assertEquals; import java.util.List; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.brooklyn.api.entity.Entity; @@ -33,6 +34,7 @@ import org.apache.brooklyn.core.config.ConfigKeys; import org.apache.brooklyn.core.entity.Entities; import org.apache.brooklyn.core.mgmt.ManagementContextInjectable; import org.apache.brooklyn.core.test.entity.TestEntity; +import org.apache.brooklyn.util.collections.MutableSet; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.flags.SetFromFlag; import org.apache.brooklyn.util.core.flags.TypeCoercions; @@ -42,6 +44,8 @@ import org.testng.Assert; import org.testng.annotations.Test; import com.google.common.base.Charsets; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.hash.HashCode; import com.google.common.hash.Hashing; @@ -182,6 +186,11 @@ public class ObjectsYamlTest extends AbstractYamlTest { public <T> T set(HasConfigKey<T> key, Task<T> val) { return set(key.getConfigKey(), val); } + + @Override + public Set<ConfigKey<?>> findKeys(Predicate<ConfigKey<?>> predicate) { + return MutableSet.copyOf(Iterables.filter(bag.getAllConfigAsConfigKeyMap().keySet(), predicate)); + } } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/config/BasicConfigInheritance.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/config/BasicConfigInheritance.java b/core/src/main/java/org/apache/brooklyn/core/config/BasicConfigInheritance.java index edd8550..2ed7d48 100644 --- a/core/src/main/java/org/apache/brooklyn/core/config/BasicConfigInheritance.java +++ b/core/src/main/java/org/apache/brooklyn/core/config/BasicConfigInheritance.java @@ -18,45 +18,43 @@ */ package org.apache.brooklyn.core.config; -import java.util.Iterator; import java.util.Map; -import java.util.NoSuchElementException; - -import javax.annotation.Nullable; import org.apache.brooklyn.config.ConfigInheritance; +import org.apache.brooklyn.config.ConfigInheritances; +import org.apache.brooklyn.config.ConfigInheritances.BasicConfigValueAtContainer; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.config.ConfigValueAtContainer; -import org.apache.brooklyn.core.config.internal.BasicConfigValueAtContainer; -import org.apache.brooklyn.core.config.internal.LazyContainerAndKeyValue; import org.apache.brooklyn.util.collections.CollectionMerger; +import org.apache.brooklyn.util.exceptions.ReferenceWithError; import org.apache.brooklyn.util.guava.Maybe; -import com.google.common.base.Function; - public class BasicConfigInheritance implements ConfigInheritance { private static final long serialVersionUID = -5916548049057961051L; + public static final String CONFLICT_RESOLUTION_STRATEGY_DEEP_MERGE = "deep_merge"; + public static final String CONFLICT_RESOLUTION_STRATEGY_OVERWRITE = "overwrite"; + /** Indicates that a config key value should not be passed down from a container where it is defined. * Unlike {@link #NEVER_INHERITED} these values can be passed down if set as anonymous keys at a container * (ie the container does not expect it) to a container which does expect it, but it will not be passed down further. * If the inheritor also defines a value the parent's value is ignored irrespective * (as in {@link #OVERWRITE}; see {@link #NOT_REINHERITED_ELSE_DEEP_MERGE} if merging is desired). */ - public static BasicConfigInheritance NOT_REINHERITED = new BasicConfigInheritance(false,"overwrite",false); + public static BasicConfigInheritance NOT_REINHERITED = new BasicConfigInheritance(false,CONFLICT_RESOLUTION_STRATEGY_OVERWRITE,false); /** As {@link #NOT_REINHERITED} but in cases where a value is inherited because a parent did not recognize it, * if the inheritor also defines a value the two values should be merged. */ - public static BasicConfigInheritance NOT_REINHERITED_ELSE_DEEP_MERGE = new BasicConfigInheritance(false,"deep_merge",false); + public static BasicConfigInheritance NOT_REINHERITED_ELSE_DEEP_MERGE = new BasicConfigInheritance(false,CONFLICT_RESOLUTION_STRATEGY_DEEP_MERGE,false); /** Indicates that a key's value should never be inherited, even if defined on a container that does not know the key. * Most usages will prefer {@link #NOT_REINHERITED}. */ - public static BasicConfigInheritance NEVER_INHERITED = new BasicConfigInheritance(false,"overwrite",true); + public static BasicConfigInheritance NEVER_INHERITED = new BasicConfigInheritance(false,CONFLICT_RESOLUTION_STRATEGY_OVERWRITE,true); /** Indicates that if a key has a value at both an ancestor and a descendant, the descendant and his descendants * will prefer the value at the descendant. */ - public static BasicConfigInheritance OVERWRITE = new BasicConfigInheritance(true,"overwrite",false); + public static BasicConfigInheritance OVERWRITE = new BasicConfigInheritance(true,CONFLICT_RESOLUTION_STRATEGY_OVERWRITE,false); /** Indicates that if a key has a value at both an ancestor and a descendant, the descendant and his descendants * should attempt to merge the values. If the values are not mergable behaviour is undefined * (and often the descendant's value will simply overwrite). */ - public static BasicConfigInheritance DEEP_MERGE = new BasicConfigInheritance(true,"deep_merge",false); + public static BasicConfigInheritance DEEP_MERGE = new BasicConfigInheritance(true,CONFLICT_RESOLUTION_STRATEGY_DEEP_MERGE,false); // reinheritable? true/false; if false, children/descendants/inheritors will never see it; default true protected final boolean isReinherited; @@ -80,118 +78,89 @@ public class BasicConfigInheritance implements ConfigInheritance { return null; } + @Override - public <TContainer,TValue> ConfigValueAtContainer<TContainer,TValue> resolveInheriting( - @Nullable ConfigKey<TValue> key, Maybe<TValue> localValue, TContainer container, - Iterator<? extends ConfigValueAtContainer<TContainer,TValue>> ancestorContainerKeyValues, ConfigInheritanceContext context) { - ConfigInheritance inh = key==null ? null : key.getInheritanceByContext(context); - if (inh==null) inh = this; - if (inh!=this) return inh.resolveInheriting(key, localValue, container, ancestorContainerKeyValues, context); - - ConfigValueAtContainer<TContainer,TValue> v2 = null; - if (OVERWRITE.conflictResolutionStrategy.equals(conflictResolutionStrategy) && - (localValue.isPresent() || useLocalDefaultValue)) { - // don't inherit - } else if (ancestorContainerKeyValues==null || !ancestorContainerKeyValues.hasNext()) { - // nothing to inherit - } else { - // check whether parent allows us to get inherited value - ConfigValueAtContainer<TContainer,TValue> c = ancestorContainerKeyValues.next(); - ConfigInheritance inh2 = c.getKey()==null ? null : c.getKey().getInheritanceByContext(context); - if (inh2!=null && !ConfigKeys.isKeyReinheritable(c.getKey(), context)) { - // can't inherit - } else { - // get inherited value - if (inh2==null) inh2=this; - v2 = inh2.resolveInheriting(c.getKey()!=null ? c.getKey() : null, - c.isValueExplicitlySet() ? c.asMaybe() : Maybe.<TValue>absent(), c.getContainer(), - ancestorContainerKeyValues, context); - } + public <TContainer, TValue> boolean isReinheritable(ConfigValueAtContainer<TContainer, TValue> parent, ConfigInheritanceContext context) { + if (!equals(ConfigInheritances.findInheritance(parent, context, this))) + throw new IllegalStateException("Method can only be invoked on inheritance at "+parent); + return isReinherited(); + } + + @Override + public <TContainer,TValue> boolean considerParent( + ConfigValueAtContainer<TContainer,TValue> local, + ConfigValueAtContainer<TContainer,TValue> parent, + ConfigInheritanceContext context) { + if (!equals(ConfigInheritances.findInheritance(local, context, this))) + throw new IllegalStateException("Method can only be invoked on inheritance at "+local); + if (parent==null) return false; + if (CONFLICT_RESOLUTION_STRATEGY_OVERWRITE.equals(conflictResolutionStrategy)) { + // overwrite means ignore if there's an explicit value, or we're using the local default + return !local.isValueExplicitlySet() && !getUseLocalDefaultValue(); } + return true; + } - BasicConfigValueAtContainer<TContainer,TValue> v = new BasicConfigValueAtContainer<TContainer,TValue>(); - v.setContainer(container); - v.setKey(key); + @Override + public <TContainer,TValue> ReferenceWithError<ConfigValueAtContainer<TContainer,TValue>> resolveWithParent( + ConfigValueAtContainer<TContainer,TValue> local, + ConfigValueAtContainer<TContainer,TValue> parent, + ConfigInheritanceContext context) { - Maybe<TValue> localValueOrConflictableDefault = localValue.isPresent() ? localValue : - useLocalDefaultValue ? v.getDefaultValueMaybe() : Maybe.<TValue>absent(); - if (v2!=null && v2.isValueExplicitlySet() && !localValueOrConflictableDefault.isPresent()) return v2; - if (v2==null || !v2.isValueExplicitlySet()) { - v.setValueWasExplicitlySet(localValue.isPresent()); - v.setValue(v.isValueExplicitlySet() ? localValue : v.getDefaultValueMaybe()); - } else { - v.setValue(resolveConflict(key, localValue, v2.asMaybe())); - v.setValueWasExplicitlySet(true); + if (!parent.isValueExplicitlySet() && !getUseLocalDefaultValue()) + return ReferenceWithError.newInstanceWithoutError(new BasicConfigValueAtContainer<TContainer,TValue>(local)); + + // parent explicitly set (or we might have to merge defaults), + // and by the contract of this method we can assume reinheritable + if (!local.isValueExplicitlySet() && !getUseLocalDefaultValue()) + return ReferenceWithError.newInstanceWithoutError(new BasicConfigValueAtContainer<TContainer,TValue>(parent)); + + // both explicitly set or defaults applicable, and not overwriting; it should be merge + if (CONFLICT_RESOLUTION_STRATEGY_DEEP_MERGE.equals(conflictResolutionStrategy)) { + BasicConfigValueAtContainer<TContainer, TValue> result = new BasicConfigValueAtContainer<TContainer,TValue>(local); + ReferenceWithError<Maybe<? extends TValue>> resolvedValue = deepMerge( + local.isValueExplicitlySet() ? local.asMaybe() : local.getDefaultValue(), + parent.isValueExplicitlySet() ? parent.asMaybe() : parent.getDefaultValue()); + result.setValue(resolvedValue.getWithoutError()); + return ReferenceWithError.newInstanceThrowingError(result, resolvedValue.getError()); } - return v; + + return resolveWithParentCustomStrategy(local, parent, context); } - /** only invoked if there is an ancestor value; custom strategies can overwrite */ - protected <T> Maybe<T> resolveConflict(ConfigKey<T> key, Maybe<T> localValue, Maybe<T> ancestorValue) { - if (OVERWRITE.conflictResolutionStrategy.equals(conflictResolutionStrategy)) { - if (localValue.isPresent()) return localValue; - if (useLocalDefaultValue) return (key==null || !key.hasDefaultValue()) ? Maybe.<T>absent() : Maybe.ofAllowingNull(key.getDefaultValue()); - return ancestorValue; - } - if (DEEP_MERGE.conflictResolutionStrategy.equals(conflictResolutionStrategy)) { - localValue = localValue.isPresent() ? localValue : - useLocalDefaultValue && key!=null && key.hasDefaultValue() ? Maybe.ofAllowingNull(key.getDefaultValue()) : - Maybe.<T>absent(); - @SuppressWarnings("unchecked") - Maybe<T> result = (Maybe<T>) deepMerge(localValue, ancestorValue); - return result; - } - throw new IllegalStateException("Unknown config conflict resolution strategy '"+conflictResolutionStrategy+"' evaluating "+key); + + protected <TContainer, TValue> ReferenceWithError<ConfigValueAtContainer<TContainer, TValue>> resolveWithParentCustomStrategy( + ConfigValueAtContainer<TContainer, TValue> local, ConfigValueAtContainer<TContainer, TValue> parent, + ConfigInheritanceContext context) { + throw new IllegalStateException("Unknown config conflict resolution strategy '"+conflictResolutionStrategy+"' evaluating "+local+"/"+parent); } - private static <T> Maybe<? extends T> deepMerge(Maybe<? extends T> val1, Maybe<? extends T> val2) { + + private static <T> ReferenceWithError<Maybe<? extends T>> deepMerge(Maybe<? extends T> val1, Maybe<? extends T> val2) { if (val2.isAbsent() || val2.isNull()) { - return val1; + return ReferenceWithError.newInstanceWithoutError(val1); } else if (val1.isAbsent()) { - return val2; + return ReferenceWithError.newInstanceWithoutError(val2); } else if (val1.isNull()) { - return val1; // an explicit null means an override; don't merge + return ReferenceWithError.newInstanceWithoutError(val1); // an explicit null means an override; don't merge } else if (val1.get() instanceof Map && val2.get() instanceof Map) { @SuppressWarnings({ "unchecked", "rawtypes" }) Maybe<T> result = (Maybe)Maybe.of(CollectionMerger.builder().build().merge((Map<?,?>)val1.get(), (Map<?,?>)val2.get())); - return result; + return ReferenceWithError.newInstanceWithoutError(result); } else { // cannot merge; just return val1 - return val1; + return ReferenceWithError.newInstanceThrowingError(val1, new IllegalArgumentException("Cannot merge '"+val1.get()+"' and '"+val2.get()+"'")); } } - - public static class AncestorContainerAndKeyValueIterator<TContainer,TValue> implements Iterator<ConfigValueAtContainer<TContainer,TValue>> { - private TContainer lastContainer; - private final Function<TContainer, ConfigKey<TValue>> keyFindingFunction; - private final Function<TContainer, Maybe<TValue>> localEvaluationFunction; - private final Function<TContainer, TContainer> parentFunction; - - public AncestorContainerAndKeyValueIterator(TContainer childContainer, - Function<TContainer, ConfigKey<TValue>> keyFindingFunction, - Function<TContainer, Maybe<TValue>> localEvaluationFunction, - Function<TContainer, TContainer> parentFunction) { - this.lastContainer = childContainer; - this.keyFindingFunction = keyFindingFunction; - this.localEvaluationFunction = localEvaluationFunction; - this.parentFunction = parentFunction; - } - - @Override - public boolean hasNext() { - return parentFunction.apply(lastContainer)!=null; - } - - @Override - public ConfigValueAtContainer<TContainer,TValue> next() { - TContainer nextContainer = parentFunction.apply(lastContainer); - if (nextContainer==null) throw new NoSuchElementException("Cannot search ancestors further than "+lastContainer); - lastContainer = nextContainer; - return new LazyContainerAndKeyValue<TContainer,TValue>(keyFindingFunction.apply(lastContainer), lastContainer, localEvaluationFunction); - } - - @Override - public void remove() { - throw new UnsupportedOperationException("This iterator does not support removal"); - } + + public boolean isReinherited() { + return isReinherited; + } + + public String getConflictResolutionStrategy() { + return conflictResolutionStrategy; + } + + public boolean getUseLocalDefaultValue() { + return useLocalDefaultValue; } } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/config/ConfigKeys.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/config/ConfigKeys.java b/core/src/main/java/org/apache/brooklyn/core/config/ConfigKeys.java index 2743b80..6359907 100644 --- a/core/src/main/java/org/apache/brooklyn/core/config/ConfigKeys.java +++ b/core/src/main/java/org/apache/brooklyn/core/config/ConfigKeys.java @@ -22,26 +22,20 @@ import java.util.Map; import javax.annotation.Nonnull; -import org.apache.brooklyn.config.ConfigInheritance; import org.apache.brooklyn.config.ConfigInheritance.ConfigInheritanceContext; import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.config.ConfigValueAtContainer; import org.apache.brooklyn.core.config.BasicConfigKey.BasicConfigKeyOverwriting; -import org.apache.brooklyn.core.config.internal.LazyContainerAndKeyValue; import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey; import org.apache.brooklyn.core.sensor.BasicAttributeSensorAndConfigKey; import org.apache.brooklyn.core.sensor.PortAttributeSensorAndConfigKey; import org.apache.brooklyn.core.sensor.TemplatedStringAttributeSensorAndConfigKey; -import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.core.config.ConfigBag; -import org.apache.brooklyn.util.guava.Maybe; import org.apache.brooklyn.util.text.Strings; import org.apache.brooklyn.util.time.Duration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.CaseFormat; -import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.reflect.TypeToken; @@ -289,35 +283,4 @@ public class ConfigKeys { } - /** determine whether a key is reinheritable from the point in the given inheritance hierarchy where it is introduced; - * default is true, but some keys may define not being reinherited or may have that effective result - * <p> - * note that this does not mean a value should never be *inherited*; - * callers should query with the key defined at a given point in a hierarchy, - * so if a key is not defined at some point in the hierarchy - * (eg not on a type in the type hierarchy, or not an an entity in the runtime management hierarchy) - * then null should be passed and values will be reinheritable */ - public static <T> boolean isKeyReinheritable(final ConfigKey<T> key, final ConfigInheritanceContext context) { - if (key==null) return true; - ConfigInheritance inh = key.getInheritanceByContext(context); - if (inh==null) return true; - if (inh instanceof BasicConfigInheritance) { - return ((BasicConfigInheritance)inh).isReinherited; - } - - // evaluate by faking a parent who sets a value and seeing if it's reinherited - Iterable<? extends ConfigValueAtContainer<Void,T>> ckvi = MutableList.of( - new LazyContainerAndKeyValue<Void,T>(key, null, new Function<Void,Maybe<T>>() { - @Override - public Maybe<T> apply(Void input) { - return Maybe.ofAllowingNull(null); - } - })); - - ConfigValueAtContainer<Void,T> combinedVal = BasicConfigInheritance.OVERWRITE.resolveInheriting( - key, Maybe.<T>absent(), null, - ckvi.iterator(), InheritanceContext.TYPE_DEFINITION); - return combinedVal.isValueExplicitlySet(); - } - } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/config/internal/AbstractConfigMapImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/config/internal/AbstractConfigMapImpl.java b/core/src/main/java/org/apache/brooklyn/core/config/internal/AbstractConfigMapImpl.java index 6c31b97..e964d24 100644 --- a/core/src/main/java/org/apache/brooklyn/core/config/internal/AbstractConfigMapImpl.java +++ b/core/src/main/java/org/apache/brooklyn/core/config/internal/AbstractConfigMapImpl.java @@ -20,31 +20,46 @@ package org.apache.brooklyn.core.config.internal; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.Future; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import org.apache.brooklyn.api.mgmt.ExecutionContext; import org.apache.brooklyn.api.objs.BrooklynObject; +import org.apache.brooklyn.config.ConfigInheritance; +import org.apache.brooklyn.config.ConfigInheritances; +import org.apache.brooklyn.config.ConfigInheritances.BasicConfigValueAtContainer; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.config.ConfigKey.HasConfigKey; -import org.apache.brooklyn.config.ConfigMap; +import org.apache.brooklyn.config.ConfigMap.ConfigMapWithInheritance; +import org.apache.brooklyn.config.ConfigValueAtContainer; +import org.apache.brooklyn.core.config.BasicConfigInheritance; import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.config.ConfigKeys.InheritanceContext; import org.apache.brooklyn.core.config.Sanitizer; import org.apache.brooklyn.core.config.StructuredConfigKey; -import org.apache.brooklyn.core.entity.internal.ConfigMapViewWithStringKeys; import org.apache.brooklyn.core.objs.BrooklynObjectInternal; +import org.apache.brooklyn.util.collections.MutableList; import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.collections.MutableSet; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.flags.TypeCoercions; import org.apache.brooklyn.util.core.internal.ConfigKeySelfExtracting; import org.apache.brooklyn.util.core.task.DeferredSupplier; +import org.apache.brooklyn.util.exceptions.ReferenceWithError; import org.apache.brooklyn.util.guava.Maybe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; -public abstract class AbstractConfigMapImpl implements ConfigMap { +public abstract class AbstractConfigMapImpl<TContainer extends BrooklynObject> implements ConfigMapWithInheritance<TContainer> { /* * Changed Sept 2016 so that keys can determine inheritance strategy at every level in the hierarchy, @@ -53,9 +68,10 @@ public abstract class AbstractConfigMapImpl implements ConfigMap { private static final Logger LOG = LoggerFactory.getLogger(AbstractConfigMapImpl.class); - protected final ConfigMapViewWithStringKeys mapViewWithStringKeys = new ConfigMapViewWithStringKeys(this); + @SuppressWarnings("deprecation") + protected final transient org.apache.brooklyn.core.entity.internal.ConfigMapViewWithStringKeys mapViewWithStringKeys = new org.apache.brooklyn.core.entity.internal.ConfigMapViewWithStringKeys(this); - protected BrooklynObjectInternal bo; + protected TContainer bo; /** * Map of configuration information that is defined at start-up time for the entity. These @@ -64,27 +80,30 @@ public abstract class AbstractConfigMapImpl implements ConfigMap { */ protected final Map<ConfigKey<?>,Object> ownConfig; - protected AbstractConfigMapImpl(BrooklynObject bo) { + protected AbstractConfigMapImpl(TContainer bo) { // Not using ConcurrentMap, because want to (continue to) allow null values. // Could use ConcurrentMapAcceptingNullVals (with the associated performance hit on entrySet() etc). this(bo, Collections.synchronizedMap(new LinkedHashMap<ConfigKey<?>, Object>())); } - protected AbstractConfigMapImpl(BrooklynObject bo, Map<ConfigKey<?>, Object> storage) { - this.bo = (BrooklynObjectInternal) bo; + protected AbstractConfigMapImpl(TContainer bo, Map<ConfigKey<?>, Object> storage) { + this.bo = bo; this.ownConfig = storage; } - public BrooklynObjectInternal getBrooklynObject() { + public TContainer getContainer() { return bo; } + protected final BrooklynObjectInternal getBrooklynObject() { + return (BrooklynObjectInternal)bo; + } + public <T> T getConfig(ConfigKey<T> key) { - return getConfigImpl(key).orNull(); + return getConfigImpl(key, false).getWithoutError().get(); } - public <T> T getConfig(HasConfigKey<T> key) { - return getConfigImpl(key.getConfigKey()).orNull(); + return getConfigImpl(key.getConfigKey(), false).getWithoutError().get(); } @Override @@ -92,58 +111,38 @@ public abstract class AbstractConfigMapImpl implements ConfigMap { return getConfigRaw(key, false); } - protected abstract <T> Maybe<T> getConfigImpl(ConfigKey<T> key); - protected abstract ExecutionContext getExecutionContext(BrooklynObject bo); protected abstract void postLocalEvaluate(ConfigKey<?> key, BrooklynObject bo, Maybe<?> rawValue, Maybe<?> resolvedValue); - protected class LocalEvaluateKeyValue<TContainer extends BrooklynObject, TValue> implements Function<TContainer,Maybe<TValue>> { - ConfigKey<TValue> keyIgnoringInheritance; - - public LocalEvaluateKeyValue(ConfigKey<TValue> keyIgnoringInheritance) { - this.keyIgnoringInheritance = keyIgnoringInheritance; - } - - @Override - public Maybe<TValue> apply(TContainer bo) { - ExecutionContext exec = getExecutionContext(bo); - - ConfigMap configMap = ((BrooklynObjectInternal)bo).config().getInternalConfigMap(); - Map<ConfigKey<?>,Object> ownConfig = ((AbstractConfigMapImpl)configMap).ownConfig; - Maybe<Object> rawValue = configMap.getConfigLocalRaw(keyIgnoringInheritance); - Maybe<TValue> ownValue; - - // Get own value - if (keyIgnoringInheritance instanceof ConfigKeySelfExtracting) { - if (((ConfigKeySelfExtracting<TValue>)keyIgnoringInheritance).isSet(ownConfig)) { - Map<ConfigKey<?>, ?> ownCopy; - synchronized (ownConfig) { - // wasteful to make a copy to look up; maybe try once opportunistically? - ownCopy = MutableMap.copyOf(ownConfig); - } - ownValue = Maybe.of(((ConfigKeySelfExtracting<TValue>) keyIgnoringInheritance).extractValue(ownCopy, exec)); - } else { - ownValue = Maybe.<TValue>absent(); - } - } else { - // all our keys are self-extracting - LOG.warn("Unexpected key type "+keyIgnoringInheritance+" ("+keyIgnoringInheritance.getClass()+") in "+bo+"; ignoring value"); - ownValue = Maybe.<TValue>absent(); - } - - postLocalEvaluate(keyIgnoringInheritance, bo, rawValue, ownValue); - return ownValue; - } + @Override + public Map<ConfigKey<?>,Object> getAllConfigLocalRaw() { + Map<ConfigKey<?>,Object> result = new LinkedHashMap<ConfigKey<?>,Object>(); + result.putAll(ownConfig); + return Collections.unmodifiableMap(result); } - /** an immutable copy of the config defined at this entity, ie not inherited */ - public Map<ConfigKey<?>,Object> getLocalConfig() { - Map<ConfigKey<?>,Object> result = new LinkedHashMap<ConfigKey<?>,Object>(ownConfig.size()); + /** an immutable copy of the config visible at this entity, local and inherited (preferring local) */ + @Override @Deprecated + public Map<ConfigKey<?>,Object> getAllConfig() { + Map<ConfigKey<?>,Object> result = new LinkedHashMap<ConfigKey<?>,Object>(); + if (getParent()!=null) + result.putAll( getParentInternal().config().getInternalConfigMap().getAllConfig() ); result.putAll(ownConfig); return Collections.unmodifiableMap(result); } - - /** Creates an immutable copy of the config defined at this entity, ie not inherited, including those that did not match config keys */ + + /** Creates an immutable copy of the config visible at this entity, local and inherited (preferring local), including those that did not match config keys */ + @Deprecated + public ConfigBag getAllConfigBag() { + ConfigBag result = ConfigBag.newInstance().putAll(ownConfig); + if (getParent()!=null) { + result.putIfAbsent( + ((AbstractConfigMapImpl<?>)getParentInternal().config().getInternalConfigMap()).getAllConfigBag() ); + } + return result.seal(); + } + + /** As {@link #getLocalConfigRaw()} but in a {@link ConfigBag} for convenience */ public ConfigBag getLocalConfigBag() { return ConfigBag.newInstance().putAll(ownConfig).seal(); } @@ -170,7 +169,7 @@ public abstract class AbstractConfigMapImpl implements ConfigMap { } @SuppressWarnings("unchecked") - public void addToLocalBag(Map<?,?> vals) { + public void putAll(Map<?,?> vals) { // ConfigBag ownConfigBag = ConfigBag.newInstance().putAll(vals); // ownConfig.putAll(ownConfigBag.getAllConfigAsConfigKeyMap()); // below seems more straightforward; should be the same. @@ -188,45 +187,30 @@ public abstract class AbstractConfigMapImpl implements ConfigMap { } } - public void removeFromLocalBag(String key) { - // previously removed the string (?) + public void removeKey(String key) { ownConfig.remove(ConfigKeys.newConfigKey(Object.class, key)); } - public void removeFromLocalBag(ConfigKey<?> key) { + public void removeKey(ConfigKey<?> key) { ownConfig.remove(key); } - protected abstract BrooklynObjectInternal getParent(); - - @Override + protected final TContainer getParent() { + return getParentOfContainer(getContainer()); + } + + protected final BrooklynObjectInternal getParentInternal() { + return (BrooklynObjectInternal) getParent(); + } + + @Override @Deprecated public Maybe<Object> getConfigRaw(ConfigKey<?> key, boolean includeInherited) { - // TODO does not currently respect inheritance modes + // does not currently respect inheritance modes if (ownConfig.containsKey(key)) return Maybe.of(ownConfig.get(key)); if (!includeInherited || getParent()==null) return Maybe.absent(); - return getParent().config().getInternalConfigMap().getConfigRaw(key, includeInherited); + return getParentInternal().config().getInternalConfigMap().getConfigRaw(key, includeInherited); } - /** an immutable copy of the config visible at this entity, local and inherited (preferring local) */ - // TODO deprecate because key inheritance not respected - public Map<ConfigKey<?>,Object> getAllConfig() { - Map<ConfigKey<?>,Object> result = new LinkedHashMap<ConfigKey<?>,Object>(); - if (getParent()!=null) - result.putAll( getParent().config().getInternalConfigMap().getAllConfig() ); - result.putAll(ownConfig); - return Collections.unmodifiableMap(result); - } - - /** Creates an immutable copy of the config visible at this entity, local and inherited (preferring local), including those that did not match config keys */ - // TODO deprecate because key inheritance not respected - public ConfigBag getAllConfigBag() { - ConfigBag result = ConfigBag.newInstance().putAll(ownConfig); - if (getParent()!=null) { - result.putIfAbsent( - ((AbstractConfigMapImpl)getParent().config().getInternalConfigMap()).getAllConfigBag() ); - } - return result.seal(); - } protected Object coerceConfigVal(ConfigKey<?> key, Object v) { if ((v instanceof Future) || (v instanceof DeferredSupplier)) { // no coercion for these (coerce on exit) @@ -269,6 +253,219 @@ public abstract class AbstractConfigMapImpl implements ConfigMap { return ownConfig.isEmpty(); } + protected ConfigInheritance getDefaultRuntimeInheritance() { + return BasicConfigInheritance.OVERWRITE; + } + + public <T> ReferenceWithError<ConfigValueAtContainer<TContainer,T>> getConfigAndContainer(ConfigKey<T> key) { + return getConfigImpl(key, false); + } + + protected abstract TContainer getParentOfContainer(TContainer container); + + @Nullable protected final <T> ConfigKey<T> getKeyAtContainer(TContainer container, ConfigKey<T> queryKey) { + if (container==null) return null; + @SuppressWarnings("unchecked") + ConfigKey<T> candidate = (ConfigKey<T>) getKeyAtContainerImpl(container, queryKey); + return candidate; + } + + @Nullable protected abstract <T> ConfigKey<?> getKeyAtContainerImpl(@Nonnull TContainer container, ConfigKey<T> queryKey); + + protected Maybe<Object> getRawValueAtContainer(TContainer container, ConfigKey<? extends Object> configKey) { + return ((BrooklynObjectInternal)container).config().getInternalConfigMap().getConfigLocalRaw(configKey); + } + protected Maybe<Object> resolveRawValueFromContainer(TContainer container, ConfigKey<?> key, Object value) { + Map<ConfigKey<?>, Object> oc = ((AbstractConfigMapImpl<?>) ((BrooklynObjectInternal)container).config().getInternalConfigMap()).ownConfig; + if (key instanceof ConfigKeySelfExtracting) { + if (((ConfigKeySelfExtracting<?>)key).isSet(oc)) { + Map<ConfigKey<?>, ?> ownCopy; + synchronized (oc) { + // wasteful to make a copy to look up; maybe try once opportunistically? + ownCopy = MutableMap.copyOf(oc); + } + return Maybe.of((Object) ((ConfigKeySelfExtracting<?>) key).extractValue(ownCopy, getExecutionContext(container)) ); + } else { + return Maybe.absent(); + } + } else { + // all our keys are self-extracting + LOG.warn("Unexpected key type "+key+" ("+key.getClass()+") in "+bo+"; ignoring value"); + return Maybe.absent(); + } + } + + @SuppressWarnings("unchecked") + protected <T> T coerce(Object value, Class<T> type) { + if (type==null || value==null) return (T) value; + return (T) TypeCoercions.coerce(value, type); + } + + protected <T> ReferenceWithError<ConfigValueAtContainer<TContainer,T>> getConfigImpl(final ConfigKey<T> queryKey, final boolean raw) { + // In case this entity class has overridden the given key (e.g. to set default), then retrieve this entity's key + Function<TContainer, ConfigKey<T>> keyFn = new Function<TContainer, ConfigKey<T>>() { + @Override public ConfigKey<T> apply(TContainer input) { + // should return null if the key is not known, to indicate selected inheritance rules from base key should take effect + return getKeyAtContainer(input, queryKey); + } + }; + ConfigKey<T> ownKey = keyFn.apply(getContainer()); + if (ownKey==null) ownKey = queryKey; + @SuppressWarnings("unchecked") + final Class<T> type = (Class<T>) ownKey.getType(); + + // takes type of own key (or query key if own key not available) + // takes default of own key if available and has default, else of query key + + Function<Maybe<Object>, Maybe<T>> coerceFn = new Function<Maybe<Object>, Maybe<T>>() { + @SuppressWarnings("unchecked") @Override public Maybe<T> apply(Maybe<Object> input) { + if (raw || input==null || input.isAbsent()) return (Maybe<T>)input; + return Maybe.ofAllowingNull(coerce(input.get(), type)); + } + }; + // prefer default and type of ownKey + Maybe<T> defaultValue = raw ? Maybe.<T>absent() : + ownKey.hasDefaultValue() ? coerceFn.apply(Maybe.of((Object)ownKey.getDefaultValue())) : + queryKey.hasDefaultValue() ? coerceFn.apply(Maybe.of((Object)queryKey.getDefaultValue())) : + Maybe.<T>absent(); + + if (ownKey instanceof ConfigKeySelfExtracting) { + + Function<TContainer, Maybe<Object>> lookupFn = new Function<TContainer, Maybe<Object>>() { + @Override public Maybe<Object> apply(TContainer input) { + Maybe<Object> result = getRawValueAtContainer(input, queryKey); + if (!raw) result = resolveRawValueFromContainer(input, queryKey, result); + return result; + } + }; + Function<TContainer, TContainer> parentFn = new Function<TContainer, TContainer>() { + @Override public TContainer apply(TContainer input) { + return getParentOfContainer(input); + } + }; + AncestorContainerAndKeyValueIterator<TContainer, T> ckvi = new AncestorContainerAndKeyValueIterator<TContainer,T>( + getContainer(), keyFn, lookupFn, coerceFn, parentFn); + + return ConfigInheritances.resolveInheriting( + getContainer(), ownKey, coerceFn.apply(lookupFn.apply(getContainer())), defaultValue, + ckvi, InheritanceContext.RUNTIME_MANAGEMENT, getDefaultRuntimeInheritance()); + + } else { + String message = "Config key "+ownKey+" of "+getBrooklynObject()+" is not a ConfigKeySelfExtracting; cannot retrieve value; returning default"; + LOG.warn(message); + return ReferenceWithError.newInstanceThrowingError(new BasicConfigValueAtContainer<TContainer,T>(getContainer(), ownKey, null, false, + defaultValue), + new IllegalStateException(message)); + } + } + + public List<ConfigValueAtContainer<TContainer,?>> getConfigAllInheritedRaw(ConfigKey<?> queryKey) { + List<ConfigValueAtContainer<TContainer, ?>> result = MutableList.of(); + TContainer c = getContainer(); + int count=0; + + final InheritanceContext context = InheritanceContext.RUNTIME_MANAGEMENT; + ConfigInheritance currentInheritance = ConfigInheritances.findInheritance(queryKey, context, getDefaultRuntimeInheritance()); + + BasicConfigValueAtContainer<TContainer, Object> last = null; + + while (c!=null) { + Maybe<Object> v = getRawValueAtContainer(c, queryKey); + BasicConfigValueAtContainer<TContainer, Object> next = new BasicConfigValueAtContainer<TContainer, Object>(c, getKeyAtContainer(c, queryKey), v); + + if (last!=null && !currentInheritance.considerParent(last, next, context)) break; + + currentInheritance = ConfigInheritances.findInheritance(next.getKey(), InheritanceContext.RUNTIME_MANAGEMENT, currentInheritance); + if (count>0 && !currentInheritance.isReinheritable(next, context)) break; + + if (next.isValueExplicitlySet()) result.add(0, next); + + last = next; + c = getParentOfContainer(c); + } + + return result; + } + + @Override + public Set<ConfigKey<?>> findKeys(Predicate<ConfigKey<?>> filter) { + MutableSet<ConfigKey<?>> result = MutableSet.of(); + result.addAll(Iterables.filter(ownConfig.keySet(), filter)); + // due to set semantics local should be added first, it prevents equal items from parent from being added on top + if (getParent()!=null) { + result.addAll( getParentInternal().config().getInternalConfigMap().findKeys(filter) ); + } + return result; + } + + @SuppressWarnings("unchecked") + public ReferenceWithError<ConfigValueAtContainer<TContainer,?>> getConfigInheritedRaw(ConfigKey<?> key) { + return (ReferenceWithError<ConfigValueAtContainer<TContainer,?>>) (ReferenceWithError<?>) getConfigImpl(key, true); + } + + @Override + public Map<ConfigKey<?>, Object> getAllConfigInheritedRawValuesIgnoringErrors() { + Map<ConfigKey<?>, ReferenceWithError<ConfigValueAtContainer<TContainer, ?>>> input = getAllConfigInheritedRawWithErrors(); + Map<ConfigKey<?>, Object> result = MutableMap.of(); + for (Map.Entry<ConfigKey<?>, ReferenceWithError<ConfigValueAtContainer<TContainer, ?>>> pair: input.entrySet()) { + result.put(pair.getKey(), pair.getValue().getWithoutError().get()); + } + return result; + } + @Override + public Map<ConfigKey<?>, ReferenceWithError<ConfigValueAtContainer<TContainer, ?>>> getAllConfigInheritedRawWithErrors() { + return getSelectedConfigInheritedRaw(false); + } + + public Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>> getAllReinheritableConfigRaw() { + return getSelectedConfigInheritedRaw(true); + } + + protected Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>> getSelectedConfigInheritedRaw(boolean onlyReinheritable) { + Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>> parents = MutableMap.of(); + if (getParent()!=null) { + @SuppressWarnings("unchecked") + Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>> po = (Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>>) (Map<?,?>) + getParentInternal().config().getInternalConfigMap().getAllReinheritableConfigRaw(); + parents.putAll(po); + } + + Map<ConfigKey<?>, Object> local = getAllConfigLocalRaw(); + + Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>> result = MutableMap.of(); + + for (ConfigKey<?> k: local.keySet()) { + Object v = local.get(k); + ReferenceWithError<ConfigValueAtContainer<TContainer, ?>> vpr = parents.remove(k); + @SuppressWarnings("unchecked") + ConfigValueAtContainer<TContainer, Object> vp = vpr==null ? null : (ConfigValueAtContainer<TContainer,Object>) vpr.getWithoutError(); + ConfigInheritance inh = ConfigInheritances.findInheritance(k, InheritanceContext.RUNTIME_MANAGEMENT, getDefaultRuntimeInheritance()); + ConfigValueAtContainer<TContainer,Object> vl = new BasicConfigValueAtContainer<TContainer,Object>(getContainer(), k, Maybe.ofAllowingNull(v)); + ReferenceWithError<ConfigValueAtContainer<TContainer, Object>> vlr = null; + if (inh.considerParent(vl, vp, InheritanceContext.RUNTIME_MANAGEMENT)) { + vlr = inh.resolveWithParent(vl, vp, InheritanceContext.RUNTIME_MANAGEMENT); + } else { + // no need to consider parent, just take vl + vlr = ReferenceWithError.newInstanceWithoutError(vl); + } + if (onlyReinheritable) { + if (ConfigInheritances.findInheritance(k, InheritanceContext.RUNTIME_MANAGEMENT, getDefaultRuntimeInheritance()) + .isReinheritable(vl, InheritanceContext.RUNTIME_MANAGEMENT)) { + // continue + } else { + // skip this one + continue; + } + } + @SuppressWarnings("unchecked") + ReferenceWithError<ConfigValueAtContainer<TContainer, ?>> vlro = (ReferenceWithError<ConfigValueAtContainer<TContainer, ?>>) (ReferenceWithError<?>) vlr; + result.put(k, vlro); + } + result.putAll(parents); + + return result; + } + @Override public String toString() { Map<ConfigKey<?>, Object> sanitizeConfig; http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/config/internal/AncestorContainerAndKeyValueIterator.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/config/internal/AncestorContainerAndKeyValueIterator.java b/core/src/main/java/org/apache/brooklyn/core/config/internal/AncestorContainerAndKeyValueIterator.java index 62fb970..f20f0d0 100644 --- a/core/src/main/java/org/apache/brooklyn/core/config/internal/AncestorContainerAndKeyValueIterator.java +++ b/core/src/main/java/org/apache/brooklyn/core/config/internal/AncestorContainerAndKeyValueIterator.java @@ -30,16 +30,19 @@ import com.google.common.base.Function; public class AncestorContainerAndKeyValueIterator<TContainer,TValue> implements Iterator<ConfigValueAtContainer<TContainer,TValue>> { private TContainer lastContainer; private final Function<TContainer, ConfigKey<TValue>> keyFindingFunction; - private final Function<TContainer, Maybe<TValue>> localEvaluationFunction; + private final Function<TContainer, Maybe<Object>> lookupResolutionFunction; + private final Function<Maybe<Object>, Maybe<TValue>> coercionFunction; private final Function<TContainer, TContainer> parentFunction; public AncestorContainerAndKeyValueIterator(TContainer childContainer, Function<TContainer, ConfigKey<TValue>> keyFindingFunction, - Function<TContainer, Maybe<TValue>> localEvaluationFunction, + Function<TContainer, Maybe<Object>> lookupResolutionFunction, + Function<Maybe<Object>, Maybe<TValue>> coercionFunction, Function<TContainer, TContainer> parentFunction) { this.lastContainer = childContainer; this.keyFindingFunction = keyFindingFunction; - this.localEvaluationFunction = localEvaluationFunction; + this.lookupResolutionFunction = lookupResolutionFunction; + this.coercionFunction = coercionFunction; this.parentFunction = parentFunction; } @@ -53,7 +56,8 @@ public class AncestorContainerAndKeyValueIterator<TContainer,TValue> implements TContainer nextContainer = parentFunction.apply(lastContainer); if (nextContainer==null) throw new NoSuchElementException("Cannot search ancestors further than "+lastContainer); lastContainer = nextContainer; - return new LazyContainerAndKeyValue<TContainer,TValue>(keyFindingFunction.apply(lastContainer), lastContainer, localEvaluationFunction); + return new LazyContainerAndKeyValue<TContainer,TValue>(keyFindingFunction.apply(lastContainer), lastContainer, + lookupResolutionFunction, coercionFunction); } @Override http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/config/internal/BasicConfigValueAtContainer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/config/internal/BasicConfigValueAtContainer.java b/core/src/main/java/org/apache/brooklyn/core/config/internal/BasicConfigValueAtContainer.java deleted file mode 100644 index 79041d4..0000000 --- a/core/src/main/java/org/apache/brooklyn/core/config/internal/BasicConfigValueAtContainer.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.brooklyn.core.config.internal; - -import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.config.ConfigValueAtContainer; -import org.apache.brooklyn.util.guava.Maybe; - -public class BasicConfigValueAtContainer<TContainer,TValue> implements ConfigValueAtContainer<TContainer,TValue> { - - TContainer container = null; - Maybe<TValue> value = Maybe.absent(); - boolean valueWasExplicitlySet; - ConfigKey<TValue> key = null; - - @Override public TContainer getContainer() { return container; } - @Override public TValue get() { return value.orNull(); } - @Override public Maybe<TValue> asMaybe() { return value; } - @Override public boolean isValueExplicitlySet() { return valueWasExplicitlySet; } - @Override public ConfigKey<TValue> getKey() { return key; } - @Override public TValue getDefaultValue() { return getDefaultValueMaybe().orNull(); } - - public void setContainer(TContainer container) { - this.container = container; - } - public void setValue(Maybe<TValue> value) { - this.value = value; - } - public void setValueWasExplicitlySet(boolean valueWasExplicitlySet) { - this.valueWasExplicitlySet = valueWasExplicitlySet; - } - public void setKey(ConfigKey<TValue> key) { - this.key = key; - } - - public Maybe<TValue> getDefaultValueMaybe() { return key!=null && key.hasDefaultValue() ? Maybe.ofAllowingNull(key.getDefaultValue()) : Maybe.<TValue>absent(); } - -} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/config/internal/LazyContainerAndKeyValue.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/config/internal/LazyContainerAndKeyValue.java b/core/src/main/java/org/apache/brooklyn/core/config/internal/LazyContainerAndKeyValue.java index df11735..fec13af 100644 --- a/core/src/main/java/org/apache/brooklyn/core/config/internal/LazyContainerAndKeyValue.java +++ b/core/src/main/java/org/apache/brooklyn/core/config/internal/LazyContainerAndKeyValue.java @@ -28,18 +28,23 @@ public class LazyContainerAndKeyValue<TContainer,TValue> implements ConfigValueA private final TContainer container; private final ConfigKey<TValue> key; - private final Function<TContainer,Maybe<TValue>> evaluationFunction; + private final Function<TContainer,Maybe<Object>> lookupResolutionFunction; + private final Function<Maybe<Object>,Maybe<TValue>> conversionFunction; private Maybe<TValue> resolved; - public LazyContainerAndKeyValue(ConfigKey<TValue> key, TContainer container, Function<TContainer, Maybe<TValue>> evaluationFunction) { + public LazyContainerAndKeyValue(ConfigKey<TValue> key, TContainer container, + Function<TContainer, Maybe<Object>> lookupResolutionFunction, + Function<Maybe<Object>, Maybe<TValue>> conversionFunction) { this.key = key; this.container = container; - this.evaluationFunction = evaluationFunction; + this.lookupResolutionFunction = lookupResolutionFunction; + this.conversionFunction = conversionFunction; } protected synchronized Maybe<TValue> resolve() { if (resolved==null) { - resolved = evaluationFunction.apply(getContainer()); + resolved = conversionFunction.apply( + lookupResolutionFunction.apply(getContainer())); } return resolved; } @@ -52,13 +57,13 @@ public class LazyContainerAndKeyValue<TContainer,TValue> implements ConfigValueA @Override public TValue get() { if (resolve().isPresent()) return resolve().get(); - return getDefaultValue(); + return getDefaultValue().orNull(); } @Override public Maybe<TValue> asMaybe() { if (resolve().isPresent()) return resolve(); - return getDefaultValueMaybe(); + return getDefaultValue(); } @Override @@ -72,12 +77,8 @@ public class LazyContainerAndKeyValue<TContainer,TValue> implements ConfigValueA } @Override - public TValue getDefaultValue() { - return getDefaultValueMaybe().orNull(); - } - - public Maybe<TValue> getDefaultValueMaybe() { + public Maybe<TValue> getDefaultValue() { if (key==null || !key.hasDefaultValue()) return Maybe.absent(); - return Maybe.of(key.getDefaultValue()); + return conversionFunction.apply(Maybe.of((Object)key.getDefaultValue())); } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java b/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java index 29c1480..1f46314 100644 --- a/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java +++ b/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java @@ -20,6 +20,7 @@ package org.apache.brooklyn.core.effector.ssh; import java.util.List; import java.util.Map; +import java.util.Set; import javax.annotation.Nullable; @@ -30,17 +31,16 @@ import org.apache.brooklyn.api.mgmt.Task; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.config.StringConfigMap; import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.config.ConfigPredicates; import org.apache.brooklyn.core.config.ConfigUtils; import org.apache.brooklyn.core.effector.EffectorBody; import org.apache.brooklyn.core.effector.EffectorTasks; import org.apache.brooklyn.core.effector.EffectorTasks.EffectorTaskFactory; -import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks; import org.apache.brooklyn.core.entity.EntityInternal; import org.apache.brooklyn.core.location.internal.LocationInternal; import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.apache.brooklyn.location.ssh.SshMachineLocation; +import org.apache.brooklyn.util.collections.MutableSet; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.internal.ssh.SshTool; import org.apache.brooklyn.util.core.task.Tasks; @@ -53,7 +53,10 @@ import org.apache.brooklyn.util.core.task.ssh.internal.AbstractSshExecTaskFactor import org.apache.brooklyn.util.core.task.ssh.internal.PlainSshExecTaskFactory; import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory; import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; +import org.apache.brooklyn.util.guava.Maybe; import org.apache.brooklyn.util.ssh.BashCommands; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.annotations.Beta; import com.google.common.base.Function; @@ -291,42 +294,42 @@ public class SshEffectorTasks { * the SshTool is created or re-used by the SshMachineLocation making use of these properties */ @Beta public static Map<String, Object> getSshFlags(Entity entity, Location optionalLocation) { - ConfigBag allConfig = ConfigBag.newInstance(); + Set<ConfigKey<?>> sshConfig = MutableSet.of(); - StringConfigMap globalConfig = ((EntityInternal)entity).getManagementContext().getConfig(); - allConfig.putAll(globalConfig.getAllConfig()); + sshConfig.addAll(((EntityInternal)entity).config().findKeys(ConfigPredicates.nameStartsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX))); if (optionalLocation!=null) - allConfig.putAll(((LocationInternal)optionalLocation).config().getBag()); + sshConfig.addAll(optionalLocation.config().findKeys(ConfigPredicates.nameStartsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX))); - allConfig.putAll(((EntityInternal)entity).config().getBag()); + StringConfigMap globalConfig = ((EntityInternal)entity).getManagementContext().getConfig(); + sshConfig.addAll(globalConfig.findKeys(ConfigPredicates.nameStartsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX))); Map<String, Object> result = Maps.newLinkedHashMap(); - for (String keyS : allConfig.getAllConfig().keySet()) { - if (keyS.startsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX)) { - ConfigKey<?> key = ConfigKeys.newConfigKey(Object.class, keyS); - - Object val = allConfig.getStringKey(keyS); - - /* - * NOV 2013 changing this to rely on config above being inserted in the right order, - * so entity config will be preferred over location, and location over global. - * If that is consistent then remove the lines below. - * (We can also accept null entity and so combine with SshTasks.getSshFlags.) - */ - -// // have to use raw config to test whether the config is set -// Object val = ((EntityInternal)entity).getConfigMap().getRawConfig(key); -// if (val!=null) { -// val = entity.getConfig(key); -// } else { -// val = globalConfig.getRawConfig(key); -// if (val!=null) val = globalConfig.getConfig(key); -// } -// if (val!=null) { - result.put(ConfigUtils.unprefixedKey(SshTool.BROOKLYN_CONFIG_KEY_PREFIX, key).getName(), val); -// } + for (ConfigKey<?> key : sshConfig) { + /* + * Rely on config in the right order: + * entity config will be preferred over location, and location over global. + * (We can also accept null entity and so combine with SshTasks.getSshFlags.) + */ + + Maybe<Object> mv = ((EntityInternal)entity).config().getRaw(key); + Object v = null; + if (v==null && mv.isPresent()) { + v = entity.config().get(key); + } + + if (mv.isAbsent() && optionalLocation!=null) { + mv = ((LocationInternal)optionalLocation).config().getRaw(key); + } + if (v==null && mv.isPresent()) { + v = optionalLocation.config().get(key); + } + + if (mv.isAbsent()) { + v = globalConfig.getConfig(key); } + + result.put(ConfigUtils.unprefixedKey(SshTool.BROOKLYN_CONFIG_KEY_PREFIX, key).getName(), v); } return result; } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java index 8ba1bc3..6c5f73e 100644 --- a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java +++ b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java @@ -408,7 +408,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E if (!flags.isEmpty()) { LOG.warn("Unsupported flags when configuring {}; storing: {}", this, flags); - configsInternal.addToLocalBag(flags); + configsInternal.putAll(flags); } return this; @@ -542,8 +542,8 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E if (iconUrl.isNull()) iconUrl.set(oldIconUrl); configsInternal = new EntityConfigMap(this, managementContext.getStorage().<ConfigKey<?>, Object>getMap(getId()+"-config")); - if (oldConfig.getLocalConfig().size() > 0) { - configsInternal.setLocalConfig(oldConfig.getLocalConfig()); + if (!oldConfig.isEmpty()) { + configsInternal.setLocalConfig(oldConfig.getAllConfigLocalRaw()); } config().refreshInheritedConfig(); @@ -1212,7 +1212,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E ConfigConstraints.assertValid(AbstractEntity.this, key, val); } - protected AbstractConfigMapImpl getConfigsInternal() { + protected AbstractConfigMapImpl<?> getConfigsInternal() { return configsInternal; } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/entity/internal/ConfigMapViewWithStringKeys.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/internal/ConfigMapViewWithStringKeys.java b/core/src/main/java/org/apache/brooklyn/core/entity/internal/ConfigMapViewWithStringKeys.java index 7d91af4..38f83c7 100644 --- a/core/src/main/java/org/apache/brooklyn/core/entity/internal/ConfigMapViewWithStringKeys.java +++ b/core/src/main/java/org/apache/brooklyn/core/entity/internal/ConfigMapViewWithStringKeys.java @@ -24,21 +24,23 @@ import java.util.Map; import java.util.Set; import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.config.ConfigMap; import org.apache.brooklyn.core.config.BasicConfigKey; -import com.google.common.annotations.Beta; import com.google.common.collect.Sets; /** * Internal class that presents a view over a ConfigMap, so it looks like a Map (with the * keys being the config key names). + * + * @deprecated since 0.10.0 removed support, no longer needed */ -@Beta +@Deprecated public class ConfigMapViewWithStringKeys implements Map<String,Object> { - private org.apache.brooklyn.config.ConfigMap target; + private ConfigMap target; - public ConfigMapViewWithStringKeys(org.apache.brooklyn.config.ConfigMap target) { + public ConfigMapViewWithStringKeys(ConfigMap target) { this.target = target; } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/entity/internal/EntityConfigMap.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/internal/EntityConfigMap.java b/core/src/main/java/org/apache/brooklyn/core/entity/internal/EntityConfigMap.java index 15f8ffa..400694e 100644 --- a/core/src/main/java/org/apache/brooklyn/core/entity/internal/EntityConfigMap.java +++ b/core/src/main/java/org/apache/brooklyn/core/entity/internal/EntityConfigMap.java @@ -26,28 +26,20 @@ import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.mgmt.ExecutionContext; import org.apache.brooklyn.api.mgmt.Task; import org.apache.brooklyn.api.objs.BrooklynObject; -import org.apache.brooklyn.config.ConfigInheritance; import org.apache.brooklyn.config.ConfigKey; -import org.apache.brooklyn.config.ConfigValueAtContainer; -import org.apache.brooklyn.core.config.BasicConfigInheritance; -import org.apache.brooklyn.core.config.BasicConfigInheritance.AncestorContainerAndKeyValueIterator; -import org.apache.brooklyn.core.config.ConfigKeys.InheritanceContext; import org.apache.brooklyn.core.config.internal.AbstractConfigMapImpl; -import org.apache.brooklyn.core.entity.EntityFunctions; import org.apache.brooklyn.core.entity.EntityInternal; -import org.apache.brooklyn.core.objs.BrooklynObjectInternal; import org.apache.brooklyn.core.objs.BrooklynObjectInternal.ConfigurationSupportInternal; -import org.apache.brooklyn.util.core.internal.ConfigKeySelfExtracting; import org.apache.brooklyn.util.guava.Maybe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.Maps; -public class EntityConfigMap extends AbstractConfigMapImpl { +public class EntityConfigMap extends AbstractConfigMapImpl<Entity> { + @SuppressWarnings("unused") private static final Logger LOG = LoggerFactory.getLogger(EntityConfigMap.class); public EntityConfigMap(EntityInternal entity) { @@ -62,17 +54,17 @@ public class EntityConfigMap extends AbstractConfigMapImpl { * @deprecated since 0.10.0 kept for serialization */ @Deprecated private EntityInternal entity; @Override - public BrooklynObjectInternal getBrooklynObject() { - BrooklynObjectInternal result = super.getBrooklynObject(); - if (result!=null) return result; + public EntityInternal getContainer() { + Entity result = super.getContainer(); + if (result!=null) return (EntityInternal) result; synchronized (this) { - result = super.getBrooklynObject(); - if (result!=null) return result; + result = super.getContainer(); + if (result!=null) return (EntityInternal) result; bo = entity; entity = null; } - return super.getBrooklynObject(); + return (EntityInternal) super.getBrooklynObject(); } protected EntityInternal getEntity() { @@ -99,45 +91,19 @@ public class EntityConfigMap extends AbstractConfigMapImpl { ((EntityInternal)bo).getManagementSupport().getEntityChangeListener().onConfigChanged(key); } } - - @Override - protected <T> Maybe<T> getConfigImpl(ConfigKey<T> key) { - Function<Entity, ConfigKey<T>> keyFn = EntityFunctions.configKeyFinder(key, null); - - // In case this entity class has overridden the given key (e.g. to set default), then retrieve this entity's key - ConfigKey<T> ownKey = keyFn.apply(getEntity()); - if (ownKey==null) ownKey = key; - LocalEvaluateKeyValue<Entity,T> evalFn = new LocalEvaluateKeyValue<Entity,T>(ownKey); - - if (ownKey instanceof ConfigKeySelfExtracting) { - Maybe<T> ownExplicitValue = evalFn.apply(getEntity()); - - AncestorContainerAndKeyValueIterator<Entity, T> ckvi = new AncestorContainerAndKeyValueIterator<Entity,T>( - getEntity(), keyFn, evalFn, EntityFunctions.parent()); - - ConfigValueAtContainer<Entity,T> result = getDefaultRuntimeInheritance().resolveInheriting(ownKey, - ownExplicitValue, getEntity(), - ckvi, InheritanceContext.RUNTIME_MANAGEMENT); - - return result.asMaybe(); - } else { - LOG.warn("Config key {} of {} is not a ConfigKeySelfExtracting; cannot retrieve value; returning default", ownKey, getBrooklynObject()); - return Maybe.absent(); - } - } - - private ConfigInheritance getDefaultRuntimeInheritance() { - return BasicConfigInheritance.OVERWRITE; + @Override + protected Entity getParentOfContainer(Entity container) { + if (container==null) return null; + return container.getParent(); } @Override - protected BrooklynObjectInternal getParent() { - return (EntityInternal) getEntity().getParent(); + protected <T> ConfigKey<?> getKeyAtContainerImpl(Entity container, ConfigKey<T> queryKey) { + return container.getEntityType().getConfigKey(queryKey.getName()); } - - @Override - // TODO deprecate or clarify syntax + + @Override @Deprecated public EntityConfigMap submap(Predicate<ConfigKey<?>> filter) { EntityConfigMap m = new EntityConfigMap(getEntity(), Maps.<ConfigKey<?>, Object>newLinkedHashMap()); synchronized (ownConfig) { @@ -153,9 +119,10 @@ public class EntityConfigMap extends AbstractConfigMapImpl { return m; } + @Deprecated private void merge(EntityConfigMap local, EntityConfigMap parent) { for (ConfigKey<?> k: parent.ownConfig.keySet()) { - // TODO apply inheritance + // should apply inheritance; but only used in submap which is deprecated if (!local.ownConfig.containsKey(k)) { local.ownConfig.put(k, parent.ownConfig.get(k)); } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynPropertiesImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynPropertiesImpl.java b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynPropertiesImpl.java index 9ed6a17..03fb13d 100644 --- a/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynPropertiesImpl.java +++ b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynPropertiesImpl.java @@ -19,7 +19,6 @@ package org.apache.brooklyn.core.internal; import static com.google.common.base.Preconditions.checkNotNull; -import groovy.lang.Closure; import java.io.File; import java.io.FileInputStream; @@ -29,9 +28,11 @@ import java.io.InputStream; import java.net.URL; import java.util.Arrays; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Map; import java.util.NoSuchElementException; import java.util.Properties; +import java.util.Set; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.config.ConfigKey.HasConfigKey; @@ -54,6 +55,8 @@ import com.google.common.base.Predicate; import com.google.common.base.Throwables; import com.google.common.collect.Maps; +import groovy.lang.Closure; + /** * TODO methods in this class are not thread safe. * intention is that they are set during startup and not modified thereafter. @@ -455,13 +458,29 @@ public class BrooklynPropertiesImpl extends LinkedHashMap implements BrooklynPro } @Override - public Map<ConfigKey<?>, Object> getAllConfig() { + public Map<ConfigKey<?>,Object> getAllConfigLocalRaw() { Map<ConfigKey<?>, Object> result = new LinkedHashMap<ConfigKey<?>, Object>(); for (Object entry: entrySet()) result.put(new BasicConfigKey<Object>(Object.class, ""+((Map.Entry)entry).getKey()), ((Map.Entry)entry).getValue()); return result; } + @Override @Deprecated + public Map<ConfigKey<?>, Object> getAllConfig() { + return getAllConfigLocalRaw(); + } + + @Override + public Set<ConfigKey<?>> findKeys(Predicate<ConfigKey<?>> filter) { + Set<ConfigKey<?>> result = new LinkedHashSet<ConfigKey<?>>(); + for (Object entry: entrySet()) { + ConfigKey<?> k = new BasicConfigKey<Object>(Object.class, ""+((Map.Entry)entry).getKey()); + if (filter.apply(k)) + result.add(new BasicConfigKey<Object>(Object.class, ""+((Map.Entry)entry).getKey())); + } + return result; + } + @Override public BrooklynPropertiesImpl submap(Predicate<ConfigKey<?>> filter) { BrooklynPropertiesImpl result = Factory.newEmpty();