http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java b/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java deleted file mode 100644 index 2af7e77..0000000 --- a/core/src/main/java/brooklyn/management/internal/BrooklynObjectManagerInternal.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.management.internal; - -import org.apache.brooklyn.api.basic.BrooklynObject; - -public interface BrooklynObjectManagerInternal<T extends BrooklynObject> { - - ManagementTransitionMode getLastManagementTransitionMode(String itemId); - void setManagementTransitionMode(T item, ManagementTransitionMode mode); - - /** - * Begins management for the given rebinded root, recursively; - * if rebinding as a read-only copy, {@link #setReadOnly(T, boolean)} should be called prior to this. - */ - void manageRebindedRoot(T item); - - void unmanage(final T e, final ManagementTransitionMode info); - -}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/CollectionChangeListener.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/CollectionChangeListener.java b/core/src/main/java/brooklyn/management/internal/CollectionChangeListener.java deleted file mode 100644 index 654debc..0000000 --- a/core/src/main/java/brooklyn/management/internal/CollectionChangeListener.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.management.internal; - -public interface CollectionChangeListener<Item> { - void onItemAdded(Item item); - void onItemRemoved(Item item); -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/EffectorUtils.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/EffectorUtils.java b/core/src/main/java/brooklyn/management/internal/EffectorUtils.java deleted file mode 100644 index fe38cb6..0000000 --- a/core/src/main/java/brooklyn/management/internal/EffectorUtils.java +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.management.internal; - -import static brooklyn.util.GroovyJavaMethods.truth; - -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; - -import org.apache.brooklyn.api.entity.Effector; -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.ParameterType; -import org.apache.brooklyn.api.management.Task; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.entity.basic.BasicParameterType; -import brooklyn.entity.basic.BrooklynTaskTags; -import brooklyn.entity.basic.EntityInternal; -import brooklyn.util.collections.MutableList; -import brooklyn.util.collections.MutableMap; -import brooklyn.util.config.ConfigBag; -import brooklyn.util.exceptions.Exceptions; -import brooklyn.util.exceptions.PropagatedRuntimeException; -import brooklyn.util.flags.TypeCoercions; -import brooklyn.util.guava.Maybe; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - -/** - * Utility methods for invoking effectors. - */ -public class EffectorUtils { - - private static final Logger log = LoggerFactory.getLogger(EffectorUtils.class); - - /** prepares arguments for an effector either accepting: - * an array, which should contain the arguments in order, optionally omitting those which have defaults defined; - * or a map, which should contain the arguments by name, again optionally omitting those which have defaults defined, - * and in this case also performing type coercion. - */ - public static Object[] prepareArgsForEffector(Effector<?> eff, Object args) { - if (args != null && args.getClass().isArray()) { - return prepareArgsForEffectorFromArray(eff, (Object[]) args); - } - if (args instanceof Map) { - return prepareArgsForEffectorFromMap(eff, (Map) args); - } - log.warn("Deprecated effector invocation style for call to "+eff+", expecting a map or an array, got: "+args); - if (log.isDebugEnabled()) { - log.debug("Deprecated effector invocation style for call to "+eff+", expecting a map or an array, got: "+args, - new Throwable("Trace for deprecated effector invocation style")); - } - return oldPrepareArgsForEffector(eff, args); - } - - /** method used for calls such as entity.effector(arg1, arg2) - * get routed here from AbstractEntity.invokeMethod */ - private static Object[] prepareArgsForEffectorFromArray(Effector<?> eff, Object args[]) { - int newArgsNeeded = eff.getParameters().size(); - if (args.length==1 && args[0] instanceof Map) { - if (newArgsNeeded!=1 || !eff.getParameters().get(0).getParameterClass().isAssignableFrom(args[0].getClass())) { - // treat a map in an array as a map passed directly (unless the method takes a single-arg map) - // this is to support effector(param1: val1) - return prepareArgsForEffectorFromMap(eff, (Map) args[0]); - } - } - return prepareArgsForEffectorAsMapFromArray(eff, args).values().toArray(new Object[0]); - } - - public static Map prepareArgsForEffectorAsMapFromArray(Effector<?> eff, Object args[]) { - int newArgsNeeded = eff.getParameters().size(); - List l = Lists.newArrayList(); - l.addAll(Arrays.asList(args)); - Map newArgs = new LinkedHashMap(); - - for (int index = 0; index < eff.getParameters().size(); index++) { - ParameterType<?> it = eff.getParameters().get(index); - - if (l.size() >= newArgsNeeded) { - //all supplied (unnamed) arguments must be used; ignore map - newArgs.put(it.getName(), l.remove(0)); - // TODO do we ignore arguments in the same order that groovy does? - } else if (!l.isEmpty() && it.getParameterClass().isInstance(l.get(0))) { - //if there are parameters supplied, and type is correct, they get applied before default values - //(this is akin to groovy) - newArgs.put(it.getName(), l.remove(0)); - } else if (it instanceof BasicParameterType && ((BasicParameterType)it).hasDefaultValue()) { - //finally, default values are used to make up for missing parameters - newArgs.put(it.getName(), ((BasicParameterType)it).getDefaultValue()); - } else { - throw new IllegalArgumentException("Invalid arguments (count mismatch) for effector "+eff+": "+args); - } - - newArgsNeeded--; - } - if (newArgsNeeded > 0) { - throw new IllegalArgumentException("Invalid arguments (missing "+newArgsNeeded+") for effector "+eff+": "+args); - } - if (!l.isEmpty()) { - throw new IllegalArgumentException("Invalid arguments ("+l.size()+" extra) for effector "+eff+": "+args); - } - return newArgs; - } - - private static Object[] prepareArgsForEffectorFromMap(Effector<?> eff, Map m) { - m = Maps.newLinkedHashMap(m); //make editable copy - List newArgs = Lists.newArrayList(); - int newArgsNeeded = eff.getParameters().size(); - - for (int index = 0; index < eff.getParameters().size(); index++) { - ParameterType<?> it = eff.getParameters().get(index); - Object v; - if (truth(it.getName()) && m.containsKey(it.getName())) { - // argument is in the map - v = m.remove(it.getName()); - } else if (it instanceof BasicParameterType && ((BasicParameterType)it).hasDefaultValue()) { - //finally, default values are used to make up for missing parameters - v = ((BasicParameterType)it).getDefaultValue(); - } else { - throw new IllegalArgumentException("Invalid arguments (missing argument "+it+") for effector "+eff+": "+m); - } - - newArgs.add(TypeCoercions.coerce(v, it.getParameterClass())); - newArgsNeeded--; - } - if (newArgsNeeded>0) - throw new IllegalArgumentException("Invalid arguments (missing "+newArgsNeeded+") for effector "+eff+": "+m); - return newArgs.toArray(new Object[newArgs.size()]); - } - - /** - * Takes arguments, and returns an array of arguments suitable for use by the Effector - * according to the ParameterTypes it exposes. - * <p> - * The args can be: - * <ol> - * <li>an array of ordered arguments - * <li>a collection (which will be automatically converted to an array) - * <li>a single argument (which will then be wrapped in an array) - * <li>a map containing the (named) arguments - * <li>an array or collection single entry of a map (treated same as 5 above) - * <li>a semi-populated array or collection that also containing a map as first arg - - * uses ordered args in array, but uses named values from map in preference. - * <li>semi-populated array or collection, where default values will otherwise be used. - * </ol> - */ - public static Object[] oldPrepareArgsForEffector(Effector<?> eff, Object args) { - //attempt to coerce unexpected types - Object[] argsArray; - if (args==null) { - argsArray = new Object[0]; - } else if (args.getClass().isArray()) { - argsArray = (Object[]) args; - } else { - if (args instanceof Collection) { - argsArray = ((Collection) args).toArray(new Object[((Collection) args).size()]); - } else { - argsArray = new Object[] { args }; - } - } - - //if args starts with a map, assume it contains the named arguments - //(but only use it when we have insufficient supplied arguments) - List l = Lists.newArrayList(); - l.addAll(Arrays.asList(argsArray)); - Map m = (argsArray.length > 0 && argsArray[0] instanceof Map ? Maps.newLinkedHashMap((Map) l.remove(0)) : null); - List newArgs = Lists.newArrayList(); - int newArgsNeeded = eff.getParameters().size(); - boolean mapUsed = false; - - for (int index = 0; index < eff.getParameters().size(); index++) { - ParameterType<?> it = eff.getParameters().get(index); - - if (l.size() >= newArgsNeeded) { - //all supplied (unnamed) arguments must be used; ignore map - newArgs.add(l.remove(0)); - } else if (truth(m) && truth(it.getName()) && m.containsKey(it.getName())) { - //some arguments were not supplied, and this one is in the map - newArgs.add(m.remove(it.getName())); - } else if (index == 0 && Map.class.isAssignableFrom(it.getParameterClass())) { - //if first arg is a map it takes the supplied map - newArgs.add(m); - mapUsed = true; - } else if (!l.isEmpty() && it.getParameterClass().isInstance(l.get(0))) { - //if there are parameters supplied, and type is correct, they get applied before default values - //(this is akin to groovy) - newArgs.add(l.remove(0)); - } else if (it instanceof BasicParameterType && ((BasicParameterType)it).hasDefaultValue()) { - //finally, default values are used to make up for missing parameters - newArgs.add(((BasicParameterType)it).getDefaultValue()); - } else { - throw new IllegalArgumentException("Invalid arguments (count mismatch) for effector "+eff+": "+args); - } - - newArgsNeeded--; - } - if (newArgsNeeded > 0) { - throw new IllegalArgumentException("Invalid arguments (missing "+newArgsNeeded+") for effector "+eff+": "+args); - } - if (!l.isEmpty()) { - throw new IllegalArgumentException("Invalid arguments ("+l.size()+" extra) for effector "+eff+": "+args); - } - if (truth(m) && !mapUsed) { - throw new IllegalArgumentException("Invalid arguments ("+m.size()+" extra named) for effector "+eff+": "+args); - } - return newArgs.toArray(new Object[newArgs.size()]); - } - - /** - * Invokes a method effector so that its progress is tracked. For internal use only, when we know the effector is backed by a method which is local. - */ - public static <T> T invokeMethodEffector(Entity entity, Effector<T> eff, Object[] args) { - String name = eff.getName(); - - try { - if (log.isDebugEnabled()) log.debug("Invoking effector {} on {}", new Object[] {name, entity}); - if (log.isTraceEnabled()) log.trace("Invoking effector {} on {} with args {}", new Object[] {name, entity, args}); - EntityManagementSupport mgmtSupport = ((EntityInternal)entity).getManagementSupport(); - if (!mgmtSupport.isDeployed()) { - mgmtSupport.attemptLegacyAutodeployment(name); - } - ManagementContextInternal mgmtContext = (ManagementContextInternal) ((EntityInternal) entity).getManagementContext(); - - mgmtSupport.getEntityChangeListener().onEffectorStarting(eff, args); - try { - return mgmtContext.invokeEffectorMethodSync(entity, eff, args); - } finally { - mgmtSupport.getEntityChangeListener().onEffectorCompleted(eff); - } - } catch (Exception e) { - handleEffectorException(entity, eff, e); - // (won't return below) - return null; - } - } - - public static void handleEffectorException(Entity entity, Effector<?> effector, Throwable throwable) { - String message = "Error invoking " + effector.getName() + " at " + entity; - // Avoid throwing a PropagatedRuntimeException that just repeats the last PropagatedRuntimeException. - if (throwable instanceof PropagatedRuntimeException && - throwable.getMessage() != null && - throwable.getMessage().startsWith(message)) { - throw PropagatedRuntimeException.class.cast(throwable); - } else { - log.warn(message + ": " + Exceptions.collapseText(throwable)); - throw new PropagatedRuntimeException(message, throwable); - } - } - - public static <T> Task<T> invokeEffectorAsync(Entity entity, Effector<T> eff, Map<String,?> parameters) { - String name = eff.getName(); - - if (log.isDebugEnabled()) log.debug("Invoking-async effector {} on {}", new Object[] { name, entity }); - if (log.isTraceEnabled()) log.trace("Invoking-async effector {} on {} with args {}", new Object[] { name, entity, parameters }); - EntityManagementSupport mgmtSupport = ((EntityInternal)entity).getManagementSupport(); - if (!mgmtSupport.isDeployed()) { - mgmtSupport.attemptLegacyAutodeployment(name); - } - ManagementContextInternal mgmtContext = (ManagementContextInternal) ((EntityInternal)entity).getManagementContext(); - - // FIXME seems brittle to have the listeners in the Utils method; better to move into the context.invokeEff - // (or whatever the last mile before invoking the effector is - though currently there is not such a canonical place!) - mgmtSupport.getEntityChangeListener().onEffectorStarting(eff, parameters); - try { - return mgmtContext.invokeEffector(entity, eff, parameters); - } finally { - // FIXME this is really Effector submitted - mgmtSupport.getEntityChangeListener().onEffectorCompleted(eff); - } - } - - /** @deprecated since 0.7.0, not used */ - @Deprecated - public static Effector<?> findEffectorMatching(Entity entity, Method method) { - outer: for (Effector<?> effector : entity.getEntityType().getEffectors()) { - if (!effector.getName().equals(entity)) continue; - if (effector.getParameters().size() != method.getParameterTypes().length) continue; - for (int i = 0; i < effector.getParameters().size(); i++) { - if (effector.getParameters().get(i).getParameterClass() != method.getParameterTypes()[i]) continue outer; - } - return effector; - } - return null; - } - - /** @deprecated since 0.7.0, expects parameters but does not use them! */ - @Deprecated - public static Effector<?> findEffectorMatching(Set<Effector<?>> effectors, String effectorName, Map<String, ?> parameters) { - // TODO Support overloading: check parameters as well - for (Effector<?> effector : effectors) { - if (effector.getName().equals(effectorName)) { - return effector; - } - } - return null; - } - - /** matches effectors by name only (not parameters) */ - public static Maybe<Effector<?>> findEffector(Collection<? extends Effector<?>> effectors, String effectorName) { - for (Effector<?> effector : effectors) { - if (effector.getName().equals(effectorName)) { - return Maybe.<Effector<?>>of(effector); - } - } - return Maybe.absent(new NoSuchElementException("No effector with name "+effectorName+" (contenders "+effectors+")")); - } - - /** matches effectors by name only (not parameters), based on what is declared on the entity static type */ - public static Maybe<Effector<?>> findEffectorDeclared(Entity entity, String effectorName) { - return findEffector(entity.getEntityType().getEffectors(), effectorName); - } - - /** @deprecated since 0.7.0 use {@link #getTaskFlagsForEffectorInvocation(Entity, Effector, ConfigBag)} */ - public static Map<Object,Object> getTaskFlagsForEffectorInvocation(Entity entity, Effector<?> effector) { - return getTaskFlagsForEffectorInvocation(entity, effector, null); - } - - /** returns a (mutable) map of the standard flags which should be placed on an effector */ - public static Map<Object,Object> getTaskFlagsForEffectorInvocation(Entity entity, Effector<?> effector, ConfigBag parameters) { - return MutableMap.builder() - .put("description", "Invoking effector "+effector.getName() - +" on "+entity.getDisplayName() - +(parameters!=null ? " with parameters "+parameters.getAllConfig() : "")) - .put("displayName", effector.getName()) - .put("tags", MutableList.of( - BrooklynTaskTags.EFFECTOR_TAG, - BrooklynTaskTags.tagForEffectorCall(entity, effector.getName(), parameters), - BrooklynTaskTags.tagForTargetEntity(entity))) - .build(); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/EntityChangeListener.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/EntityChangeListener.java b/core/src/main/java/brooklyn/management/internal/EntityChangeListener.java deleted file mode 100644 index 1b67d2d..0000000 --- a/core/src/main/java/brooklyn/management/internal/EntityChangeListener.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.management.internal; - -import org.apache.brooklyn.api.entity.Effector; -import org.apache.brooklyn.api.entity.Feed; -import org.apache.brooklyn.api.event.AttributeSensor; -import org.apache.brooklyn.api.policy.Enricher; -import org.apache.brooklyn.api.policy.Policy; - -import brooklyn.config.ConfigKey; - -public interface EntityChangeListener { - - // TODO for testing only! - public static final EntityChangeListener NOOP = new EntityChangeListener() { - @Override public void onChanged() {} - @Override public void onAttributeChanged(AttributeSensor<?> attribute) {} - @Override public void onConfigChanged(ConfigKey<?> key) {} - @Override public void onLocationsChanged() {} - @Override public void onMembersChanged() {} - @Override public void onTagsChanged() {} - @Override public void onChildrenChanged() {} - @Override public void onPolicyAdded(Policy policy) {} - @Override public void onPolicyRemoved(Policy policy) {} - @Override public void onEnricherAdded(Enricher enricher) {} - @Override public void onEnricherRemoved(Enricher enricher) {} - @Override public void onFeedAdded(Feed feed) {} - @Override public void onFeedRemoved(Feed feed) {} - @Override public void onEffectorStarting(Effector<?> effector, Object parameters) {} - @Override public void onEffectorCompleted(Effector<?> effector) {} - }; - - void onChanged(); - - void onAttributeChanged(AttributeSensor<?> attribute); - - void onConfigChanged(ConfigKey<?> key); - - void onLocationsChanged(); - - void onTagsChanged(); - - void onMembersChanged(); - - void onChildrenChanged(); - - void onPolicyAdded(Policy policy); - - void onPolicyRemoved(Policy policy); - - void onEnricherAdded(Enricher enricher); - - void onEnricherRemoved(Enricher enricher); - - void onFeedAdded(Feed feed); - - void onFeedRemoved(Feed feed); - - void onEffectorStarting(Effector<?> effector, Object parameters); - - void onEffectorCompleted(Effector<?> effector); -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java b/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java deleted file mode 100644 index 596c8b2..0000000 --- a/core/src/main/java/brooklyn/management/internal/EntityManagementSupport.java +++ /dev/null @@ -1,478 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.management.internal; - -import static com.google.common.base.Preconditions.checkNotNull; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.apache.brooklyn.api.entity.Application; -import org.apache.brooklyn.api.entity.Effector; -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.Feed; -import org.apache.brooklyn.api.event.AttributeSensor; -import org.apache.brooklyn.api.management.ExecutionContext; -import org.apache.brooklyn.api.management.ManagementContext; -import org.apache.brooklyn.api.management.SubscriptionContext; -import org.apache.brooklyn.api.management.entitlement.EntitlementManager; -import org.apache.brooklyn.api.policy.Enricher; -import org.apache.brooklyn.api.policy.Policy; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.config.ConfigKey; -import brooklyn.entity.basic.AbstractEntity; -import brooklyn.entity.basic.Entities; -import brooklyn.entity.basic.EntityInternal; -import brooklyn.management.entitlement.Entitlements; -import brooklyn.management.entitlement.Entitlements.EntityAndItem; -import brooklyn.management.entitlement.Entitlements.StringAndArgument; -import brooklyn.management.internal.NonDeploymentManagementContext.NonDeploymentManagementContextMode; -import brooklyn.util.exceptions.Exceptions; - -import com.google.common.annotations.Beta; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.base.Stopwatch; - -/** - * Encapsulates management activities at an entity. - * <p> - * On entity deployment, ManagementContext.manage(entity) causes - * <p> - * * onManagementStarting(ManagementContext) - * * onManagementStartingSubscriptions() - * * onManagementStartingSensorEmissions() - * * onManagementStartingExecutions() - * * onManagementStarted() - when all the above is said and done - * * onManagementStartingHere(); - * <p> - * on unmanage it hits onManagementStoppingHere() then onManagementStopping(). - * <p> - * When an entity's management migrates, it invoked onManagementStoppingHere() at the old location, - * then onManagementStartingHere() at the new location. - */ -public class EntityManagementSupport { - - private static final Logger log = LoggerFactory.getLogger(EntityManagementSupport.class); - - public EntityManagementSupport(AbstractEntity entity) { - this.entity = entity; - nonDeploymentManagementContext = new NonDeploymentManagementContext(entity, NonDeploymentManagementContextMode.PRE_MANAGEMENT); - } - - protected transient AbstractEntity entity; - NonDeploymentManagementContext nonDeploymentManagementContext; - - protected transient ManagementContext initialManagementContext; - protected transient ManagementContext managementContext; - protected transient SubscriptionContext subscriptionContext; - protected transient ExecutionContext executionContext; - - // TODO the application - // (elaborate or remove ^^^ ? -AH, Sept 2014) - - protected final AtomicBoolean managementContextUsable = new AtomicBoolean(false); - protected final AtomicBoolean currentlyDeployed = new AtomicBoolean(false); - protected final AtomicBoolean everDeployed = new AtomicBoolean(false); - protected Boolean readOnly = null; - protected final AtomicBoolean managementFailed = new AtomicBoolean(false); - - private volatile EntityChangeListener entityChangeListener = EntityChangeListener.NOOP; - - /** - * Whether this entity is managed (i.e. "onManagementStarting" has been called, so the framework knows about it, - * and it has not been unmanaged). - */ - public boolean isDeployed() { return currentlyDeployed.get(); } - public boolean isNoLongerManaged() { - return wasDeployed() && !isDeployed(); - } - /** whether entity has ever been deployed (managed) */ - public boolean wasDeployed() { return everDeployed.get(); } - - @Beta - public void setReadOnly(boolean isReadOnly) { - if (isDeployed()) - throw new IllegalStateException("Cannot set read only after deployment"); - this.readOnly = isReadOnly; - } - - /** Whether the entity and its adjuncts should be treated as read-only; - * may be null briefly when initializing if RO status is unknown. */ - @Beta - public Boolean isReadOnlyRaw() { - return readOnly; - } - - /** Whether the entity and its adjuncts should be treated as read-only; - * error if initializing and RO status is unknown. */ - @Beta - public boolean isReadOnly() { - Preconditions.checkNotNull(readOnly, "Read-only status of %s not yet known", entity); - return readOnly; - } - - /** - * Whether the entity's management lifecycle is complete (i.e. both "onManagementStarting" and "onManagementStarted" have - * been called, and it is has not been unmanaged). - */ - public boolean isFullyManaged() { - return (nonDeploymentManagementContext == null) && currentlyDeployed.get(); - } - - public synchronized void setManagementContext(ManagementContextInternal val) { - if (initialManagementContext != null) { - throw new IllegalStateException("Initial management context is already set for "+entity+"; cannot change"); - } - if (managementContext != null && !managementContext.equals(val)) { - throw new IllegalStateException("Management context is already set for "+entity+"; cannot change"); - } - - this.initialManagementContext = checkNotNull(val, "managementContext"); - if (nonDeploymentManagementContext != null) { - nonDeploymentManagementContext.setManagementContext(val); - } - } - - public void onRebind(ManagementTransitionInfo info) { - nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_REBINDING); - } - - public void onManagementStarting(ManagementTransitionInfo info) { - try { - synchronized (this) { - boolean alreadyManaging = isDeployed(); - - if (alreadyManaging) { - log.warn("Already managed: "+entity+" ("+nonDeploymentManagementContext+"); onManagementStarting is no-op"); - } else if (nonDeploymentManagementContext == null || !nonDeploymentManagementContext.getMode().isPreManaged()) { - throw new IllegalStateException("Not in expected pre-managed state: "+entity+" ("+nonDeploymentManagementContext+")"); - } - if (managementContext != null && !managementContext.equals(info.getManagementContext())) { - throw new IllegalStateException("Already has management context: "+managementContext+"; can't set "+info.getManagementContext()); - } - if (initialManagementContext != null && !initialManagementContext.equals(info.getManagementContext())) { - throw new IllegalStateException("Already has different initial management context: "+initialManagementContext+"; can't set "+info.getManagementContext()); - } - if (alreadyManaging) { - return; - } - - this.managementContext = info.getManagementContext(); - nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_STARTING); - - if (!isReadOnly()) { - nonDeploymentManagementContext.getSubscriptionManager().setDelegate((AbstractSubscriptionManager) managementContext.getSubscriptionManager()); - nonDeploymentManagementContext.getSubscriptionManager().startDelegatingForSubscribing(); - } - - managementContextUsable.set(true); - currentlyDeployed.set(true); - everDeployed.set(true); - - entityChangeListener = new EntityChangeListenerImpl(); - } - - /* - * TODO framework starting events - phase 1, including rebind - * - establish hierarchy (child, groups, etc; construction if necessary on rebind) - * - set location - * - set local config values - * - set saved sensor values - * - register subscriptions -- BUT nothing is allowed to execute - * [these operations may be done before we invoke starting also; above can happen in any order; - * sensor _publications_ and executor submissions are queued] - * then: set the management context and the entity is "managed" from the perspective of external viewers (ManagementContext.isManaged(entity) returns true) - */ - - if (!isReadOnly()) { - entity.onManagementStarting(); - } - } catch (Throwable t) { - managementFailed.set(true); - throw Exceptions.propagate(t); - } - } - - @SuppressWarnings("deprecation") - public void onManagementStarted(ManagementTransitionInfo info) { - try { - synchronized (this) { - boolean alreadyManaged = isFullyManaged(); - - if (alreadyManaged) { - log.warn("Already managed: "+entity+" ("+nonDeploymentManagementContext+"); onManagementStarted is no-op"); - } else if (nonDeploymentManagementContext == null || nonDeploymentManagementContext.getMode() != NonDeploymentManagementContextMode.MANAGEMENT_STARTING) { - throw new IllegalStateException("Not in expected \"management starting\" state: "+entity+" ("+nonDeploymentManagementContext+")"); - } - if (managementContext != info.getManagementContext()) { - throw new IllegalStateException("Already has management context: "+managementContext+"; can't set "+info.getManagementContext()); - } - if (alreadyManaged) { - return; - } - - nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_STARTED); - - /* - * - set derived/inherited config values - * - publish all queued sensors - * - start all queued executions (e.g. subscription delivery) - * [above happens in exactly this order, at each entity] - * then: the entity internally knows it fully managed (ManagementSupport.isManaged() returns true -- though not sure we need that); - * subsequent sensor events and executions occur directly (no queueing) - */ - - if (!isReadOnly()) { - nonDeploymentManagementContext.getSubscriptionManager().startDelegatingForPublishing(); - } - - // TODO more of the above - // TODO custom started activities - // (elaborate or remove ^^^ ? -AH, Sept 2014) - } - - if (!isReadOnly()) { - entity.onManagementBecomingMaster(); - entity.onManagementStarted(); - } - - synchronized (this) { - nonDeploymentManagementContext = null; - } - } catch (Throwable t) { - managementFailed.set(true); - throw Exceptions.propagate(t); - } - } - - @SuppressWarnings("deprecation") - public void onManagementStopping(ManagementTransitionInfo info) { - synchronized (this) { - if (managementContext != info.getManagementContext()) { - throw new IllegalStateException("onManagementStopping encountered different management context for "+entity+ - (!wasDeployed() ? " (wasn't deployed)" : !isDeployed() ? " (no longer deployed)" : "")+ - ": "+managementContext+"; expected "+info.getManagementContext()+" (may be a pre-registered entity which was never properly managed)"); - } - Stopwatch startTime = Stopwatch.createStarted(); - while (!managementFailed.get() && nonDeploymentManagementContext!=null && - nonDeploymentManagementContext.getMode()==NonDeploymentManagementContextMode.MANAGEMENT_STARTING) { - // still becoming managed - try { - if (startTime.elapsed(TimeUnit.SECONDS) > 30) { - // emergency fix, 30s timeout for management starting - log.error("Management stopping event "+info+" in "+this+" timed out waiting for start; proceeding to stopping"); - break; - } - wait(100); - } catch (InterruptedException e) { - Exceptions.propagate(e); - } - } - if (nonDeploymentManagementContext==null) { - nonDeploymentManagementContext = new NonDeploymentManagementContext(entity, NonDeploymentManagementContextMode.MANAGEMENT_STOPPING); - } else { - // already stopped? or not started? - nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_STOPPING); - } - } - // TODO custom stopping activities - // TODO framework stopping events - no more sensors, executions, etc - // (elaborate or remove ^^^ ? -AH, Sept 2014) - - if (!isReadOnly() && info.getMode().isDestroying()) { - // if we support remote parent of local child, the following call will need to be properly remoted - if (entity.getParent()!=null) entity.getParent().removeChild(entity.getProxyIfAvailable()); - } - // new subscriptions will be queued / not allowed - nonDeploymentManagementContext.getSubscriptionManager().stopDelegatingForSubscribing(); - // new publications will be queued / not allowed - nonDeploymentManagementContext.getSubscriptionManager().stopDelegatingForPublishing(); - - if (!isReadOnly()) { - entity.onManagementNoLongerMaster(); - entity.onManagementStopped(); - } - } - - public void onManagementStopped(ManagementTransitionInfo info) { - synchronized (this) { - if (managementContext == null && nonDeploymentManagementContext.getMode() == NonDeploymentManagementContextMode.MANAGEMENT_STOPPED) { - return; - } - if (managementContext != info.getManagementContext()) { - throw new IllegalStateException("Has different management context: "+managementContext+"; expected "+info.getManagementContext()); - } - getSubscriptionContext().unsubscribeAll(); - entityChangeListener = EntityChangeListener.NOOP; - managementContextUsable.set(false); - currentlyDeployed.set(false); - executionContext = null; - subscriptionContext = null; - } - - // TODO framework stopped activities, e.g. serialize state ? - entity.invalidateReferences(); - - synchronized (this) { - managementContext = null; - nonDeploymentManagementContext.setMode(NonDeploymentManagementContextMode.MANAGEMENT_STOPPED); - } - } - - @VisibleForTesting - @Beta - public boolean isManagementContextReal() { - return managementContextUsable.get(); - } - - public synchronized ManagementContext getManagementContext() { - return (managementContextUsable.get()) ? managementContext : nonDeploymentManagementContext; - } - - public synchronized ExecutionContext getExecutionContext() { - if (executionContext!=null) return executionContext; - if (managementContextUsable.get()) { - executionContext = managementContext.getExecutionContext(entity); - return executionContext; - } - return nonDeploymentManagementContext.getExecutionContext(entity); - } - public synchronized SubscriptionContext getSubscriptionContext() { - if (subscriptionContext!=null) return subscriptionContext; - if (managementContextUsable.get()) { - subscriptionContext = managementContext.getSubscriptionContext(entity); - return subscriptionContext; - } - return nonDeploymentManagementContext.getSubscriptionContext(entity); - } - public synchronized EntitlementManager getEntitlementManager() { - return getManagementContext().getEntitlementManager(); - } - - public void attemptLegacyAutodeployment(String effectorName) { - synchronized (this) { - if (managementContext != null) { - log.warn("Autodeployment suggested but not required for " + entity + "." + effectorName); - return; - } - if (entity instanceof Application) { - log.warn("Autodeployment with new management context triggered for " + entity + "." + effectorName + " -- will not be supported in future. Explicit manage call required."); - if (initialManagementContext != null) { - initialManagementContext.getEntityManager().manage(entity); - } else { - Entities.startManagement(entity); - } - return; - } - } - if ("start".equals(effectorName)) { - Entity e=entity; - if (e.getParent()!=null && ((EntityInternal)e.getParent()).getManagementSupport().isDeployed()) { - log.warn("Autodeployment in parent's management context triggered for "+entity+"."+effectorName+" -- will not be supported in future. Explicit manage call required."); - ((EntityInternal)e.getParent()).getManagementContext().getEntityManager().manage(entity); - return; - } - } - log.warn("Autodeployment not available for "+entity+"."+effectorName); - } - - public EntityChangeListener getEntityChangeListener() { - return entityChangeListener; - } - - private class EntityChangeListenerImpl implements EntityChangeListener { - @Override - public void onChanged() { - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - } - @Override - public void onChildrenChanged() { - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - } - @Override - public void onLocationsChanged() { - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - } - @Override - public void onTagsChanged() { - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - } - @Override - public void onMembersChanged() { - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - } - @Override - public void onPolicyAdded(Policy policy) { - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - getManagementContext().getRebindManager().getChangeListener().onManaged(policy); - } - @Override - public void onEnricherAdded(Enricher enricher) { - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - getManagementContext().getRebindManager().getChangeListener().onManaged(enricher); - } - @Override - public void onFeedAdded(Feed feed) { - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - getManagementContext().getRebindManager().getChangeListener().onManaged(feed); - } - @Override - public void onPolicyRemoved(Policy policy) { - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - getManagementContext().getRebindManager().getChangeListener().onUnmanaged(policy); - } - @Override - public void onEnricherRemoved(Enricher enricher) { - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - getManagementContext().getRebindManager().getChangeListener().onUnmanaged(enricher); - } - @Override - public void onFeedRemoved(Feed feed) { - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - getManagementContext().getRebindManager().getChangeListener().onUnmanaged(feed); - } - @Override - public void onAttributeChanged(AttributeSensor<?> attribute) { - // TODO Could make this more efficient by inspecting the attribute to decide if needs persisted - // immediately, or not important, or transient (e.g. do we really need to persist - // request-per-second count for rebind purposes?!) - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - } - @Override - public void onConfigChanged(ConfigKey<?> key) { - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - } - @Override - public void onEffectorStarting(Effector<?> effector, Object parameters) { - Entitlements.checkEntitled(getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(entity, StringAndArgument.of(effector.getName(), parameters))); - } - @Override - public void onEffectorCompleted(Effector<?> effector) { - getManagementContext().getRebindManager().getChangeListener().onChanged(entity); - } - } - - @Override - public String toString() { - return super.toString()+"["+(entity==null ? "null" : entity.getId())+"]"; - } -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/EntityManagementUtils.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/EntityManagementUtils.java b/core/src/main/java/brooklyn/management/internal/EntityManagementUtils.java deleted file mode 100644 index 24ece98..0000000 --- a/core/src/main/java/brooklyn/management/internal/EntityManagementUtils.java +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.management.internal; - -import io.brooklyn.camp.CampPlatform; -import io.brooklyn.camp.spi.Assembly; -import io.brooklyn.camp.spi.AssemblyTemplate; -import io.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator; - -import java.io.StringReader; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Callable; - -import javax.annotation.Nullable; - -import org.apache.brooklyn.api.entity.Application; -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.entity.basic.EntityLocal; -import org.apache.brooklyn.api.entity.proxying.EntitySpec; -import org.apache.brooklyn.api.management.ManagementContext; -import org.apache.brooklyn.api.management.Task; -import org.apache.brooklyn.api.management.classloading.BrooklynClassLoadingContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator; -import brooklyn.config.BrooklynServerConfig; -import brooklyn.config.ConfigKey; -import brooklyn.entity.basic.BrooklynTaskTags; -import brooklyn.entity.basic.ConfigKeys; -import brooklyn.entity.basic.Entities; -import brooklyn.entity.basic.EntityFunctions; -import brooklyn.entity.effector.Effectors; -import brooklyn.entity.trait.Startable; -import brooklyn.management.classloading.JavaBrooklynClassLoadingContext; -import brooklyn.util.collections.MutableList; -import brooklyn.util.collections.MutableMap; -import brooklyn.util.exceptions.Exceptions; -import brooklyn.util.guava.Maybe; -import brooklyn.util.task.TaskBuilder; -import brooklyn.util.task.Tasks; -import brooklyn.util.text.Strings; -import brooklyn.util.time.Duration; - -import com.google.common.annotations.Beta; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; - -/** Utility methods for working with entities and applications */ -public class EntityManagementUtils { - - private static final Logger log = LoggerFactory.getLogger(EntityManagementUtils.class); - - /** - * A marker config value which indicates that an application was created automatically - * to allow the management of a non-app entity. - */ - public static final ConfigKey<Boolean> WRAPPER_APP_MARKER = ConfigKeys.newBooleanConfigKey("brooklyn.wrapper_app"); - - /** creates an application from the given app spec, managed by the given management context */ - public static <T extends Application> T createUnstarted(ManagementContext mgmt, EntitySpec<T> spec) { - T app = mgmt.getEntityManager().createEntity(spec); - Entities.startManagement(app, mgmt); - return app; - } - - /** convenience for accessing camp */ - public static Maybe<CampPlatform> getCampPlatform(ManagementContext mgmt) { - return BrooklynServerConfig.getCampPlatform(mgmt); - } - - /** as {@link #createApplication(ManagementContext, EntitySpec)} but for a YAML spec */ - public static <T extends Application> T createUnstarted(ManagementContext mgmt, String yaml) { - AssemblyTemplate at = getCampPlatform(mgmt).get().pdp().registerDeploymentPlan( new StringReader(yaml) ); - return createUnstarted(mgmt, at); - } - - /** as {@link #createApplication(ManagementContext, EntitySpec)} but for an assembly template */ - @SuppressWarnings("unchecked") - public static <T extends Application> T createUnstarted(ManagementContext mgmt, AssemblyTemplate at) { - CampPlatform camp = getCampPlatform(mgmt).get(); - AssemblyTemplateInstantiator instantiator; - try { - instantiator = at.getInstantiator().newInstance(); - } catch (Exception e) { - throw Exceptions.propagate(e); - } - Assembly assembly; - if (instantiator instanceof AssemblyTemplateSpecInstantiator) { - BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt); - - EntitySpec<?> spec = ((AssemblyTemplateSpecInstantiator) instantiator).createSpec(at, camp, loader, true); - Entity app = mgmt.getEntityManager().createEntity(spec); - Entities.startManagement((Application)app, mgmt); - return (T) app; - } else { - // currently, all brooklyn plans should produce the above; currently this will always throw Unsupported - try { - assembly = instantiator.instantiate(at, camp); - return (T) mgmt.getEntityManager().getEntity(assembly.getId()); - } catch (UnsupportedOperationException e) { - if (at.getPlatformComponentTemplates()==null || at.getPlatformComponentTemplates().isEmpty()) { - if (at.getCustomAttributes().containsKey("brooklyn.catalog")) - throw new IllegalArgumentException("Unrecognized application blueprint format: expected an application, not a brooklyn.catalog"); - throw new IllegalArgumentException("Unrecognized application blueprint format: no services defined"); - } - // map this (expected) error to a nicer message - throw new IllegalArgumentException("Unrecognized application blueprint format"); - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - throw new IllegalArgumentException("Invalid plan: "+at, e); - } - } - } - - /** container for operation which creates something and which wants to return both - * the items created and any pending create/start task */ - public static class CreationResult<T,U> { - private final T thing; - @Nullable private final Task<U> task; - public CreationResult(T thing, Task<U> task) { - super(); - this.thing = thing; - this.task = task; - } - - protected static <T,U> CreationResult<T,U> of(T thing, @Nullable Task<U> task) { - return new CreationResult<T,U>(thing, task); - } - - /** returns the thing/things created */ - @Nullable public T get() { return thing; } - /** associated task, ie the one doing the creation/starting */ - public Task<U> task() { return task; } - public CreationResult<T,U> blockUntilComplete(Duration timeout) { if (task!=null) task.blockUntilEnded(timeout); return this; } - public CreationResult<T,U> blockUntilComplete() { if (task!=null) task.blockUntilEnded(); return this; } - } - - public static <T extends Application> CreationResult<T,Void> createStarting(ManagementContext mgmt, EntitySpec<T> appSpec) { - return start(createUnstarted(mgmt, appSpec)); - } - - public static CreationResult<? extends Application,Void> createStarting(ManagementContext mgmt, String appSpec) { - return start(createUnstarted(mgmt, appSpec)); - } - - public static CreationResult<? extends Application,Void> createStarting(ManagementContext mgmt, AssemblyTemplate at) { - return start(createUnstarted(mgmt, at)); - } - - public static <T extends Application> CreationResult<T,Void> start(T app) { - Task<Void> task = Entities.invokeEffector((EntityLocal)app, app, Startable.START, - // locations already set in the entities themselves; - // TODO make it so that this arg does not have to be supplied to START ! - MutableMap.of("locations", MutableList.of())); - return CreationResult.of(app, task); - } - - public static CreationResult<List<Entity>, List<String>> addChildren(final EntityLocal parent, String yaml, Boolean start) { - if (Boolean.FALSE.equals(start)) - return CreationResult.of(addChildrenUnstarted(parent, yaml), null); - return addChildrenStarting(parent, yaml); - } - - /** adds entities from the given yaml, under the given parent; but does not start them */ - public static List<Entity> addChildrenUnstarted(final EntityLocal parent, String yaml) { - log.debug("Creating child of "+parent+" from yaml:\n{}", yaml); - - ManagementContext mgmt = parent.getApplication().getManagementContext(); - CampPlatform camp = BrooklynServerConfig.getCampPlatform(mgmt).get(); - - AssemblyTemplate at = camp.pdp().registerDeploymentPlan( new StringReader(yaml) ); - - AssemblyTemplateInstantiator instantiator; - try { - instantiator = at.getInstantiator().newInstance(); - } catch (Exception e) { - throw Exceptions.propagate(e); - } - if (instantiator instanceof AssemblyTemplateSpecInstantiator) { - BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt); - EntitySpec<?> specA = ((AssemblyTemplateSpecInstantiator) instantiator).createSpec(at, camp, loader, false); - - // see whether we can promote children - List<EntitySpec<?>> specs = MutableList.of(); - if (hasNoNameOrCustomKeysOrRoot(at, specA)) { - // we can promote - for (EntitySpec<?> specC: specA.getChildren()) { - collapseSpec(specA, specC); - specs.add(specC); - } - } else { - // if not promoting, set a nice name if needed - if (Strings.isEmpty(specA.getDisplayName())) { - int size = specA.getChildren().size(); - String childrenCountString = size+" "+(size!=1 ? "children" : "child"); - specA.displayName("Dynamically added "+childrenCountString); - } - specs.add(specA); - } - - final List<Entity> children = MutableList.of(); - for (EntitySpec<?> spec: specs) { - Entity child = (Entity)parent.addChild(spec); - Entities.manage(child); - children.add(child); - } - - return children; - } else { - throw new IllegalStateException("Spec could not be parsed to supply a compatible instantiator"); - } - } - - public static CreationResult<List<Entity>,List<String>> addChildrenStarting(final EntityLocal parent, String yaml) { - final List<Entity> children = addChildrenUnstarted(parent, yaml); - String childrenCountString; - - int size = children.size(); - childrenCountString = size+" "+(size!=1 ? "children" : "child"); - - TaskBuilder<List<String>> taskM = Tasks.<List<String>>builder().name("add children") - .dynamic(true) - .tag(BrooklynTaskTags.NON_TRANSIENT_TASK_TAG) - .body(new Callable<List<String>>() { - @Override public List<String> call() throws Exception { - return ImmutableList.copyOf(Iterables.transform(children, EntityFunctions.id())); - }}) - .description("Add and start "+childrenCountString); - - TaskBuilder<?> taskS = Tasks.builder().parallel(true).name("add (parallel)").description("Start each new entity"); - - // autostart if requested - for (Entity child: children) { - if (child instanceof Startable) { - taskS.add(Effectors.invocation(child, Startable.START, ImmutableMap.of("locations", ImmutableList.of()))); - } else { - // include a task, just to give feedback in the GUI - taskS.add(Tasks.builder().name("create").description("Skipping start (not a Startable Entity)") - .body(new Runnable() { public void run() {} }) - .tag(BrooklynTaskTags.tagForTargetEntity(child)) - .build()); - } - } - taskM.add(taskS.build()); - Task<List<String>> task = Entities.submit(parent, taskM.build()); - - return CreationResult.of(children, task); - } - - /** worker method to combine specs */ - @Beta //where should this live long-term? - public static void collapseSpec(EntitySpec<?> sourceToBeCollapsed, EntitySpec<?> targetToBeExpanded) { - if (Strings.isEmpty(targetToBeExpanded.getDisplayName())) - targetToBeExpanded.displayName(sourceToBeCollapsed.getDisplayName()); - if (!sourceToBeCollapsed.getLocations().isEmpty()) - targetToBeExpanded.locations(sourceToBeCollapsed.getLocations()); - - // NB: this clobbers child config; might prefer to deeply merge maps etc - // (but this should not be surprising, as unwrapping is often parameterising the nested blueprint, so outer config should dominate) - targetToBeExpanded.configure(sourceToBeCollapsed.getConfig()); - targetToBeExpanded.configure(sourceToBeCollapsed.getFlags()); - - // TODO copying tags to all entities is not ideal; - // in particular the BrooklynTags.YAML_SPEC tag will show all entities if the root has multiple - targetToBeExpanded.tags(sourceToBeCollapsed.getTags()); - } - - /** worker method to help determine whether child/children can be promoted */ - @Beta //where should this live long-term? - public static boolean hasNoNameOrCustomKeysOrRoot(AssemblyTemplate template, EntitySpec<?> spec) { - if (Strings.isNonEmpty(template.getName())) { - if (spec.getChildren().size()==1) { - String childName = Iterables.getOnlyElement(spec.getChildren()).getDisplayName(); - if (Strings.isEmpty(childName) || childName.equals(template.getName())) { - // if child has no name, or it's the same, could still promote - } else { - return false; - } - } else { - // if name set at root and promoting children would be ambiguous, do not promote - return false; - } - } else if (spec.getChildren().size()>1) { - // don't allow multiple children if a name is specified as a root - return false; - } - - Set<String> rootAttrs = template.getCustomAttributes().keySet(); - for (String rootAttr: rootAttrs) { - if (rootAttr.equals("brooklyn.catalog") || rootAttr.equals("brooklyn.config")) { - // these do not block promotion - continue; - } - if (rootAttr.startsWith("brooklyn.")) { - // any others in 'brooklyn' namespace will block promotion - return false; - } - // location is allowed in both, and is copied on promotion - // (name also copied) - // others are root currently are ignored on promotion; they are usually metadata - // TODO might be nice to know what we are excluding - } - - return true; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java b/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java deleted file mode 100644 index aa55b59..0000000 --- a/core/src/main/java/brooklyn/management/internal/EntityManagerInternal.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.management.internal; - -import org.apache.brooklyn.api.entity.Application; -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.management.EntityManager; - -public interface EntityManagerInternal extends EntityManager, BrooklynObjectManagerInternal<Entity> { - - /** gets all entities currently known to the application, including entities that are not yet managed */ - Iterable<Entity> getAllEntitiesInApplication(Application application); - - public Iterable<String> getEntityIds(); - -} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/GroovyObservablesPropertyChangeToCollectionChangeAdapter.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/GroovyObservablesPropertyChangeToCollectionChangeAdapter.java b/core/src/main/java/brooklyn/management/internal/GroovyObservablesPropertyChangeToCollectionChangeAdapter.java deleted file mode 100644 index 973e030..0000000 --- a/core/src/main/java/brooklyn/management/internal/GroovyObservablesPropertyChangeToCollectionChangeAdapter.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.management.internal; - -import groovy.util.ObservableList; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -public class GroovyObservablesPropertyChangeToCollectionChangeAdapter implements PropertyChangeListener { - @SuppressWarnings("rawtypes") - private final CollectionChangeListener delegate; - - public GroovyObservablesPropertyChangeToCollectionChangeAdapter(@SuppressWarnings("rawtypes") CollectionChangeListener delegate) { - this.delegate = delegate; - } - - @SuppressWarnings("unchecked") - public void propertyChange(PropertyChangeEvent evt) { - if (evt instanceof ObservableList.ElementAddedEvent) { - delegate.onItemAdded(evt.getNewValue()); - } else if (evt instanceof ObservableList.ElementRemovedEvent) { - delegate.onItemRemoved(evt.getOldValue()); - } else if (evt instanceof ObservableList.ElementUpdatedEvent) { - delegate.onItemRemoved(evt.getOldValue()); - delegate.onItemAdded(evt.getNewValue()); - } else if (evt instanceof ObservableList.ElementClearedEvent) { - for (Object value : ((ObservableList.ElementClearedEvent) evt).getValues()) { - delegate.onItemAdded(value); - } - } else if(evt instanceof ObservableList.MultiElementAddedEvent ) { - for(Object value: ((ObservableList.MultiElementAddedEvent)evt).getValues()){ - delegate.onItemAdded(value); - } - } - } - - public int hashCode() { - return delegate.hashCode(); - } - - public boolean equals(Object other) { - if (other instanceof GroovyObservablesPropertyChangeToCollectionChangeAdapter) - return delegate.equals(((GroovyObservablesPropertyChangeToCollectionChangeAdapter) other).delegate); - if (other instanceof CollectionChangeListener) - return delegate.equals(other); - return false; - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6602f694/core/src/main/java/brooklyn/management/internal/LocalAccessManager.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/brooklyn/management/internal/LocalAccessManager.java b/core/src/main/java/brooklyn/management/internal/LocalAccessManager.java deleted file mode 100644 index 696d0f0..0000000 --- a/core/src/main/java/brooklyn/management/internal/LocalAccessManager.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package brooklyn.management.internal; - -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.brooklyn.api.entity.Entity; -import org.apache.brooklyn.api.location.Location; -import org.apache.brooklyn.api.management.AccessController; - -import com.google.common.annotations.Beta; - -@Beta -public class LocalAccessManager implements AccessManager { - - private volatile boolean locationProvisioningAllowed = true; - private volatile boolean locationManagementAllowed = true; - private volatile boolean entityManagementAllowed = true; - - private final AtomicReference<AccessControllerImpl> controller = new AtomicReference<AccessControllerImpl>(); - - public LocalAccessManager() { - updateAccessController(); - } - - @Override - public AccessController getAccessController() { - return controller.get(); - } - - @Override - public boolean isLocationProvisioningAllowed() { - return locationProvisioningAllowed; - } - - @Override - public boolean isLocationManagementAllowed() { - return locationManagementAllowed; - } - - @Override - public boolean isEntityManagementAllowed() { - return entityManagementAllowed; - } - - @Override - public void setLocationProvisioningAllowed(boolean allowed) { - locationProvisioningAllowed = allowed; - updateAccessController(); - } - - @Override - public void setLocationManagementAllowed(boolean allowed) { - locationManagementAllowed = allowed; - updateAccessController(); - } - - @Override - public void setEntityManagementAllowed(boolean allowed) { - entityManagementAllowed = allowed; - updateAccessController(); - } - - private void updateAccessController() { - controller.set(new AccessControllerImpl(locationProvisioningAllowed, locationManagementAllowed, entityManagementAllowed)); - } - - private static class AccessControllerImpl implements AccessController { - private final boolean locationProvisioningAllowed; - private final boolean locationManagementAllowed; - private final boolean entityManagementAllowed; - - public AccessControllerImpl(boolean locationProvisioningAllowed, boolean locationManagementAllowed, - boolean entityManagementAllowed) { - this.locationProvisioningAllowed = locationProvisioningAllowed; - this.locationManagementAllowed = locationManagementAllowed; - this.entityManagementAllowed = entityManagementAllowed; - } - - @Override - public Response canProvisionLocation(Location provisioner) { - return (locationProvisioningAllowed ? Response.allowed() : Response.disallowed("location provisioning disabled")); - } - - @Override - public Response canManageLocation(Location loc) { - return (locationManagementAllowed ? Response.allowed() : Response.disallowed("location management disabled")); - } - - @Override - public Response canManageEntity(Entity entity) { - return (entityManagementAllowed ? Response.allowed() : Response.disallowed("entity management disabled")); - } - } -}
