http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java new file mode 100644 index 0000000..6279121 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/Entity.java @@ -0,0 +1,265 @@ +/* + * 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.api.entity; + +import java.util.Collection; +import java.util.Map; + +import javax.annotation.Nullable; + +import org.apache.brooklyn.api.basic.BrooklynObject; +import org.apache.brooklyn.api.entity.proxying.EntitySpec; +import org.apache.brooklyn.management.Task; +import org.apache.brooklyn.policy.Enricher; +import org.apache.brooklyn.policy.EnricherSpec; +import org.apache.brooklyn.policy.Policy; +import org.apache.brooklyn.policy.PolicySpec; + +import brooklyn.config.ConfigKey; +import brooklyn.config.ConfigKey.HasConfigKey; +import brooklyn.event.AttributeSensor; +import brooklyn.location.Location; +import brooklyn.util.guava.Maybe; + +/** + * The basic interface for a Brooklyn entity. + * <p> + * Implementors of entities are strongly encouraged to extend {@link brooklyn.entity.basic.AbstractEntity}. + * <p> + * To instantiate an entity, see {@code managementContext.getEntityManager().createEntity(entitySpec)}. + * Also see {@link brooklyn.entity.basic.ApplicationBuilder}, + * {@link brooklyn.entity.basic.AbstractEntity#addChild(EntitySpec)}, and + * {@link org.apache.brooklyn.api.entity.proxying.EntitySpec}. + * <p> + * + * @see brooklyn.entity.basic.AbstractEntity + */ +public interface Entity extends BrooklynObject { + /** + * The unique identifier for this entity. + */ + @Override + String getId(); + + /** + * Returns the creation time for this entity, in UTC. + */ + long getCreationTime(); + + /** + * A display name; recommended to be a concise single-line description. + */ + String getDisplayName(); + + /** + * A URL pointing to an image which can be used to represent this entity. + */ + @Nullable String getIconUrl(); + + /** + * Information about the type of this entity; analogous to Java's object.getClass. + */ + EntityType getEntityType(); + + /** + * @return the {@link Application} this entity is registered with, or null if not registered. + */ + Application getApplication(); + + /** + * @return the id of the {@link Application} this entity is registered with, or null if not registered. + */ + String getApplicationId(); + + /** + * The parent of this entity, null if no parent. + * + * The parent is normally the entity responsible for creating/destroying/managing this entity. + * + * @see #setParent(Entity) + * @see #clearParent + */ + Entity getParent(); + + /** + * Return the entities that are children of (i.e. "owned by") this entity + */ + Collection<Entity> getChildren(); + + /** + * Sets the parent (i.e. "owner") of this entity. Returns this entity, for convenience. + * + * @see #getParent + * @see #clearParent + */ + Entity setParent(Entity parent); + + /** + * Clears the parent (i.e. "owner") of this entity. Also cleans up any references within its parent entity. + * + * @see #getParent + * @see #setParent + */ + void clearParent(); + + /** + * Add a child {@link Entity}, and set this entity as its parent, + * returning the added child. + * <p> + * As with {@link #addChild(EntitySpec)} the child is <b>not</b> brought under management + * as part of this call. It should not be managed prior to this call either. + */ + <T extends Entity> T addChild(T child); + + /** + * Creates an {@link Entity} from the given spec and adds it, setting this entity as the parent, + * returning the added child. + * <p> + * The added child is <b>not</b> managed as part of this call, even if the parent is managed, + * so if adding post-management an explicit call to manage the child will be needed; + * see the convenience method <code>Entities.manage(...)</code>. + * */ + <T extends Entity> T addChild(EntitySpec<T> spec); + + /** + * Removes the specified child {@link Entity}; its parent will be set to null. + * + * @return True if the given entity was contained in the set of children + */ + boolean removeChild(Entity child); + + /** + * @return an immutable thread-safe view of the policies. + */ + Collection<Policy> getPolicies(); + + /** + * @return an immutable thread-safe view of the enrichers. + */ + Collection<Enricher> getEnrichers(); + + /** + * The {@link Collection} of {@link Group}s that this entity is a member of. + * + * Groupings can be used to allow easy management/monitoring of a group of entities. + */ + Collection<Group> getGroups(); + + /** + * Add this entity as a member of the given {@link Group}. Called by framework. + * <p> + * Users should call {@link Group#addMember(Entity)} instead; this method will then + * automatically be called. However, the reverse is not true (calling this method will + * not tell the group; this behaviour may change in a future release!) + */ + void addGroup(Group group); + + /** + * Removes this entity as a member of the given {@link Group}. Called by framework. + * <p> + * Users should call {@link Group#removeMember(Entity)} instead; this method will then + * automatically be called. However, the reverse is not true (calling this method will + * not tell the group; this behaviour may change in a future release!) + */ + void removeGroup(Group group); + + /** + * Return all the {@link Location}s this entity is deployed to. + */ + Collection<Location> getLocations(); + + /** + * Gets the value of the given attribute on this entity, or null if has not been set. + * + * Attributes can be things like workrate and status information, as well as + * configuration (e.g. url/jmxHost/jmxPort), etc. + */ + <T> T getAttribute(AttributeSensor<T> sensor); + + /** + * Convenience for calling {@link ConfigurationSupport#getConfig(ConfigKey)}, + * via code like {@code config().get(key)}. + */ + <T> T getConfig(ConfigKey<T> key); + + /** + * @see #getConfig(ConfigKey)} + */ + <T> T getConfig(HasConfigKey<T> key); + + /** + * Returns the uncoerced value for this config key as set on this entity, if available, + * not following any inheritance chains and not taking any default. + * + * @deprecated since 0.7.0; use {@code ((EntityInternal)entity).config().getRaw()} or + * {@code ((EntityInternal)entity).config().getLocalRaw()} + */ + @Deprecated + Maybe<Object> getConfigRaw(ConfigKey<?> key, boolean includeInherited); + + /** + * @see {@link #getConfigRaw(ConfigKey, boolean)}. + * + * @deprecated since 0.7.0 + */ + @Deprecated + Maybe<Object> getConfigRaw(HasConfigKey<?> key, boolean includeInherited); + + /** + * Invokes the given effector, with the given parameters to that effector. + */ + <T> Task<T> invoke(Effector<T> eff, Map<String,?> parameters); + + /** + * Adds the given policy to this entity. Also calls policy.setEntity if available. + */ + void addPolicy(Policy policy); + + /** + * Adds the given policy to this entity. Also calls policy.setEntity if available. + */ + <T extends Policy> T addPolicy(PolicySpec<T> enricher); + + /** + * Removes the given policy from this entity. + * @return True if the policy existed at this entity; false otherwise + */ + boolean removePolicy(Policy policy); + + /** + * Adds the given enricher to this entity. Also calls enricher.setEntity if available. + */ + void addEnricher(Enricher enricher); + + /** + * Adds the given enricher to this entity. Also calls enricher.setEntity if available. + */ + <T extends Enricher> T addEnricher(EnricherSpec<T> enricher); + + /** + * Removes the given enricher from this entity. + * @return True if the policy enricher at this entity; false otherwise + */ + boolean removeEnricher(Enricher enricher); + + /** + * Adds the given feed to this entity. Also calls feed.setEntity if available. + */ + <T extends Feed> T addFeed(T feed); +}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/EntityType.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/EntityType.java b/api/src/main/java/org/apache/brooklyn/api/entity/EntityType.java new file mode 100644 index 0000000..98d6258 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/EntityType.java @@ -0,0 +1,73 @@ +/* + * 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.api.entity; + +import java.util.NoSuchElementException; +import java.util.Set; + +import org.apache.brooklyn.api.basic.BrooklynType; + +import brooklyn.event.Sensor; +import brooklyn.util.guava.Maybe; + +/** + * Gives type information for an {@link Entity}. It is an immutable snapshot. + * + * It reflects a given entity at the time the snapshot was created: if sensors + * were added or removed on-the-fly then those changes will be included in subsequent + * snapshots. Therefore instances of a given class of entity could have different + * EntityTypes. + */ +public interface EntityType extends BrooklynType { + + /** + * Sensors available on this entity. + */ + Set<Sensor<?>> getSensors(); + + /** + * Effectors available on this entity. + */ + Set<Effector<?>> getEffectors(); + + /** @return an effector with the given name, if it exists. + */ + public Maybe<Effector<?>> getEffectorByName(String name); + + /** + * @return the matching effector on this entity + * @throws NoSuchElementException If there is no exact match for this signature + * <p> + * @deprecated since 0.7.0 use {@link #getEffectorByName(String)}; + * use of multiple effectors with the same name is not supported by the EntityDynamicType implementation, + * so should be discouraged. overloading can be achieved by inspecting the parameters map. + */ + @Deprecated + Effector<?> getEffector(String name, Class<?>... parameterTypes); + + /** + * The Sensor with the given name, or null if not found. + */ + Sensor<?> getSensor(String name); + + /** + * @return True if has the sensor with the given name; false otherwise. + */ + boolean hasSensor(String name); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/Feed.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/Feed.java b/api/src/main/java/org/apache/brooklyn/api/entity/Feed.java new file mode 100644 index 0000000..134f3f0 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/Feed.java @@ -0,0 +1,70 @@ +/* + * 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.api.entity; + +import org.apache.brooklyn.api.entity.rebind.RebindSupport; +import org.apache.brooklyn.api.entity.rebind.Rebindable; +import org.apache.brooklyn.mementos.FeedMemento; +import org.apache.brooklyn.policy.EntityAdjunct; + +import com.google.common.annotations.Beta; + +/** + * A sensor feed. + * These generally poll or subscribe to get sensor values for an entity. + * They make it easy to poll over http, jmx, etc. + * + * Assumes: + * <ul> + * <li>There will not be concurrent calls to start and stop. + * <li>There will only be one call to start and that will be done immediately after construction, + * in the same thread. + * <li>Once stopped, the feed will not be re-started. + * </ul> + */ +@Beta +public interface Feed extends EntityAdjunct, Rebindable { + + /** + * True if everything has been _started_ (or it is starting) but not stopped, + * even if it is suspended; see also {@link #isActive()} + */ + boolean isActivated(); + + void start(); + + /** suspends this feed (stops the poller, or indicates that the feed should start in a state where the poller is stopped) */ + void suspend(); + + boolean isSuspended(); + + /** resumes this feed if it has been suspended and not stopped */ + void resume(); + + void stop(); + + /** + * Users are strongly discouraged from calling or overriding this method. + * It is for internal calls only, relating to persisting/rebinding entities. + * This method may change (or be removed) in a future release without notice. + */ + @Override + @Beta + RebindSupport<FeedMemento> getRebindSupport(); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/Group.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/Group.java b/api/src/main/java/org/apache/brooklyn/api/entity/Group.java new file mode 100644 index 0000000..27d8880 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/Group.java @@ -0,0 +1,73 @@ +/* + * 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.api.entity; + +import java.util.Collection; + +import org.apache.brooklyn.api.entity.proxying.EntitySpec; + +/** + * An {@link Entity} that groups together other entities. + * + * The grouping can be for any purpose, such as allowing easy management/monitoring of + * a group of entities. The grouping could be static (i.e. a fixed set of entities) + * or dynamic (i.e. contains all entities that match some filter). + */ +public interface Group extends Entity { + + /** + * Return the entities that are members of this group. + */ + Collection<Entity> getMembers(); + + /** + * @return True if it is a member of this group. + */ + boolean hasMember(Entity member); + + /** + * Adds the given member, returning true if this modifies the set of members (i.e. it was not already a member). + */ + boolean addMember(Entity member); + + /** + * Removes the given member, returning true if this modifies the set of members (i.e. it was a member). + */ + boolean removeMember(Entity member); + + /** + * @return The number of members in this group. + */ + Integer getCurrentSize(); + + /** As {@link #addChild(EntitySpec)} followed by {@link #addMember(Entity)} */ + <T extends Entity> T addMemberChild(EntitySpec<T> spec); + + /** As {@link #addChild(Entity)} followed by {@link #addMember(Entity)} */ + <T extends Entity> T addMemberChild(T child); + + /** As in super, but note this does NOT by default add it as a member; see {@link #addMemberChild(EntitySpec)} */ + @Override + <T extends Entity> T addChild(EntitySpec<T> spec); + + /** As in super, but note this does NOT by default add it as a member; see {@link #addMemberChild(Entity)} */ + @Override + <T extends Entity> T addChild(T child); + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/ParameterType.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/ParameterType.java b/api/src/main/java/org/apache/brooklyn/api/entity/ParameterType.java new file mode 100644 index 0000000..570e77e --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/ParameterType.java @@ -0,0 +1,48 @@ +/* + * 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.api.entity; + +import java.io.Serializable; + +import javax.management.MBeanParameterInfo; + +/** + * Similar to the concepts in the JMX {@link MBeanParameterInfo} class. + * + * @see Effector + */ +public interface ParameterType<T> extends Serializable { + + public String getName(); + + public Class<T> getParameterClass(); + + /** + * The canonical name of the parameter class; especially useful if the class + * cannot be resolved after deserialization. + */ + public String getParameterClassName(); + + public String getDescription(); + + /** + * @return The default value for this parameter, if not supplied during an effector call. + */ + public T getDefaultValue(); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/basic/EntityLocal.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/basic/EntityLocal.java b/api/src/main/java/org/apache/brooklyn/api/entity/basic/EntityLocal.java new file mode 100644 index 0000000..0860814 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/basic/EntityLocal.java @@ -0,0 +1,180 @@ +/* + * 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.api.entity.basic; + +import java.util.Map; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.Group; +import org.apache.brooklyn.api.entity.trait.Configurable; +import org.apache.brooklyn.management.SubscriptionContext; +import org.apache.brooklyn.management.SubscriptionHandle; +import org.apache.brooklyn.management.SubscriptionManager; +import org.apache.brooklyn.management.Task; + +import brooklyn.config.ConfigKey; +import brooklyn.config.ConfigKey.HasConfigKey; +import brooklyn.event.AttributeSensor; +import brooklyn.event.Sensor; +import brooklyn.event.SensorEvent; +import brooklyn.event.SensorEventListener; +import brooklyn.util.guava.Maybe; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; + +/** + * Extended Entity interface for use in places where the caller should have certain privileges, + * such as setting attribute values, adding policies, etc. + * + * FIXME Moved from core project to api project because of bug in groovy's covariant return types. + * EntityDriver needs to return EntityLocal rather than Entity, to avoid changing a whole load + * of sub-types. + * FIXME Add {@link setAttribute(AttributeSensorAndConfigKey<?,T>)} back in if/when move it back, + * or if we extract an interface for AttributeSensorAndConfigKey. + */ +public interface EntityLocal extends Entity { + + // FIXME Rename to something other than EntityLocal. + // Separate out what is specific to "local jvm", and what is here for an SPI rather than API. + + /** + * Sets the entity's display name. + * Must be called before the entity is managed. + */ + void setDisplayName(String displayName); + + /** + * @deprecated since 0.7.0; use {@link #config()}, such as {@code entity.config().set(key, val)} + */ + @Deprecated + <T> T setConfig(ConfigKey<T> key, T val); + + /** + * @deprecated since 0.7.0; use {@link #config()}, such as {@code entity.config().set(key, val)} + */ + @Deprecated + <T> T setConfig(ConfigKey<T> key, Task<T> val); + + /** + * @deprecated since 0.7.0; use {@link #config()}, such as {@code entity.config().set(key, val)} + */ + @Deprecated + <T> T setConfig(HasConfigKey<T> key, T val); + + /** + * @deprecated since 0.7.0; use {@link #config()}, such as {@code entity.config().set(key, val)} + */ + @Deprecated + <T> T setConfig(HasConfigKey<T> key, Task<T> val); + + /** + * Sets the {@link AttributeSensor} data for the given attribute to the specified value. + * + * This can be used to "enrich" the entity, such as adding aggregated information, + * rolling averages, etc. + * + * @return the old value for the attribute (possibly {@code null}) + */ + <T> T setAttribute(AttributeSensor<T> attribute, T val); + + /** + * Atomically modifies the {@link AttributeSensor}, ensuring that only one modification is done + * at a time. + * + * If the modifier returns {@link Maybe#absent()} then the attribute will be + * left unmodified, and the existing value will be returned. + * + * For details of the synchronization model used to achieve this, refer to the underlying + * attribute store (e.g. AttributeMap). + * + * @return the old value for the attribute (possibly {@code null}) + * @since 0.7.0-M2 + */ + @Beta + <T> T modifyAttribute(AttributeSensor<T> attribute, Function<? super T, Maybe<T>> modifier); + + /** + * @deprecated in 0.5; use {@link #getConfig(ConfigKey)} + */ + <T> T getConfig(ConfigKey<T> key, T defaultValue); + + /** + * @deprecated in 0.5; use {@link #getConfig(HasConfigKey)} + */ + <T> T getConfig(HasConfigKey<T> key, T defaultValue); + + /** + * Emits a {@link SensorEvent} event on behalf of this entity (as though produced by this entity). + * <p> + * Note that for attribute sensors it is nearly always recommended to use setAttribute, + * as this method will not update local values. + */ + <T> void emit(Sensor<T> sensor, T value); + + /** + * Allow us to subscribe to data from a {@link Sensor} on another entity. + * + * @return a subscription id which can be used to unsubscribe + * + * @see SubscriptionManager#subscribe(Map, Entity, Sensor, SensorEventListener) + */ + // FIXME remove from interface? + @Beta + <T> SubscriptionHandle subscribe(Entity producer, Sensor<T> sensor, SensorEventListener<? super T> listener); + + /** @see SubscriptionManager#subscribeToChildren(Map, Entity, Sensor, SensorEventListener) */ + // FIXME remove from interface? + @Beta + <T> SubscriptionHandle subscribeToChildren(Entity parent, Sensor<T> sensor, SensorEventListener<? super T> listener); + + /** @see SubscriptionManager#subscribeToMembers(Group, Sensor, SensorEventListener) */ + // FIXME remove from interface? + @Beta + <T> SubscriptionHandle subscribeToMembers(Group group, Sensor<T> sensor, SensorEventListener<? super T> listener); + + /** + * Unsubscribes from the given producer. + * + * @see SubscriptionContext#unsubscribe(SubscriptionHandle) + */ + @Beta + boolean unsubscribe(Entity producer); + + /** + * Unsubscribes the given handle. + * + * @see SubscriptionContext#unsubscribe(SubscriptionHandle) + */ + @Beta + boolean unsubscribe(Entity producer, SubscriptionHandle handle); + + /** + * Removes all policy from this entity. + * @return True if any policies existed at this entity; false otherwise + */ + boolean removeAllPolicies(); + + /** + * Removes all enricher from this entity. + * Use with caution as some entities automatically register enrichers; this will remove those enrichers as well. + * @return True if any enrichers existed at this entity; false otherwise + */ + boolean removeAllEnrichers(); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/drivers/DriverDependentEntity.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/drivers/DriverDependentEntity.java b/api/src/main/java/org/apache/brooklyn/api/entity/drivers/DriverDependentEntity.java new file mode 100644 index 0000000..b59e9cc --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/drivers/DriverDependentEntity.java @@ -0,0 +1,36 @@ +/* + * 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.api.entity.drivers; + +import javax.annotation.Nullable; + +import org.apache.brooklyn.api.entity.Entity; + +/** + * An Entity that needs to have a driver. + * + * @param <D> + */ +public interface DriverDependentEntity<D extends EntityDriver> extends Entity { + + Class<D> getDriverInterface(); + + @Nullable D getDriver(); + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/drivers/EntityDriver.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/drivers/EntityDriver.java b/api/src/main/java/org/apache/brooklyn/api/entity/drivers/EntityDriver.java new file mode 100644 index 0000000..16b4a83 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/drivers/EntityDriver.java @@ -0,0 +1,55 @@ +/* + * 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.api.entity.drivers; + +import org.apache.brooklyn.api.entity.basic.EntityLocal; + +import brooklyn.location.Location; + +import com.google.common.annotations.Beta; + +/** + * The EntityDriver provides an abstraction between the Entity and the environment (the {@link Location} it is running + * in, so that an entity is not tightly coupled to a specific Location. E.g. you could have a TomcatEntity that uses + * a TomcatDriver (an interface) and you could have different driver implementations like the + * TomcatSshDriver/TomcatWindowsDriver and if in the future support for Puppet needs to be added, a TomcatPuppetDriver + * could be added. + * + * @author Peter Veentjer. + * @see DriverDependentEntity + * @see EntityDriverManager + */ +public interface EntityDriver { + + /** + * The entity instance that this is a driver for. + * + * FIXME The signature of this will change to return Entity instead of EntityLocal. + * This is a temporary workaround for groovy not supporting covariant return types, + * see http://jira.codehaus.org/browse/GROOVY-5418. It is fixed in groovy 2.0.4 so + * we will need to upgrade from 1.8.6 first. + */ + @Beta + EntityLocal getEntity(); + + /** + * The location the entity is running in. + */ + Location getLocation(); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/drivers/EntityDriverManager.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/drivers/EntityDriverManager.java b/api/src/main/java/org/apache/brooklyn/api/entity/drivers/EntityDriverManager.java new file mode 100644 index 0000000..45bc7a4 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/drivers/EntityDriverManager.java @@ -0,0 +1,49 @@ +/* + * 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.api.entity.drivers; + +import brooklyn.location.Location; + +/** + * Responsible for creating a driver for a given entity/location. Also used for customizing which + * type of driver should be used by entities in given locations. + * + * The idea is that an entity should not be tightly coupled to a specific driver implementation, + * so that there is flexibility for driver changes, without changing the entity itself. The + * advantage is that drivers can easily be reconfigured, replaced or new drivers for different + * environments can be added, without needing to modify Brooklyn. + * + * To obtain an instance of a driver, use {@link #build(DriverDependentEntity, Location)}. + * This will use the registered driver types, or if one is not registered will fallback to the + * default strategy. + */ +public interface EntityDriverManager { + + /** + * Builds a new {@link EntityDriver} for the given entity/location. + * + * @param entity the {@link DriverDependentEntity} to create the {@link EntityDriver} for. + * @param location the {@link Location} where the {@link DriverDependentEntity} is running. + * @param <D> + * @return the creates EntityDriver. + */ + <D extends EntityDriver> D build(DriverDependentEntity<D> entity, Location location); + + <D extends EntityDriver> void registerDriver(Class<D> driverInterface, Class<? extends Location> locationClazz, Class<? extends D> driverClazz); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/drivers/downloads/DownloadResolver.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/drivers/downloads/DownloadResolver.java b/api/src/main/java/org/apache/brooklyn/api/entity/drivers/downloads/DownloadResolver.java new file mode 100644 index 0000000..56befa4 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/drivers/downloads/DownloadResolver.java @@ -0,0 +1,58 @@ +/* + * 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.api.entity.drivers.downloads; + +import java.util.List; + +import com.google.common.annotations.Beta; + +/** + * Gives download details for an entity or an entity add-on. + * Returned by the {@link DownloadResolverManager}, when queried for a specific entity or entity add-on. + * + * @author aled + */ +public interface DownloadResolver { + /** + * The targets (normally URLs) for downloading the artifact. These should be tried in-order + * until one works. + */ + public List<String> getTargets(); + + /** + * The name of the artifact. + * The caller is free to use this name, or not. But using this name gives consistency particularly + * between brooklyn local-repos and brooklyn install directories. + */ + public String getFilename(); + + /** + * The name of the directory in the expanded artifact (e.g. if it's a tar.gz file then the name of + * the directory within it). If no value is known, the defaultVal will be returned. + * + * This can return null if the artifact is not an archive (and if defaultVal is null). + * + * TODO The driver needs to know what will happen when an install archive is unpacked (e.g. an + * AS7 install tgz may be automatically expanded into a directory named "jboss-as-7.1.1-FINAL"). + * However, it's unclear where the best place to encode that is. The driver supplying the default + * seems sensible. + */ + @Beta + public String getUnpackedDirectoryName(String defaultVal); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/drivers/downloads/DownloadResolverManager.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/drivers/downloads/DownloadResolverManager.java b/api/src/main/java/org/apache/brooklyn/api/entity/drivers/downloads/DownloadResolverManager.java new file mode 100644 index 0000000..3597041 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/drivers/downloads/DownloadResolverManager.java @@ -0,0 +1,158 @@ +/* + * 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.api.entity.drivers.downloads; + +import java.util.List; +import java.util.Map; + +import org.apache.brooklyn.api.entity.drivers.EntityDriver; + +import com.google.common.base.Function; + +/** + * Used by an {@link EntityDriver} to obtain the download locations when installing an entity. + * + * Most commonly, the {@link DownloadResolver}'s targets are URIs. However, an EntityDriver + * implementation is free to interpret the String however is appropriate (e.g. the name of a + * custom package to install from the enterprise's package manager repository). + + * Also supports registering other "resolvers" for determining where to download the installers + * from, for different entities. + * + * When using {@link resolve(EntityDriver)} to get the list of things to try (in-order until one succeeds), + * the manager will go through each of the registered resolvers in-order to get their contributions. + * These contributions are split into "primary" and "fallback". All of the primaries will be added to the + * list first, and then all of the fallbacks. + * + * @author aled + */ +public interface DownloadResolverManager { + + /** + * For installing the main entity. + * Returns a list of options, to be tried in order until one of them works. + */ + public DownloadResolver newDownloader(EntityDriver driver); + + /** + * For installing the main entity. + * Returns a list of options, to be tried in order until one of them works. + */ + public DownloadResolver newDownloader(EntityDriver driver, Map<String,?> properties); + + /** + * For installing an entity add-on. + * Returns a list of options, to be tried in order until one of them works. + * This is used for resolving the download for an "add-on" - e.g. an additional module required + * during an entity's installation. Common properties include: + * <ul> + * <li>addonversion: the required version of the add-on + * </ul> + */ + public DownloadResolver newDownloader(EntityDriver driver, String addonName, Map<String,?> addonProperties); + + /** + * Registers a producer, to be tried before all other producers. + * + * A "producer" will generate the download targets to be tried, when installing a given entity + * or entity add-on. + * + * The function should not return null (instead see {@code BasicDownloadTargets.empty()}). + * + * @see registerResolver(Function) + */ + public void registerPrimaryProducer(Function<? super DownloadRequirement, ? extends DownloadTargets> resolver); + + /** + * Registers a producer, to be tried after all other registered producers have been tried. + * The function should not return null (instead see {@code BasicDownloadTargets.empty()}). + */ + public void registerProducer(Function<? super DownloadRequirement, ? extends DownloadTargets> resolver); + + /** + * Registers a producer for generating the expected filename of the download artifact. + * + * If all such registered producers return null, then default behaviour is to infer the download + * name from the first target in the {@link resolve(EntityDriver)} result. + */ + public void registerFilenameProducer(Function<? super DownloadRequirement, String> producer); + + /** + * Gives artifact meta-data for what is required to be downloaded. + * + * @author aled + */ + public interface DownloadRequirement { + /** + * The {@link EntityDriver} that this download is for. + */ + public EntityDriver getEntityDriver(); + + /** + * The name of the add-on to be downloaded, or null if it is the main installed. + * For example, can be used to specify nginx sticky-module or pcre download. + */ + public String getAddonName(); + + /** + * Default properties for this download. These will be made available when resolving the + * download template. + * + * For the main entity download, properties include: + * <ul> + * <li>fileSuffix: expected file suffix + * </ul> + * + * For an add-on, common properties include: + * <ul> + * <li>version: version of the add-on to be used + * <li>fileSuffix: expected file suffix + * </ul> + */ + public Map<String, ?> getProperties(); + } + + + /** + * Describes the download locations, and their order, to try. + * + * @author aled + */ + public interface DownloadTargets { + /** + * Gets the locations to try (in-order). + */ + public List<String> getPrimaryLocations(); + + /** + * Gets the locations to try (in-order), to be used only after all primary locations + * have been tried. + */ + public List<String> getFallbackLocations(); + + /** + * Indicates whether or not the results of this resolver are the last that should be used. + * If returns false, {@link resolve(EntityDriver)} will not iterate over any other resolvers. + * + * For example, useful in an enterprise to disable any other resolvers that would have + * resulted in going out to the public internet. + */ + public boolean canContinueResolving(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/proxying/EntityInitializer.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/proxying/EntityInitializer.java b/api/src/main/java/org/apache/brooklyn/api/entity/proxying/EntityInitializer.java new file mode 100644 index 0000000..19f39e0 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/proxying/EntityInitializer.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.brooklyn.api.entity.proxying; + +import java.util.Map; + +import org.apache.brooklyn.api.entity.basic.EntityLocal; + +/** + * Instances of this class supply logic which can be used to initialize entities. + * These can be added to an {@link EntitySpec} programmatically, or declared as part + * of YAML recipes in a <code>brooklyn.initializers</code> section. + * In the case of the latter, implementing classes should define a no-arg constructor + * or a {@link Map} constructor so that YAML parameters can be supplied. + **/ +public interface EntityInitializer { + + /** Applies initialization logic to a just-built entity. + * Invoked immediately after the "init" call on the AbstractEntity constructed. + * + * @param entity guaranteed to be the actual implementation instance, + * thus guaranteed to be castable to EntityInternal which is often desired, + * or to the type at hand (it is not even a proxy) + */ + public void apply(EntityLocal entity); + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/proxying/EntitySpec.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/proxying/EntitySpec.java b/api/src/main/java/org/apache/brooklyn/api/entity/proxying/EntitySpec.java new file mode 100644 index 0000000..0d10956 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/proxying/EntitySpec.java @@ -0,0 +1,473 @@ +/* + * 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.api.entity.proxying; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.annotation.Nullable; + +import org.apache.brooklyn.api.basic.AbstractBrooklynObjectSpec; +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.Group; +import org.apache.brooklyn.management.Task; +import org.apache.brooklyn.policy.Enricher; +import org.apache.brooklyn.policy.EnricherSpec; +import org.apache.brooklyn.policy.Policy; +import org.apache.brooklyn.policy.PolicySpec; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import brooklyn.config.ConfigKey; +import brooklyn.config.ConfigKey.HasConfigKey; +import brooklyn.location.Location; +import brooklyn.util.collections.MutableList; + +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + +/** + * Gives details of an entity to be created. It describes the entity's configuration, and is + * reusable to create multiple entities with the same configuration. + * + * To create an EntitySpec, it is strongly encouraged to use {@link #create(Class)} etc. + * Users who need to implement this are strongly encouraged to extend + * {@link org.apache.brooklyn.api.entity.proxying.EntitySpec}. + * + * @param <T> The type of entity to be created + * + * @author aled + */ +public class EntitySpec<T extends Entity> extends AbstractBrooklynObjectSpec<T,EntitySpec<T>> { + + private static final long serialVersionUID = -2247153452919128990L; + + private static final Logger log = LoggerFactory.getLogger(EntitySpec.class); + + /** + * Creates a new {@link EntitySpec} instance for an entity of the given type. The returned + * {@link EntitySpec} can then be customized. + * + * @param type An {@link Entity} interface + */ + public static <T extends Entity> EntitySpec<T> create(Class<T> type) { + return new EntitySpec<T>(type); + } + + /** + * Creates a new {@link EntitySpec} instance for an entity of the given type. The returned + * {@link EntitySpec} can then be customized. + * + * @param type An {@link Entity} interface + * @param implType An {@link Entity} implementation, which implements the {@code type} interface + */ + public static <T extends Entity, U extends T> EntitySpec<T> create(Class<T> type, Class<U> implType) { + return new EntitySpec<T>(type).impl(implType); + } + + /** + * Creates a new {@link EntitySpec} instance with the given config, for an entity of the given type. + * + * This is primarily for groovy code; equivalent to {@code EntitySpec.create(type).configure(config)}. + * + * @param config The spec's configuration (see {@link EntitySpec#configure(Map)}). + * @param type An {@link Entity} interface + */ + public static <T extends Entity> EntitySpec<T> create(Map<?,?> config, Class<T> type) { + return EntitySpec.create(type).configure(config); + } + + /** + * Copies entity spec so its configuration can be overridden without modifying the + * original entity spec. + */ + public static <T extends Entity> EntitySpec<T> create(EntitySpec<T> spec) { + EntitySpec<T> result = create(spec.getType()) + .displayName(spec.getDisplayName()) + .tags(spec.getTags()) + .additionalInterfaces(spec.getAdditionalInterfaces()) + .configure(spec.getConfig()) + .configure(spec.getFlags()) + .policySpecs(spec.getPolicySpecs()) + .policies(spec.getPolicies()) + .enricherSpecs(spec.getEnricherSpecs()) + .enrichers(spec.getEnrichers()) + .addInitializers(spec.getInitializers()) + .children(spec.getChildren()) + .members(spec.getMembers()) + .groups(spec.getGroups()) + .catalogItemId(spec.getCatalogItemId()) + .locations(spec.getLocations()); + + if (spec.getParent() != null) result.parent(spec.getParent()); + if (spec.getImplementation() != null) result.impl(spec.getImplementation()); + + return result; + } + + public static <T extends Entity> EntitySpec<T> newInstance(Class<T> type) { + return new EntitySpec<T>(type); + } + + private Class<? extends T> impl; + private Entity parent; + private final Map<String, Object> flags = Maps.newLinkedHashMap(); + private final Map<ConfigKey<?>, Object> config = Maps.newLinkedHashMap(); + private final List<Policy> policies = Lists.newArrayList(); + private final List<PolicySpec<?>> policySpecs = Lists.newArrayList(); + private final List<Enricher> enrichers = Lists.newArrayList(); + private final List<EnricherSpec<?>> enricherSpecs = Lists.newArrayList(); + private final List<Location> locations = Lists.newArrayList(); + private final Set<Class<?>> additionalInterfaces = Sets.newLinkedHashSet(); + private final List<EntityInitializer> entityInitializers = Lists.newArrayList(); + private final List<EntitySpec<?>> children = Lists.newArrayList(); + private final List<Entity> members = Lists.newArrayList(); + private final List<Group> groups = Lists.newArrayList(); + private volatile boolean immutable; + + public EntitySpec(Class<T> type) { + super(type); + } + + @SuppressWarnings("unchecked") + public Class<T> getType() { + return (Class<T>)super.getType(); + } + + @Override + protected void checkValidType(Class<? extends T> type) { + // EntitySpec does nothing. Other specs do check it's an implementation etc. + } + + /** + * @return The implementation of the entity; if not null. this overrides any defaults or other configuration + * + * @see ImplementedBy on the entity interface classes for how defaults are defined. + * @see EntityTypeRegistry for how implementations can be defined globally + */ + @Nullable + public Class<? extends T> getImplementation() { + return impl; + } + + /** + * @return Additional interfaces (other than just {@link #getType()}) that this entity implements; + * important for when accessing entity through a proxy to determine which interfaces the proxy exposes. + */ + public Set<Class<?>> getAdditionalInterfaces() { + return additionalInterfaces; + } + + /** @return {@link EntityInitializer} objects which customize the entity to be created */ + public List<EntityInitializer> getInitializers() { + return entityInitializers; + } + + public List<EntitySpec<?>> getChildren() { + return children; + } + + public List<Entity> getMembers() { + return members; + } + + public List<Group> getGroups() { + return groups; + } + + /** + * @return The entity's parent + */ + public Entity getParent() { + return parent; + } + + /** + * @return Read-only construction flags + * @see SetFromFlag declarations on the entity type + */ + public Map<String, ?> getFlags() { + return Collections.unmodifiableMap(flags); + } + + /** + * @return Read-only configuration values + */ + public Map<ConfigKey<?>, Object> getConfig() { + return Collections.unmodifiableMap(config); + } + + /** Clears the config map, removing any config previously set. */ + public void clearConfig() { + config.clear(); + } + + public List<PolicySpec<?>> getPolicySpecs() { + return policySpecs; + } + + public List<Policy> getPolicies() { + return policies; + } + + public List<EnricherSpec<?>> getEnricherSpecs() { + return enricherSpecs; + } + + public List<Enricher> getEnrichers() { + return enrichers; + } + + public List<Location> getLocations() { + return locations; + } + + public EntitySpec<T> impl(Class<? extends T> val) { + checkMutable(); + checkIsImplementation(checkNotNull(val, "impl"), getType()); + checkIsNewStyleImplementation(val); + impl = val; + return this; + } + + public EntitySpec<T> additionalInterfaces(Class<?>... vals) { + checkMutable(); + for (Class<?> val : vals) { + additionalInterfaces.add(val); + } + return this; + } + + public EntitySpec<T> additionalInterfaces(Iterable<Class<?>> val) { + checkMutable(); + additionalInterfaces.addAll(Sets.newLinkedHashSet(val)); + return this; + } + + public EntitySpec<T> addInitializer(EntityInitializer initializer) { + checkMutable(); + entityInitializers.add(initializer); + return this; + } + + public EntitySpec<T> addInitializers(Iterable<? extends EntityInitializer> initializers) { + checkMutable(); + Iterables.addAll(entityInitializers, initializers); + return this; + } + + /** The supplied class must have a public no-arg constructor. */ + public EntitySpec<T> addInitializer(Class<? extends EntityInitializer> initializerType) { + checkMutable(); + try { + entityInitializers.add(initializerType.newInstance()); + } catch (Exception e) { + throw Throwables.propagate(e); + } + return this; + } + + public EntitySpec<T> children(Iterable<? extends EntitySpec<?>> children) { + checkMutable(); + Iterables.addAll(this.children, children); + return this; + } + + /** The supplied class must have a public no-arg constructor. */ + public EntitySpec<T> child(EntitySpec<?> child) { + checkMutable(); + children.add(child); + return this; + } + + public EntitySpec<T> members(Iterable<? extends Entity> members) { + checkMutable(); + Iterables.addAll(this.members, members); + return this; + } + + public EntitySpec<T> member(Entity member) { + checkMutable(); + members.add(member); + return this; + } + + public EntitySpec<T> groups(Iterable<? extends Group> groups) { + checkMutable(); + Iterables.addAll(this.groups, groups); + return this; + } + + public EntitySpec<T> group(Group group) { + checkMutable(); + groups.add(group); + return this; + } + + public EntitySpec<T> parent(Entity val) { + checkMutable(); + parent = checkNotNull(val, "parent"); + return this; + } + + /** strings inserted as flags, config keys inserted as config keys; + * if you want to force one or the other, create a ConfigBag and convert to the appropriate map type */ + public EntitySpec<T> configure(Map<?,?> val) { + checkMutable(); + for (Map.Entry<?, ?> entry: val.entrySet()) { + if (entry.getKey()==null) throw new NullPointerException("Null key not permitted"); + if (entry.getKey() instanceof CharSequence) + flags.put(entry.getKey().toString(), entry.getValue()); + else if (entry.getKey() instanceof ConfigKey<?>) + config.put((ConfigKey<?>)entry.getKey(), entry.getValue()); + else if (entry.getKey() instanceof HasConfigKey<?>) + config.put(((HasConfigKey<?>)entry.getKey()).getConfigKey(), entry.getValue()); + else { + log.warn("Spec "+this+" ignoring unknown config key "+entry.getKey()); + } + } + return this; + } + + public EntitySpec<T> configure(CharSequence key, Object val) { + checkMutable(); + flags.put(checkNotNull(key, "key").toString(), val); + return this; + } + + public <V> EntitySpec<T> configure(ConfigKey<V> key, V val) { + checkMutable(); + config.put(checkNotNull(key, "key"), val); + return this; + } + + public <V> EntitySpec<T> configure(ConfigKey<V> key, Task<? extends V> val) { + checkMutable(); + config.put(checkNotNull(key, "key"), val); + return this; + } + + public <V> EntitySpec<T> configure(ConfigKey<V> key, Supplier<? extends V> val) { + checkMutable(); + config.put(checkNotNull(key, "key"), val); + return this; + } + + public <V> EntitySpec<T> configure(HasConfigKey<V> key, V val) { + checkMutable(); + config.put(checkNotNull(key, "key").getConfigKey(), val); + return this; + } + + public <V> EntitySpec<T> configure(HasConfigKey<V> key, Task<? extends V> val) { + checkMutable(); + config.put(checkNotNull(key, "key").getConfigKey(), val); + return this; + } + + + /** adds a policy to the spec */ + public <V> EntitySpec<T> policy(Policy val) { + checkMutable(); + policies.add(checkNotNull(val, "policy")); + return this; + } + + /** adds a policy to the spec */ + public <V> EntitySpec<T> policy(PolicySpec<?> val) { + checkMutable(); + policySpecs.add(checkNotNull(val, "policySpec")); + return this; + } + + /** adds the supplied policies to the spec */ + public <V> EntitySpec<T> policySpecs(Iterable<? extends PolicySpec<?>> val) { + checkMutable(); + policySpecs.addAll(MutableList.copyOf(checkNotNull(val, "policySpecs"))); + return this; + } + + /** adds the supplied policies to the spec */ + public <V> EntitySpec<T> policies(Iterable<? extends Policy> val) { + checkMutable(); + policies.addAll(MutableList.copyOf(checkNotNull(val, "policies"))); + return this; + } + + /** adds a policy to the spec */ + public <V> EntitySpec<T> enricher(Enricher val) { + checkMutable(); + enrichers.add(checkNotNull(val, "enricher")); + return this; + } + + /** adds a policy to the spec */ + public <V> EntitySpec<T> enricher(EnricherSpec<?> val) { + checkMutable(); + enricherSpecs.add(checkNotNull(val, "enricherSpec")); + return this; + } + + /** adds the supplied policies to the spec */ + public <V> EntitySpec<T> enricherSpecs(Iterable<? extends EnricherSpec<?>> val) { + checkMutable(); + enricherSpecs.addAll(MutableList.copyOf(checkNotNull(val, "enricherSpecs"))); + return this; + } + + /** adds the supplied policies to the spec */ + public <V> EntitySpec<T> enrichers(Iterable<? extends Enricher> val) { + checkMutable(); + enrichers.addAll(MutableList.copyOf(checkNotNull(val, "enrichers"))); + return this; + } + + /** adds a location to the spec */ + public <V> EntitySpec<T> location(Location val) { + checkMutable(); + locations.add(checkNotNull(val, "location")); + return this; + } + + /** adds the supplied locations to the spec */ + public <V> EntitySpec<T> locations(Iterable<? extends Location> val) { + checkMutable(); + locations.addAll(MutableList.copyOf(checkNotNull(val, "locations"))); + return this; + } + + /** "seals" this spec, preventing any future changes */ + public EntitySpec<T> immutable() { + immutable = true; + return this; + } + + private void checkMutable() { + if (immutable) throw new IllegalStateException("Cannot modify immutable entity spec "+this); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/proxying/EntityTypeRegistry.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/proxying/EntityTypeRegistry.java b/api/src/main/java/org/apache/brooklyn/api/entity/proxying/EntityTypeRegistry.java new file mode 100644 index 0000000..53cf6bf --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/proxying/EntityTypeRegistry.java @@ -0,0 +1,65 @@ +/* + * 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.api.entity.proxying; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.drivers.DriverDependentEntity; +import org.apache.brooklyn.api.entity.drivers.EntityDriver; + +import brooklyn.location.Location; + +/** + * A registry of the entity implementations to be used when creating an entity of a given type. + * + * A given implementation can only be associated with one entity type interface. + */ +public interface EntityTypeRegistry { + + /** + * Returns the implementation to be used for the given entity type. + * + * @param entity the {@link DriverDependentEntity} to create the {@link EntityDriver} for. + * @param location the {@link Location} where the {@link DriverDependentEntity} is running. + * @param <D> + * @return the creates EntityDriver. + * @throws IllegalArgumentException If no implementation registered, and the given interface is not annotated with {@link ImplementedBy} + * @throws IllegalStateException If the given type is not an interface, or if the implementation class is not a concrete class implementing it + */ + <T extends Entity> Class<? extends T> getImplementedBy(Class<T> type); + + /** + * Returns the interface of this entity implementation. + * E.g. for use as the fully qualified name in {@code entity.getEntityType().getName()}. + * + * @throws IllegalArgumentException If no interface is registered against this implementation, + * and no super-type of the class is annotated with {@link ImplementedBy} to point at the given class + */ + <T extends Entity> Class<? super T> getEntityTypeOf(Class<T> type); + + /** + * Registers the implementation to use for a given entity type. + * + * The implementation must be a non-abstract class implementing the given type, and must + * have a no-argument constructor. + * + * @throws IllegalArgumentException If this implementation has already been registered for a different type + * @throws IllegalStateException If the implClazz is not a concrete class, or does not implement type + */ + <T extends Entity> EntityTypeRegistry registerImplementation(Class<T> type, Class<? extends T> implClazz); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/proxying/ImplementedBy.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/proxying/ImplementedBy.java b/api/src/main/java/org/apache/brooklyn/api/entity/proxying/ImplementedBy.java new file mode 100644 index 0000000..c11c2fa --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/proxying/ImplementedBy.java @@ -0,0 +1,48 @@ +/* + * 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.api.entity.proxying; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import org.apache.brooklyn.api.entity.Entity; + +/** + * A pointer to the default implementation of an entity. + * + * A common naming convention is for the implementation class to have the suffix "Impl", + * but this is not required. + * + * See {@link EntityTypeRegistry} for how to override the implementation to be used, if + * the class referenced by this annotation is not desired. + * + * @author aled + */ +@Retention(RUNTIME) +@Target(TYPE) +public @interface ImplementedBy { + + /** + * The implementation type. + */ + Class<? extends Entity> value(); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/rebind/BrooklynObjectType.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/rebind/BrooklynObjectType.java b/api/src/main/java/org/apache/brooklyn/api/entity/rebind/BrooklynObjectType.java new file mode 100644 index 0000000..03323e9 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/rebind/BrooklynObjectType.java @@ -0,0 +1,69 @@ +/* + * 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.api.entity.rebind; + +import org.apache.brooklyn.api.basic.BrooklynObject; +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.Feed; +import org.apache.brooklyn.catalog.CatalogItem; +import org.apache.brooklyn.policy.Enricher; +import org.apache.brooklyn.policy.Policy; + +import brooklyn.location.Location; + +import com.google.common.annotations.Beta; +import com.google.common.base.CaseFormat; + +@Beta +public enum BrooklynObjectType { + ENTITY(Entity.class, "entities"), + LOCATION(Location.class, "locations"), + POLICY(Policy.class, "policies"), + ENRICHER(Enricher.class, "enrichers"), + FEED(Feed.class, "feeds"), + CATALOG_ITEM(CatalogItem.class, "catalog"), + UNKNOWN(null, "unknown"); + + private Class<? extends BrooklynObject> interfaceType; + private final String subPathName; + + BrooklynObjectType(Class<? extends BrooklynObject> interfaceType, String subPathName) { + this.interfaceType = interfaceType; + this.subPathName = subPathName; + } + public String toCamelCase() { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, this.name()); + } + + public String getSubPathName() { + return subPathName; + } + + public Class<? extends BrooklynObject> getInterfaceType() { + return interfaceType; + } + + public static BrooklynObjectType of(BrooklynObject instance) { + for (BrooklynObjectType t: values()) { + if (t.getInterfaceType()!=null && t.getInterfaceType().isInstance(instance)) + return t; + } + return UNKNOWN; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/rebind/ChangeListener.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/rebind/ChangeListener.java b/api/src/main/java/org/apache/brooklyn/api/entity/rebind/ChangeListener.java new file mode 100644 index 0000000..7a149a1 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/rebind/ChangeListener.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.brooklyn.api.entity.rebind; + +import org.apache.brooklyn.api.basic.BrooklynObject; + +/** + * Listener to be notified of changes within brooklyn, so that the new state + * of the entity/location/policy can be persisted. + * + * Users are not expected to implement this class. It is for use by the {@link RebindManager}. + * + * @author aled + */ +public interface ChangeListener { + + public static final ChangeListener NOOP = new ChangeListener() { + @Override public void onChanged(BrooklynObject instance) {} + @Override public void onManaged(BrooklynObject instance) {} + @Override public void onUnmanaged(BrooklynObject instance) {} + }; + + void onManaged(BrooklynObject instance); + + void onUnmanaged(BrooklynObject instance); + + void onChanged(BrooklynObject instance); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/rebind/PersistenceExceptionHandler.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/rebind/PersistenceExceptionHandler.java b/api/src/main/java/org/apache/brooklyn/api/entity/rebind/PersistenceExceptionHandler.java new file mode 100644 index 0000000..dafbdf2 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/rebind/PersistenceExceptionHandler.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.brooklyn.api.entity.rebind; + +import org.apache.brooklyn.api.basic.BrooklynObject; +import org.apache.brooklyn.mementos.Memento; + +import com.google.common.annotations.Beta; + +/** + * Handler called on all exceptions to do with persistence. + * + * @author aled + */ +@Beta +public interface PersistenceExceptionHandler { + + void stop(); + + void onGenerateMementoFailed(BrooklynObjectType type, BrooklynObject instance, Exception e); + + void onPersistMementoFailed(Memento memento, Exception e); + + void onPersistRawMementoFailed(BrooklynObjectType type, String id, Exception e); + + void onDeleteMementoFailed(String id, Exception e); +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/rebind/RebindContext.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/rebind/RebindContext.java b/api/src/main/java/org/apache/brooklyn/api/entity/rebind/RebindContext.java new file mode 100644 index 0000000..a2b39c5 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/rebind/RebindContext.java @@ -0,0 +1,52 @@ +/* + * 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.api.entity.rebind; + +import java.util.Map; + +import org.apache.brooklyn.api.basic.BrooklynObject; +import org.apache.brooklyn.mementos.BrooklynMementoPersister.LookupContext; + +import com.google.common.annotations.Beta; + +/** + * Gives access to things that are being currently rebinding. This is used during a + * rebind to wire everything back together again, e.g. to find the necessary entity + * instances even before they are available through + * {@code managementContext.getEntityManager().getEnties()}. + * <p> + * Users are not expected to implement this class. It is for use by {@link Rebindable} + * instances, and will generally be created by the {@link RebindManager}. + * <p> + */ +@Beta +public interface RebindContext { + + /** Returns an unmodifiable view of all objects by ID */ + Map<String,BrooklynObject> getAllBrooklynObjects(); + + Class<?> loadClass(String typeName) throws ClassNotFoundException; + + RebindExceptionHandler getExceptionHandler(); + + boolean isReadOnly(BrooklynObject item); + + LookupContext lookup(); + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/a76dac4f/api/src/main/java/org/apache/brooklyn/api/entity/rebind/RebindExceptionHandler.java ---------------------------------------------------------------------- diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/rebind/RebindExceptionHandler.java b/api/src/main/java/org/apache/brooklyn/api/entity/rebind/RebindExceptionHandler.java new file mode 100644 index 0000000..7feae31 --- /dev/null +++ b/api/src/main/java/org/apache/brooklyn/api/entity/rebind/RebindExceptionHandler.java @@ -0,0 +1,110 @@ +/* + * 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.api.entity.rebind; + +import java.util.List; + +import org.apache.brooklyn.api.basic.BrooklynObject; +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.Feed; +import org.apache.brooklyn.api.entity.basic.EntityLocal; +import org.apache.brooklyn.catalog.CatalogItem; +import org.apache.brooklyn.policy.Enricher; +import org.apache.brooklyn.policy.Policy; + +import brooklyn.location.Location; + +import com.google.common.annotations.Beta; + +/** + * Handler called on all exceptions to do with rebind. + * A handler instance is linked to a single rebind pass; + * it should not be invoked after {@link #onDone()}. + * <p> + * {@link #onStart()} must be invoked before the run. + * {@link #onDone()} must be invoked after a successful run, and it may throw. + * <p> + * Implementations may propagate errors or may catch them until {@link #onDone()} is invoked, + * and that may throw or report elsewhere, as appropriate. + * + * @author aled + */ +@Beta +public interface RebindExceptionHandler { + + void onLoadMementoFailed(BrooklynObjectType type, String msg, Exception e); + + /** + * @return the entity to use in place of the missing one, or null (if hasn't thrown an exception) + */ + Entity onDanglingEntityRef(String id); + + /** + * @return the location to use in place of the missing one, or null (if hasn't thrown an exception) + */ + Location onDanglingLocationRef(String id); + + /** + * @return the policy to use in place of the missing one, or null (if hasn't thrown an exception) + */ + Policy onDanglingPolicyRef(String id); + + /** + * @return the enricher to use in place of the missing one, or null (if hasn't thrown an exception) + */ + Enricher onDanglingEnricherRef(String id); + + /** + * @return the feed to use in place of the missing one, or null (if hasn't thrown an exception) + */ + Feed onDanglingFeedRef(String id); + + /** + * @return the catalog item to use in place of the missing one + */ + CatalogItem<?, ?> onDanglingCatalogItemRef(String id); + + void onCreateFailed(BrooklynObjectType type, String id, String instanceType, Exception e); + + void onNotFound(BrooklynObjectType type, String id); + + void onRebindFailed(BrooklynObjectType type, BrooklynObject instance, Exception e); + + void onAddPolicyFailed(EntityLocal entity, Policy policy, Exception e); + + void onAddEnricherFailed(EntityLocal entity, Enricher enricher, Exception e); + + void onAddFeedFailed(EntityLocal entity, Feed feed, Exception e); + + void onManageFailed(BrooklynObjectType type, BrooklynObject instance, Exception e); + + /** invoked for any high-level, unexpected, or otherwise uncaught failure; + * may be invoked on catching above errors */ + RuntimeException onFailed(Exception e); + + /** invoked before the rebind pass */ + void onStart(RebindContext context); + + /** invoked after the complete rebind pass, always on success and possibly on failure */ + void onDone(); + + List<Exception> getExceptions(); + List<String> getWarnings(); + +}
