You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2015/11/17 23:51:22 UTC
[07/14] incubator-brooklyn git commit: Working CampTypePlanTransformer
Working CampTypePlanTransformer
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/904c45e9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/904c45e9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/904c45e9
Branch: refs/heads/master
Commit: 904c45e961f5e6b596e6c7238ebf86ee7a6ce7bc
Parents: 817e9bd
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Wed Nov 4 10:47:22 2015 -0500
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Tue Nov 10 17:13:02 2015 +0000
----------------------------------------------------------------------
.../apache/brooklyn/api/entity/EntitySpec.java | 2 -
.../internal/AbstractBrooklynObjectSpec.java | 16 ++
.../brooklyn/api/typereg/RegisteredType.java | 20 +-
.../api/typereg/RegisteredTypeConstraint.java | 5 +
.../core/catalog/internal/CatalogUtils.java | 17 +-
.../brooklyn/core/plan/PlanToSpecFactory.java | 2 +-
.../entity/DelegatingEntitySpecResolver.java | 2 +-
.../core/typereg/BasicBrooklynTypeRegistry.java | 8 +-
.../core/typereg/BasicRegisteredType.java | 27 +-
.../JavaClassNameTypePlanTransformer.java | 90 +++++++
.../core/typereg/JavaTypePlanTransformer.java | 112 --------
.../core/typereg/RegisteredTypeConstraints.java | 59 +++-
.../core/typereg/RegisteredTypePredicates.java | 32 ++-
.../brooklyn/core/typereg/RegisteredTypes.java | 143 +++++++++-
...lyn.core.typereg.BrooklynTypePlanTransformer | 19 ++
.../brooklyn/core/sensor/StaticSensorTest.java | 8 +-
.../core/test/entity/TestEntityImpl.java | 1 -
.../typereg/JavaTypePlanTransformerTest.java | 6 +-
.../api/AssemblyTemplateSpecInstantiator.java | 6 +-
.../BrooklynAssemblyTemplateInstantiator.java | 17 +-
.../brooklyn/spi/creation/CampCatalogUtils.java | 54 +---
.../spi/creation/CampInternalUtils.java | 247 +++++++++++++++++
.../brooklyn/spi/creation/CampResolver.java | 142 ++++++++++
.../spi/creation/CampToSpecTransformer.java | 15 +-
.../spi/creation/CampTypePlanTransformer.java | 90 +++++++
.../camp/brooklyn/spi/creation/CampUtils.java | 267 -------------------
.../service/UrlServiceSpecResolver.java | 19 +-
...lyn.core.typereg.BrooklynTypePlanTransformer | 19 ++
.../camp/brooklyn/AbstractYamlTest.java | 42 ++-
.../camp/brooklyn/EntitiesYamlTest.java | 2 +
.../camp/brooklyn/ReferencedYamlTest.java | 1 +
.../CatalogOsgiVersionMoreEntityTest.java | 18 +-
.../catalog/CatalogYamlLocationTest.java | 3 +-
.../test/lite/TestAppAssemblyInstantiator.java | 10 +-
.../rest/util/BrooklynRestResourceUtils.java | 2 +-
.../exceptions/PropagatedRuntimeException.java | 6 +
36 files changed, 995 insertions(+), 534 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java b/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java
index a38e52e..500952d 100644
--- a/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java
+++ b/api/src/main/java/org/apache/brooklyn/api/entity/EntitySpec.java
@@ -337,8 +337,6 @@ public class EntitySpec<T extends Entity> extends AbstractBrooklynObjectSpec<T,E
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()) {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java b/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
index 6ba5a3c..de2954d 100644
--- a/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
+++ b/api/src/main/java/org/apache/brooklyn/api/internal/AbstractBrooklynObjectSpec.java
@@ -23,8 +23,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.lang.reflect.Modifier;
import java.util.List;
+import java.util.Map;
import java.util.Set;
+import org.apache.brooklyn.api.mgmt.EntityManager;
+import org.apache.brooklyn.api.objs.BrooklynObject;
import org.apache.brooklyn.api.objs.SpecParameter;
import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.exceptions.Exceptions;
@@ -34,6 +37,15 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
+/** Defines a spec for creating a {@link BrooklynObject}.
+ * <p>
+ * In addition to the contract defined by the code,
+ * subclasses should provide a public static <code>create(Class)</code>
+ * method to create an instance of the spec for the target type indicated by the argument.
+ * <p>
+ * The spec is then passed to type-specific methods,
+ * e.g. {@link EntityManager#createEntity(org.apache.brooklyn.api.entity.EntitySpec)}
+ * to create a managed instance of the target type. */
public abstract class AbstractBrooklynObjectSpec<T,SpecT extends AbstractBrooklynObjectSpec<T,SpecT>> implements Serializable {
private static final long serialVersionUID = 3010955277740333030L;
@@ -160,5 +172,9 @@ public abstract class AbstractBrooklynObjectSpec<T,SpecT extends AbstractBrookly
public int hashCode() {
return Objects.hashCode(getCatalogItemId(), getDisplayName(), getType(), getTags());
}
+
+ /** 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 abstract SpecT configure(Map<?,?> val);
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
index a1fc5cf..ed84179 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredType.java
@@ -19,11 +19,13 @@
package org.apache.brooklyn.api.typereg;
import java.util.Collection;
+import java.util.Set;
import javax.annotation.Nullable;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.objs.BrooklynObject;
import org.apache.brooklyn.api.objs.Identifiable;
import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
@@ -44,22 +46,24 @@ public interface RegisteredType extends Identifiable {
String getDescription();
String getIconUrl();
- /** @return the java type or a supertype thereof that this registered type represents.
+ /** @return all declared supertypes or super-interfaces of this registered type,
+ * consisting of a collection of {@link Class} or {@link RegisteredType}
* <p>
- * For beans, this is the type that the {@link BrooklynTypeRegistry} will create.
- * For specs, this is what the spec that will be created points at
- * (e.g. the concrete {@link Entity}, not the {@link EntitySpec});
+ * This should normally include at least one {@link Class} object:
+ * For beans, this should include the java type that the {@link BrooklynTypeRegistry} will create.
+ * For specs, this should refer to the {@link BrooklynObject} type that the created spec will point at
+ * (e.g. the concrete {@link Entity}, not the {@link EntitySpec}).
* <p>
- * In some cases this may return an interface or a super-type of what will actually be created,
+ * This may not necessarily return the most specific java class or classes;
* such as if the concrete type is private and callers should know only about a particular public interface,
* or if precise type details are unavailable and all that is known at creation is some higher level interface/supertype
* (e.g. this may return {@link Entity} even though the spec points at a specific subclass,
* for instance because the YAML has not yet been parsed or OSGi bundles downloaded).
* <p>
- * If nothing is known, this will return null, and the item will not participate in type filtering.
+ * This may include other registered types such as marker interfaces.
*/
@Beta
- @Nullable Class<?> getJavaType();
+ @Nullable Set<Object> getSuperTypes();
/**
* @return True if the item has been deprecated (i.e. its use is discouraged)
@@ -84,5 +88,5 @@ public interface RegisteredType extends Identifiable {
/** data for the implementation; may be more specific */
Object getPlanData();
}
-
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
index 851d88a..8bcff38 100644
--- a/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
+++ b/api/src/main/java/org/apache/brooklyn/api/typereg/RegisteredTypeConstraint.java
@@ -42,4 +42,9 @@ public interface RegisteredTypeConstraint {
* if we have already attempted to resolve a given type,
* the instantiator can avoid recursive cycles */
@Nonnull public Set<String> getEncounteredTypes();
+
+ /** A special loader to use, if available.
+ * For internal use only; implementations should be a BrooklynClassLoadingContext */
+ @Nullable public Object getLoader();
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
index db4b72a..2955895 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogUtils.java
@@ -69,7 +69,11 @@ public class CatalogUtils {
}
public static BrooklynClassLoadingContext newClassLoadingContext(ManagementContext mgmt, RegisteredType item) {
- return newClassLoadingContext(mgmt, item.getId(), item.getLibraries());
+ return newClassLoadingContext(mgmt, item.getId(), item.getLibraries(), null);
+ }
+
+ public static BrooklynClassLoadingContext newClassLoadingContext(ManagementContext mgmt, RegisteredType item, BrooklynClassLoadingContext loader) {
+ return newClassLoadingContext(mgmt, item.getId(), item.getLibraries(), loader);
}
public static BrooklynClassLoadingContext getClassLoadingContext(Entity entity) {
@@ -85,16 +89,23 @@ public class CatalogUtils {
}
public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, String catalogItemId, Collection<? extends OsgiBundleWithUrl> libraries) {
+ return newClassLoadingContext(mgmt, catalogItemId, libraries, null);
+ }
+
+ public static BrooklynClassLoadingContext newClassLoadingContext(@Nullable ManagementContext mgmt, String catalogItemId, Collection<? extends OsgiBundleWithUrl> libraries, BrooklynClassLoadingContext loader) {
BrooklynClassLoadingContextSequential result = new BrooklynClassLoadingContextSequential(mgmt);
if (libraries!=null && !libraries.isEmpty()) {
result.add(new OsgiBrooklynClassLoadingContext(mgmt, catalogItemId, libraries));
}
- BrooklynClassLoadingContext loader = BrooklynLoaderTracker.getLoader();
- if (loader != null) {
+ if (loader !=null) {
result.add(loader);
}
+ BrooklynClassLoadingContext threadLocalLoader = BrooklynLoaderTracker.getLoader();
+ if (threadLocalLoader != null) {
+ result.add(threadLocalLoader);
+ }
result.addSecondary(JavaBrooklynClassLoadingContext.create(mgmt));
return result;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
index 5614b97..7aef313 100644
--- a/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
+++ b/core/src/main/java/org/apache/brooklyn/core/plan/PlanToSpecFactory.java
@@ -111,7 +111,7 @@ public class PlanToSpecFactory {
(Strings.isNonBlank(e.getMessage()) ? " ("+e.getMessage()+")" : ""));
} catch (Throwable e) {
Exceptions.propagateIfFatal(e);
- otherProblemsFromTransformers.add(new PropagatedRuntimeException("Transformer for "+t.getShortDescription()+" gave an error creating this plan: "+
+ otherProblemsFromTransformers.add(new PropagatedRuntimeException("Transformer for "+t.getShortDescription()+" gave an error creating this plan: ",
Exceptions.collapseText(e), e));
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java
index 2ccc468..415f209 100644
--- a/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java
+++ b/core/src/main/java/org/apache/brooklyn/core/resolve/entity/DelegatingEntitySpecResolver.java
@@ -105,7 +105,7 @@ public class DelegatingEntitySpecResolver extends AbstractEntitySpecResolver {
resolversWhoDontSupport.add(resolver.getName() + " (returned null)");
}
} catch (Exception e) {
- otherProblemsFromResolvers.add(new PropagatedRuntimeException("Transformer for "+resolver.getName()+" gave an error creating this plan: "+
+ otherProblemsFromResolvers.add(new PropagatedRuntimeException("Transformer for "+resolver.getName()+" gave an error creating this plan: ",
Exceptions.collapseText(e), e));
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
index 08b6103..0ca8bc7 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicBrooklynTypeRegistry.java
@@ -112,7 +112,7 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
// TODO implement using java if permitted
}
}
- constraint = RegisteredTypeConstraints.extendedWithSpecSuperType(constraint, specSuperType);
+ constraint = RegisteredTypeConstraints.withSpecSuperType(constraint, specSuperType);
Maybe<Object> result = TypePlanTransformers.transform(mgmt, type, constraint);
if (result.isPresent()) return (SpecT) result.get();
@@ -120,6 +120,10 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
// fallback: look up in (legacy) catalog
// TODO remove once all transformers are available in the new style
CatalogItem item = (CatalogItem) mgmt.getCatalog().getCatalogItem(type.getSymbolicName(), type.getVersion());
+ if (item==null) {
+ // if not in catalog (because loading new one?) then throw original
+ result.get();
+ }
try {
return (SpecT) BasicBrooklynCatalog.internalCreateSpecWithTransformers(mgmt, item, constraint.getEncounteredTypes());
} catch (Exception e) {
@@ -127,7 +131,7 @@ public class BasicBrooklynTypeRegistry implements BrooklynTypeRegistry {
// for now, combine this failure with the original
try {
result.get();
- // won't come here
+ // above will throw -- so won't come here
throw new IllegalStateException("should have failed getting type resolution for "+type);
} catch (Exception e0) {
// prefer older exception, until the new transformer is the primary pathway
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
index ac0b266..54b04a3 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicRegisteredType.java
@@ -20,19 +20,27 @@ package org.apache.brooklyn.core.typereg;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.brooklyn.util.core.config.ConfigBag;
import org.apache.brooklyn.util.javalang.JavaClassNames;
+import com.google.common.collect.ImmutableSet;
+
+/** Instances are usually created by methods in {@link RegisteredTypes}. */
public class BasicRegisteredType implements RegisteredType {
final String symbolicName;
final String version;
final RegisteredTypeKind kind;
- List<OsgiBundleWithUrl> bundles;
+ Set<Object> superTypes = MutableSet.of();
+ List<OsgiBundleWithUrl> bundles = MutableList.of();
String displayName;
String description;
String iconUrl;
@@ -41,14 +49,12 @@ public class BasicRegisteredType implements RegisteredType {
TypeImplementationPlan implementationPlan;
- // TODO ensure this is re-populated on rebind? or remove?
- transient Class<?> javaType;
+ private transient ConfigBag cache = new ConfigBag();
- public BasicRegisteredType(RegisteredTypeKind kind, String symbolicName, String version, Class<?> javaType, TypeImplementationPlan implementationPlan) {
+ BasicRegisteredType(RegisteredTypeKind kind, String symbolicName, String version, TypeImplementationPlan implementationPlan) {
this.kind = kind;
this.symbolicName = symbolicName;
this.version = version;
- this.javaType = javaType;
this.implementationPlan = implementationPlan;
}
@@ -74,7 +80,7 @@ public class BasicRegisteredType implements RegisteredType {
@Override
public Collection<OsgiBundleWithUrl> getLibraries() {
- return bundles;
+ return ImmutableSet.copyOf(bundles);
}
@Override
@@ -103,8 +109,12 @@ public class BasicRegisteredType implements RegisteredType {
}
@Override
- public Class<?> getJavaType() {
- return javaType;
+ public Set<Object> getSuperTypes() {
+ return ImmutableSet.copyOf(superTypes);
+ }
+
+ public ConfigBag getCache() {
+ return cache;
}
@Override
@@ -117,6 +127,7 @@ public class BasicRegisteredType implements RegisteredType {
return JavaClassNames.simpleClassName(this)+"["+getId()+
(isDisabled() ? ";DISABLED" : "")+
(isDeprecated() ? ";deprecated" : "")+
+ (getPlan()!=null ? ";"+getPlan().getPlanFormat() : "")+
"]";
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
new file mode 100644
index 0000000..a84c9f5
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/JavaClassNameTypePlanTransformer.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.typereg;
+
+import java.util.List;
+
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.util.text.Identifiers;
+
+/**
+ * Instantiates classes from a registered type which simply
+ * defines the java class name and OSGi bundles to use.
+ * <p>
+ * This is used where a {@link RegisteredType} is defined simply with the name of a java class
+ * e.g. with a no-arg constructor -- no YAML etc just the name of the class.
+ */
+public class JavaClassNameTypePlanTransformer extends AbstractTypePlanTransformer {
+
+ public static final String FORMAT = "java-type-name";
+
+ public static class JavaTypeNameImplementation extends AbstractCustomImplementationPlan<String> {
+ public JavaTypeNameImplementation(String javaType) { super(FORMAT, javaType); }
+ }
+
+ public JavaClassNameTypePlanTransformer() {
+ super(FORMAT, "Java type name", "Expects a java type name in a format suitable for use with ClassLoader.loadClass");
+ }
+
+ @Override
+ protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeConstraint context) {
+ if (type.getPlan().getPlanData() instanceof String &&
+ ((String)type.getPlan().getPlanData()).matches(Identifiers.JAVA_BINARY_REGEX)) {
+ return 0.1;
+ }
+ return 0;
+ }
+
+ @Override
+ protected double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeConstraint context) {
+ return 0;
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ @Override
+ protected AbstractBrooklynObjectSpec<?,?> createSpec(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+ return RegisteredTypes.newSpecInstance(mgmt, (Class<? extends BrooklynObject>) getType(type, context));
+ }
+
+ @Override
+ protected Object createBean(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+ return getType(type, context).newInstance();
+ }
+
+ private Class<?> getType(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
+ return RegisteredTypes.loadActualJavaType((String)type.getPlan().getPlanData(), mgmt, type, context);
+ }
+
+
+ // not supported as a catalog format (yet? should we?)
+
+ @Override
+ public double scoreForTypeDefinition(String formatCode, Object catalogData) {
+ return 0;
+ }
+
+ @Override
+ public List<RegisteredType> createFromTypeDefinition(String formatCode, Object catalogData) {
+ throw new UnsupportedTypePlanException("this transformer does not support YAML catalog additions");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformer.java b/core/src/main/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformer.java
deleted file mode 100644
index febf52a..0000000
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformer.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.brooklyn.core.typereg;
-
-import java.util.List;
-
-import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
-import org.apache.brooklyn.api.typereg.RegisteredType;
-import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
-import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
-import org.apache.brooklyn.util.text.Identifiers;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Instantiates classes from a registered type which simply
- * defines the java class name and OSGi bundles to use.
- * <p>
- * This is used where a {@link RegisteredType} is defined simply with the name of a java class
- * e.g. with a no-arg constructor -- no YAML etc just the name of the class.
- */
-public class JavaTypePlanTransformer extends AbstractTypePlanTransformer {
-
- private static final Logger log = LoggerFactory.getLogger(JavaTypePlanTransformer.class);
- public static final String FORMAT = "java-type-name";
-
- public static class JavaTypeNameImplementation extends AbstractCustomImplementationPlan<String> {
- private transient Class<?> cachedType;
- public JavaTypeNameImplementation(String javaType) {
- super(FORMAT, javaType);
- }
- public Class<?> getCachedType() {
- return cachedType;
- }
- }
-
- public JavaTypePlanTransformer() {
- super(FORMAT, "Java type name", "Expects a java type name in a format suitable for use with ClassLoader.loadClass");
- }
-
- @Override
- protected double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeConstraint context) {
- if (type.getPlan().getPlanData() instanceof String &&
- ((String)type.getPlan().getPlanData()).matches(Identifiers.JAVA_BINARY_REGEX)) {
- return 0.1;
- }
- return 0;
- }
-
- @Override
- protected double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeConstraint context) {
- return 0;
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- protected AbstractBrooklynObjectSpec<?,?> createSpec(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
- Class targetType = getType(type, context);
- Class specType = RegisteredTypeConstraints.spec((Class)targetType).getJavaSuperType();
- AbstractBrooklynObjectSpec result = (AbstractBrooklynObjectSpec) specType.getConstructor(Class.class).newInstance(targetType);
- return result;
- }
-
- @Override
- protected Object createBean(RegisteredType type, RegisteredTypeConstraint context) throws Exception {
- return getType(type, context).newInstance();
- }
-
- private Class<?> getType(RegisteredType type, RegisteredTypeConstraint context) {
- if (type.getPlan() instanceof JavaTypeNameImplementation) {
- Class<?> cachedType = ((JavaTypeNameImplementation)type.getPlan()).getCachedType();
- if (cachedType==null) {
- log.debug("Storing cached type "+cachedType+" for "+type);
- cachedType = loadType(type, context);
- }
- return cachedType;
- }
- return loadType(type, context);
- }
- private Class<?> loadType(RegisteredType type, RegisteredTypeConstraint context) {
- return CatalogUtils.newClassLoadingContext(mgmt, type).loadClass( ((String)type.getPlan().getPlanData()) );
- }
-
-
- // TODO not supported as a catalog format (yet)
- @Override
- public double scoreForTypeDefinition(String formatCode, Object catalogData) {
- return 0;
- }
-
- @Override
- public List<RegisteredType> createFromTypeDefinition(String formatCode, Object catalogData) {
- throw new UnsupportedTypePlanException("this transformer does not support YAML catalog additions");
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
index c880b7e..5b4c0cf 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypeConstraints.java
@@ -31,7 +31,9 @@ import org.apache.brooklyn.api.objs.BrooklynObject;
import org.apache.brooklyn.api.objs.BrooklynObjectType;
import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.brooklyn.util.javalang.JavaClassNames;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,6 +48,7 @@ public class RegisteredTypeConstraints {
@Nullable private RegisteredTypeKind kind;
@Nullable private Class<?> javaSuperType;
@Nonnull private Set<String> encounteredTypes = ImmutableSet.of();
+ @Nullable BrooklynClassLoadingContext loader;
private BasicRegisteredTypeConstraint() {}
@@ -55,6 +58,7 @@ public class RegisteredTypeConstraints {
this.kind = source.getKind();
this.javaSuperType = source.getJavaSuperType();
this.encounteredTypes = source.getEncounteredTypes();
+ this.loader = (BrooklynClassLoadingContext) source.getLoader();
}
@Override
@@ -75,8 +79,13 @@ public class RegisteredTypeConstraints {
}
@Override
+ public BrooklynClassLoadingContext getLoader() {
+ return loader;
+ }
+
+ @Override
public String toString() {
- return super.toString()+"["+kind+","+javaSuperType+","+encounteredTypes+"]";
+ return JavaClassNames.cleanSimpleClassName(this)+"["+kind+","+javaSuperType+","+encounteredTypes+"]";
}
}
@@ -97,7 +106,11 @@ public class RegisteredTypeConstraints {
result.encounteredTypes = encounteredTypes.asUnmodifiable();
return result;
}
-
+
+ public static RegisteredTypeConstraint alreadyVisited(Set<String> encounteredTypeSymbolicNames, BrooklynClassLoadingContext loader) {
+ return withLoader(alreadyVisited(encounteredTypeSymbolicNames), loader);
+ }
+
private static RegisteredTypeConstraint of(RegisteredTypeKind kind, Class<? extends BrooklynObject> javaSuperType) {
BasicRegisteredTypeConstraint result = new BasicRegisteredTypeConstraint();
result.kind = kind;
@@ -109,7 +122,7 @@ public class RegisteredTypeConstraints {
return of(RegisteredTypeKind.SPEC, javaSuperType);
}
- public static <T extends AbstractBrooklynObjectSpec<?,?>> RegisteredTypeConstraint extendedWithSpecSuperType(@Nullable RegisteredTypeConstraint source, @Nullable Class<T> specSuperType) {
+ public static <T extends AbstractBrooklynObjectSpec<?,?>> RegisteredTypeConstraint withSpecSuperType(@Nullable RegisteredTypeConstraint source, @Nullable Class<T> specSuperType) {
Class<?> superType = lookupTargetTypeForSpec(specSuperType);
BasicRegisteredTypeConstraint constraint = new BasicRegisteredTypeConstraint(source);
if (source==null) source = constraint;
@@ -131,8 +144,9 @@ public class RegisteredTypeConstraints {
return source;
}
- /** given a spec, returns the class of the item it targets, for instance {@link EntitySpec} for {@link Entity} */
- private static <T extends AbstractBrooklynObjectSpec<?,?>> Class<? extends BrooklynObject> lookupTargetTypeForSpec(Class<T> specSuperType) {
+ /** given a spec, returns the class of the item it targets, for instance returns {@link Entity} given {@link EntitySpec};
+ * see also {@link #lookupSpecTypeForTarget(Class)} */
+ static <T extends AbstractBrooklynObjectSpec<?,?>> Class<? extends BrooklynObject> lookupTargetTypeForSpec(Class<T> specSuperType) {
if (specSuperType==null) return BrooklynObject.class;
BrooklynObjectType best = null;
@@ -154,4 +168,39 @@ public class RegisteredTypeConstraints {
return best.getInterfaceType();
}
+ /** given a {@link BrooklynObject}, returns the spec class which would generate it, for instance returns {@link EntitySpec} given {@link Entity},
+ * or null if not known */
+ static <BO extends BrooklynObject> Class<? extends AbstractBrooklynObjectSpec<?,?>> lookupSpecTypeForTarget(Class<BO> targetSuperType) {
+ if (targetSuperType==null) return null;
+ BrooklynObjectType best = null;
+
+ for (BrooklynObjectType t: BrooklynObjectType.values()) {
+ if (t.getSpecType()==null) continue;
+ if (!t.getInterfaceType().isAssignableFrom(targetSuperType)) continue;
+ // on equality, exit immediately
+ if (t.getInterfaceType().equals(targetSuperType)) return t.getSpecType();
+ // else pick which is best
+ if (best==null) { best = t; continue; }
+ // if t is more specific, it is better (handles case when e.g. a Policy is a subclass of Entity)
+ if (best.getSpecType().isAssignableFrom(t.getSpecType())) { best = t; continue; }
+ }
+ if (best==null) {
+ log.warn("Unexpected target supertype ("+targetSuperType+"); unable to infer spec type");
+ return null;
+ }
+ // the spec is more specific, but we're not familiar with it here; return the best
+ return best.getSpecType();
+ }
+
+ public static RegisteredTypeConstraint loader(BrooklynClassLoadingContext loader) {
+ BasicRegisteredTypeConstraint result = new BasicRegisteredTypeConstraint();
+ result.loader = loader;
+ return result;
+ }
+
+ public static RegisteredTypeConstraint withLoader(RegisteredTypeConstraint constraint, BrooklynClassLoadingContext loader) {
+ ((BasicRegisteredTypeConstraint)constraint).loader = loader;
+ return constraint;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
index 3560e47..2e7c038 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypePredicates.java
@@ -109,36 +109,46 @@ public class RegisteredTypePredicates {
}
}
- public static <T> Predicate<RegisteredType> javaType(final Predicate<Class<T>> filter) {
- return new JavaTypeMatches(filter);
+ public static <T> Predicate<RegisteredType> anySuperType(final Predicate<Class<T>> filter) {
+ return new AnySuperTypeMatches(filter);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
- public static Predicate<RegisteredType> javaTypeAssignableFrom(final Class<?> filter) {
- return javaType((Predicate)Predicates.assignableFrom(filter));
+ public static Predicate<RegisteredType> assignableFrom(final Class<?> filter) {
+ return anySuperType((Predicate)Predicates.assignableFrom(filter));
}
- private static class JavaTypeMatches implements Predicate<RegisteredType> {
+ private static class AnySuperTypeMatches implements Predicate<RegisteredType> {
private final Predicate<Class<?>> filter;
@SuppressWarnings({ "rawtypes", "unchecked" })
- private <T> JavaTypeMatches(Predicate filter) {
+ private <T> AnySuperTypeMatches(Predicate filter) {
this.filter = filter;
}
@Override
public boolean apply(@Nullable RegisteredType item) {
if (item==null) return false;
- return (item != null) && filter.apply(item.getJavaType());
+ for (Object o: item.getSuperTypes()) {
+ if (o instanceof Class) {
+ if (filter.apply((Class<?>)o)) return true;
+ }
+ }
+ for (Object o: item.getSuperTypes()) {
+ if (o instanceof RegisteredType) {
+ if (apply((RegisteredType)o)) return true;
+ }
+ }
+ return false;
}
}
- public static final Predicate<RegisteredType> IS_APPLICATION = javaTypeAssignableFrom(Application.class);
+ public static final Predicate<RegisteredType> IS_APPLICATION = assignableFrom(Application.class);
// TODO do we need this? introduced already deprecated in 0.9.0 so can be removed, or enabled
@Deprecated
public static final Predicate<RegisteredType> IS_TEMPLATE = IS_APPLICATION;
- public static final Predicate<RegisteredType> IS_ENTITY = javaTypeAssignableFrom(Entity.class);
- public static final Predicate<RegisteredType> IS_LOCATION = javaTypeAssignableFrom(Location.class);
- public static final Predicate<RegisteredType> IS_POLICY = javaTypeAssignableFrom(Policy.class);
+ public static final Predicate<RegisteredType> IS_ENTITY = assignableFrom(Entity.class);
+ public static final Predicate<RegisteredType> IS_LOCATION = assignableFrom(Location.class);
+ public static final Predicate<RegisteredType> IS_POLICY = assignableFrom(Policy.class);
public static Predicate<RegisteredType> entitledToSee(final ManagementContext mgmt) {
return new EntitledToSee(mgmt);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
index 7e35084..0ebbdcd 100644
--- a/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
+++ b/core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java
@@ -18,19 +18,50 @@
*/
package org.apache.brooklyn.core.typereg;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
import org.apache.brooklyn.api.catalog.CatalogItem;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.objs.BrooklynObject;
import org.apache.brooklyn.api.typereg.BrooklynTypeRegistry.RegisteredTypeKind;
import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl;
import org.apache.brooklyn.api.typereg.RegisteredType;
import org.apache.brooklyn.api.typereg.RegisteredType.TypeImplementationPlan;
-import org.apache.brooklyn.core.typereg.JavaTypePlanTransformer.JavaTypeNameImplementation;
+import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.typereg.JavaClassNameTypePlanTransformer.JavaTypeNameImplementation;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.yaml.Yamls;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.reflect.TypeToken;
+/**
+ * Utility and preferred creation mechanisms for working with {@link RegisteredType} instances.
+ * <p>
+ * Use {@link #bean(String, String, TypeImplementationPlan, Class)} and {@link #spec(String, String, TypeImplementationPlan, Class)}
+ * to create {@link RegisteredType} instances.
+ * <p>
+ * See {@link #isSubTypeOf(RegisteredType, Class)} or {@link #isSubTypeOf(RegisteredType, RegisteredType)} to
+ * inspect the type hierarchy.
+ */
public class RegisteredTypes {
+ @SuppressWarnings("serial")
+ static ConfigKey<Class<?>> ACTUAL_JAVA_TYPE = ConfigKeys.newConfigKey(new TypeToken<Class<?>>() {}, "java.type.actual",
+ "The actual Java type which will be instantiated (bean) or pointed at (spec)");
+
/** @deprecated since it was introduced in 0.9.0; for backwards compatibility only, may be removed at any point */
@Deprecated
static final Function<CatalogItem<?,?>,RegisteredType> CI_TO_RT = new Function<CatalogItem<?,?>, RegisteredType>() {
@@ -53,7 +84,7 @@ public class RegisteredTypes {
throw new IllegalStateException("Unsupported catalog item "+item+" when trying to create RegisteredType");
}
- BasicRegisteredType type = (BasicRegisteredType) spec(item.getSymbolicName(), item.getVersion(), item.getCatalogItemJavaType(), impl);
+ BasicRegisteredType type = (BasicRegisteredType) spec(item.getSymbolicName(), item.getVersion(), impl, item.getCatalogItemJavaType());
type.bundles = item.getLibraries()==null ? ImmutableList.<OsgiBundleWithUrl>of() : ImmutableList.<OsgiBundleWithUrl>copyOf(item.getLibraries());
type.displayName = item.getDisplayName();
type.description = item.getDescription();
@@ -66,13 +97,49 @@ public class RegisteredTypes {
// maybe: tags ?
return type;
}
-
- public static RegisteredType bean(String symbolicName, String version, Class<?> javaType, TypeImplementationPlan plan) {
- return new BasicRegisteredType(RegisteredTypeKind.BEAN, symbolicName, version, javaType, plan);
+
+ /** Preferred mechanism for defining a bean {@link RegisteredType} */
+ public static RegisteredType bean(String symbolicName, String version, TypeImplementationPlan plan, @Nullable Class<?> superType) {
+ return addSuperType(new BasicRegisteredType(RegisteredTypeKind.BEAN, symbolicName, version, plan), superType);
}
- public static RegisteredType spec(String symbolicName, String version, Class<?> javaType, TypeImplementationPlan plan) {
- return new BasicRegisteredType(RegisteredTypeKind.SPEC, symbolicName, version, javaType, plan);
+ public static RegisteredType spec(String symbolicName, String version, TypeImplementationPlan plan, @Nullable Class<?> superType) {
+ return addSuperType(new BasicRegisteredType(RegisteredTypeKind.SPEC, symbolicName, version, plan), superType);
+ }
+
+ /** returns the {@link Class} object corresponding to the given java type name,
+ * using the cache on the type and the loader defined on the type
+ * @param mgmt */
+ @Beta
+ // TODO should this be on the AbstractTypePlanTransformer ?
+ public static Class<?> loadActualJavaType(String javaTypeName, ManagementContext mgmt, RegisteredType type, RegisteredTypeConstraint constraint) throws Exception {
+ Class<?> result = ((BasicRegisteredType)type).getCache().get(ACTUAL_JAVA_TYPE);
+ if (result!=null) return result;
+
+ result = CatalogUtils.newClassLoadingContext(mgmt, type).loadClass( javaTypeName );
+ Preconditions.checkNotNull(result, "Could not load class "+javaTypeName+"; returned null (should have thrown a different exception!)");
+
+ ((BasicRegisteredType)type).getCache().put(ACTUAL_JAVA_TYPE, result);
+ return result;
+ }
+
+ @Beta
+ public static RegisteredType addSuperType(RegisteredType type, @Nullable Class<?> superType) {
+ if (superType!=null) {
+ ((BasicRegisteredType)type).superTypes.add(superType);
+ }
+ return type;
+ }
+
+ @Beta
+ public static RegisteredType addSuperType(RegisteredType type, @Nullable RegisteredType superType) {
+ if (superType!=null) {
+ if (isSubTypeOf(superType, type)) {
+ throw new IllegalStateException(superType+" declares "+type+" as a supertype; cannot set "+superType+" as a supertype of "+type);
+ }
+ ((BasicRegisteredType)type).superTypes.add(superType);
+ }
+ return type;
}
/** returns the implementation data for a spec if it is a string (e.g. plan yaml or java class name); else false */
@@ -84,4 +151,66 @@ public class RegisteredTypes {
return (String)data;
}
+ /** returns an implementation of the spec class corresponding to the given target type;
+ * for use in {@link BrooklynTypePlanTransformer#create(RegisteredType, RegisteredTypeConstraint)}
+ * implementations when dealing with a spec; returns null if none found
+ * @param mgmt */
+ @Beta
+ public static AbstractBrooklynObjectSpec<?,?> newSpecInstance(ManagementContext mgmt, Class<? extends BrooklynObject> targetType) throws Exception {
+ Class<? extends AbstractBrooklynObjectSpec<?, ?>> specType = RegisteredTypeConstraints.lookupSpecTypeForTarget(targetType);
+ if (specType==null) return null;
+ Method createMethod = specType.getMethod("create", Class.class);
+ return (AbstractBrooklynObjectSpec<?, ?>) createMethod.invoke(null, targetType);
+ }
+
+ /** Returns a wrapped map, if the object is YAML which parses as a map;
+ * otherwise returns absent capable of throwing an error with more details */
+ @SuppressWarnings("unchecked")
+ public static Maybe<Map<Object,Object>> getAsYamlMap(Object planData) {
+ if (!(planData instanceof String)) return Maybe.absent("not a string");
+ Iterable<Object> result;
+ try {
+ result = Yamls.parseAll((String)planData);
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ return Maybe.absent(e);
+ }
+ Iterator<Object> ri = result.iterator();
+ if (!ri.hasNext()) return Maybe.absent("YAML has no elements in it");
+ Object r1 = ri.next();
+ if (!ri.hasNext()) return Maybe.absent("YAML has multiple elements in it");
+ if (r1 instanceof Map) return Maybe.of((Map<Object,Object>)r1);
+ return Maybe.absent("YAML does not contain a map");
+ }
+
+ /**
+ * Queries recursively the supertypes of {@link RegisteredType} to see whether it
+ * declares a supertype compatible with the given {@link Class} */
+ public static boolean isSubTypeOf(RegisteredType type, Class<?> superType) {
+ for (Object st: type.getSuperTypes()) {
+ if (st instanceof Class) {
+ if (superType.isAssignableFrom((Class<?>)st)) return true;
+ }
+ }
+ for (Object st: type.getSuperTypes()) {
+ if (st instanceof RegisteredType) {
+ if (isSubTypeOf((RegisteredType)st, superType)) return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Queries recursively the supertypes of {@link RegisteredType} to see whether it
+ * declares a supertype compatible with the given {@link Class} */
+ public static boolean isSubTypeOf(RegisteredType type, RegisteredType superType) {
+ if (type.equals(superType)) return true;
+ for (Object st: type.getSuperTypes()) {
+ if (st instanceof RegisteredType) {
+ if (isSubTypeOf((RegisteredType)st, superType)) return true;
+ }
+ }
+ return false;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/main/resources/META-INF/services/org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer
----------------------------------------------------------------------
diff --git a/core/src/main/resources/META-INF/services/org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer b/core/src/main/resources/META-INF/services/org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer
new file mode 100644
index 0000000..48c4a9d
--- /dev/null
+++ b/core/src/main/resources/META-INF/services/org.apache.brooklyn.core.typereg.BrooklynTypePlanTransformer
@@ -0,0 +1,19 @@
+#
+# 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.core.typereg.JavaClassNameTypePlanTransformer
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/test/java/org/apache/brooklyn/core/sensor/StaticSensorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/sensor/StaticSensorTest.java b/core/src/test/java/org/apache/brooklyn/core/sensor/StaticSensorTest.java
index 1e6efb1..a574aeb 100644
--- a/core/src/test/java/org/apache/brooklyn/core/sensor/StaticSensorTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/sensor/StaticSensorTest.java
@@ -19,11 +19,9 @@
package org.apache.brooklyn.core.sensor;
import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.core.sensor.Sensors;
-import org.apache.brooklyn.core.sensor.StaticSensor;
+import org.apache.brooklyn.core.entity.EntityAsserts;
import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
import org.apache.brooklyn.entity.stock.BasicEntity;
-import org.apache.brooklyn.test.EntityTestUtils;
import org.apache.brooklyn.util.core.config.ConfigBag;
import org.testng.annotations.Test;
@@ -39,7 +37,7 @@ public class StaticSensorTest extends BrooklynAppUnitTestSupport {
StaticSensor.SENSOR_TYPE, String.class.getName(),
StaticSensor.STATIC_VALUE, "myval")))));
- EntityTestUtils.assertAttributeEquals(entity, Sensors.newSensor(String.class, "myname"), "myval");
+ EntityAsserts.assertAttributeEquals(entity, Sensors.newSensor(String.class, "myname"), "myval");
}
@Test
@@ -50,6 +48,6 @@ public class StaticSensorTest extends BrooklynAppUnitTestSupport {
StaticSensor.SENSOR_TYPE, Integer.class.getName(),
StaticSensor.STATIC_VALUE, "1")))));
- EntityTestUtils.assertAttributeEquals(entity, Sensors.newSensor(Integer.class, "myname"), 1);
+ EntityAsserts.assertAttributeEquals(entity, Sensors.newSensor(Integer.class, "myname"), 1);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntityImpl.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntityImpl.java b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntityImpl.java
index 6c3b913..77d4672 100644
--- a/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntityImpl.java
+++ b/core/src/test/java/org/apache/brooklyn/core/test/entity/TestEntityImpl.java
@@ -157,7 +157,6 @@ public class TestEntityImpl extends AbstractEntity implements TestEntity {
public <T extends Entity> T createAndManageChild(EntitySpec<T> spec) {
if (!getManagementSupport().isDeployed()) throw new IllegalStateException("Entity "+this+" not managed");
T child = createChild(spec);
- getEntityManager().manage(child);
return child;
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java b/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
index c4d8038..def79d8 100644
--- a/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/typereg/JavaTypePlanTransformerTest.java
@@ -37,16 +37,16 @@ public class JavaTypePlanTransformerTest extends BrooklynMgmtUnitTestSupport {
@Override
public void setUp() throws Exception {
super.setUp();
- type = newNoArgRegisteredType(JavaTypePlanTransformer.FORMAT);
+ type = newNoArgRegisteredType(JavaClassNameTypePlanTransformer.FORMAT);
transformer = newTransformer();
}
protected RegisteredType newNoArgRegisteredType(String format) {
- return RegisteredTypes.bean("no-arg", "1.0", null, new BasicTypeImplementationPlan(format, NoArg.class.getName()));
+ return RegisteredTypes.bean("no-arg", "1.0", new BasicTypeImplementationPlan(format, NoArg.class.getName()), null);
}
protected BrooklynTypePlanTransformer newTransformer() {
- BrooklynTypePlanTransformer xf = new JavaTypePlanTransformer();
+ BrooklynTypePlanTransformer xf = new JavaClassNameTypePlanTransformer();
xf.injectManagementContext(mgmt);
return xf;
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
index 1dfc351..8fb7164 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java
@@ -30,12 +30,16 @@ import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
public interface AssemblyTemplateSpecInstantiator extends AssemblyTemplateInstantiator {
+ @Deprecated /** @deprecaed since 0.9.0 include encountered types */
+ EntitySpec<? extends Application> createApplicationSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext loader);
+
/**
* Gets the single item returned by {@link #createServiceSpecs}
* and wraps it in an Application if needed, applying top-level
* attributes and locations to the root entity.
*/
- EntitySpec<? extends Application> createApplicationSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext loader);
+ EntitySpec<? extends Application> createApplicationSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext loader, Set<String> encounteredCatalogTypes);
+
/** Returns specs for each item in the services list */
List<EntitySpec<?>> createServiceSpecs(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext itemLoader, Set<String> encounteredCatalogTypes);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index a400758..5070777 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -35,12 +35,12 @@ import org.apache.brooklyn.core.mgmt.EntityManagementUtils.CreationResult;
import org.apache.brooklyn.core.mgmt.HasBrooklynManagementContext;
import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
+import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.core.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpecInstantiator {
@@ -59,7 +59,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
private Application create(AssemblyTemplate template, CampPlatform platform) {
ManagementContext mgmt = getManagementContext(platform);
BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt);
- EntitySpec<? extends Application> spec = createApplicationSpec(template, platform, loader);
+ EntitySpec<? extends Application> spec = createApplicationSpec(template, platform, loader, MutableSet.<String>of());
Application instance = mgmt.getEntityManager().createEntity(spec);
log.info("CAMP created '{}'", instance);
return instance;
@@ -78,15 +78,24 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
AssemblyTemplate template,
CampPlatform platform,
BrooklynClassLoadingContext loader) {
+ return createApplicationSpec(template, platform, loader, MutableSet.<String>of());
+ }
+
+ @Override
+ public EntitySpec<? extends Application> createApplicationSpec(
+ AssemblyTemplate template,
+ CampPlatform platform,
+ BrooklynClassLoadingContext loader,
+ Set<String> encounteredTypeSymbolicNames) {
log.debug("CAMP creating application instance for {} ({})", template.getId(), template);
// AssemblyTemplates created via PDP, _specifying_ then entities to put in
- EntitySpec<? extends Application> app = CampUtils.createWrapperApp(template, loader);
+ EntitySpec<? extends Application> app = CampInternalUtils.createWrapperApp(template, loader);
app.configure(EntityManagementUtils.WRAPPER_APP_MARKER, Boolean.TRUE);
// first build the children into an empty shell app
- List<EntitySpec<?>> childSpecs = createServiceSpecs(template, platform, loader, Sets.<String>newLinkedHashSet());
+ List<EntitySpec<?>> childSpecs = createServiceSpecs(template, platform, loader, encounteredTypeSymbolicNames);
for (EntitySpec<?> childSpec : childSpecs) {
app.child(childSpec);
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java
index d4c5142..32f7c0e 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java
@@ -24,61 +24,17 @@ import org.apache.brooklyn.api.catalog.CatalogItem;
import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.camp.CampPlatform;
-import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
-import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
-import org.apache.brooklyn.util.text.Strings;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
+@Deprecated /** @deprecated since 0.9.0 use RegisteredType and CampResolver */
public class CampCatalogUtils {
public static AbstractBrooklynObjectSpec<?, ?> createSpec(ManagementContext mgmt, CatalogItem<?, ?> item, Set<String> parentEncounteredTypes) {
- // preferred way is to parse the yaml, to resolve references late;
- // the parsing on load is to populate some fields, but it is optional.
- // TODO messy for location and policy that we need brooklyn.{locations,policies} root of the yaml, but it works;
- // see related comment when the yaml is set, in addAbstractCatalogItems
- // (not sure if anywhere else relies on that syntax; if not, it should be easy to fix!)
- BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, item);
- Preconditions.checkNotNull(item.getCatalogItemType(), "catalog item type for "+item.getPlanYaml());
-
- Set<String> encounteredTypes;
- // symbolicName could be null if coming from the catalog parser where it tries to load before knowing the id
- if (item.getSymbolicName() != null) {
- encounteredTypes = ImmutableSet.<String>builder()
- .addAll(parentEncounteredTypes)
- .add(item.getSymbolicName())
- .build();
- } else {
- encounteredTypes = parentEncounteredTypes;
- }
-
- AbstractBrooklynObjectSpec<?, ?> spec;
- switch (item.getCatalogItemType()) {
- case TEMPLATE:
- case ENTITY:
- spec = CampUtils.createRootServiceSpec(item.getPlanYaml(), loader, encounteredTypes);
- break;
- case LOCATION:
- spec = CampUtils.createLocationSpec(item.getPlanYaml(), loader, encounteredTypes);
- break;
- case POLICY:
- spec = CampUtils.createPolicySpec(item.getPlanYaml(), loader, encounteredTypes);
- break;
- default:
- throw new IllegalStateException("Unknown CI Type "+item.getCatalogItemType()+" for "+item.getPlanYaml());
- }
-
- ((AbstractBrooklynObjectSpec<?, ?>)spec).catalogItemId(item.getId());
-
- if (Strings.isBlank( ((AbstractBrooklynObjectSpec<?, ?>)spec).getDisplayName() ))
- ((AbstractBrooklynObjectSpec<?, ?>)spec).displayName(item.getDisplayName());
-
- return spec;
+ return CampResolver.createSpecFromFull(mgmt, RegisteredTypes.of(item), parentEncounteredTypes, null);
}
-
+
public static CampPlatform getCampPlatform(ManagementContext mgmt) {
- return CampUtils.getCampPlatform(mgmt);
+ return CampInternalUtils.getCampPlatform(mgmt);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
new file mode 100644
index 0000000..abd32c6
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampInternalUtils.java
@@ -0,0 +1,247 @@
+/*
+ * 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.creation;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.StringReader;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.objs.SpecParameter;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.policy.PolicySpec;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.camp.CampPlatform;
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
+import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
+import org.apache.brooklyn.camp.spi.AssemblyTemplate;
+import org.apache.brooklyn.camp.spi.AssemblyTemplate.Builder;
+import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+import org.apache.brooklyn.camp.spi.pdp.DeploymentPlan;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
+import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker;
+import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.objs.BasicSpecParameter;
+import org.apache.brooklyn.core.objs.BrooklynObjectInternal.ConfigurationSupportInternal;
+import org.apache.brooklyn.entity.stock.BasicApplicationImpl;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.stream.Streams;
+import org.apache.brooklyn.util.yaml.Yamls;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
+/** package-private; as {@link RegisteredType} becomes standard hopefully we can remove this */
+class CampInternalUtils {
+
+ static EntitySpec<? extends Application> createWrapperApp(AssemblyTemplate template, BrooklynClassLoadingContext loader) {
+ BrooklynComponentTemplateResolver resolver = BrooklynComponentTemplateResolver.Factory.newInstance(
+ loader, buildWrapperAppTemplate(template));
+ EntitySpec<Application> wrapperSpec = resolver.resolveSpec(ImmutableSet.<String>of());
+ resetSpecIfTemplateHasNoExplicitParameters(template, wrapperSpec);
+ // caller always sets WRAPPER_APP config; should we do it here?
+ return wrapperSpec;
+ }
+
+ static void resetSpecIfTemplateHasNoExplicitParameters(AssemblyTemplate template, EntitySpec<? extends Application> wrapperSpec) {
+ if (!template.getCustomAttributes().containsKey(BrooklynCampReservedKeys.BROOKLYN_PARAMETERS)) {
+ // Clear out default parameters (coming from the wrapper app's class) so they don't overwrite the entity's params on unwrap.
+ wrapperSpec.parameters(ImmutableList.<SpecParameter<?>>of());
+ }
+ }
+
+ private static AssemblyTemplate buildWrapperAppTemplate(AssemblyTemplate template) {
+ Builder<? extends AssemblyTemplate> builder = AssemblyTemplate.builder();
+ builder.type("brooklyn:" + BasicApplicationImpl.class.getName());
+ builder.id(template.getId());
+ builder.name(template.getName());
+ builder.sourceCode(template.getSourceCode());
+ for (Entry<String, Object> entry : template.getCustomAttributes().entrySet()) {
+ builder.customAttribute(entry.getKey(), entry.getValue());
+ }
+ builder.instantiator(template.getInstantiator());
+ AssemblyTemplate wrapTemplate = builder.build();
+ return wrapTemplate;
+ }
+
+ static AssemblyTemplateInstantiator getInstantiator(AssemblyTemplate at) {
+ try {
+ return at.getInstantiator().newInstance();
+ } catch (Exception e) {
+ throw Exceptions.propagate(e);
+ }
+ }
+
+ static AssemblyTemplate registerDeploymentPlan(String plan, BrooklynClassLoadingContext loader, CampPlatform camp) {
+ BrooklynLoaderTracker.setLoader(loader);
+ try {
+ return camp.pdp().registerDeploymentPlan(new StringReader(plan));
+ } finally {
+ BrooklynLoaderTracker.unsetLoader(loader);
+ }
+ }
+
+ static PolicySpec<?> createPolicySpec(String yamlPlan, BrooklynClassLoadingContext loader, Set<String> encounteredCatalogTypes) {
+ DeploymentPlan plan = makePlanFromYaml(loader.getManagementContext(), yamlPlan);
+
+ //Would ideally re-use the PolicySpecResolver
+ //but it is CAMP specific and there is no easy way to get hold of it.
+ Object policies = checkNotNull(plan.getCustomAttributes().get(BasicBrooklynCatalog.POLICIES_KEY), "policy config");
+ if (!(policies instanceof Iterable<?>)) {
+ throw new IllegalStateException("The value of " + BasicBrooklynCatalog.POLICIES_KEY + " must be an Iterable.");
+ }
+
+ Object policy = Iterables.getOnlyElement((Iterable<?>)policies);
+
+ return createPolicySpec(loader, policy, encounteredCatalogTypes);
+ }
+
+ @SuppressWarnings("unchecked")
+ static PolicySpec<?> createPolicySpec(BrooklynClassLoadingContext loader, Object policy, Set<String> encounteredCatalogTypes) {
+ Map<String, Object> itemMap;
+ if (policy instanceof String) {
+ itemMap = ImmutableMap.<String, Object>of("type", policy);
+ } else if (policy instanceof Map) {
+ itemMap = (Map<String, Object>) policy;
+ } else {
+ throw new IllegalStateException("Policy expected to be string or map. Unsupported object type " + policy.getClass().getName() + " (" + policy.toString() + ")");
+ }
+
+ String versionedId = (String) checkNotNull(Yamls.getMultinameAttribute(itemMap, "policy_type", "policyType", "type"), "policy type");
+ PolicySpec<? extends Policy> spec = resolvePolicySpec(versionedId, loader, encounteredCatalogTypes);
+ Map<String, Object> brooklynConfig = (Map<String, Object>) itemMap.get(BrooklynCampReservedKeys.BROOKLYN_CONFIG);
+ if (brooklynConfig != null) {
+ spec.configure(brooklynConfig);
+ }
+ List<?> parameters = (List<?>) itemMap.get(BrooklynCampReservedKeys.BROOKLYN_PARAMETERS);
+ initParameters(parameters, spec, loader);
+ return spec;
+ }
+
+ static LocationSpec<?> createLocationSpec(String yamlPlan, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) {
+ DeploymentPlan plan = makePlanFromYaml(loader.getManagementContext(), yamlPlan);
+ Object locations = checkNotNull(plan.getCustomAttributes().get(BasicBrooklynCatalog.LOCATIONS_KEY), "location config");
+ if (!(locations instanceof Iterable<?>)) {
+ throw new IllegalStateException("The value of " + BasicBrooklynCatalog.LOCATIONS_KEY + " must be an Iterable.");
+ }
+
+ Object location = Iterables.getOnlyElement((Iterable<?>)locations);
+ return createLocationSpec(loader, location);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static LocationSpec<?> createLocationSpec(BrooklynClassLoadingContext loader, Object location) {
+ Map<String, Object> itemMap;
+ if (location instanceof String) {
+ itemMap = ImmutableMap.<String, Object>of("type", location);
+ } else if (location instanceof Map) {
+ itemMap = (Map<String, Object>) location;
+ } else {
+ throw new IllegalStateException("Location expected to be string or map. Unsupported object type " + location.getClass().getName() + " (" + location.toString() + ")");
+ }
+
+ String type = (String) checkNotNull(Yamls.getMultinameAttribute(itemMap, "location_type", "locationType", "type"), "location type");
+ Map<String, Object> brooklynConfig = (Map<String, Object>) itemMap.get("brooklyn.config");
+ LocationSpec<?> locationSpec = resolveLocationSpec(type, brooklynConfig, loader);
+ List<?> explicitParams = (List<?>) itemMap.get(BrooklynCampReservedKeys.BROOKLYN_PARAMETERS);
+ initParameters(explicitParams, locationSpec, loader);
+ return locationSpec;
+ }
+
+ private static void initParameters(List<?> explicitParams, AbstractBrooklynObjectSpec<?, ?> spec, BrooklynClassLoadingContext loader) {
+ if (explicitParams != null) {
+ spec.parameters(BasicSpecParameter.fromConfigList(explicitParams, loader));
+ } else {
+ spec.parameters(BasicSpecParameter.fromSpec(loader.getManagementContext(), spec));
+ }
+ }
+
+ public static DeploymentPlan makePlanFromYaml(ManagementContext mgmt, String yaml) {
+ CampPlatform camp = getCampPlatform(mgmt);
+ return camp.pdp().parseDeploymentPlan(Streams.newReaderWithContents(yaml));
+ }
+
+ public static CampPlatform getCampPlatform(ManagementContext mgmt) {
+ CampPlatform result = mgmt.getConfig().getConfig(BrooklynCampConstants.CAMP_PLATFORM);
+ if (result!=null) {
+ return result;
+ } else {
+ throw new IllegalStateException("No CAMP Platform is registered with this Brooklyn management context.");
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static PolicySpec<? extends Policy> resolvePolicySpec(
+ String versionedId,
+ BrooklynClassLoadingContext loader,
+ Set<String> encounteredCatalogTypes) {
+
+ PolicySpec<? extends Policy> spec;
+ RegisteredType item = loader.getManagementContext().getTypeRegistry().get(versionedId);
+ if (item != null && !encounteredCatalogTypes.contains(item.getSymbolicName())) {
+ return loader.getManagementContext().getTypeRegistry().createSpec(item, null, PolicySpec.class);
+ } else {
+ // TODO-type-registry pass the loader in to the above, and allow it to load with the loader
+ spec = PolicySpec.create(loader.loadClass(versionedId, Policy.class));
+ }
+ return spec;
+ }
+
+ private static LocationSpec<?> resolveLocationSpec(
+ String type,
+ Map<String, Object> brooklynConfig,
+ BrooklynClassLoadingContext loader) {
+ Maybe<Class<? extends Location>> javaClass = loader.tryLoadClass(type, Location.class);
+ if (javaClass.isPresent()) {
+ LocationSpec<?> spec = LocationSpec.create(javaClass.get());
+ if (brooklynConfig != null) {
+ spec.configure(brooklynConfig);
+ }
+ return spec;
+ } else {
+ Maybe<Location> loc = loader.getManagementContext().getLocationRegistry().resolve(type, false, brooklynConfig);
+ if (loc.isPresent()) {
+ // TODO extensions?
+ Map<String, Object> locConfig = ((ConfigurationSupportInternal)loc.get().config()).getBag().getAllConfig();
+ Class<? extends Location> locType = loc.get().getClass();
+ Set<Object> locTags = loc.get().tags().getTags();
+ String locDisplayName = loc.get().getDisplayName();
+ return LocationSpec.create(locType)
+ .configure(locConfig)
+ .displayName(locDisplayName)
+ .tags(locTags);
+ } else {
+ throw new IllegalStateException("No class or resolver found for location type "+type);
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/904c45e9/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
new file mode 100644
index 0000000..1fc6eaf
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampResolver.java
@@ -0,0 +1,142 @@
+/*
+ * 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.creation;
+
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.api.policy.Policy;
+import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.api.typereg.RegisteredTypeConstraint;
+import org.apache.brooklyn.camp.CampPlatform;
+import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator;
+import org.apache.brooklyn.camp.spi.AssemblyTemplate;
+import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator;
+import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
+import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.core.typereg.RegisteredTypes;
+import org.apache.brooklyn.util.text.Strings;
+
+import com.google.common.collect.ImmutableSet;
+
+class CampResolver {
+
+ private ManagementContext mgmt;
+ private RegisteredType type;
+ private RegisteredTypeConstraint context;
+
+ /** whether to allow parsing of the 'full' syntax for applications,
+ * where items are wrapped in a "services:" block, and if the wrapper is an application,
+ * to promote it */
+ boolean allowApplicationFullSyntax = true;
+
+ /** whether to allow parsing of the legacy 'full' syntax,
+ * where a non-application items are wrapped:
+ * <li> in a "services:" block for entities,
+ * <li> in a "brooklyn.locations" or "brooklyn.policies" block for locations and policies */
+ boolean allowLegacyFullSyntax = true;
+
+ /** whether to allow parsing of the type syntax, where an item is a map with a "type:" field,
+ * i.e. not wrapped in any "services:" or "brooklyn.{locations,policies}" block */
+ boolean allowTypeSyntax = true;
+
+ public CampResolver(ManagementContext mgmt, RegisteredType type, RegisteredTypeConstraint context) {
+ this.mgmt = mgmt;
+ this.type = type;
+ this.context = context;
+ }
+
+ public AbstractBrooklynObjectSpec<?, ?> createSpec() {
+ // TODO modern approach
+ // AbstractBrooklynObjectSpec<?, ?> spec = RegisteredTypes.newSpecInstance(mgmt, /* 'type' key */);
+ // spec.configure(keysAndValues);
+ return createSpecFromFull(mgmt, type,
+ context.getEncounteredTypes(), (BrooklynClassLoadingContext) context.getLoader());
+ }
+
+ static AbstractBrooklynObjectSpec<?, ?> createSpecFromFull(ManagementContext mgmt, RegisteredType item, Set<String> parentEncounteredTypes, BrooklynClassLoadingContext loaderO) {
+ // for this method, a prefix "services" or "brooklyn.{location,policies}" is required at the root;
+ // we now prefer items to come in "{ type: .. }" format, except for application roots which
+ // should have a "services: [ ... ]" block (and which may subsequently be unwrapped)
+ BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, item, loaderO);
+
+ Set<String> encounteredTypes;
+ // symbolicName could be null if coming from the catalog parser where it tries to load before knowing the id
+ if (item.getSymbolicName() != null) {
+ encounteredTypes = ImmutableSet.<String>builder()
+ .addAll(parentEncounteredTypes)
+ .add(item.getSymbolicName())
+ .build();
+ } else {
+ encounteredTypes = parentEncounteredTypes;
+ }
+
+ AbstractBrooklynObjectSpec<?, ?> spec;
+ String planYaml = RegisteredTypes.getImplementationDataStringForSpec(item);
+ if (RegisteredTypes.isSubTypeOf(item, Policy.class)) {
+ spec = CampInternalUtils.createPolicySpec(planYaml, loader, encounteredTypes);
+ } else if (RegisteredTypes.isSubTypeOf(item, Location.class)) {
+ spec = CampInternalUtils.createLocationSpec(planYaml, loader, encounteredTypes);
+ } else if (RegisteredTypes.isSubTypeOf(item, Application.class)) {
+ spec = createEntitySpecFromServicesBlock(planYaml, loader, encounteredTypes, true);
+ } else if (RegisteredTypes.isSubTypeOf(item, Entity.class)) {
+ spec = createEntitySpecFromServicesBlock(planYaml, loader, encounteredTypes, false);
+ } else {
+ // try any of them???
+
+ throw new IllegalStateException("Cannot detect spec type from "+item.getSuperTypes()+" for "+item+"\n"+planYaml);
+ }
+
+ ((AbstractBrooklynObjectSpec<?, ?>)spec).catalogItemId(item.getId());
+
+ if (Strings.isBlank( ((AbstractBrooklynObjectSpec<?, ?>)spec).getDisplayName() ))
+ ((AbstractBrooklynObjectSpec<?, ?>)spec).displayName(item.getDisplayName());
+
+ return spec;
+ }
+
+ private static EntitySpec<?> createEntitySpecFromServicesBlock(String plan, BrooklynClassLoadingContext loader, Set<String> encounteredTypes, boolean isApplication) {
+ CampPlatform camp = CampInternalUtils.getCampPlatform(loader.getManagementContext());
+
+ AssemblyTemplate at = CampInternalUtils.registerDeploymentPlan(plan, loader, camp);
+ AssemblyTemplateInstantiator instantiator = CampInternalUtils.getInstantiator(at);
+ if (instantiator instanceof AssemblyTemplateSpecInstantiator) {
+ EntitySpec<? extends Application> appSpec = ((AssemblyTemplateSpecInstantiator)instantiator).createApplicationSpec(at, camp, loader, encounteredTypes);
+ CampInternalUtils.resetSpecIfTemplateHasNoExplicitParameters(at, appSpec);
+
+ if (!isApplication && EntityManagementUtils.canPromoteChildrenInWrappedApplication(appSpec) && appSpec.getChildren().size()==1) {
+ EntitySpec<?> childSpec = appSpec.getChildren().get(0);
+ EntityManagementUtils.mergeWrapperParentSpecToChildEntity(appSpec, childSpec);
+ return childSpec;
+ }
+ return appSpec;
+
+ } else {
+ throw new IllegalStateException("Unable to instantiate YAML; incompatible instantiator "+instantiator+" for "+at);
+ }
+
+ }
+
+}
\ No newline at end of file