You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/08/05 22:56:19 UTC
[15/20] incubator-brooklyn git commit: Package rename to
org.apache.brooklyn: usage/camp/
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
new file mode 100644
index 0000000..e30f7f2
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
@@ -0,0 +1,188 @@
+/*
+ * 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.camp.brooklyn.spi.dsl;
+
+import io.brooklyn.camp.spi.resolve.PlanInterpreter;
+import io.brooklyn.camp.spi.resolve.PlanInterpreter.PlanInterpreterAdapter;
+import io.brooklyn.camp.spi.resolve.interpret.PlanInterpretationNode;
+import io.brooklyn.camp.spi.resolve.interpret.PlanInterpretationNode.Role;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.BrooklynDslCommon;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.parse.DslParser;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.parse.FunctionWithArgs;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.parse.QuotedString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.javalang.Reflections;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Optional;
+
+/**
+ * {@link PlanInterpreter} which understands the $brooklyn DSL
+ */
+public class BrooklynDslInterpreter extends PlanInterpreterAdapter {
+
+ private static final Logger log = LoggerFactory.getLogger(BrooklynDslInterpreter.class);
+
+ @Override
+ public boolean isInterestedIn(PlanInterpretationNode node) {
+ return node.matchesPrefix("$brooklyn:") || node.getNewValue() instanceof FunctionWithArgs;
+ }
+
+ private static ThreadLocal<PlanInterpretationNode> currentNode = new ThreadLocal<PlanInterpretationNode>();
+ /** returns the current node, stored in a thread-local, to populate the dsl field of {@link BrooklynDslDeferredSupplier} instances */
+ public static PlanInterpretationNode currentNode() {
+ return currentNode.get();
+ }
+ /** sets the current node */
+ public static void currentNode(PlanInterpretationNode node) {
+ currentNode.set(node);
+ }
+ public static void currentNodeClear() {
+ currentNode.set(null);
+ }
+
+ @Override
+ public void applyYamlPrimitive(PlanInterpretationNode node) {
+ String expression = node.getNewValue().toString();
+
+ try {
+ currentNode.set(node);
+ Object parsedNode = new DslParser(expression).parse();
+ if ((parsedNode instanceof FunctionWithArgs) && ((FunctionWithArgs)parsedNode).getArgs()==null) {
+ if (node.getRoleInParent() == Role.MAP_KEY) {
+ node.setNewValue(parsedNode);
+ // will be handled later
+ } else {
+ throw new IllegalStateException("Invalid function-only expression '"+((FunctionWithArgs)parsedNode).getFunction()+"'");
+ }
+ } else {
+ node.setNewValue( evaluate(parsedNode, true) );
+ }
+ } catch (Exception e) {
+ log.warn("Error evaluating node (rethrowing) '"+expression+"': "+e);
+ Exceptions.propagateIfFatal(e);
+ throw new IllegalArgumentException("Error evaluating node '"+expression+"'", e);
+ } finally {
+ currentNodeClear();
+ }
+ }
+
+ @Override
+ public boolean applyMapEntry(PlanInterpretationNode node, Map<Object, Object> mapIn, Map<Object, Object> mapOut,
+ PlanInterpretationNode key, PlanInterpretationNode value) {
+ if (key.getNewValue() instanceof FunctionWithArgs) {
+ try {
+ currentNode.set(node);
+
+ FunctionWithArgs f = (FunctionWithArgs) key.getNewValue();
+ if (f.getArgs()!=null)
+ throw new IllegalStateException("Invalid map key function "+f.getFunction()+"; should not have arguments if taking arguments from map");
+
+ // means evaluation acts on values
+ List<Object> args = new ArrayList<Object>();
+ if (value.getNewValue() instanceof Iterable<?>) {
+ for (Object vi: (Iterable<?>)value.getNewValue())
+ args.add(vi);
+ } else {
+ args.add(value.getNewValue());
+ }
+
+ try {
+ // TODO in future we should support functions of the form 'Maps.clear', 'Maps.reset', 'Maps.remove', etc;
+ // default approach only supported if mapIn has single item and mapOut is empty
+ if (mapIn.size()!=1)
+ throw new IllegalStateException("Map-entry DSL syntax only supported with single item in map, not "+mapIn);
+ if (mapOut.size()!=0)
+ throw new IllegalStateException("Map-entry DSL syntax only supported with empty output map-so-far, not "+mapOut);
+
+ node.setNewValue( evaluate(new FunctionWithArgs(f.getFunction(), args), false) );
+ return false;
+ } catch (Exception e) {
+ log.warn("Error evaluating map-entry (rethrowing) '"+f.getFunction()+args+"': "+e);
+ Exceptions.propagateIfFatal(e);
+ throw new IllegalArgumentException("Error evaluating map-entry '"+f.getFunction()+args+"'", e);
+ }
+
+ } finally {
+ currentNodeClear();
+ }
+ }
+ return super.applyMapEntry(node, mapIn, mapOut, key, value);
+ }
+
+ public Object evaluate(Object f, boolean deepEvaluation) {
+ if (f instanceof FunctionWithArgs) {
+ return evaluateOn(BrooklynDslCommon.class, (FunctionWithArgs) f, deepEvaluation);
+ }
+
+ if (f instanceof List) {
+ Object o = BrooklynDslCommon.class;
+ for (Object i: (List<?>)f) {
+ o = evaluateOn( o, (FunctionWithArgs)i, deepEvaluation );
+ }
+ return o;
+ }
+
+ if (f instanceof QuotedString) {
+ return ((QuotedString)f).unwrapped();
+ }
+
+ throw new IllegalArgumentException("Unexpected element in parse tree: '"+f+"' (type "+(f!=null ? f.getClass() : null)+")");
+ }
+
+ public Object evaluateOn(Object o, FunctionWithArgs f, boolean deepEvaluation) {
+ if (f.getArgs()==null)
+ throw new IllegalStateException("Invalid function-only expression '"+f.getFunction()+"'");
+
+ Class<?> clazz;
+ if (o instanceof Class) {
+ clazz = (Class<?>)o;
+ } else {
+ clazz = o.getClass();
+ }
+ if (!(clazz.getPackage().getName().startsWith(BrooklynDslCommon.class.getPackage().getName())))
+ throw new IllegalArgumentException("Not permitted to invoke function on '"+clazz+"' (outside allowed package scope)");
+
+ String fn = f.getFunction();
+ fn = Strings.removeFromStart(fn, "$brooklyn:");
+ try {
+ List<Object> args = new ArrayList<Object>();
+ for (Object arg: f.getArgs()) {
+ args.add( deepEvaluation ? evaluate(arg, true) : arg );
+ }
+ Optional<Object> v = Reflections.invokeMethodWithArgs(o, fn, args);
+ if (v.isPresent()) return v.get();
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ throw Exceptions.propagate(new InvocationTargetException(e, "Error invoking '"+fn+"' on '"+o+"'"));
+ }
+
+ throw new IllegalArgumentException("No such function '"+fn+"' on "+o);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.java
new file mode 100644
index 0000000..e5194bf
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslUtils.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.camp.brooklyn.spi.dsl;
+
+import brooklyn.util.task.DeferredSupplier;
+
+import com.google.common.collect.Iterables;
+
+public class DslUtils {
+
+ /** true iff none of the args are deferred / tasks */
+ public static boolean resolved(Iterable<Object> args) {
+ return resolved(Iterables.toArray(args, Object.class));
+ }
+
+ /** true iff none of the args are deferred / tasks */
+ public static boolean resolved(final Object... args) {
+ boolean allResolved = true;
+ for (Object arg: args) {
+ if (arg instanceof DeferredSupplier<?>) {
+ allResolved = false;
+ break;
+ }
+ }
+ return allResolved;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
new file mode 100644
index 0000000..37bc043
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
@@ -0,0 +1,301 @@
+/*
+ * 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.camp.brooklyn.spi.dsl.methods;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
+import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator;
+import org.apache.brooklyn.camp.brooklyn.spi.creation.EntitySpecConfiguration;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslDeferredSupplier;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslUtils;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.Scope;
+import org.apache.commons.beanutils.BeanUtils;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.EntityDynamicType;
+import brooklyn.entity.trait.Configurable;
+import brooklyn.event.Sensor;
+import brooklyn.event.basic.DependentConfiguration;
+import brooklyn.management.Task;
+import brooklyn.management.TaskAdaptable;
+import brooklyn.management.TaskFactory;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.config.ConfigBag;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.flags.ClassCoercionException;
+import brooklyn.util.flags.FlagUtils;
+import brooklyn.util.flags.TypeCoercions;
+import brooklyn.util.javalang.Reflections;
+import brooklyn.util.task.DeferredSupplier;
+import brooklyn.util.text.StringEscapes.JavaStringEscapes;
+import brooklyn.util.text.Strings;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+/** static import functions which can be used in `$brooklyn:xxx` contexts */
+public class BrooklynDslCommon {
+
+ // Access specific entities
+
+ public static DslComponent entity(String id) {
+ return new DslComponent(Scope.GLOBAL, id);
+ }
+ public static DslComponent parent() {
+ return new DslComponent(Scope.PARENT, null);
+ }
+ public static DslComponent child(String id) {
+ return new DslComponent(Scope.CHILD, id);
+ }
+ public static DslComponent sibling(String id) {
+ return new DslComponent(Scope.SIBLING, id);
+ }
+ public static DslComponent descendant(String id) {
+ return new DslComponent(Scope.DESCENDANT, id);
+ }
+ public static DslComponent ancestor(String id) {
+ return new DslComponent(Scope.ANCESTOR, id);
+ }
+ // prefer the syntax above to the below now, but not deprecating the below
+ public static DslComponent component(String id) {
+ return component("global", id);
+ }
+ public static DslComponent component(String scope, String id) {
+ if (!DslComponent.Scope.isValid(scope)) {
+ throw new IllegalArgumentException(scope + " is not a valid scope");
+ }
+ return new DslComponent(DslComponent.Scope.fromString(scope), id);
+ }
+
+ // Access things on entities
+
+ public static BrooklynDslDeferredSupplier<?> config(String keyName) {
+ return new DslComponent(Scope.THIS, "").config(keyName);
+ }
+
+ public static BrooklynDslDeferredSupplier<?> attributeWhenReady(String sensorName) {
+ return new DslComponent(Scope.THIS, "").attributeWhenReady(sensorName);
+ }
+
+ /** Returns a {@link Sensor}, looking up the sensor on the context if available and using that,
+ * or else defining an untyped (Object) sensor */
+ public static BrooklynDslDeferredSupplier<Sensor<?>> sensor(String sensorName) {
+ return new DslComponent(Scope.THIS, "").sensor(sensorName);
+ }
+
+ /** Returns a {@link Sensor} declared on the type (e.g. entity class) declared in the first argument. */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public static Sensor<?> sensor(String clazzName, String sensorName) {
+ try {
+ // TODO Should use catalog's classloader, rather than Class.forName; how to get that? Should we return a future?!
+ Class<?> clazz = Class.forName(clazzName);
+ Sensor<?> sensor;
+ if (Entity.class.isAssignableFrom(clazz)) {
+ sensor = new EntityDynamicType((Class<? extends Entity>) clazz).getSensor(sensorName);
+ } else {
+ // Some non-entity classes (e.g. ServiceRestarter policy) declare sensors that other
+ // entities/policies/enrichers may wish to reference.
+ Map<String,Sensor<?>> sensors = EntityDynamicType.findSensors((Class)clazz, null);
+ sensor = sensors.get(sensorName);
+ }
+ if (sensor == null) {
+ // TODO could extend API to return a sensor of the given type; useful but makes API ambiguous in theory (unlikely in practise, but still...)
+ throw new IllegalArgumentException("Sensor " + sensorName + " not found on class " + clazzName);
+ }
+ return sensor;
+ } catch (ClassNotFoundException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ // Build complex things
+
+ public static EntitySpecConfiguration entitySpec(Map<String, Object> arguments) {
+ return new EntitySpecConfiguration(arguments);
+ }
+
+ /**
+ * Return an instance of the specified class with its fields set according
+ * to the {@link Map} or a {@link BrooklynDslDeferredSupplier} if the arguments are not
+ * yet fully resolved.
+ */
+ @SuppressWarnings("unchecked")
+ public static Object object(Map<String, Object> arguments) {
+ ConfigBag config = ConfigBag.newInstance(arguments);
+ String typeName = BrooklynYamlTypeInstantiator.InstantiatorFromKey.extractTypeName("object", config).orNull();
+ Map<String,Object> objectFields = (Map<String, Object>) config.getStringKeyMaybe("object.fields").or(MutableMap.of());
+ Map<String,Object> brooklynConfig = (Map<String, Object>) config.getStringKeyMaybe(BrooklynCampReservedKeys.BROOKLYN_CONFIG).or(MutableMap.of());
+ try {
+ // TODO Should use catalog's classloader, rather than Class.forName; how to get that? Should we return a future?!
+ Class<?> type = Class.forName(typeName);
+ if (!Reflections.hasNoArgConstructor(type)) {
+ throw new IllegalStateException(String.format("Cannot construct %s bean: No public no-arg constructor available", type));
+ }
+ if ((objectFields.isEmpty() || DslUtils.resolved(objectFields.values())) &&
+ (brooklynConfig.isEmpty() || DslUtils.resolved(brooklynConfig.values()))) {
+ return DslObject.create(type, objectFields, brooklynConfig);
+ } else {
+ return new DslObject(type, objectFields, brooklynConfig);
+ }
+ } catch (ClassNotFoundException e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ // String manipulation
+
+ /** Return the expression as a literal string without any further parsing. */
+ public static Object literal(Object expression) {
+ return expression;
+ }
+
+ /**
+ * Returns a formatted string or a {@link BrooklynDslDeferredSupplier} if the arguments
+ * are not yet fully resolved.
+ */
+ public static Object formatString(final String pattern, final Object...args) {
+ if (DslUtils.resolved(args)) {
+ // if all args are resolved, apply the format string now
+ return String.format(pattern, args);
+ } else {
+ return new DslFormatString(pattern, args);
+ }
+ }
+
+ /**
+ * Deferred execution of String formatting.
+ *
+ * @see DependentConfiguration#formatString(String, Object...)
+ */
+ protected static class DslFormatString extends BrooklynDslDeferredSupplier<String> {
+
+ private static final long serialVersionUID = -4849297712650560863L;
+
+ private String pattern;
+ private Object[] args;
+
+ public DslFormatString(String pattern, Object ...args) {
+ this.pattern = pattern;
+ this.args = args;
+ }
+
+ @Override
+ public Task<String> newTask() {
+ return DependentConfiguration.formatString(pattern, args);
+ }
+
+ @Override
+ public String toString() {
+ return "$brooklyn:formatString("+
+ JavaStringEscapes.wrapJavaString(pattern)+
+ (args==null || args.length==0 ? "" : ","+Strings.join(args, ","))+")";
+ }
+ }
+
+ /** @deprecated since 0.7.0; use {@link DslFormatString} */
+ @SuppressWarnings("serial")
+ @Deprecated
+ protected static class FormatString extends DslFormatString {
+ public FormatString(String pattern, Object[] args) {
+ super(pattern, args);
+ }
+ }
+
+ /** Deferred execution of Object creation. */
+ protected static class DslObject extends BrooklynDslDeferredSupplier<Object> {
+
+ private static final long serialVersionUID = 8878388748085419L;
+
+ private Class<?> type;
+ private Map<String,Object> fields, config;
+
+ public DslObject(Class<?> type, Map<String,Object> fields, Map<String,Object> config) {
+ this.type = type;
+ this.fields = MutableMap.copyOf(fields);
+ this.config = MutableMap.copyOf(config);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Task<Object> newTask() {
+ List<TaskAdaptable<Object>> tasks = Lists.newLinkedList();
+ for (Object value : Iterables.concat(fields.values(), config.values())) {
+ if (value instanceof TaskAdaptable) {
+ tasks.add((TaskAdaptable<Object>) value);
+ } else if (value instanceof TaskFactory) {
+ tasks.add(((TaskFactory<TaskAdaptable<Object>>) value).newTask());
+ }
+ }
+ Map<String,?> flags = MutableMap.<String,String>of("displayName", "building '"+type+"' with "+tasks.size()+" task"+(tasks.size()!=1?"s":""));
+ return DependentConfiguration.transformMultiple(flags, new Function<List<Object>, Object>() {
+ @Override
+ public Object apply(List<Object> input) {
+ Iterator<Object> values = input.iterator();
+ for (String name : fields.keySet()) {
+ Object value = fields.get(name);
+ if (value instanceof TaskAdaptable || value instanceof TaskFactory) {
+ fields.put(name, values.next());
+ } else if (value instanceof DeferredSupplier) {
+ fields.put(name, ((DeferredSupplier<?>) value).get());
+ }
+ }
+ for (String name : config.keySet()) {
+ Object value = config.get(name);
+ if (value instanceof TaskAdaptable || value instanceof TaskFactory) {
+ config.put(name, values.next());
+ } else if (value instanceof DeferredSupplier) {
+ config.put(name, ((DeferredSupplier<?>) value).get());
+ }
+ }
+ return create(type, fields, config);
+ }
+ }, tasks);
+ }
+
+ public static <T> T create(Class<T> type, Map<String,?> fields, Map<String,?> config) {
+ try {
+ T bean;
+ try {
+ bean = (T) TypeCoercions.coerce(fields, type);
+ } catch (ClassCoercionException ex) {
+ bean = Reflections.invokeConstructorWithArgs(type).get();
+ BeanUtils.populate(bean, fields);
+ }
+ if (bean instanceof Configurable && config.size() > 0) {
+ ConfigBag brooklyn = ConfigBag.newInstance(config);
+ FlagUtils.setFieldsFromFlags(bean, brooklyn);
+ FlagUtils.setAllConfigKeys((Configurable) bean, brooklyn, true);
+ }
+ return bean;
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "$brooklyn:object(\""+type.getName()+"\")";
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
new file mode 100644
index 0000000..4801a41
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
@@ -0,0 +1,320 @@
+/*
+ * 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.camp.brooklyn.spi.dsl.methods;
+
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslDeferredSupplier;
+
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.BrooklynTaskTags;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.entity.basic.Entities;
+import brooklyn.entity.basic.EntityInternal;
+import brooklyn.entity.basic.EntityPredicates;
+import brooklyn.event.AttributeSensor;
+import brooklyn.event.Sensor;
+import brooklyn.event.basic.DependentConfiguration;
+import brooklyn.event.basic.Sensors;
+import brooklyn.management.Task;
+import brooklyn.management.internal.EntityManagerInternal;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.task.TaskBuilder;
+import brooklyn.util.task.Tasks;
+import brooklyn.util.text.StringEscapes.JavaStringEscapes;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
+
+ private static final long serialVersionUID = -7715984495268724954L;
+
+ private final String componentId;
+ private final DslComponent scopeComponent;
+ private final Scope scope;
+
+ public DslComponent(String componentId) {
+ this(Scope.GLOBAL, componentId);
+ }
+
+ public DslComponent(Scope scope, String componentId) {
+ this(null, scope, componentId);
+ }
+
+ public DslComponent(DslComponent scopeComponent, Scope scope, String componentId) {
+ Preconditions.checkNotNull(scope, "scope");
+ this.scopeComponent = scopeComponent;
+ this.componentId = componentId;
+ this.scope = scope;
+ }
+
+ // ---------------------------
+
+ @Override
+ public Task<Entity> newTask() {
+ return TaskBuilder.<Entity>builder().name(toString()).tag(BrooklynTaskTags.TRANSIENT_TASK_TAG)
+ .body(new EntityInScopeFinder(scopeComponent, scope, componentId)).build();
+ }
+
+ protected static class EntityInScopeFinder implements Callable<Entity> {
+ protected final DslComponent scopeComponent;
+ protected final Scope scope;
+ protected final String componentId;
+
+ public EntityInScopeFinder(DslComponent scopeComponent, Scope scope, String componentId) {
+ this.scopeComponent = scopeComponent;
+ this.scope = scope;
+ this.componentId = componentId;
+ }
+
+ protected EntityInternal getEntity() {
+ if (scopeComponent!=null) {
+ return (EntityInternal)scopeComponent.get();
+ } else {
+ return entity();
+ }
+ }
+
+ @Override
+ public Entity call() throws Exception {
+ Iterable<Entity> entitiesToSearch = null;
+ switch (scope) {
+ case THIS:
+ return getEntity();
+ case PARENT:
+ return getEntity().getParent();
+ case GLOBAL:
+ entitiesToSearch = ((EntityManagerInternal)getEntity().getManagementContext().getEntityManager())
+ .getAllEntitiesInApplication( entity().getApplication() );
+ break;
+ case DESCENDANT:
+ entitiesToSearch = Entities.descendants(getEntity());
+ break;
+ case ANCESTOR:
+ entitiesToSearch = Entities.ancestors(getEntity());
+ break;
+ case SIBLING:
+ entitiesToSearch = getEntity().getParent().getChildren();
+ break;
+ case CHILD:
+ entitiesToSearch = getEntity().getChildren();
+ break;
+ default:
+ throw new IllegalStateException("Unexpected scope "+scope);
+ }
+
+ Optional<Entity> result = Iterables.tryFind(entitiesToSearch, EntityPredicates.configEqualTo(BrooklynCampConstants.PLAN_ID, componentId));
+
+ if (result.isPresent())
+ return result.get();
+
+ // TODO may want to block and repeat on new entities joining?
+ throw new NoSuchElementException("No entity matching id " + componentId+
+ (scope==Scope.GLOBAL ? "" : ", in scope "+scope+" wrt "+getEntity()+
+ (scopeComponent!=null ? " ("+scopeComponent+" from "+entity()+")" : "")));
+ }
+ }
+
+ // -------------------------------
+
+ // DSL words which move to a new component
+
+ public DslComponent entity(String scopeOrId) {
+ return new DslComponent(this, Scope.GLOBAL, scopeOrId);
+ }
+ public DslComponent child(String scopeOrId) {
+ return new DslComponent(this, Scope.CHILD, scopeOrId);
+ }
+ public DslComponent sibling(String scopeOrId) {
+ return new DslComponent(this, Scope.SIBLING, scopeOrId);
+ }
+ public DslComponent descendant(String scopeOrId) {
+ return new DslComponent(this, Scope.DESCENDANT, scopeOrId);
+ }
+ public DslComponent ancestor(String scopeOrId) {
+ return new DslComponent(this, Scope.ANCESTOR, scopeOrId);
+ }
+
+ @Deprecated /** @deprecated since 0.7.0 */
+ public DslComponent component(String scopeOrId) {
+ return new DslComponent(this, Scope.GLOBAL, scopeOrId);
+ }
+
+ public DslComponent parent() {
+ return new DslComponent(this, Scope.PARENT, "");
+ }
+
+ public DslComponent component(String scope, String id) {
+ if (!DslComponent.Scope.isValid(scope)) {
+ throw new IllegalArgumentException(scope + " is not a vlaid scope");
+ }
+ return new DslComponent(this, DslComponent.Scope.fromString(scope), id);
+ }
+
+ // DSL words which return things
+
+ public BrooklynDslDeferredSupplier<?> attributeWhenReady(final String sensorName) {
+ return new AttributeWhenReady(this, sensorName);
+ }
+ // class simply makes the memento XML files nicer
+ protected static class AttributeWhenReady extends BrooklynDslDeferredSupplier<Object> {
+ private static final long serialVersionUID = 1740899524088902383L;
+ private final DslComponent component;
+ private final String sensorName;
+ public AttributeWhenReady(DslComponent component, String sensorName) {
+ this.component = Preconditions.checkNotNull(component);
+ this.sensorName = sensorName;
+ }
+ @SuppressWarnings("unchecked")
+ @Override
+ public Task<Object> newTask() {
+ Entity targetEntity = component.get();
+ Sensor<?> targetSensor = targetEntity.getEntityType().getSensor(sensorName);
+ if (!(targetSensor instanceof AttributeSensor<?>)) {
+ targetSensor = Sensors.newSensor(Object.class, sensorName);
+ }
+ return (Task<Object>) DependentConfiguration.attributeWhenReady(targetEntity, (AttributeSensor<?>)targetSensor);
+ }
+ @Override
+ public String toString() {
+ return (component.scope==Scope.THIS ? "" : component.toString()+".") +
+ "attributeWhenReady("+JavaStringEscapes.wrapJavaString(sensorName)+")";
+ }
+ }
+
+ public BrooklynDslDeferredSupplier<?> config(final String keyName) {
+ return new DslConfigSupplier(this, keyName);
+ }
+ protected final static class DslConfigSupplier extends BrooklynDslDeferredSupplier<Object> {
+ private final DslComponent component;
+ private final String keyName;
+ private static final long serialVersionUID = -4735177561947722511L;
+
+ public DslConfigSupplier(DslComponent component, String keyName) {
+ this.component = Preconditions.checkNotNull(component);
+ this.keyName = keyName;
+ }
+
+ @Override
+ public Task<Object> newTask() {
+ return Tasks.builder().name("retrieving config for "+keyName).tag(BrooklynTaskTags.TRANSIENT_TASK_TAG).dynamic(false).body(new Callable<Object>() {
+ @Override
+ public Object call() throws Exception {
+ Entity targetEntity = component.get();
+ return targetEntity.getConfig(ConfigKeys.newConfigKey(Object.class, keyName));
+ }
+ }).build();
+ }
+
+ @Override
+ public String toString() {
+ return (component.scope==Scope.THIS ? "" : component.toString()+".") +
+ "config("+JavaStringEscapes.wrapJavaString(keyName)+")";
+ }
+ }
+
+ public BrooklynDslDeferredSupplier<Sensor<?>> sensor(final String sensorName) {
+ return new DslSensorSupplier(this, sensorName);
+ }
+ protected final static class DslSensorSupplier extends BrooklynDslDeferredSupplier<Sensor<?>> {
+ private final DslComponent component;
+ private final String sensorName;
+ private static final long serialVersionUID = -4735177561947722511L;
+
+ public DslSensorSupplier(DslComponent component, String sensorName) {
+ this.component = Preconditions.checkNotNull(component);
+ this.sensorName = sensorName;
+ }
+
+ @Override
+ public Task<Sensor<?>> newTask() {
+ return Tasks.<Sensor<?>>builder().name("looking up sensor for "+sensorName).dynamic(false).body(new Callable<Sensor<?>>() {
+ @Override
+ public Sensor<?> call() throws Exception {
+ Entity targetEntity = component.get();
+ Sensor<?> result = null;
+ if (targetEntity!=null) {
+ result = targetEntity.getEntityType().getSensor(sensorName);
+ }
+ if (result!=null) return result;
+ return Sensors.newSensor(Object.class, sensorName);
+ }
+ }).build();
+ }
+
+ @Override
+ public String toString() {
+ return (component.scope==Scope.THIS ? "" : component.toString()+".") +
+ "sensor("+JavaStringEscapes.wrapJavaString(sensorName)+")";
+ }
+ }
+
+ public static enum Scope {
+ GLOBAL ("global"),
+ CHILD ("child"),
+ PARENT ("parent"),
+ SIBLING ("sibling"),
+ DESCENDANT ("descendant"),
+ ANCESTOR("ancestor"),
+ THIS ("this");
+
+ public static final Set<Scope> VALUES = ImmutableSet.of(GLOBAL, CHILD, PARENT, SIBLING, DESCENDANT, ANCESTOR, THIS);
+
+ private final String name;
+
+ private Scope(String name) {
+ this.name = name;
+ }
+
+ public static Scope fromString(String name) {
+ return tryFromString(name).get();
+ }
+
+ public static Maybe<Scope> tryFromString(String name) {
+ for (Scope scope : VALUES)
+ if (scope.name.toLowerCase().equals(name.toLowerCase()))
+ return Maybe.of(scope);
+ return Maybe.absent(new IllegalArgumentException(name + " is not a valid scope"));
+ }
+
+ public static boolean isValid(String name) {
+ for (Scope scope : VALUES)
+ if (scope.name.toLowerCase().equals(name.toLowerCase()))
+ return true;
+ return false;
+ }
+ }
+
+
+ @Override
+ public String toString() {
+ return "$brooklyn:entity("+
+ (scopeComponent==null ? "" : JavaStringEscapes.wrapJavaString(scopeComponent.toString())+", ")+
+ (scope==Scope.GLOBAL ? "" : JavaStringEscapes.wrapJavaString(scope.toString())+", ")+
+ JavaStringEscapes.wrapJavaString(componentId)+
+ ")";
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/DslParser.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/DslParser.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/DslParser.java
new file mode 100644
index 0000000..345de05
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/DslParser.java
@@ -0,0 +1,144 @@
+/*
+ * 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.camp.brooklyn.spi.dsl.parse;
+
+import java.util.Collection;
+import java.util.List;
+
+import brooklyn.util.collections.MutableList;
+
+public class DslParser {
+ private final String expression;
+ int index = -1;
+
+ public DslParser(String expression) {
+ this.expression = expression;
+ }
+
+ public synchronized Object parse() {
+ if (index>=0)
+ throw new IllegalStateException("Parser can only be used once");
+
+ index++;
+ Object result = next();
+
+ if (index < expression.length())
+ throw new IllegalStateException("Unexpected character at position "+index+" in "+expression);
+
+ return result;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object next() {
+ int start = index;
+
+ skipWhitespace();
+ if (index >= expression.length())
+ throw new IllegalStateException("Unexpected end of expression to parse, looking for content since position "+start);
+
+ if (expression.charAt(index)=='"') {
+ // assume a string
+ int stringStart = index;
+ index++;
+ do {
+ if (index >= expression.length())
+ throw new IllegalStateException("Unexpected end of expression to parse, looking for close quote since position "+stringStart);
+ char c = expression.charAt(index);
+ if (c=='"') break;
+ if (c=='\\') index++;
+ index++;
+ } while (true);
+ index++;
+ return new QuotedString(expression.substring(stringStart, index));
+ }
+
+ // not a string, must be a function (or chain thereof)
+ List<FunctionWithArgs> result = new MutableList<FunctionWithArgs>();
+
+ int fnStart = index;
+ do {
+ if (index >= expression.length())
+ break;
+ char c = expression.charAt(index);
+ if (Character.isJavaIdentifierPart(c)) ;
+ // these chars also permitted
+ else if (".:".indexOf(c)>=0) ;
+ // other things e.g. whitespace, parentheses, etc, skip
+ else break;
+ index++;
+ } while (true);
+ String fn = expression.substring(fnStart, index);
+ if (fn.length()==0)
+ throw new IllegalStateException("Expected a function name at position "+start);
+ skipWhitespace();
+
+ if (index < expression.length() && expression.charAt(index)=='(') {
+ // collect arguments
+ int parenStart = index;
+ List<Object> args = new MutableList<Object>();
+ index ++;
+ do {
+ skipWhitespace();
+ if (index >= expression.length())
+ throw new IllegalStateException("Unexpected end of arguments to function '"+fn+"', no close parenthesis matching character at position "+parenStart);
+ char c = expression.charAt(index);
+ if (c==')') break;
+ if (c==',') {
+ if (args.isEmpty())
+ throw new IllegalStateException("Invalid character at position"+index);
+ index++;
+ } else {
+ if (!args.isEmpty())
+ throw new IllegalStateException("Expected , before position"+index);
+ }
+ args.add(next());
+ } while (true);
+ result.add(new FunctionWithArgs(fn, args));
+ index++;
+ skipWhitespace();
+ if (index >= expression.length())
+ return result;
+ char c = expression.charAt(index);
+ if (c=='.') {
+ // chained expression
+ int chainStart = index;
+ index++;
+ Object next = next();
+ if (next instanceof List) {
+ result.addAll((Collection<? extends FunctionWithArgs>) next);
+ return result;
+ } else {
+ throw new IllegalStateException("Expected functions following position"+chainStart);
+ }
+ } else {
+ // following word not something handled at this level; assume parent will handle (or throw) - e.g. a , or extra )
+ return result;
+ }
+ } else {
+ // it is just a word; return it with args as null
+ return new FunctionWithArgs(fn, null);
+ }
+ }
+
+ private void skipWhitespace() {
+ while (index<expression.length() && Character.isWhitespace(expression.charAt(index)))
+ index++;
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/FunctionWithArgs.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/FunctionWithArgs.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/FunctionWithArgs.java
new file mode 100644
index 0000000..41bc837
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/FunctionWithArgs.java
@@ -0,0 +1,57 @@
+/*
+ * 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.camp.brooklyn.spi.dsl.parse;
+
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+
+public class FunctionWithArgs {
+ private final String function;
+ private final List<Object> args;
+
+ public FunctionWithArgs(String function, List<Object> args) {
+ this.function = function;
+ this.args = args==null ? null : ImmutableList.copyOf(args);
+ }
+
+ public String getFunction() {
+ return function;
+ }
+
+ /**
+ * arguments (typically {@link QuotedString} or more {@link FunctionWithArgs}).
+ *
+ * null means it is a function in a map key which expects map value to be the arguments -- specified without parentheses;
+ * empty means parentheses already applied, with 0 args.
+ */
+ public List<Object> getArgs() {
+ return args;
+ }
+
+ @Override
+ public String toString() {
+ return function+(args==null ? "" : args);
+ }
+
+ public Object arg(int i) {
+ return args.get(i);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/QuotedString.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/QuotedString.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/QuotedString.java
new file mode 100644
index 0000000..8076bfb
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/parse/QuotedString.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.camp.brooklyn.spi.dsl.parse;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import brooklyn.util.text.StringEscapes.JavaStringEscapes;
+
+import com.google.common.base.Objects;
+
+public class QuotedString {
+ private final String s;
+
+ public QuotedString(String s) {
+ this.s = checkNotNull(s, "string");
+ }
+ @Override
+ public String toString() {
+ return s;
+ }
+ public String unwrapped() {
+ return JavaStringEscapes.unwrapJavaString(s);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return (obj instanceof QuotedString) && ((QuotedString)obj).toString().equals(toString());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(s);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AbstractBrooklynResourceLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AbstractBrooklynResourceLookup.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AbstractBrooklynResourceLookup.java
new file mode 100644
index 0000000..6f4670d
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AbstractBrooklynResourceLookup.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.camp.brooklyn.spi.lookup;
+
+import io.brooklyn.camp.spi.AbstractResource;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+import io.brooklyn.camp.spi.collection.AbstractResourceLookup;
+import brooklyn.management.ManagementContext;
+
+public abstract class AbstractBrooklynResourceLookup<T extends AbstractResource> extends AbstractResourceLookup<T> {
+
+ protected final PlatformRootSummary root;
+ protected final ManagementContext bmc;
+
+ public AbstractBrooklynResourceLookup(PlatformRootSummary root, ManagementContext bmc) {
+ this.root = root;
+ this.bmc = bmc;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
new file mode 100644
index 0000000..b7a276c
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AbstractTemplateBrooklynLookup.java
@@ -0,0 +1,62 @@
+/*
+ * 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.camp.brooklyn.spi.lookup;
+
+import io.brooklyn.camp.spi.AbstractResource;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+import io.brooklyn.camp.spi.collection.ResolvableLink;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.internal.CatalogUtils;
+import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.management.ManagementContext;
+
+public abstract class AbstractTemplateBrooklynLookup<T extends AbstractResource> extends AbstractBrooklynResourceLookup<T> {
+
+ private static final Logger log = LoggerFactory.getLogger(AbstractTemplateBrooklynLookup.class);
+
+ public AbstractTemplateBrooklynLookup(PlatformRootSummary root, ManagementContext bmc) {
+ super(root, bmc);
+ }
+
+ @Override
+ public T get(String id) {
+ CatalogItem<?,?> item = getCatalogItem(id);
+ if (item==null) {
+ log.warn("Could not find item '"+id+"' in Brooklyn catalog; returning null");
+ return null;
+ }
+ return adapt(item);
+ }
+
+ private CatalogItem<?, ?> getCatalogItem(String versionedId) {
+ return CatalogUtils.getCatalogItemOptionalVersion(bmc, versionedId);
+ }
+
+ public abstract T adapt(CatalogItem<?,?> item);
+
+ protected ResolvableLink<T> newLink(CatalogItem<? extends Entity,EntitySpec<?>> li) {
+ return newLink(li.getId(), li.getDisplayName());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AssemblyBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AssemblyBrooklynLookup.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AssemblyBrooklynLookup.java
new file mode 100644
index 0000000..e3130e0
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AssemblyBrooklynLookup.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.camp.brooklyn.spi.lookup;
+
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+import io.brooklyn.camp.spi.collection.ResolvableLink;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import brooklyn.entity.Application;
+import brooklyn.entity.Entity;
+import brooklyn.management.ManagementContext;
+
+
+public class AssemblyBrooklynLookup extends AbstractBrooklynResourceLookup<Assembly> {
+
+ private PlatformComponentBrooklynLookup pcs;
+
+ public AssemblyBrooklynLookup(PlatformRootSummary root, ManagementContext bmc, PlatformComponentBrooklynLookup pcs) {
+ super(root, bmc);
+ this.pcs = pcs;
+ }
+
+ @Override
+ public Assembly get(String id) {
+ Entity entity = bmc.getEntityManager().getEntity(id);
+ if (!(entity instanceof Application))
+ throw new IllegalArgumentException("Element for "+id+" is not an Application ("+entity+")");
+ Assembly.Builder<? extends Assembly> builder = Assembly.builder()
+ .created(new Date(entity.getCreationTime()))
+ .id(entity.getId())
+ .name(entity.getDisplayName());
+
+ builder.customAttribute("externalManagementUri", BrooklynUrlLookup.getUrl(bmc, entity));
+
+ for (Entity child: entity.getChildren())
+ // FIXME this walks the whole damn tree!
+ builder.add( pcs.get(child.getId() ));
+ return builder.build();
+ }
+
+ @Override
+ public List<ResolvableLink<Assembly>> links() {
+ List<ResolvableLink<Assembly>> result = new ArrayList<ResolvableLink<Assembly>>();
+ for (Application app: bmc.getApplications())
+ result.add(newLink(app.getId(), app.getDisplayName()));
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.java
new file mode 100644
index 0000000..1e0d6a1
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/AssemblyTemplateBrooklynLookup.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.camp.brooklyn.spi.lookup;
+
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+import io.brooklyn.camp.spi.collection.ResolvableLink;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynAssemblyTemplateInstantiator;
+import org.apache.brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.CatalogPredicates;
+import brooklyn.entity.Application;
+import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.management.ManagementContext;
+
+public class AssemblyTemplateBrooklynLookup extends AbstractTemplateBrooklynLookup<AssemblyTemplate> {
+
+ public AssemblyTemplateBrooklynLookup(PlatformRootSummary root, ManagementContext bmc) {
+ super(root, bmc);
+ }
+
+ @Override
+ public AssemblyTemplate adapt(CatalogItem<?,?> item) {
+ return AssemblyTemplate.builder().
+ name(item.getDisplayName()).
+ id(item.getId()).
+ description(item.getDescription()).
+ created(root.getCreated()).
+ instantiator(BrooklynAssemblyTemplateInstantiator.class).
+ build();
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ // why can I not pass an EntitySpec<? extends Application> to newLink(EntitySpec<?> spec) ?
+ // feels to me (alexheneveld) that `? extends Application` should be both covariant and contravariant to `?` ..
+ // but it's not, so we introduce this conversion method
+ protected ResolvableLink<AssemblyTemplate> newApplicationLink(CatalogItem<? extends Entity, EntitySpec<? extends Application>> li) {
+ return super.newLink((CatalogItem)li);
+ }
+
+ @Override
+ public List<ResolvableLink<AssemblyTemplate>> links() {
+ Iterable<CatalogItem<Application,EntitySpec<? extends Application>>> l = bmc.getCatalog().getCatalogItems(CatalogPredicates.IS_TEMPLATE);
+ List<ResolvableLink<AssemblyTemplate>> result = new ArrayList<ResolvableLink<AssemblyTemplate>>();
+ for (CatalogItem<Application,EntitySpec<? extends Application>> li: l)
+ result.add(newApplicationLink(li));
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/BrooklynUrlLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/BrooklynUrlLookup.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/BrooklynUrlLookup.java
new file mode 100644
index 0000000..f9bc390
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/BrooklynUrlLookup.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.camp.brooklyn.spi.lookup;
+
+import brooklyn.config.ConfigKey;
+import brooklyn.entity.Entity;
+import brooklyn.entity.basic.ConfigKeys;
+import brooklyn.management.ManagementContext;
+import brooklyn.util.net.Urls;
+
+public class BrooklynUrlLookup {
+
+ public static ConfigKey<String> BROOKLYN_ROOT_URL = ConfigKeys.newStringConfigKey("brooklyn.root.url");
+
+ public static String getUrl(ManagementContext bmc, Entity entity) {
+ String root = bmc.getConfig().getConfig(BROOKLYN_ROOT_URL);
+ if (root==null) return null;
+ return Urls.mergePaths(root, "#/",
+ "/v1/applications/"+entity.getApplicationId()+"/entities/"+entity.getId());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentBrooklynLookup.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentBrooklynLookup.java
new file mode 100644
index 0000000..6b26849
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentBrooklynLookup.java
@@ -0,0 +1,61 @@
+/*
+ * 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.camp.brooklyn.spi.lookup;
+
+import io.brooklyn.camp.spi.PlatformComponent;
+import io.brooklyn.camp.spi.PlatformComponent.Builder;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+import io.brooklyn.camp.spi.collection.ResolvableLink;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import brooklyn.entity.Entity;
+import brooklyn.management.ManagementContext;
+
+
+public class PlatformComponentBrooklynLookup extends AbstractBrooklynResourceLookup<PlatformComponent> {
+
+ public PlatformComponentBrooklynLookup(PlatformRootSummary root, ManagementContext bmc) {
+ super(root, bmc);
+ }
+
+ @Override
+ public PlatformComponent get(String id) {
+ Entity entity = bmc.getEntityManager().getEntity(id);
+ Builder<? extends PlatformComponent> builder = PlatformComponent.builder()
+ .created(new Date(entity.getCreationTime()))
+ .id(entity.getId())
+ .name(entity.getDisplayName())
+ .externalManagementUri(BrooklynUrlLookup.getUrl(bmc, entity));
+
+ for (Entity child: entity.getChildren())
+ // FIXME this walks the whole damn tree!
+ builder.add( get(child.getId() ));
+ return builder.build();
+ }
+
+ // platform components are not listed at the top level -- you have to walk the assemblies
+ @Override
+ public List<ResolvableLink<PlatformComponent>> links() {
+ return Collections.emptyList();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
new file mode 100644
index 0000000..b990464
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/lookup/PlatformComponentTemplateBrooklynLookup.java
@@ -0,0 +1,59 @@
+/*
+ * 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.camp.brooklyn.spi.lookup;
+
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+import io.brooklyn.camp.spi.collection.ResolvableLink;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.CatalogPredicates;
+import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.management.ManagementContext;
+
+public class PlatformComponentTemplateBrooklynLookup extends AbstractTemplateBrooklynLookup<PlatformComponentTemplate> {
+
+ public PlatformComponentTemplateBrooklynLookup(PlatformRootSummary root, ManagementContext bmc) {
+ super(root, bmc);
+ }
+
+ @Override
+ public PlatformComponentTemplate adapt(CatalogItem<?,?> item) {
+ return PlatformComponentTemplate.builder().
+ name(item.getDisplayName()).
+ id(item.getId()).
+ description(item.getDescription()).
+ created(root.getCreated()).
+ build();
+ }
+
+ @Override
+ public List<ResolvableLink<PlatformComponentTemplate>> links() {
+ Iterable<CatalogItem<Entity,EntitySpec<?>>> l = bmc.getCatalog().getCatalogItems(CatalogPredicates.IS_ENTITY);
+ List<ResolvableLink<PlatformComponentTemplate>> result = new ArrayList<ResolvableLink<PlatformComponentTemplate>>();
+ for (CatalogItem<Entity,EntitySpec<?>> li: l)
+ result.add(newLink(li));
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java
new file mode 100644
index 0000000..c04c134
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/platform/BrooklynImmutableCampPlatform.java
@@ -0,0 +1,109 @@
+/*
+ * 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.camp.brooklyn.spi.platform;
+
+import io.brooklyn.camp.CampPlatform;
+import io.brooklyn.camp.spi.ApplicationComponent;
+import io.brooklyn.camp.spi.ApplicationComponentTemplate;
+import io.brooklyn.camp.spi.Assembly;
+import io.brooklyn.camp.spi.AssemblyTemplate;
+import io.brooklyn.camp.spi.PlatformComponent;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+import io.brooklyn.camp.spi.PlatformRootSummary;
+import io.brooklyn.camp.spi.PlatformTransaction;
+import io.brooklyn.camp.spi.collection.BasicResourceLookup;
+import io.brooklyn.camp.spi.collection.ResourceLookup;
+import io.brooklyn.camp.spi.collection.ResourceLookup.EmptyResourceLookup;
+
+import org.apache.brooklyn.camp.brooklyn.spi.lookup.AssemblyBrooklynLookup;
+import org.apache.brooklyn.camp.brooklyn.spi.lookup.AssemblyTemplateBrooklynLookup;
+import org.apache.brooklyn.camp.brooklyn.spi.lookup.PlatformComponentBrooklynLookup;
+import org.apache.brooklyn.camp.brooklyn.spi.lookup.PlatformComponentTemplateBrooklynLookup;
+
+import brooklyn.camp.brooklyn.api.HasBrooklynManagementContext;
+import brooklyn.management.ManagementContext;
+
+/** Immutable CAMP platform which reflects things in the underlying Brooklyn system */
+public class BrooklynImmutableCampPlatform extends CampPlatform implements HasBrooklynManagementContext {
+
+ private final ManagementContext bmc;
+ private final AssemblyTemplateBrooklynLookup ats;
+ private final PlatformComponentTemplateBrooklynLookup pcts;
+ private final BasicResourceLookup<ApplicationComponentTemplate> acts;
+ private final PlatformComponentBrooklynLookup pcs;
+ private final AssemblyBrooklynLookup assemblies;
+
+ public BrooklynImmutableCampPlatform(PlatformRootSummary root, ManagementContext managementContext) {
+ super(root);
+ this.bmc = managementContext;
+
+ // these come from brooklyn
+ pcts = new PlatformComponentTemplateBrooklynLookup(root(), getBrooklynManagementContext());
+ ats = new AssemblyTemplateBrooklynLookup(root(), getBrooklynManagementContext());
+ pcs = new PlatformComponentBrooklynLookup(root(), getBrooklynManagementContext());
+ assemblies = new AssemblyBrooklynLookup(root(), getBrooklynManagementContext(), pcs);
+
+ // ACT's are not known in brooklyn (everything comes in as config) -- to be extended to support!
+ acts = new BasicResourceLookup<ApplicationComponentTemplate>();
+ }
+
+ // --- brooklyn setup
+
+ public ManagementContext getBrooklynManagementContext() {
+ return bmc;
+ }
+
+ // --- camp comatibility setup
+
+ @Override
+ public ResourceLookup<PlatformComponentTemplate> platformComponentTemplates() {
+ return pcts;
+ }
+
+ @Override
+ public ResourceLookup<ApplicationComponentTemplate> applicationComponentTemplates() {
+ return acts;
+ }
+
+ @Override
+ public ResourceLookup<AssemblyTemplate> assemblyTemplates() {
+ return ats;
+ }
+
+ @Override
+ public ResourceLookup<PlatformComponent> platformComponents() {
+ return pcs;
+ }
+
+ @Override
+ public ResourceLookup<ApplicationComponent> applicationComponents() {
+ return new EmptyResourceLookup<ApplicationComponent>();
+ }
+
+ @Override
+ public ResourceLookup<Assembly> assemblies() {
+ return assemblies;
+ }
+
+ @Override
+ public PlatformTransaction transaction() {
+ throw new IllegalStateException(this+" does not support adding new items");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/resources/META-INF/services/io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/resources/META-INF/services/io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver b/usage/camp/src/main/resources/META-INF/services/io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver
deleted file mode 100644
index 1a48ccb..0000000
--- a/usage/camp/src/main/resources/META-INF/services/io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver
+++ /dev/null
@@ -1,22 +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.
-#
-io.brooklyn.camp.brooklyn.spi.creation.service.BrooklynServiceTypeResolver
-io.brooklyn.camp.brooklyn.spi.creation.service.CatalogServiceTypeResolver
-io.brooklyn.camp.brooklyn.spi.creation.service.ChefServiceTypeResolver
-io.brooklyn.camp.brooklyn.spi.creation.service.JavaServiceTypeResolver
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/main/resources/META-INF/services/org.apache.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/resources/META-INF/services/org.apache.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver b/usage/camp/src/main/resources/META-INF/services/org.apache.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver
new file mode 100644
index 0000000..9c941df
--- /dev/null
+++ b/usage/camp/src/main/resources/META-INF/services/org.apache.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+org.apache.brooklyn.camp.brooklyn.spi.creation.service.BrooklynServiceTypeResolver
+org.apache.brooklyn.camp.brooklyn.spi.creation.service.CatalogServiceTypeResolver
+org.apache.brooklyn.camp.brooklyn.spi.creation.service.ChefServiceTypeResolver
+org.apache.brooklyn.camp.brooklyn.spi.creation.service.JavaServiceTypeResolver
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/e406d1ad/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
deleted file mode 100644
index 226ec67..0000000
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/AbstractYamlRebindTest.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package io.brooklyn.camp.brooklyn;
-
-import io.brooklyn.camp.spi.Assembly;
-import io.brooklyn.camp.spi.AssemblyTemplate;
-
-import java.io.Reader;
-import java.io.StringReader;
-import java.util.Set;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-
-import brooklyn.catalog.internal.CatalogUtils;
-import brooklyn.entity.Entity;
-import brooklyn.entity.basic.BrooklynTaskTags;
-import brooklyn.entity.basic.Entities;
-import brooklyn.entity.basic.StartableApplication;
-import brooklyn.entity.rebind.RebindOptions;
-import brooklyn.entity.rebind.RebindTestFixture;
-import brooklyn.management.ManagementContext;
-import brooklyn.management.Task;
-import brooklyn.management.internal.LocalManagementContext;
-import brooklyn.util.ResourceUtils;
-import brooklyn.util.config.ConfigBag;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-
-public class AbstractYamlRebindTest extends RebindTestFixture<StartableApplication> {
-
- private static final Logger LOG = LoggerFactory.getLogger(AbstractYamlTest.class);
- protected static final String TEST_VERSION = "0.1.2";
-
- protected BrooklynCampPlatform platform;
- protected BrooklynCampPlatformLauncherNoServer launcher;
- private boolean forceUpdate;
-
- @BeforeMethod(alwaysRun = true)
- @Override
- public void setUp() throws Exception {
- super.setUp();
- launcher = new BrooklynCampPlatformLauncherNoServer() {
- @Override
- protected LocalManagementContext newMgmtContext() {
- return (LocalManagementContext) mgmt();
- }
- };
- launcher.launch();
- platform = launcher.getCampPlatform();
- }
-
- @AfterMethod(alwaysRun = true)
- @Override
- public void tearDown() throws Exception {
- try {
- super.tearDown();
- } finally {
- if (launcher != null) launcher.stopServers();
- }
- }
-
- protected StartableApplication rebind(RebindOptions options) throws Exception {
- StartableApplication result = super.rebind(options);
- if (launcher != null) {
- launcher.stopServers();
- launcher = new BrooklynCampPlatformLauncherNoServer() {
- @Override
- protected LocalManagementContext newMgmtContext() {
- return (LocalManagementContext) mgmt();
- }
- };
- launcher.launch();
- platform = launcher.getCampPlatform();
- }
- return result;
- }
-
- @Override
- protected StartableApplication createApp() {
- return null;
- }
-
- protected ManagementContext mgmt() {
- return (newManagementContext != null) ? newManagementContext : origManagementContext;
- }
-
- ///////////////////////////////////////////////////
- // TODO code below is duplicate of AbstractYamlTest
- ///////////////////////////////////////////////////
-
- protected void waitForApplicationTasks(Entity app) {
- Set<Task<?>> tasks = BrooklynTaskTags.getTasksInEntityContext(origManagementContext.getExecutionManager(), app);
- getLogger().info("Waiting on " + tasks.size() + " task(s)");
- for (Task<?> t : tasks) {
- t.blockUntilEnded();
- }
- }
-
- protected Reader loadYaml(String yamlFileName, String ...extraLines) throws Exception {
- String input = new ResourceUtils(this).getResourceAsString(yamlFileName).trim();
- StringBuilder builder = new StringBuilder(input);
- for (String l: extraLines)
- builder.append("\n").append(l);
- return new StringReader(builder.toString());
- }
-
- protected Entity createAndStartApplication(String... multiLineYaml) throws Exception {
- return createAndStartApplication(joinLines(multiLineYaml));
- }
-
- protected Entity createAndStartApplication(String input) throws Exception {
- return createAndStartApplication(new StringReader(input));
- }
-
- protected Entity createAndStartApplication(Reader input) throws Exception {
- AssemblyTemplate at = platform.pdp().registerDeploymentPlan(input);
- Assembly assembly;
- try {
- assembly = at.getInstantiator().newInstance().instantiate(at, platform);
- } catch (Exception e) {
- getLogger().warn("Unable to instantiate " + at + " (rethrowing): " + e);
- throw e;
- }
- getLogger().info("Test - created " + assembly);
- final Entity app = origManagementContext.getEntityManager().getEntity(assembly.getId());
- getLogger().info("App - " + app);
-
- // wait for app to have started
- Set<Task<?>> tasks = origManagementContext.getExecutionManager().getTasksWithAllTags(ImmutableList.of(
- BrooklynTaskTags.EFFECTOR_TAG,
- BrooklynTaskTags.tagForContextEntity(app),
- BrooklynTaskTags.tagForEffectorCall(app, "start", ConfigBag.newInstance(ImmutableMap.of("locations", ImmutableMap.of())))));
- Iterables.getOnlyElement(tasks).get();
-
- return app;
- }
-
- protected Entity createStartWaitAndLogApplication(Reader input) throws Exception {
- Entity app = createAndStartApplication(input);
- waitForApplicationTasks(app);
-
- getLogger().info("App started:");
- Entities.dumpInfo(app);
-
- return app;
- }
-
- protected void addCatalogItems(Iterable<String> catalogYaml) {
- addCatalogItems(joinLines(catalogYaml));
- }
-
- protected void addCatalogItems(String... catalogYaml) {
- addCatalogItems(joinLines(catalogYaml));
- }
-
- protected void addCatalogItems(String catalogYaml) {
- mgmt().getCatalog().addItems(catalogYaml, forceUpdate);
- }
-
- protected void deleteCatalogEntity(String catalogItem) {
- mgmt().getCatalog().deleteCatalogItem(catalogItem, TEST_VERSION);
- }
-
- protected Logger getLogger() {
- return LOG;
- }
-
- private String joinLines(Iterable<String> catalogYaml) {
- return Joiner.on("\n").join(catalogYaml);
- }
-
- private String joinLines(String[] catalogYaml) {
- return Joiner.on("\n").join(catalogYaml);
- }
-
- protected String ver(String id) {
- return CatalogUtils.getVersionedId(id, TEST_VERSION);
- }
-
- public void forceCatalogUpdate() {
- forceUpdate = true;
- }
-
-}