You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by sj...@apache.org on 2015/10/15 16:02:27 UTC
[06/16] incubator-brooklyn git commit: Split
BrooklynComponentTemplateResolver into independent ServiceSpecResolver
Split BrooklynComponentTemplateResolver into independent ServiceSpecResolver
ServiceSpecResolver is not specific to CAMP, it deals with converting a type (i.e. a catalog item, a java class, chef declaration) to a spec. BrooklynComponentTemplateResolver then takes the spec and applies the CAMP config on it.
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/4485fe5c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/4485fe5c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/4485fe5c
Branch: refs/heads/master
Commit: 4485fe5c212ee5fddf4e6452c9fb17b77429b5b5
Parents: c71d722
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Wed Oct 14 15:02:26 2015 +0300
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Wed Oct 14 17:11:07 2015 +0300
----------------------------------------------------------------------
.../internal/JavaCatalogToSpecTransformer.java | 13 +-
.../core/mgmt/EntityManagementUtils.java | 4 +-
.../brooklyn/core/plan/PlanToSpecFactory.java | 2 +-
.../BrooklynAssemblyTemplateInstantiator.java | 12 +-
.../BrooklynComponentTemplateResolver.java | 264 ++++---------------
.../spi/creation/CampToSpecTransformer.java | 17 +-
.../service/AbstractServiceSpecResolver.java | 65 +++++
.../service/BrooklynServiceTypeResolver.java | 80 ------
.../service/CatalogServiceSpecResolver.java | 110 ++++++++
.../service/CatalogServiceTypeResolver.java | 77 ------
.../service/ChefServiceSpecResolver.java | 41 +++
.../service/ChefServiceTypeResolver.java | 61 -----
.../service/DefaultServiceTypeResolver.java | 23 --
.../service/DelegatingServiceSpecResolver.java | 127 +++++++++
.../HardcodedCatalogServiceSpecResolver.java | 95 +++++++
.../service/JavaServiceSpecResolver.java | 91 +++++++
.../service/JavaServiceTypeResolver.java | 38 ---
.../creation/service/ServiceSpecResolver.java | 56 ++++
.../creation/service/ServiceTypeResolver.java | 3 +
.../service/ServiceTypeResolverAdaptor.java | 62 +++++
.../service/UrlServiceSpecResolver.java | 70 +++++
...lyn.spi.creation.service.ServiceSpecResolver | 23 ++
...lyn.spi.creation.service.ServiceTypeResolver | 22 --
.../brooklyn/catalog/CatalogXmlOsgiTest.java | 16 +-
.../brooklyn/catalog/CatalogYamlEntityTest.java | 49 +++-
.../rest/resources/ApplicationResource.java | 4 +-
26 files changed, 882 insertions(+), 543 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/core/src/main/java/org/apache/brooklyn/core/catalog/internal/JavaCatalogToSpecTransformer.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/JavaCatalogToSpecTransformer.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/JavaCatalogToSpecTransformer.java
index 9b4a83c..a6a8e3a 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/JavaCatalogToSpecTransformer.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/JavaCatalogToSpecTransformer.java
@@ -34,6 +34,11 @@ import org.apache.brooklyn.core.plan.PlanToSpecTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+/**
+ * Old-style catalog items (can be defined in catalog.xml only) don't have structure, only a single type, so
+ * they are loaded as a simple java type, only taking the class name from the catalog item instead of the
+ * type value in the YAML. Classpath entries in the item are also used (through the catalog root classloader).
+ */
public class JavaCatalogToSpecTransformer implements PlanToSpecTransformer {
private static final Logger log = LoggerFactory.getLogger(JavaCatalogToSpecTransformer.class);
@@ -64,8 +69,12 @@ public class JavaCatalogToSpecTransformer implements PlanToSpecTransformer {
CatalogItem<T, SpecT> item, Set<String> encounteredTypes) throws PlanNotRecognizedException {
if (item.getJavaType() != null) {
log.warn("Deprecated functionality (since 0.9.0). Using old-style xml catalog items with java type attribute for " + item);
- BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, item);
- Class<?> type = loader.loadClass(item.getJavaType());
+ Class<?> type;
+ try {
+ type = mgmt.getCatalogClassLoader().loadClass(item.getJavaType());
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Unable to load old-style java catalog item type " + item.getJavaType() + " for item " + item, e);
+ }
AbstractBrooklynObjectSpec<?,?> spec;
if (Entity.class.isAssignableFrom(type)) {
@SuppressWarnings("unchecked")
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
index 0dca83c..cda3f5b 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/EntityManagementUtils.java
@@ -44,6 +44,7 @@ import org.apache.brooklyn.core.plan.PlanToSpecTransformer;
import org.apache.brooklyn.entity.stock.BasicApplication;
import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.core.task.TaskBuilder;
import org.apache.brooklyn.util.core.task.Tasks;
import org.apache.brooklyn.util.text.Strings;
@@ -56,7 +57,6 @@ import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
@@ -99,7 +99,7 @@ public class EntityManagementUtils {
}
public static <T,SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT createCatalogSpec(ManagementContext mgmt, CatalogItem<T, SpecT> item) {
- return createCatalogSpec(mgmt, item, ImmutableSet.<String>of());
+ return createCatalogSpec(mgmt, item, MutableSet.<String>of());
}
public static <T,SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT createCatalogSpec(ManagementContext mgmt, final CatalogItem<T, SpecT> item, final Set<String> encounteredTypes) {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/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 3328545..1b49170 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
@@ -117,7 +117,7 @@ public class PlanToSpecFactory {
// at least one thought he could do it
log.debug("Plan could not be transformed; failure will be propagated (other transformers tried = "+transformersWhoDontSupport+"): "+otherProblemsFromTransformers);
result = otherProblemsFromTransformers.size()==1 ? Exceptions.create(null, otherProblemsFromTransformers) :
- Exceptions.create("Plan transformers all failed", otherProblemsFromTransformers);
+ Exceptions.create("All plan transformers failed", otherProblemsFromTransformers);
} else {
result = new PlanNotRecognizedException("Invalid plan; format could not be recognized, trying with: "+transformersWhoDontSupport);
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/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 e54e2ef..19aa100 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
@@ -39,6 +39,7 @@ 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.entity.stock.BasicApplicationImpl;
+import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.core.flags.TypeCoercions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -71,10 +72,11 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
}
@Override
- public List<EntitySpec<?>> createServiceSpecs(AssemblyTemplate template,
+ public List<EntitySpec<?>> createServiceSpecs(
+ AssemblyTemplate template,
CampPlatform platform, BrooklynClassLoadingContext itemLoader,
Set<String> encounteredCatalogTypes) {
- return buildTemplateServicesAsSpecs(itemLoader, template, platform, encounteredCatalogTypes, true);
+ return buildTemplateServicesAsSpecs(itemLoader, template, platform, encounteredCatalogTypes);
}
@Override
@@ -88,7 +90,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
BrooklynComponentTemplateResolver resolver = BrooklynComponentTemplateResolver.Factory.newInstance(
loader, buildWrapperAppTemplate(template));
- EntitySpec<? extends Application> app = resolver.resolveSpec(null, false);
+ EntitySpec<? extends Application> app = resolver.resolveSpec(MutableSet.<String>of());
app.configure(EntityManagementUtils.WRAPPER_APP_MARKER, Boolean.TRUE);
// first build the children into an empty shell app
@@ -124,13 +126,13 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
return EntityManagementUtils.canPromoteWrappedApplication(app);
}
- private List<EntitySpec<?>> buildTemplateServicesAsSpecs(BrooklynClassLoadingContext loader, AssemblyTemplate template, CampPlatform platform, Set<String> encounteredCatalogTypes, boolean canUseOtherTransformers) {
+ private List<EntitySpec<?>> buildTemplateServicesAsSpecs(BrooklynClassLoadingContext loader, AssemblyTemplate template, CampPlatform platform, Set<String> encounteredCatalogTypes) {
List<EntitySpec<?>> result = Lists.newArrayList();
for (ResolvableLink<PlatformComponentTemplate> ctl: template.getPlatformComponentTemplates().links()) {
PlatformComponentTemplate appChildComponentTemplate = ctl.resolve();
BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(loader, appChildComponentTemplate);
- EntitySpec<?> spec = entityResolver.resolveSpec(encounteredCatalogTypes, canUseOtherTransformers);
+ EntitySpec<?> spec = entityResolver.resolveSpec(encounteredCatalogTypes);
result.add(spec);
}
return result;
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index f42145d..05252f5 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -18,6 +18,7 @@
*/
package org.apache.brooklyn.camp.brooklyn.spi.creation;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
@@ -28,17 +29,16 @@ import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nullable;
-import org.apache.brooklyn.api.catalog.CatalogItem;
-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.camp.brooklyn.BrooklynCampConstants;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys;
-import org.apache.brooklyn.camp.brooklyn.spi.creation.service.DefaultServiceTypeResolver;
+import org.apache.brooklyn.camp.brooklyn.spi.creation.service.DelegatingServiceSpecResolver;
+import org.apache.brooklyn.camp.brooklyn.spi.creation.service.ServiceSpecResolver;
import org.apache.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver;
+import org.apache.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolverAdaptor;
import org.apache.brooklyn.camp.spi.AbstractResource;
import org.apache.brooklyn.camp.spi.ApplicationComponentTemplate;
import org.apache.brooklyn.camp.spi.AssemblyTemplate;
@@ -46,21 +46,17 @@ import org.apache.brooklyn.camp.spi.PlatformComponentTemplate;
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.mgmt.BrooklynTags;
import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
-import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext;
import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.collections.MutableSet;
-import org.apache.brooklyn.util.core.ResourceUtils;
import org.apache.brooklyn.util.core.config.ConfigBag;
import org.apache.brooklyn.util.core.flags.FlagUtils;
import org.apache.brooklyn.util.core.flags.FlagUtils.FlagConfigKeyAndValueRecord;
import org.apache.brooklyn.util.core.task.Tasks;
import org.apache.brooklyn.util.guava.Maybe;
-import org.apache.brooklyn.util.javalang.Reflections;
import org.apache.brooklyn.util.net.Urls;
import org.apache.brooklyn.util.text.Strings;
import org.slf4j.Logger;
@@ -75,6 +71,7 @@ import com.google.common.collect.Maps;
* This generates instances of a template resolver that use a {@link ServiceTypeResolver}
* to parse the {@code serviceType} line in the template.
*/
+@SuppressWarnings("deprecation") // Because of ServiceTypeResolver
public class BrooklynComponentTemplateResolver {
private static final Logger log = LoggerFactory.getLogger(BrooklynComponentTemplateResolver.class);
@@ -85,47 +82,29 @@ public class BrooklynComponentTemplateResolver {
private final Maybe<AbstractResource> template;
private final BrooklynYamlTypeInstantiator.Factory yamlLoader;
private final String type;
- private final ServiceTypeResolver typeResolver;
private final AtomicBoolean alreadyBuilt = new AtomicBoolean(false);
+ private final ServiceSpecResolver serviceSpecResolver;
- private BrooklynComponentTemplateResolver(BrooklynClassLoadingContext loader, ConfigBag attrs, AbstractResource optionalTemplate, String type, ServiceTypeResolver typeResolver) {
+ private BrooklynComponentTemplateResolver(BrooklynClassLoadingContext loader, ConfigBag attrs, AbstractResource optionalTemplate, String type) {
this.loader = loader;
this.mgmt = loader.getManagementContext();
this.attrs = ConfigBag.newInstanceCopying(attrs);
this.template = Maybe.fromNullable(optionalTemplate);
this.yamlLoader = new BrooklynYamlTypeInstantiator.Factory(loader, this);
this.type = type;
- this.typeResolver = typeResolver;
+ this.serviceSpecResolver = new DelegatingServiceSpecResolver(mgmt, getServiceTypeResolverOverrides());
}
- public ManagementContext getManagementContext() { return mgmt; }
- public ConfigBag getAttrs() { return attrs; }
- public BrooklynYamlTypeInstantiator.Factory getYamlLoader() { return yamlLoader; }
- public String getDeclaredType() { return type; }
+ // Deprecated because want to keep as much of the state private as possible
+ // Can't remove them because used by ServiceTypeResolver implementations
+ /** @deprecated since 0.9.0 */
+ @Deprecated public ManagementContext getManagementContext() { return mgmt; }
+ @Deprecated public ConfigBag getAttrs() { return attrs; }
+ @Deprecated public BrooklynYamlTypeInstantiator.Factory getYamlLoader() { return yamlLoader; }
+ @Deprecated public String getDeclaredType() { return type; }
public static class Factory {
- /** returns resolver type based on the service type, inspecting the arguments in order to determine the service type */
- private static ServiceTypeResolver computeResolverType(BrooklynClassLoadingContext context, String knownServiceType, AbstractResource optionalTemplate, ConfigBag attrs) {
- String type = getDeclaredType(knownServiceType, optionalTemplate, attrs);
- return findService(context, type);
- }
-
- // TODO This could be extended to support multiple prefixes per resolver and a 'best-match' algorithm
- private static ServiceTypeResolver findService(BrooklynClassLoadingContext context, String type) {
- if (type.indexOf(':') != -1) {
- String prefix = Splitter.on(":").splitToList(type).get(0);
- ServiceLoader<ServiceTypeResolver> loader = ServiceLoader.load(ServiceTypeResolver.class,
- context.getManagementContext().getCatalogClassLoader());
- for (ServiceTypeResolver resolver : loader) {
- if (prefix.equals(resolver.getTypePrefix())) {
- return resolver;
- }
- }
- }
- return null;
- }
-
public static BrooklynComponentTemplateResolver newInstance(BrooklynClassLoadingContext context, Map<String, ?> childAttrs) {
return newInstance(context, ConfigBag.newInstance(childAttrs), null);
}
@@ -139,11 +118,8 @@ public class BrooklynComponentTemplateResolver {
}
private static BrooklynComponentTemplateResolver newInstance(BrooklynClassLoadingContext context, ConfigBag attrs, AbstractResource optionalTemplate) {
- ServiceTypeResolver typeResolver = computeResolverType(context, null, optionalTemplate, attrs);
String type = getDeclaredType(null, optionalTemplate, attrs);
- if (typeResolver == null) // use default
- typeResolver = new DefaultServiceTypeResolver();
- return new BrooklynComponentTemplateResolver(context, attrs, optionalTemplate, type, typeResolver);
+ return new BrooklynComponentTemplateResolver(context, attrs, optionalTemplate, type);
}
private static String getDeclaredType(String knownServiceType, AbstractResource optionalTemplate, @Nullable ConfigBag attrs) {
@@ -164,185 +140,49 @@ public class BrooklynComponentTemplateResolver {
}
public boolean canResolve() {
- if (!(typeResolver instanceof DefaultServiceTypeResolver)) {
- return true;
- }
-
- CatalogItem<Entity, EntitySpec<?>> item = typeResolver.getCatalogItem(this, type);
- if (item != null) {
- if (item.isDisabled()) {
- log.warn("Disallowed attempt to use disabled catalog item "+item.getId());
- return false;
- } else if (item.isDeprecated()) {
- log.warn("Use of deprecated catalog item "+item.getId());
- }
- return true;
- }
-
- if (tryLoadEntityClass().isPresent()) {
- return true;
- }
-
- String protocol = Urls.getProtocol(type);
- if (protocol != null) {
- if (BrooklynCampConstants.YAML_URL_PROTOCOL_WHITELIST.contains(protocol)) {
- return true;
- } else {
- log.debug("The reference '" + type + "' looks like a URL (running the CAMP Brooklyn entity-matcher) but the protocol '" +
- protocol + "' isn't white listed " + BrooklynCampConstants.YAML_URL_PROTOCOL_WHITELIST + ". " +
- "Not recognized as catalog item or java item as well!");
- }
- }
-
- return true;
- }
-
- /** returns the entity class, if needed in contexts which scan its statics for example */
- private Class<? extends Entity> loadEntityClass() {
- Maybe<Class<? extends Entity>> result = tryLoadEntityClass();
- if (result.isAbsent())
- throw new IllegalStateException("Could not find "+typeResolver.getBrooklynType(type), ((Maybe.Absent<?>)result).getException());
- return result.get();
- }
-
- /** tries to load the Java entity class */
- private Maybe<Class<? extends Entity>> tryLoadEntityClass() {
- return loader.tryLoadClass(getJavaType(), Entity.class);
- }
-
- // TODO Generalise to have other prefixes (e.g. explicit "catalog:" etc)?
- private boolean isJavaTypePrefix() {
- return type != null && (type.toLowerCase().startsWith("java:") || type.toLowerCase().startsWith("brooklyn:java:"));
- }
-
- private String getJavaType() {
- return typeResolver.getBrooklynType(type);
+ return serviceSpecResolver.accepts(type, loader);
}
- public <T extends Entity> EntitySpec<T> resolveSpec(Set<String> encounteredCatalogTypes, boolean canUseOtherTransformers) {
+ public <T extends Entity> EntitySpec<T> resolveSpec(Set<String> encounteredCatalogTypes) {
if (alreadyBuilt.getAndSet(true))
throw new IllegalStateException("Spec can only be used once: "+this);
- String brooklynType = typeResolver.getBrooklynType(type);
- CatalogItem<Entity, EntitySpec<?>> item = typeResolver.getCatalogItem(this, type);
-
- if (log.isTraceEnabled()) log.trace("Building CAMP template services: type="+brooklynType+"; item="+item+"; loader="+loader+"; encounteredCatalogTypes="+encounteredCatalogTypes);
-
- // TODO implement as service type
- EntitySpec<T> spec = null;
- String protocol = Urls.getProtocol(brooklynType);
- if (protocol != null) {
- if (BrooklynCampConstants.YAML_URL_PROTOCOL_WHITELIST.contains(protocol)) {
- spec = tryResolveYamlUrlReferenceSpec(brooklynType, encounteredCatalogTypes);
- if (spec != null) {
- populateSpec(spec);
- }
- } else {
- // TODO this will probably be logged if we refer to chef:cookbook or other service types which BCTR accepts;
- // better would be to have BCTR supporting the calls above
- log.debug("The reference " + brooklynType + " looks like a URL (running the CAMP Brooklyn assembly-template instantiator) but the protocol " +
- protocol + " isn't white listed (" + BrooklynCampConstants.YAML_URL_PROTOCOL_WHITELIST + "). " +
- "Will try to load it as catalog item or java type.");
- }
- }
+ EntitySpec<?> spec = serviceSpecResolver.resolve(type, loader, encounteredCatalogTypes);
if (spec == null) {
- // load from java or yaml
- spec = resolveLocalSpec(encounteredCatalogTypes, canUseOtherTransformers);
+ String proto = Urls.getProtocol(type);
+ if (proto != null) {
+ log.debug("The reference " + type + " looks like a URL (running the CAMP Brooklyn assembly-template instantiator) but the protocol " +
+ proto + " isn't white listed (" + BrooklynCampConstants.YAML_URL_PROTOCOL_WHITELIST + "). " +
+ "Not a catalog item or java type as well.");
+ }
+ throw new IllegalStateException("Unable to create spec for type " + type + ". No resolver knew how to handle it.");
}
- return spec;
- }
+ populateSpec(spec, encounteredCatalogTypes);
- @SuppressWarnings("unchecked")
- private <T extends Entity> EntitySpec<T> tryResolveYamlUrlReferenceSpec(String brooklynType, Set<String> encounteredCatalogTypes) {
- String yaml;
- try {
- yaml = ResourceUtils.create(this).getResourceAsString(brooklynType);
- } catch (Exception e) {
- log.warn("AssemblyTemplate type " + brooklynType + " which looks like a URL can't be fetched.", e);
- return null;
- }
- // Referenced specs are expected to be CAMP format as well.
- List<EntitySpec<?>> serviceSpecs = CampUtils.createServiceSpecs(yaml, loader, encounteredCatalogTypes);
- if (serviceSpecs.size() > 1) {
- throw new UnsupportedOperationException("Only supporting single service in remotely referenced plans: got "+serviceSpecs);
- }
- return (EntitySpec<T>) serviceSpecs.get(0);
+ @SuppressWarnings("unchecked")
+ EntitySpec<T> typedSpec = (EntitySpec<T>) spec;
+ return typedSpec;
}
- private <T extends Entity> EntitySpec<T> resolveLocalSpec(Set<String> encounteredCatalogTypes, boolean canUseOtherTransformers) {
- CatalogItem<Entity, EntitySpec<?>> item = typeResolver.getCatalogItem(this, type);
- EntitySpec<T> spec = createSpec(item, encounteredCatalogTypes);
- populateSpec(spec);
- return spec;
- }
-
- @SuppressWarnings({ "unchecked" })
- private <T extends Entity,SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> EntitySpec<T> createSpec(CatalogItem<Entity, EntitySpec<?>> item, Set<String> encounteredCatalogTypes) {
- if (item == null) {
- // ignore; presumably a java type or some such?
- } else if (item.isDisabled()) {
- throw new IllegalStateException("Illegal use of disabled catalog item "+item.getSymbolicName()+":"+item.getVersion());
- } else if (item.isDeprecated()) {
- log.warn("Use of deprecated catalog item "+item.getSymbolicName()+":"+item.getVersion());
- }
-
- if (encounteredCatalogTypes==null) encounteredCatalogTypes = MutableSet.of();
-
- //Take the symbolicName part of the catalog item only for recursion detection to prevent
- //cross referencing of different versions. Not interested in non-catalog item types.
- //Prevent catalog items self-referencing even if explicitly different version.
- boolean firstOccurrence = (item == null || encounteredCatalogTypes.add(item.getSymbolicName()));
- boolean recursiveButTryJava = !firstOccurrence;
-
- // Load a java class from current loader if explicit java prefix, or if no item, or if item is legacy /
- // old-style catalog item (item != null && item.getJavaType() != null).
- // Old-style catalog items (can be defined in catalog.xml only) don't have structure, only a single type, so
- // they are loaded as a simple java type, only taking the class name from the catalog item instead of the
- // type value in the YAML. Classpath entries in the item are also used (through the catalog root classloader).
- if (isJavaTypePrefix() || item == null) {
- return createSpecFromJavaType();
-
- // Same as above case, but this time force java type loading (either as plain class or through an old-style
- // catalog item, since we have already loaded a class item with the same name as the type value.
- } else if (recursiveButTryJava) {
- if (tryLoadEntityClass().isAbsent()) {
- throw new IllegalStateException("Recursive reference to " + item + " (and cannot be resolved as a Java type)");
+ private List<ServiceSpecResolver> getServiceTypeResolverOverrides() {
+ List<ServiceSpecResolver> overrides = new ArrayList<>();
+ if (type.indexOf(':') != -1) {
+ String prefix = Splitter.on(":").splitToList(type).get(0);
+ ServiceLoader<ServiceTypeResolver> loader = ServiceLoader.load(ServiceTypeResolver.class,
+ mgmt.getCatalogClassLoader());
+ for (ServiceTypeResolver resolver : loader) {
+ if (prefix.equals(resolver.getTypePrefix())) {
+ overrides.add(new ServiceTypeResolverAdaptor(this, resolver));
+ }
}
- return createSpecFromJavaType();
-
- // Only case that's left is a catalog item with CAMP YAML content - try to parse it recursively
- // including its OSGi bundles in the loader classpath.
- } else {
- return (EntitySpec<T>) EntityManagementUtils.createCatalogSpec(mgmt, (CatalogItem<T,SpecT>)item, encounteredCatalogTypes);
}
- }
-
- @SuppressWarnings("unchecked")
- private <T extends Entity> EntitySpec<T> createSpecFromJavaType() {
- Class<T> type = (Class<T>) loadEntityClass();
-
- EntitySpec<T> spec;
- if (type.isInterface()) {
- spec = EntitySpec.create(type);
- } else {
- // If this is a concrete class, particularly for an Application class, we want the proxy
- // to expose all interfaces it implements.
- @SuppressWarnings("rawtypes")
- Class interfaceclazz = (Application.class.isAssignableFrom(type)) ? Application.class : Entity.class;
- List<Class<?>> additionalInterfaceClazzes = Reflections.getAllInterfaces(type);
- spec = EntitySpec.create(interfaceclazz).impl(type).additionalInterfaces(additionalInterfaceClazzes);
- }
- spec.catalogItemId(CatalogUtils.getCatalogItemIdFromLoader(loader));
- if (template.isPresent() && template.get().getSourceCode()!=null)
- spec.tag(BrooklynTags.newYamlSpecTag(template.get().getSourceCode()));
-
- return spec;
+ return overrides;
}
@SuppressWarnings("unchecked")
- private <T extends Entity> void populateSpec(EntitySpec<T> spec) {
+ private <T extends Entity> void populateSpec(EntitySpec<T> spec, Set<String> encounteredCatalogTypes) {
String name, templateId=null, planId=null;
if (template.isPresent()) {
name = template.get().getName();
@@ -356,15 +196,12 @@ public class BrooklynComponentTemplateResolver {
Object childrenObj = attrs.getStringKey(BrooklynCampReservedKeys.BROOKLYN_CHILDREN);
if (childrenObj != null) {
- // Creating a new set of encounteredCatalogTypes means that this won't check things recursively;
- // but we are looking at children so we probably *should* be resetting the recursive list we've looked at;
- // (but see also, a previous comment here which suggested otherwise? - Apr 2015)
- Set<String> encounteredCatalogTypes = MutableSet.of();
-
Iterable<Map<String,?>> children = (Iterable<Map<String,?>>)childrenObj;
for (Map<String,?> childAttrs : children) {
BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(loader, childAttrs);
- EntitySpec<? extends Entity> childSpec = entityResolver.resolveSpec(encounteredCatalogTypes, true);
+ // encounteredCatalogTypes must contain the items currently being loaded (the dependency chain),
+ // but not parent items in this catalog item already resolved.
+ EntitySpec<? extends Entity> childSpec = entityResolver.resolveSpec(encounteredCatalogTypes);
spec.child(childSpec);
}
}
@@ -379,7 +216,14 @@ public class BrooklynComponentTemplateResolver {
if (childLocations != null)
spec.locations(childLocations);
- typeResolver.decorateSpec(this, spec);
+ decoreateSpec(spec);
+ }
+
+ private <T extends Entity> void decoreateSpec(EntitySpec<T> spec) {
+ new BrooklynEntityDecorationResolver.PolicySpecResolver(yamlLoader).decorate(spec, attrs);
+ new BrooklynEntityDecorationResolver.EnricherSpecResolver(yamlLoader).decorate(spec, attrs);
+ new BrooklynEntityDecorationResolver.InitializerResolver(yamlLoader).decorate(spec, attrs);
+
configureEntityConfig(spec);
}
@@ -508,7 +352,7 @@ public class BrooklynComponentTemplateResolver {
@SuppressWarnings("unchecked")
Map<String, Object> resolvedConfig = (Map<String, Object>)transformSpecialFlags(specConfig.getSpecConfiguration());
specConfig.setSpecConfiguration(resolvedConfig);
- return Factory.newInstance(getLoader(), specConfig.getSpecConfiguration()).resolveLocalSpec(null, false);
+ return Factory.newInstance(getLoader(), specConfig.getSpecConfiguration()).resolveSpec(MutableSet.<String>of());
}
if (flag instanceof ManagementContextInjectable) {
log.debug("Injecting Brooklyn management context info object: {}", flag);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
index dd0a6f4..9104f8f 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java
@@ -76,19 +76,15 @@ public class CampToSpecTransformer implements PlanToSpecTransformer {
if (at.getPlatformComponentTemplates()==null || at.getPlatformComponentTemplates().isEmpty()) {
if (at.getCustomAttributes().containsKey("brooklyn.catalog"))
throw new IllegalArgumentException("Unrecognized application blueprint format: expected an application, not a brooklyn.catalog");
- throw new IllegalArgumentException("Unrecognized application blueprint format: no services defined");
+ throw new PlanNotRecognizedException("Unrecognized application blueprint format: no services defined");
}
// map this (expected) error to a nicer message
- throw new IllegalArgumentException("Unrecognized application blueprint format");
+ throw new PlanNotRecognizedException("Unrecognized application blueprint format");
}
} catch (Exception e) {
- if (e instanceof PlanNotRecognizedException) {
- if (log.isTraceEnabled())
- log.debug("Failed to create entity from CAMP spec:\n" + plan, e);
- } else {
- if (log.isDebugEnabled())
- log.debug("Failed to create entity from CAMP spec:\n" + plan, e);
- }
+ // TODO how do we figure out that the plan is not supported vs. invalid to wrap in a PlanNotRecognizedException?
+ if (log.isDebugEnabled())
+ log.debug("Failed to create entity from CAMP spec:\n" + plan, e);
throw Exceptions.propagate(e);
}
}
@@ -96,6 +92,9 @@ public class CampToSpecTransformer implements PlanToSpecTransformer {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public <T, SpecT extends AbstractBrooklynObjectSpec<? extends T, SpecT>> SpecT createCatalogSpec(CatalogItem<T, SpecT> item, Set<String> encounteredTypes) {
+ // Ignore old-style java type catalog items
+ if (item.getPlanYaml() == null) return null;
+
// Not really clear what should happen to the top-level attributes, ignored until a good use case appears.
return (SpecT) CampCatalogUtils.createSpec(mgmt, (CatalogItem)item, encounteredTypes);
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/AbstractServiceSpecResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/AbstractServiceSpecResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/AbstractServiceSpecResolver.java
new file mode 100644
index 0000000..3fb3c89
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/AbstractServiceSpecResolver.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.camp.brooklyn.spi.creation.service;
+
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.util.text.Strings;
+
+public abstract class AbstractServiceSpecResolver implements ServiceSpecResolver {
+ private static final String PREFIX_DELIMITER = ":";
+ protected final String name;
+ protected final String prefix;
+ protected ManagementContext mgmt;
+
+ public AbstractServiceSpecResolver(String name) {
+ this.name = name;
+ this.prefix = name + PREFIX_DELIMITER;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean accepts(String type, BrooklynClassLoadingContext loader) {
+ return type.startsWith(prefix) && canResolve(type, loader);
+ }
+
+ protected boolean canResolve(String type, BrooklynClassLoadingContext loader) {
+ return true;
+ }
+
+ protected String getLocalType(String type) {
+ return Strings.removeFromStart(type, prefix);
+ }
+
+ @Override
+ public void injectManagementContext(ManagementContext mgmt) {
+ this.mgmt = mgmt;
+ }
+
+ @Override
+ public abstract EntitySpec<?> resolve(String type, BrooklynClassLoadingContext loader, Set<String> encounteredTypes);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
deleted file mode 100644
index e0d2e9e..0000000
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
+++ /dev/null
@@ -1,80 +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.camp.brooklyn.spi.creation.service;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver;
-import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityDecorationResolver;
-import org.apache.brooklyn.camp.spi.PlatformComponentTemplate;
-import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
-import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider;
-import org.apache.brooklyn.util.text.Strings;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code brooklyn:}
- * to Brooklyn {@link EntitySpec} instances.
- */
-public class BrooklynServiceTypeResolver implements ServiceTypeResolver {
-
- @SuppressWarnings("unused")
- private static final Logger LOG = LoggerFactory.getLogger(ServiceTypeResolver.class);
-
- public BrooklynServiceTypeResolver() {
- }
-
- @Override
- public String getTypePrefix() { return DEFAULT_TYPE_PREFIX; }
-
- @Override
- public String getBrooklynType(String serviceType) {
- String type = Strings.removeFromStart(serviceType, getTypePrefix() + ":").trim();
- if (type == null) return null;
- return type;
- }
-
- @Nullable
- @Override
- public CatalogItem<Entity,EntitySpec<?>> getCatalogItem(BrooklynComponentTemplateResolver resolver, String serviceType) {
- String type = getBrooklynType(serviceType);
- if (type != null) {
- return getCatalogItemImpl(resolver.getManagementContext(), type);
- } else {
- return null;
- }
- }
-
- @Override
- public <T extends Entity> void decorateSpec(BrooklynComponentTemplateResolver resolver, EntitySpec<T> spec) {
- new BrooklynEntityDecorationResolver.PolicySpecResolver(resolver.getYamlLoader()).decorate(spec, resolver.getAttrs());
- new BrooklynEntityDecorationResolver.EnricherSpecResolver(resolver.getYamlLoader()).decorate(spec, resolver.getAttrs());
- new BrooklynEntityDecorationResolver.InitializerResolver(resolver.getYamlLoader()).decorate(spec, resolver.getAttrs());
- }
-
- protected CatalogItem<Entity,EntitySpec<?>> getCatalogItemImpl(ManagementContext mgmt, String brooklynType) {
- brooklynType = DeserializingClassRenamesProvider.findMappedName(brooklynType);
- return CatalogUtils.getCatalogItemOptionalVersion(mgmt, Entity.class, brooklynType);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceSpecResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceSpecResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceSpecResolver.java
new file mode 100644
index 0000000..19a76b3
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceSpecResolver.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.camp.brooklyn.spi.creation.service;
+
+import java.util.Set;
+
+import org.apache.brooklyn.api.catalog.CatalogItem;
+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.mgmt.ManagementContext;
+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.mgmt.persist.DeserializingClassRenamesProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CatalogServiceSpecResolver extends AbstractServiceSpecResolver {
+ private static final Logger log = LoggerFactory.getLogger(CatalogServiceSpecResolver.class);
+
+ private static final String RESOLVER_NAME = "catalog";
+ private final ServiceSpecResolver hardcodedResolver;
+
+ public CatalogServiceSpecResolver() {
+ super(RESOLVER_NAME);
+ hardcodedResolver = new HardcodedCatalogServiceSpecResolver();
+ }
+
+ @Override
+ protected boolean canResolve(String type, BrooklynClassLoadingContext loader) {
+ String localType = getLocalType(type);
+ CatalogItem<Entity, EntitySpec<?>> item = getCatalogItem(mgmt, localType);
+ if (item != null) {
+ try {
+ //Keeps behaviour of previous functionality, but probably should throw instead when using disabled items.
+ checkUsable(item);
+ return true;
+ } catch (IllegalStateException e) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public EntitySpec<?> resolve(String type, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) {
+ String localType = getLocalType(type);
+ CatalogItem<Entity, EntitySpec<?>> item = getCatalogItem(mgmt, localType);
+ if (item != null) {
+ checkUsable(item);
+
+ //Take the symbolicName part of the catalog item only for recursion detection to prevent
+ //cross referencing of different versions. Not interested in non-catalog item types.
+ //Prevent catalog items self-referencing even if explicitly different version.
+ boolean firstOccurrence = encounteredTypes.add(item.getSymbolicName());
+ boolean nonRecursiveCall = firstOccurrence;
+ if (nonRecursiveCall) {
+ // CatalogItem generics are just getting in the way, better get rid of them, we
+ // are casting anyway.
+ @SuppressWarnings({ "rawtypes" })
+ CatalogItem rawItem = item;
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ AbstractBrooklynObjectSpec rawSpec = EntityManagementUtils.createCatalogSpec(mgmt, rawItem, encounteredTypes);
+ return (EntitySpec<?>) rawSpec;
+ } else {
+ return null;
+ }
+ } else {
+ return hardcodedResolver.resolve(type, loader, encounteredTypes);
+ }
+ }
+
+ private void checkUsable(CatalogItem<Entity, EntitySpec<?>> item) {
+ if (item.isDisabled()) {
+ throw new IllegalStateException("Illegal use of disabled catalog item "+item.getSymbolicName()+":"+item.getVersion());
+ } else if (item.isDeprecated()) {
+ log.warn("Use of deprecated catalog item "+item.getSymbolicName()+":"+item.getVersion());
+ }
+ }
+
+ protected CatalogItem<Entity,EntitySpec<?>> getCatalogItem(ManagementContext mgmt, String brooklynType) {
+ brooklynType = DeserializingClassRenamesProvider.findMappedName(brooklynType);
+ return CatalogUtils.getCatalogItemOptionalVersion(mgmt, Entity.class, brooklynType);
+ }
+
+ @Override
+ public void injectManagementContext(ManagementContext mgmt) {
+ super.injectManagementContext(mgmt);
+ hardcodedResolver.injectManagementContext(mgmt);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceTypeResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceTypeResolver.java
deleted file mode 100644
index 94aa8fc..0000000
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceTypeResolver.java
+++ /dev/null
@@ -1,77 +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.camp.brooklyn.spi.creation.service;
-
-import java.util.Map;
-
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.camp.spi.PlatformComponentTemplate;
-import org.apache.brooklyn.entity.brooklynnode.BrooklynNode;
-import org.apache.brooklyn.entity.group.DynamicCluster;
-import org.apache.brooklyn.entity.group.DynamicRegionsFabric;
-import org.apache.brooklyn.entity.java.VanillaJavaApp;
-import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.CaseFormat;
-import com.google.common.base.Converter;
-import com.google.common.collect.ImmutableMap;
-
-/**
- * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code catalog:}
- * to Brooklyn {@link EntitySpec} instances.
- */
-public class CatalogServiceTypeResolver extends BrooklynServiceTypeResolver {
-
- @SuppressWarnings("unused")
- private static final Logger LOG = LoggerFactory.getLogger(ServiceTypeResolver.class);
-
- // TODO currently a hardcoded list of aliases; would like that to come from mgmt somehow
- private static final Map<String, String> CATALOG_TYPES = ImmutableMap.<String, String>builder()
- .put("cluster", DynamicCluster.class.getName())
- .put("fabric", DynamicRegionsFabric.class.getName())
- .put("vanilla", VanillaSoftwareProcess.class.getName())
- .put("software-process", VanillaSoftwareProcess.class.getName())
- .put("java-app", VanillaJavaApp.class.getName())
- .put("brooklyn-node", BrooklynNode.class.getName())
- .put("web-app-cluster","org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster")
- .build();
-
- // Allow catalog-type or CatalogType as service type string
- private static final Converter<String, String> FMT = CaseFormat.LOWER_HYPHEN.converterTo(CaseFormat.UPPER_CAMEL);
-
- @Override
- public String getTypePrefix() { return "catalog"; }
-
- @Override
- public String getBrooklynType(String serviceType) {
- String type = super.getBrooklynType(serviceType);
- if (type == null) return null;
-
- for (String check : CATALOG_TYPES.keySet()) {
- if (type.equals(check) || type.equals(FMT.convert(check))) {
- return CATALOG_TYPES.get(check);
- }
- }
-
- return type;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceSpecResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceSpecResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceSpecResolver.java
new file mode 100644
index 0000000..1910971
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceSpecResolver.java
@@ -0,0 +1,41 @@
+/*
+ * 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.service;
+
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.entity.chef.ChefConfig;
+import org.apache.brooklyn.entity.chef.ChefEntity;
+
+public class ChefServiceSpecResolver extends AbstractServiceSpecResolver {
+ private static final String RESOLVER_NAME = "chef";
+
+ public ChefServiceSpecResolver() {
+ super(RESOLVER_NAME);
+ }
+
+ @Override
+ public EntitySpec<?> resolve(String type, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) {
+ return EntitySpec.create(ChefEntity.class)
+ .configure(ChefConfig.CHEF_COOKBOOK_PRIMARY_NAME, getLocalType(type));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceTypeResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceTypeResolver.java
deleted file mode 100644
index b44deb7..0000000
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceTypeResolver.java
+++ /dev/null
@@ -1,61 +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.camp.brooklyn.spi.creation.service;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.brooklyn.api.catalog.CatalogItem;
-import org.apache.brooklyn.api.entity.Entity;
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver;
-import org.apache.brooklyn.camp.spi.PlatformComponentTemplate;
-import org.apache.brooklyn.entity.chef.ChefConfig;
-import org.apache.brooklyn.entity.chef.ChefEntity;
-import org.apache.brooklyn.util.text.Strings;
-
-/**
- * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code chef:}
- * to Brooklyn {@link EntitySpec} instances.
- */
-public class ChefServiceTypeResolver extends BrooklynServiceTypeResolver {
-
- @SuppressWarnings("unused")
- private static final Logger LOG = LoggerFactory.getLogger(ServiceTypeResolver.class);
-
- @Override
- public String getTypePrefix() { return "chef"; }
-
- @Override
- public String getBrooklynType(String serviceType) {
- return ChefEntity.class.getName();
- }
-
- /** Chef items are not in the catalog. */
- @Override
- public CatalogItem<Entity, EntitySpec<?>> getCatalogItem(BrooklynComponentTemplateResolver resolver, String serviceType) {
- return null;
- }
-
- @Override
- public <T extends Entity> void decorateSpec(BrooklynComponentTemplateResolver resolver, EntitySpec<T> spec) {
- spec.configure(ChefConfig.CHEF_COOKBOOK_PRIMARY_NAME, Strings.removeFromStart(resolver.getDeclaredType(), "chef:"));
- super.decorateSpec(resolver, spec);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/DefaultServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/DefaultServiceTypeResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/DefaultServiceTypeResolver.java
deleted file mode 100644
index fdd57d5..0000000
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/DefaultServiceTypeResolver.java
+++ /dev/null
@@ -1,23 +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.camp.brooklyn.spi.creation.service;
-
-public class DefaultServiceTypeResolver extends BrooklynServiceTypeResolver {
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/DelegatingServiceSpecResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/DelegatingServiceSpecResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/DelegatingServiceSpecResolver.java
new file mode 100644
index 0000000..e1a2f19
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/DelegatingServiceSpecResolver.java
@@ -0,0 +1,127 @@
+/*
+ * 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.service;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.exceptions.PropagatedRuntimeException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+
+public class DelegatingServiceSpecResolver extends AbstractServiceSpecResolver {
+ private static final String RESOLVER_PREFIX_CATALOG = "catalog:";
+
+ private static final String RESOLVER_PREFIX_JAVA = "java:";
+
+ private static final Logger log = LoggerFactory.getLogger(DelegatingServiceSpecResolver.class);
+
+ private static final String RESOLVER_NAME = "brooklyn";
+
+ private Collection<ServiceSpecResolver> resolvers;
+
+ public DelegatingServiceSpecResolver(@Nonnull ManagementContext mgmt, @Nonnull List<ServiceSpecResolver> overridingResolvers) {
+ super(RESOLVER_NAME);
+ this.resolvers = ImmutableList.<ServiceSpecResolver>builder()
+ .addAll(overridingResolvers)
+ .addAll(ServiceLoader.load(ServiceSpecResolver.class))
+ .build();
+ for (ServiceSpecResolver resolver : resolvers) {
+ resolver.injectManagementContext(mgmt);
+ }
+
+ injectManagementContext(mgmt);
+ }
+
+ @Override
+ public boolean accepts(String type, BrooklynClassLoadingContext loader) {
+ return accepts("", type, loader) ||
+ accepts(RESOLVER_PREFIX_CATALOG, type, loader) ||
+ accepts(RESOLVER_PREFIX_JAVA, type, loader);
+ }
+
+ private boolean accepts(String prefix, String type, BrooklynClassLoadingContext loader) {
+ for (ServiceSpecResolver resolver : resolvers) {
+ String localType = getLocalType(type);
+ if (resolver.accepts(prefix + localType, loader)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public EntitySpec<?> resolve(String type, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) {
+ String localType = getLocalType(type);
+
+ EntitySpec<?> spec = resolve(resolvers, localType, loader, encounteredTypes);
+ if (spec != null) {
+ return spec;
+ }
+ spec = resolve(resolvers, RESOLVER_PREFIX_CATALOG + localType, loader, encounteredTypes);
+ if (spec != null) {
+ return spec;
+ }
+ return resolve(resolvers, RESOLVER_PREFIX_JAVA + localType, loader, encounteredTypes);
+ }
+
+ private EntitySpec<?> resolve(
+ Collection<ServiceSpecResolver> resolvers,
+ String localType,
+ BrooklynClassLoadingContext loader,
+ Set<String> encounteredTypes) {
+ Collection<String> resolversWhoDontSupport = new ArrayList<String>();
+ Collection<Exception> otherProblemsFromResolvers = new ArrayList<Exception>();
+
+ for (ServiceSpecResolver resolver : resolvers) {
+ if (resolver.accepts(localType, loader)) {
+ try {
+ EntitySpec<?> spec = resolver.resolve(localType, loader, encounteredTypes);
+ if (spec != null) {
+ return spec;
+ } else {
+ resolversWhoDontSupport.add(resolver.getName() + " (returned null)");
+ }
+ } catch (Exception e) {
+ otherProblemsFromResolvers.add(new PropagatedRuntimeException("Transformer for "+resolver.getName()+" gave an error creating this plan: "+
+ Exceptions.collapseText(e), e));
+ }
+ }
+ }
+ if (!otherProblemsFromResolvers.isEmpty()) {
+ // at least one thought he could do it
+ log.debug("Type " + localType + " could not be resolved; failure will be propagated (other transformers tried = "+resolversWhoDontSupport+"): "+otherProblemsFromResolvers);
+ throw otherProblemsFromResolvers.size()==1 ? Exceptions.create(null, otherProblemsFromResolvers) :
+ Exceptions.create("ServiceSpecResolvers all failed", otherProblemsFromResolvers);
+ }
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/HardcodedCatalogServiceSpecResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/HardcodedCatalogServiceSpecResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/HardcodedCatalogServiceSpecResolver.java
new file mode 100644
index 0000000..2a3d7cd
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/HardcodedCatalogServiceSpecResolver.java
@@ -0,0 +1,95 @@
+/*
+ * 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.service;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.entity.brooklynnode.BrooklynNode;
+import org.apache.brooklyn.entity.group.DynamicCluster;
+import org.apache.brooklyn.entity.group.DynamicRegionsFabric;
+import org.apache.brooklyn.entity.java.VanillaJavaApp;
+import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Converter;
+import com.google.common.collect.ImmutableMap;
+
+public class HardcodedCatalogServiceSpecResolver extends AbstractServiceSpecResolver {
+ private static final String RESOLVER_NAME = "catalog";
+
+ private static final Map<String, String> CATALOG_TYPES = ImmutableMap.<String, String>builder()
+ .put("cluster", DynamicCluster.class.getName())
+ .put("fabric", DynamicRegionsFabric.class.getName())
+ .put("vanilla", VanillaSoftwareProcess.class.getName())
+ .put("software-process", VanillaSoftwareProcess.class.getName())
+ .put("java-app", VanillaJavaApp.class.getName())
+ .put("brooklyn-node", BrooklynNode.class.getName())
+ .put("web-app-cluster","org.apache.brooklyn.entity.webapp.ControlledDynamicWebAppCluster")
+ .build();
+
+ // Allow catalog-type or CatalogType as service type string
+ private static final Converter<String, String> FMT = CaseFormat.UPPER_CAMEL.converterTo(CaseFormat.LOWER_HYPHEN);
+
+ public HardcodedCatalogServiceSpecResolver() {
+ super(RESOLVER_NAME);
+ }
+
+ @Override
+ protected boolean canResolve(String type, BrooklynClassLoadingContext loader) {
+ String localType = getLocalType(type);
+ String specType = getImplementation(localType);
+ return specType != null;
+ }
+
+ @Override
+ public EntitySpec<?> resolve(String type, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) {
+ String localType = getLocalType(type);
+ String specType = getImplementation(localType);
+ if (specType != null) {
+ return buildSpec(specType);
+ } else {
+ return null;
+ }
+ }
+
+ private String getImplementation(String type) {
+ String specType = CATALOG_TYPES.get(type);
+ if (specType != null) {
+ return specType;
+ } else {
+ return CATALOG_TYPES.get(FMT.convert(type));
+ }
+ }
+
+ private EntitySpec<?> buildSpec(String specType) {
+ // TODO is this hardcoded list deprecated? If so log a warning.
+ try {
+ @SuppressWarnings("unchecked")
+ Class<Entity> specClass = (Class<Entity>)mgmt.getCatalogClassLoader().loadClass(specType);
+ return EntitySpec.create(specClass);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Unable to load hardcoded catalog type " + specType, e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceSpecResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceSpecResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceSpecResolver.java
new file mode 100644
index 0000000..fa0f9e5
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceSpecResolver.java
@@ -0,0 +1,91 @@
+/*
+ * 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.service;
+
+import java.util.List;
+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.core.catalog.internal.CatalogUtils;
+import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.javalang.Reflections;
+
+public class JavaServiceSpecResolver extends AbstractServiceSpecResolver{
+ private static final String RESOLVER_NAME = "java";
+
+ public JavaServiceSpecResolver() {
+ super(RESOLVER_NAME);
+ }
+
+ @Override
+ protected boolean canResolve(String type, BrooklynClassLoadingContext loader) {
+ String localType = getLocalType(type);
+ Maybe<?> javaType = tryLoadJavaType(localType, loader);
+ return javaType.isPresent();
+ }
+
+ @Override
+ public EntitySpec<?> resolve(String type, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) {
+ String localType = getLocalType(type);
+ try {
+ return resolveInternal(localType, loader);
+ } catch (Exception e) {
+ boolean firstOccurrence = encounteredTypes.add(localType);
+ boolean recursiveButTryJava = !firstOccurrence;
+ if (recursiveButTryJava) {
+ throw new IllegalStateException("Recursive reference to " + localType + " (and cannot be resolved as a Java type)", e);
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ private EntitySpec<?> resolveInternal(String localType, BrooklynClassLoadingContext loader) {
+ Maybe<Class<? extends Entity>> javaTypeMaybe = tryLoadJavaType(localType, loader);
+ if (javaTypeMaybe.isAbsent())
+ throw new IllegalStateException("Could not find "+localType, ((Maybe.Absent<?>)javaTypeMaybe).getException());
+ Class<? extends Entity> javaType = javaTypeMaybe.get();
+
+ EntitySpec<? extends Entity> spec;
+ if (javaType.isInterface()) {
+ spec = EntitySpec.create(javaType);
+ } else {
+ // If this is a concrete class, particularly for an Application class, we want the proxy
+ // to expose all interfaces it implements.
+ Class<? extends Entity> interfaceclazz = (Application.class.isAssignableFrom(javaType)) ? Application.class : Entity.class;
+ List<Class<?>> additionalInterfaceClazzes = Reflections.getAllInterfaces(javaType);
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ EntitySpec<?> rawSpec = EntitySpec.create(interfaceclazz)
+ .impl((Class) javaType)
+ .additionalInterfaces(additionalInterfaceClazzes);
+ spec = rawSpec;
+ }
+ spec.catalogItemId(CatalogUtils.getCatalogItemIdFromLoader(loader));
+
+ return spec;
+ }
+
+ private Maybe<Class<? extends Entity>> tryLoadJavaType(String localType, BrooklynClassLoadingContext loader) {
+ return loader.tryLoadClass(localType, Entity.class);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceTypeResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceTypeResolver.java
deleted file mode 100644
index d6c52f4..0000000
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceTypeResolver.java
+++ /dev/null
@@ -1,38 +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.camp.brooklyn.spi.creation.service;
-
-import org.apache.brooklyn.api.entity.EntitySpec;
-import org.apache.brooklyn.camp.spi.PlatformComponentTemplate;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code java:}
- * to Brooklyn {@link EntitySpec} instances.
- */
-public class JavaServiceTypeResolver extends BrooklynServiceTypeResolver {
-
- @SuppressWarnings("unused")
- private static final Logger LOG = LoggerFactory.getLogger(ServiceTypeResolver.class);
-
- @Override
- public String getTypePrefix() { return "java"; }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceSpecResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceSpecResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceSpecResolver.java
new file mode 100644
index 0000000..00d6dd5
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceSpecResolver.java
@@ -0,0 +1,56 @@
+/*
+ * 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.service;
+
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
+import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+
+/**
+ * Resolves and decorates {@link EntitySpec entity specifications} based on the {@code serviceType} in a template.
+ * <p>
+ * The resolver implementation will use the rest of the local part of the service type information
+ * to create and decorate an appropriate {@link EntitySpec entity}.
+ * <p>
+ * The resolvers are loaded using the {@link ServiceLoader} mechanism, allowing external libraries
+ * to add extra service type implementations that will be picked up at runtime.
+ */
+// TODO Not CAMP specific, move to core, to be reused by other parsers
+public interface ServiceSpecResolver extends ManagementContextInjectable {
+ /**
+ * Uniquely identifies the resolver, can be used to address the same resolver at a later point in time.
+ * For implementations: this usually matches the service type prefix, but not required.
+ */
+ String getName();
+
+ /**
+ * @return if the resolver can create a spec for the service type
+ */
+ boolean accepts(String type, BrooklynClassLoadingContext loader);
+
+ /**
+ * Create a spec for the service type
+ */
+ @Nullable EntitySpec<?> resolve(String type, BrooklynClassLoadingContext loader, Set<String> encounteredTypes);
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java
index dcbd971..c1399ff 100644
--- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java
@@ -37,7 +37,10 @@ import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateR
*
* @see BrooklynServiceTypeResolver
* @see ChefServiceTypeResolver
+ *
+ * @deprecated since 0.9.0, {@link ServiceSpecResolver} instead.
*/
+@Deprecated
public interface ServiceTypeResolver {
String DEFAULT_TYPE_PREFIX = "brooklyn";
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/4485fe5c/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolverAdaptor.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolverAdaptor.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolverAdaptor.java
new file mode 100644
index 0000000..60abd40
--- /dev/null
+++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolverAdaptor.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.creation.service;
+
+import java.util.Set;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver;
+import org.apache.brooklyn.core.mgmt.classloading.BrooklynClassLoadingContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import groovy.xml.Entity;
+
+@SuppressWarnings("deprecation")
+public class ServiceTypeResolverAdaptor extends AbstractServiceSpecResolver {
+ private static final Logger log = LoggerFactory.getLogger(ServiceTypeResolverAdaptor.class);
+ private ServiceTypeResolver serviceTypeResolver;
+ private BrooklynComponentTemplateResolver resolver;
+
+ public ServiceTypeResolverAdaptor(BrooklynComponentTemplateResolver resolver, ServiceTypeResolver serviceTypeResolver) {
+ super(serviceTypeResolver.getTypePrefix());
+ this.serviceTypeResolver = serviceTypeResolver;
+ this.resolver = resolver;
+ }
+
+ @Override
+ public boolean accepts(String type, BrooklynClassLoadingContext loader) {
+ return true;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public EntitySpec<?> resolve(String type, BrooklynClassLoadingContext loader, Set<String> encounteredTypes) {
+ // Assume this is interface! Only known implementation is DockerServiceTypeResolver.
+ String brooklynType = serviceTypeResolver.getBrooklynType(type);
+ Class<? extends Entity> javaType = loader.loadClass(brooklynType, Entity.class);
+ if (!javaType.isInterface()) {
+ log.warn("Using " + ServiceTypeResolver.class.getSimpleName() + " with a non-interface type - this usage is not supported. Use " + ServiceSpecResolver.class.getSimpleName() + " instead.");
+ }
+ EntitySpec<?> spec = EntitySpec.create((Class)javaType);
+ serviceTypeResolver.decorateSpec(resolver, spec);
+ return spec;
+ }
+
+}