You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2015/04/12 23:48:06 UTC

[1/3] incubator-brooklyn git commit: Parse service types in YAML using pluggable resolver impls

Repository: incubator-brooklyn
Updated Branches:
  refs/heads/master 4f1eb45cb -> cecaaf02b


Parse service types in YAML using pluggable resolver impls


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/303c3884
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/303c3884
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/303c3884

Branch: refs/heads/master
Commit: 303c3884e868b9167bd1551469507137634948fc
Parents: 1f14917
Author: Andrew Kennedy <gr...@apache.org>
Authored: Tue Apr 7 16:35:19 2015 +0100
Committer: Andrew Kennedy <gr...@apache.org>
Committed: Wed Apr 8 20:18:45 2015 +0100

----------------------------------------------------------------------
 .../BrooklynAssemblyTemplateInstantiator.java   |  52 ++---
 .../BrooklynComponentTemplateResolver.java      | 227 ++++++++-----------
 .../BrooklynEntityDecorationResolver.java       |   6 +-
 .../creation/ChefComponentTemplateResolver.java |  57 -----
 .../service/BrooklynServiceTypeResolver.java    |  72 ++++++
 .../service/CatalogServiceTypeResolver.java     |  58 +++++
 .../service/ChefServiceTypeResolver.java        |  62 +++++
 .../service/JavaServiceTypeResolver.java        |  30 +++
 .../creation/service/ServiceTypeResolver.java   |  43 ++++
 ...lyn.spi.creation.service.ServiceTypeResolver |  22 ++
 10 files changed, 414 insertions(+), 215 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/303c3884/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
index 379cd43..af1cbb0 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java
@@ -64,9 +64,9 @@ import com.google.common.collect.Sets;
 public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpecInstantiator {
 
     private static final Logger log = LoggerFactory.getLogger(BrooklynAssemblyTemplateInstantiator.class);
-    
+
     public static final String NEVER_UNWRAP_APPS_PROPERTY = "wrappedApp";
-    
+
     @Override
     public Assembly instantiate(AssemblyTemplate template, CampPlatform platform) {
         Application app = create(template, platform);
@@ -80,11 +80,11 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
         log.debug("CAMP created {}", instance);
         return instance;
     }
-    
+
     private ManagementContext getBrooklynManagementContext(CampPlatform platform) {
         return ((HasBrooklynManagementContext)platform).getBrooklynManagementContext();
     }
-    
+
     @SuppressWarnings("unchecked")
     public EntitySpec<? extends Application> createSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext loader, boolean autoUnwrapIfPossible) {
         log.debug("CAMP creating application instance for {} ({})", template.getId(), template);
@@ -94,24 +94,24 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
         BrooklynComponentTemplateResolver resolver = BrooklynComponentTemplateResolver.Factory.newInstance(
             loader, buildWrapperAppTemplate(template));
         EntitySpec<? extends Application> app = resolver.resolveSpec();
-        
+
         // first build the children into an empty shell app
         List<EntitySpec<?>> childSpecs = buildTemplateServicesAsSpecs(loader, template, platform);
         for (EntitySpec<?> childSpec : childSpecs) {
             app.child(childSpec);
         }
-        
+
         if (autoUnwrapIfPossible && shouldUnwrap(template, app)) {
             EntitySpec<? extends Application> oldApp = app;
             app = (EntitySpec<? extends Application>) Iterables.getOnlyElement( app.getChildren() );
-            
+
             // if promoted, apply the transformations done to the app
             // (transformations will be done by the resolveSpec call above, but we are collapsing oldApp so transfer to app=newApp)
             EntityManagementUtils.collapseSpec(oldApp, app);
         } else {
             app.configure(EntityManagementUtils.WRAPPER_APP_MARKER, Boolean.TRUE);
         }
-        
+
         return app;
     }
 
@@ -135,10 +135,10 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
             if (TypeCoercions.coerce(leaveWrapped, Boolean.class))
                 return false;
         }
-        
-        if (app.getChildren().size()!=1) 
+
+        if (app.getChildren().size()!=1)
             return false;
-        
+
         EntitySpec<?> childSpec = Iterables.getOnlyElement(app.getChildren());
         if (childSpec.getType()==null || !Application.class.isAssignableFrom(childSpec.getType()))
             return false;
@@ -152,48 +152,48 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
 
     private List<EntitySpec<?>> buildTemplateServicesAsSpecsImpl(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 = resolveSpec(entityResolver, encounteredCatalogTypes);
-            
+
             result.add(spec);
         }
         return result;
     }
 
     protected EntitySpec<?> resolveSpec(
-            BrooklynComponentTemplateResolver entityResolver, 
+            BrooklynComponentTemplateResolver entityResolver,
             Set<String> encounteredCatalogTypes) {
-        ManagementContext mgmt = entityResolver.loader.getManagementContext();
+        ManagementContext mgmt = entityResolver.getLoader().getManagementContext();
 
-        String brooklynType = entityResolver.getBrooklynType();
-        CatalogItem<Entity, EntitySpec<?>> item = entityResolver.getCatalogItem();
+        String brooklynType = entityResolver.getServiceTypeResolver().getBrooklynType(entityResolver.getDeclaredType());
+        CatalogItem<Entity, EntitySpec<?>> item = entityResolver.getServiceTypeResolver().getCatalogItem(entityResolver, entityResolver.getDeclaredType());
 
         //Take the symoblicName 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;
-        
-        if (log.isTraceEnabled()) log.trace("Building CAMP template services: type="+brooklynType+"; item="+item+"; loader="+entityResolver.loader+"; encounteredCatalogTypes="+encounteredCatalogTypes);
+
+        if (log.isTraceEnabled()) log.trace("Building CAMP template services: type="+brooklynType+"; item="+item+"; loader="+entityResolver.getLoader()+"; encounteredCatalogTypes="+encounteredCatalogTypes);
 
         EntitySpec<?> spec = null;
         String protocol = Urls.getProtocol(brooklynType);
         if (protocol != null) {
             if (BrooklynCampConstants.YAML_URL_PROTOCOL_WHITELIST.contains(protocol)) {
-                spec = tryResolveYamlURLReferenceSpec(brooklynType, entityResolver.loader, encounteredCatalogTypes);
+                spec = tryResolveYamlURLReferenceSpec(brooklynType, entityResolver.getLoader(), encounteredCatalogTypes);
                 if (spec != null) {
                     entityResolver.populateSpec(spec);
                 }
             } else {
-                log.warn("The reference " + brooklynType + " looks like an URL but the protocol " + 
+                log.warn("The reference " + brooklynType + " looks like an URL but the protocol " +
                         protocol + " isn't white listed (" + BrooklynCampConstants.YAML_URL_PROTOCOL_WHITELIST + "). " +
                         "Will try to load it as catalog item or java type.");
             }
         }
-        
+
         if (spec == null) {
             // - Load a java class from current loader (item == null || entityResolver.isJavaTypePrefix())
             // - Load a java class specified in an old-style catalog item (item != null && item.getJavaType() != null)
@@ -225,7 +225,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
     }
 
     private EntitySpec<?> tryResolveYamlURLReferenceSpec(
-            String brooklynType, BrooklynClassLoadingContext itemLoader, 
+            String brooklynType, BrooklynClassLoadingContext itemLoader,
             Set<String> encounteredCatalogTypes) {
         ManagementContext mgmt = itemLoader.getManagementContext();
         Reader yaml;
@@ -251,11 +251,11 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
             ManagementContext mgmt,
             CatalogItem<Entity, EntitySpec<?>> item,
             Set<String> encounteredCatalogTypes) {
-        
+
         String yaml = item.getPlanYaml();
         Reader input = new StringReader(yaml);
         BrooklynClassLoadingContext itemLoader = CatalogUtils.newClassLoadingContext(mgmt, item);
-        
+
         return createNestedSpec(mgmt, encounteredCatalogTypes, input, itemLoader);
     }
 
@@ -263,7 +263,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
             Set<String> encounteredCatalogTypes, Reader input,
             BrooklynClassLoadingContext itemLoader) {
         CampPlatform platform = BrooklynServerConfig.getCampPlatform(mgmt).get();
-        
+
         AssemblyTemplate at;
         BrooklynLoaderTracker.setLoader(itemLoader);
         try {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/303c3884/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index da6e395..37fccf8 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -19,7 +19,8 @@
 package io.brooklyn.camp.brooklyn.spi.creation;
 
 import io.brooklyn.camp.brooklyn.BrooklynCampConstants;
-import io.brooklyn.camp.brooklyn.spi.dsl.methods.BrooklynDslCommon;
+import io.brooklyn.camp.brooklyn.spi.creation.service.BrooklynServiceTypeResolver;
+import io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver;
 import io.brooklyn.camp.spi.AbstractResource;
 import io.brooklyn.camp.spi.ApplicationComponentTemplate;
 import io.brooklyn.camp.spi.AssemblyTemplate;
@@ -28,6 +29,7 @@ import io.brooklyn.camp.spi.PlatformComponentTemplate;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -45,23 +47,17 @@ import brooklyn.entity.basic.AbstractEntity;
 import brooklyn.entity.basic.BrooklynTags;
 import brooklyn.entity.basic.BrooklynTaskTags;
 import brooklyn.entity.basic.ConfigKeys;
-import brooklyn.entity.basic.EntityInternal;
-import brooklyn.entity.basic.VanillaSoftwareProcess;
-import brooklyn.entity.group.DynamicCluster;
-import brooklyn.entity.group.DynamicRegionsFabric;
 import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.proxying.InternalEntityFactory;
 import brooklyn.location.Location;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.ManagementContextInjectable;
 import brooklyn.management.classloading.BrooklynClassLoadingContext;
-import brooklyn.management.classloading.BrooklynClassLoadingContextSequential;
 import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
 import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.util.collections.MutableList;
 import brooklyn.util.collections.MutableSet;
 import brooklyn.util.config.ConfigBag;
-import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.flags.FlagUtils;
 import brooklyn.util.flags.FlagUtils.FlagConfigKeyAndValueRecord;
 import brooklyn.util.guava.Maybe;
@@ -70,6 +66,7 @@ import brooklyn.util.task.Tasks;
 import brooklyn.util.text.Strings;
 
 import com.google.common.base.Function;
+import com.google.common.base.Splitter;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
 
@@ -77,59 +74,80 @@ import com.google.common.collect.Maps;
  * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code brooklyn:}
  * to Brooklyn {@link EntitySpec} instances.
  * <p>
- * but TODO this should probably be done by {@link BrooklynEntityMatcher} 
+ * but TODO this should probably be done by {@link BrooklynEntityMatcher}
  * so we have a spec by the time we come to instantiate.
- * (currently privileges "brooklyn.*" key names are checked in both places!)  
+ * (currently privileges "brooklyn.*" key names are checked in both places!)
  */
 public class BrooklynComponentTemplateResolver {
 
-    private static final Logger log = LoggerFactory.getLogger(BrooklynDslCommon.class);
+    private static final Logger log = LoggerFactory.getLogger(BrooklynComponentTemplateResolver.class);
 
-    BrooklynClassLoadingContext loader;
-    final ManagementContext mgmt;
-    final ConfigBag attrs;
-    final Maybe<AbstractResource> template;
-    final BrooklynYamlTypeInstantiator.Factory yamlLoader;
-    AtomicBoolean alreadyBuilt = new AtomicBoolean(false);
+    private final BrooklynClassLoadingContext loader;
+    private final ManagementContext mgmt;
+    private final ConfigBag attrs;
+    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);
+
+    public BrooklynComponentTemplateResolver(BrooklynClassLoadingContext loader, ConfigBag attrs, AbstractResource optionalTemplate, String type, ServiceTypeResolver typeResolver) {
+        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;
+    }
+
+    public BrooklynClassLoadingContext getLoader() { return loader; }
+    public ManagementContext getManagementContext() { return mgmt; }
+    public ConfigBag getAttrs() { return attrs; }
+    public Maybe<AbstractResource> getTemplate() { return template; }
+    public BrooklynYamlTypeInstantiator.Factory getYamlLoader() { return yamlLoader; }
+    public ServiceTypeResolver getServiceTypeResolver() { return typeResolver; }
+    public String getDeclaredType() { return type; }
+    public Boolean isAlreadyBuilt() { return alreadyBuilt.get(); }
 
     public static class Factory {
 
         /** returns resolver type based on the service type, inspecting the arguments in order to determine the service type */
-        private static Class<? extends BrooklynComponentTemplateResolver> computeResolverType(String knownServiceType, AbstractResource optionalTemplate, ConfigBag attrs) {
+        private static ServiceTypeResolver computeResolverType(BrooklynClassLoadingContext context, String knownServiceType, AbstractResource optionalTemplate, ConfigBag attrs) {
             String type = getDeclaredType(knownServiceType, optionalTemplate, attrs);
-            if (type!=null) {
-                if (type.startsWith("brooklyn:") || type.startsWith("java:")) return BrooklynComponentTemplateResolver.class;
-                if (type.equalsIgnoreCase("chef") || type.startsWith("chef:")) return ChefComponentTemplateResolver.class;
-                // TODO other BrooklynComponentTemplateResolver subclasses detected here 
-                // (perhaps use regexes mapping to subclass name, defined in mgmt?)
+            return findService(context, type);
+        }
+
+        protected static ServiceTypeResolver findService(BrooklynClassLoadingContext context, String type) {
+            String prefix = Splitter.on(":").splitToList(type).get(0);
+            ServiceLoader<ServiceTypeResolver> loader = ServiceLoader.load(ServiceTypeResolver.class, context.getManagementContext().getCatalog().getRootClassLoader());
+            for (ServiceTypeResolver resolver : loader) {
+               if (prefix.equalsIgnoreCase(resolver.getTypePrefix())) return resolver;
             }
-            
             return null;
         }
 
-        public static BrooklynComponentTemplateResolver newInstance(BrooklynClassLoadingContext loader, Map<String, ?> childAttrs) {
-            return newInstance(loader, ConfigBag.newInstance(childAttrs), null);
+        public static BrooklynComponentTemplateResolver newInstance(BrooklynClassLoadingContext context, Map<String, ?> childAttrs) {
+            return newInstance(context, ConfigBag.newInstance(childAttrs), null);
         }
 
-        public static BrooklynComponentTemplateResolver newInstance(BrooklynClassLoadingContext loader, AbstractResource template) {
-            return newInstance(loader, ConfigBag.newInstance(template.getCustomAttributes()), template);
+        public static BrooklynComponentTemplateResolver newInstance(BrooklynClassLoadingContext context, AbstractResource template) {
+            return newInstance(context, ConfigBag.newInstance(template.getCustomAttributes()), template);
         }
-        
-        public static BrooklynComponentTemplateResolver newInstance(BrooklynClassLoadingContext loader, String serviceType) {
-            return newInstance(loader, ConfigBag.newInstance().configureStringKey("serviceType", serviceType), null);
+
+        public static BrooklynComponentTemplateResolver newInstance(BrooklynClassLoadingContext context, String serviceType) {
+            return newInstance(context, ConfigBag.newInstance().configureStringKey("serviceType", serviceType), null);
         }
-        
-        private static BrooklynComponentTemplateResolver newInstance(BrooklynClassLoadingContext loader, ConfigBag attrs, AbstractResource optionalTemplate) {
-            Class<? extends BrooklynComponentTemplateResolver> rt = computeResolverType(null, optionalTemplate, attrs);
-            if (rt==null) // use default 
-                rt = BrooklynComponentTemplateResolver.class;
-            
-            try {
-                return (BrooklynComponentTemplateResolver) rt.getConstructors()[0].newInstance(loader, attrs, optionalTemplate);
-            } catch (Exception e) { throw Exceptions.propagate(e); }
+
+        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 BrooklynServiceTypeResolver();
+            return new BrooklynComponentTemplateResolver(context, attrs, optionalTemplate, type, typeResolver);
         }
 
-        private static String getDeclaredType(String knownServiceType, AbstractResource optionalTemplate, @Nullable ConfigBag attrs) {
+        public static String getDeclaredType(String knownServiceType, AbstractResource optionalTemplate, @Nullable ConfigBag attrs) {
             String type = knownServiceType;
             if (type==null && optionalTemplate!=null) {
                 type = optionalTemplate.getType();
@@ -140,67 +158,20 @@ public class BrooklynComponentTemplateResolver {
             if (type==null) type = extractServiceTypeAttribute(attrs);
             return type;
         }
-        
+
         private static String extractServiceTypeAttribute(@Nullable ConfigBag attrs) {
             return BrooklynYamlTypeInstantiator.InstantiatorFromKey.extractTypeName("service", attrs).orNull();
         }
 
-        public static boolean supportsType(BrooklynClassLoadingContext loader, String serviceType) {
-            Class<? extends BrooklynComponentTemplateResolver> type = computeResolverType(serviceType, null, null);
-            if (type!=null) return true;
-            return newInstance(loader, serviceType).canResolve();
+        public static boolean supportsType(BrooklynClassLoadingContext context, String serviceType) {
+            ServiceTypeResolver typeResolver = computeResolverType(context, serviceType, null, null);
+            if (typeResolver != null) return true;
+            return newInstance(context, serviceType).canResolve();
         }
     }
 
-    public BrooklynComponentTemplateResolver(BrooklynClassLoadingContext loader, ConfigBag attrs, AbstractResource optionalTemplate) {
-        this.loader = loader;
-        this.mgmt = loader.getManagementContext();
-        this.attrs = ConfigBag.newInstanceCopying(attrs);
-        this.template = Maybe.fromNullable(optionalTemplate);
-        this.yamlLoader = new BrooklynYamlTypeInstantiator.Factory(loader, this);
-    }
-    
-    protected String getDeclaredType() {
-        return Factory.getDeclaredType(null, template.orNull(), attrs);
-    }
-    
-    // TODO Generalise to have other prefixes (e.g. explicit "catalog:" etc)?
-    protected boolean isJavaTypePrefix() {
-        String type = getDeclaredType();
-        return type != null && (type.toLowerCase().startsWith("java:") || type.toLowerCase().startsWith("brooklyn:java:"));
-    }
-
-    protected String getBrooklynType() {
-        String type = getDeclaredType();
-        type = Strings.removeFromStart(type, "brooklyn:", "java:");
-        if (type == null) return null;
-        
-        // TODO currently a hardcoded list of aliases; would like that to come from mgmt somehow
-        if (type.equals("cluster") || type.equals("Cluster")) return DynamicCluster.class.getName();
-        if (type.equals("fabric") || type.equals("Fabric")) return DynamicRegionsFabric.class.getName();
-        if (type.equals("vanilla") || type.equals("Vanilla")) return VanillaSoftwareProcess.class.getName();
-        if (type.equals("web-app-cluster") || type.equals("WebAppCluster"))
-            // TODO use service discovery; currently included as string to avoid needing a reference to it
-            return "brooklyn.entity.webapp.ControlledDynamicWebAppCluster";
-        
-        return type;
-    }
-
-    /** Returns the CatalogItem if there is one for the given type;
-     * (if no type, callers should fall back to default classloading)
-     */
-    @Nullable
-    public CatalogItem<Entity,EntitySpec<?>> getCatalogItem() {
-        String type = getBrooklynType();
-        if (type != null) {
-            return CatalogUtils.getCatalogItemOptionalVersion(mgmt, Entity.class,  type);
-        } else {
-            return null;
-        }
-    }
-    
-    public boolean canResolve() {
-        if (getCatalogItem()!=null)
+    protected boolean canResolve() {
+        if (typeResolver.getCatalogItem(this, type)!=null)
             return true;
         if (loader.tryLoadClass(getJavaType(), Entity.class).isPresent())
             return true;
@@ -208,42 +179,47 @@ public class BrooklynComponentTemplateResolver {
     }
 
     /** returns the entity class, if needed in contexts which scan its statics for example */
-    public Class<? extends Entity> loadEntityClass() {
+    protected Class<? extends Entity> loadEntityClass() {
         Maybe<Class<? extends Entity>> result = tryLoadEntityClass();
         if (result.isAbsent())
-            throw new IllegalStateException("Could not find "+getBrooklynType(), ((Maybe.Absent<?>)result).getException());
+            throw new IllegalStateException("Could not find "+typeResolver.getBrooklynType(type), ((Maybe.Absent<?>)result).getException());
         return result.get();
     }
-    
+
     /** tries to load the Java entity class */
-    public Maybe<Class<? extends Entity>> tryLoadEntityClass() {
+    protected Maybe<Class<? extends Entity>> tryLoadEntityClass() {
         return loader.tryLoadClass(getJavaType(), Entity.class);
     }
 
-    private String getJavaType() {
-        CatalogItem<Entity, EntitySpec<?>> item = getCatalogItem();
+    // TODO Generalise to have other prefixes (e.g. explicit "catalog:" etc)?
+    protected boolean isJavaTypePrefix() {
+        return type != null && (type.toLowerCase().startsWith("java:") || type.toLowerCase().startsWith("brooklyn:java:"));
+    }
+
+    protected String getJavaType() {
+        CatalogItem<Entity, EntitySpec<?>> item = typeResolver.getCatalogItem(this, type);
         if (!isJavaTypePrefix() && item != null && item.getJavaType() != null) {
             return item.getJavaType();
         } else {
-            return getBrooklynType();
+            return typeResolver.getBrooklynType(type);
         }
     }
 
     /** resolves the spec, updating the loader if a catalog item is loaded */
-    public <T extends Entity> EntitySpec<T> resolveSpec() {
+    protected <T extends Entity> EntitySpec<T> resolveSpec() {
         if (alreadyBuilt.getAndSet(true))
             throw new IllegalStateException("Spec can only be used once: "+this);
-        
+
         EntitySpec<T> spec = createSpec();
         populateSpec(spec);
-        
+
         return spec;
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    private <T extends Entity> EntitySpec<T> createSpec() {
+    protected <T extends Entity> EntitySpec<T> createSpec() {
         Class<T> type = (Class<T>) loadEntityClass();
-        
+
         EntitySpec<T> spec;
         if (type.isInterface()) {
             spec = EntitySpec.create(type);
@@ -297,19 +273,12 @@ public class BrooklynComponentTemplateResolver {
             spec.configure(BrooklynCampConstants.TEMPLATE_ID, templateId);
         if (planId != null)
             spec.configure(BrooklynCampConstants.PLAN_ID, planId);
-        
+
         List<Location> childLocations = new BrooklynYamlLocationResolver(mgmt).resolveLocations(attrs.getAllConfig(), true);
         if (childLocations != null)
             spec.locations(childLocations);
-        
-        decorateSpec(spec);
-    }
 
-    protected <T extends Entity> void decorateSpec(EntitySpec<T> spec) {
-        new BrooklynEntityDecorationResolver.PolicySpecResolver(yamlLoader).decorate(spec, attrs);
-        new BrooklynEntityDecorationResolver.EnricherSpecResolver(yamlLoader).decorate(spec, attrs);
-        new BrooklynEntityDecorationResolver.InitializerResolver(yamlLoader).decorate(spec, attrs);
-        
+        typeResolver.decorateSpec(this, spec);
         configureEntityConfig(spec);
     }
 
@@ -326,20 +295,20 @@ public class BrooklynComponentTemplateResolver {
         if (planId != null) {
             entity.config().set(BrooklynCampConstants.PLAN_ID, planId);
         }
-        
+
         if (spec.getLocations().size() > 0) {
             ((AbstractEntity)entity).addLocations(spec.getLocations());
         }
-        
+
         if (spec.getParent() != null) entity.setParent(spec.getParent());
-        
+
         return entity;
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    private void configureEntityConfig(EntitySpec<?> spec) {
+    protected void configureEntityConfig(EntitySpec<?> spec) {
         ConfigBag bag = ConfigBag.newInstance((Map<Object, Object>) attrs.getStringKey("brooklyn.config"));
-        
+
         // first take *recognised* flags and config keys from the top-level, and put them in the bag (of brooklyn.config)
         // (for component templates this will have been done already by BrooklynEntityMatcher, but for specs it is needed here)
         ConfigBag bagFlags = ConfigBag.newInstanceCopying(attrs);
@@ -384,14 +353,14 @@ public class BrooklynComponentTemplateResolver {
         protected final ManagementContext mgmt;
         /* TODO find a way to make do without loader here?
          * it is not very nice having to serialize it; but serialization of BLCL is now relatively clean.
-         * 
+         *
          * it is only used to instantiate classes, and now most things should be registered with catalog;
          * the notable exception is when one entity in a bundle is creating another in the same bundle,
-         * it wants to use his bundle CLC to do that.  but we can set up some unique reference to the entity 
+         * it wants to use his bundle CLC to do that.  but we can set up some unique reference to the entity
          * which can be used to find it from mgmt, rather than pass the loader.
          */
         private BrooklynClassLoadingContext loader = null;
-        
+
         public SpecialFlagsTransformer(BrooklynClassLoadingContext loader) {
             this.loader = loader;
             mgmt = loader.getManagementContext();
@@ -405,18 +374,18 @@ public class BrooklynComponentTemplateResolver {
                 return MutableList.copyOf(transformSpecialFlags((Iterable<?>)input));
             else if (input instanceof Iterable<?>)
                 return transformSpecialFlags((Iterable<?>)input);
-            else 
+            else
                 return transformSpecialFlags((Object)input);
         }
-        
+
         protected Map<?, ?> transformSpecialFlags(Map<?, ?> flag) {
             return Maps.transformValues(flag, this);
         }
-        
+
         protected Iterable<?> transformSpecialFlags(Iterable<?> flag) {
             return Iterables.transform(flag, this);
         }
-        
+
         protected BrooklynClassLoadingContext getLoader() {
             if (loader!=null) return loader;
             // TODO currently loader will non-null unless someone has messed with the rebind files,
@@ -426,7 +395,7 @@ public class BrooklynComponentTemplateResolver {
             if (entity!=null) return CatalogUtils.getClassLoadingContext(entity);
             return JavaBrooklynClassLoadingContext.create(mgmt);
         }
-        
+
         /**
          * Makes additional transformations to the given flag with the extra knowledge of the flag's management context.
          * @return The modified flag, or the flag unchanged.
@@ -442,7 +411,7 @@ public class BrooklynComponentTemplateResolver {
                 return Factory.newInstance(getLoader(), specConfig.getSpecConfiguration()).resolveSpec();
             }
             if (flag instanceof ManagementContextInjectable) {
-                if (log.isDebugEnabled()) { log.debug("Injecting Brooklyn management context info object: {}", flag); }
+                log.debug("Injecting Brooklyn management context info object: {}", flag);
                 ((ManagementContextInjectable) flag).injectManagementContext(loader.getManagementContext());
             }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/303c3884/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
index 8fd080b..ce814b4 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityDecorationResolver.java
@@ -88,7 +88,7 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
 
     public static class PolicySpecResolver extends BrooklynEntityDecorationResolver<PolicySpec<?>> {
         
-        protected PolicySpecResolver(BrooklynYamlTypeInstantiator.Factory loader) { super(loader); }
+        public PolicySpecResolver(BrooklynYamlTypeInstantiator.Factory loader) { super(loader); }
         @Override protected String getDecorationKind() { return "Policy"; }
 
         @Override
@@ -134,7 +134,7 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
 
     public static class EnricherSpecResolver extends BrooklynEntityDecorationResolver<EnricherSpec<?>> {
         
-        protected EnricherSpecResolver(BrooklynYamlTypeInstantiator.Factory loader) { super(loader); }
+        public EnricherSpecResolver(BrooklynYamlTypeInstantiator.Factory loader) { super(loader); }
         @Override protected String getDecorationKind() { return "Enricher"; }
 
         @Override
@@ -157,7 +157,7 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
     
     public static class InitializerResolver extends BrooklynEntityDecorationResolver<EntityInitializer> {
         
-        protected InitializerResolver(BrooklynYamlTypeInstantiator.Factory loader) { super(loader); }
+        public InitializerResolver(BrooklynYamlTypeInstantiator.Factory loader) { super(loader); }
         @Override protected String getDecorationKind() { return "Entity initializer"; }
 
         @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/303c3884/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/ChefComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/ChefComponentTemplateResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/ChefComponentTemplateResolver.java
deleted file mode 100644
index 83bb7cb..0000000
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/ChefComponentTemplateResolver.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package io.brooklyn.camp.brooklyn.spi.creation;
-
-import io.brooklyn.camp.spi.AbstractResource;
-import brooklyn.catalog.CatalogItem;
-import brooklyn.entity.Entity;
-import brooklyn.entity.chef.ChefConfig;
-import brooklyn.entity.chef.ChefEntity;
-import brooklyn.entity.proxying.EntitySpec;
-import brooklyn.management.classloading.BrooklynClassLoadingContext;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.text.Strings;
-
-public class ChefComponentTemplateResolver extends BrooklynComponentTemplateResolver {
-
-    public ChefComponentTemplateResolver(BrooklynClassLoadingContext loader, ConfigBag attrs, AbstractResource optionalTemplate) {
-        super(loader, attrs, optionalTemplate);
-    }
-
-    @Override
-    protected String getBrooklynType() {
-        return ChefEntity.class.getName();
-    }
-
-    // chef: items are not in catalog
-    @Override
-    public CatalogItem<Entity, EntitySpec<?>> getCatalogItem() {
-        return null;
-    }
-    
-    @Override
-    protected <T extends Entity> void decorateSpec(EntitySpec<T> spec) {
-        if (getDeclaredType().startsWith("chef:")) {
-            spec.configure(ChefConfig.CHEF_COOKBOOK_PRIMARY_NAME, Strings.removeFromStart(getDeclaredType(), "chef:"));
-        }
-        
-        super.decorateSpec(spec);
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/303c3884/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
new file mode 100644
index 0000000..3528cee
--- /dev/null
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package io.brooklyn.camp.brooklyn.spi.creation.service;
+
+import io.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver;
+import io.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityDecorationResolver;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.catalog.CatalogItem;
+import brooklyn.catalog.internal.CatalogUtils;
+import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
+import brooklyn.util.text.Strings;
+
+/**
+ * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code brooklyn:}
+ * to Brooklyn {@link EntitySpec} instances.
+ */
+public class BrooklynServiceTypeResolver implements ServiceTypeResolver {
+
+    private static final Logger log = LoggerFactory.getLogger(ServiceTypeResolver.class);
+
+    @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 CatalogUtils.getCatalogItemOptionalVersion(resolver.getManagementContext(), Entity.class,  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());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/303c3884/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceTypeResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceTypeResolver.java
new file mode 100644
index 0000000..4b33649
--- /dev/null
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceTypeResolver.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package io.brooklyn.camp.brooklyn.spi.creation.service;
+
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.basic.VanillaSoftwareProcess;
+import brooklyn.entity.group.DynamicCluster;
+import brooklyn.entity.group.DynamicRegionsFabric;
+import brooklyn.entity.proxying.EntitySpec;
+
+/**
+ * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code catalog:}
+ * to Brooklyn {@link EntitySpec} instances.
+ */
+public class CatalogServiceTypeResolver extends BrooklynServiceTypeResolver {
+
+    private static final Logger log = LoggerFactory.getLogger(ServiceTypeResolver.class);
+
+    @Override
+    public String getTypePrefix() { return "catalog"; }
+
+    @Override
+    public String getBrooklynType(String serviceType) {
+        String type = super.getBrooklynType(serviceType);
+        if (type == null) return null;
+
+        // TODO currently a hardcoded list of aliases; would like that to come from mgmt somehow
+        if (type.equals("cluster") || type.equals("Cluster")) return DynamicCluster.class.getName();
+        if (type.equals("fabric") || type.equals("Fabric")) return DynamicRegionsFabric.class.getName();
+        if (type.equals("vanilla") || type.equals("Vanilla")) return VanillaSoftwareProcess.class.getName();
+        if (type.equals("web-app-cluster") || type.equals("WebAppCluster"))
+            // TODO use service discovery; currently included as string to avoid needing a reference to it
+            return "brooklyn.entity.webapp.ControlledDynamicWebAppCluster";
+
+        return type;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/303c3884/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceTypeResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceTypeResolver.java
new file mode 100644
index 0000000..9f266e5
--- /dev/null
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceTypeResolver.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 io.brooklyn.camp.brooklyn.spi.creation.service;
+
+import io.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver;
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.catalog.CatalogItem;
+import brooklyn.entity.Entity;
+import brooklyn.entity.chef.ChefConfig;
+import brooklyn.entity.chef.ChefEntity;
+import brooklyn.entity.proxying.EntitySpec;
+import 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 {
+
+    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 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/303c3884/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceTypeResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceTypeResolver.java
new file mode 100644
index 0000000..7c30c6a
--- /dev/null
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceTypeResolver.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package io.brooklyn.camp.brooklyn.spi.creation.service;
+
+/**
+ * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code java:}
+ * to Brooklyn {@link EntitySpec} instances.
+ */
+public class JavaServiceTypeResolver extends BrooklynServiceTypeResolver {
+
+    @Override
+    public String getTypePrefix() { return "java"; }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/303c3884/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java
new file mode 100644
index 0000000..74c7990
--- /dev/null
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package io.brooklyn.camp.brooklyn.spi.creation.service;
+
+import io.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver;
+import brooklyn.catalog.CatalogItem;
+import brooklyn.entity.Entity;
+import brooklyn.entity.proxying.EntitySpec;
+
+public interface ServiceTypeResolver {
+
+    String DEFAULT_TYPE_PREFIX = "brooklyn";
+
+    String getTypePrefix();
+
+    String getBrooklynType(String serviceType);
+
+    /**
+     * Returns the {@link CatalogItem} if there is one for the given type.
+     * <p>
+     * If no type, callers should fall back to default classloading.
+     */
+    CatalogItem<Entity, EntitySpec<?>> getCatalogItem(BrooklynComponentTemplateResolver resolver, String serviceType);
+
+    <T extends Entity> void decorateSpec(BrooklynComponentTemplateResolver resolver, EntitySpec<T> spec);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/303c3884/usage/camp/src/main/resources/META-INF/services/io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/resources/META-INF/services/io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver b/usage/camp/src/main/resources/META-INF/services/io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver
new file mode 100644
index 0000000..1a48ccb
--- /dev/null
+++ b/usage/camp/src/main/resources/META-INF/services/io.brooklyn.camp.brooklyn.spi.creation.service.ServiceTypeResolver
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+io.brooklyn.camp.brooklyn.spi.creation.service.BrooklynServiceTypeResolver
+io.brooklyn.camp.brooklyn.spi.creation.service.CatalogServiceTypeResolver
+io.brooklyn.camp.brooklyn.spi.creation.service.ChefServiceTypeResolver
+io.brooklyn.camp.brooklyn.spi.creation.service.JavaServiceTypeResolver


[3/3] incubator-brooklyn git commit: This closes #587

Posted by al...@apache.org.
This closes #587


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/cecaaf02
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/cecaaf02
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/cecaaf02

Branch: refs/heads/master
Commit: cecaaf02bfef1a2dba428be37a2a66eeab57b23d
Parents: 4f1eb45 1f6731e
Author: Aled Sage <al...@gmail.com>
Authored: Sun Apr 12 16:40:15 2015 -0500
Committer: Aled Sage <al...@gmail.com>
Committed: Sun Apr 12 16:40:15 2015 -0500

----------------------------------------------------------------------
 .../BrooklynAssemblyTemplateInstantiator.java   |  52 ++--
 .../BrooklynComponentTemplateResolver.java      | 238 ++++++++-----------
 .../BrooklynEntityDecorationResolver.java       |   6 +-
 .../creation/ChefComponentTemplateResolver.java |  57 -----
 .../service/BrooklynServiceTypeResolver.java    |  72 ++++++
 .../service/CatalogServiceTypeResolver.java     |  78 ++++++
 .../service/ChefServiceTypeResolver.java        |  62 +++++
 .../service/JavaServiceTypeResolver.java        |  39 +++
 .../creation/service/ServiceTypeResolver.java   |  73 ++++++
 ...lyn.spi.creation.service.ServiceTypeResolver |  22 ++
 10 files changed, 480 insertions(+), 219 deletions(-)
----------------------------------------------------------------------



[2/3] incubator-brooklyn git commit: Better documentation and added check suggested in review

Posted by al...@apache.org.
Better documentation and added check suggested in review


Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/1f6731ef
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/1f6731ef
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/1f6731ef

Branch: refs/heads/master
Commit: 1f6731ef0ebbb5ddc27859cba0295e5a1685c063
Parents: 303c388
Author: Andrew Kennedy <gr...@apache.org>
Authored: Thu Apr 9 14:09:36 2015 +0100
Committer: Andrew Kennedy <gr...@apache.org>
Committed: Thu Apr 9 14:13:52 2015 +0100

----------------------------------------------------------------------
 .../BrooklynComponentTemplateResolver.java      | 23 +++++++------
 .../service/BrooklynServiceTypeResolver.java    |  2 +-
 .../service/CatalogServiceTypeResolver.java     | 36 +++++++++++++++-----
 .../service/ChefServiceTypeResolver.java        |  4 +--
 .../service/JavaServiceTypeResolver.java        |  9 +++++
 .../creation/service/ServiceTypeResolver.java   | 30 ++++++++++++++++
 6 files changed, 83 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1f6731ef/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index 37fccf8..67e5af1 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -28,6 +28,7 @@ import io.brooklyn.camp.spi.PlatformComponentTemplate;
 
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.ServiceLoader;
 import java.util.Set;
@@ -71,12 +72,8 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
 
 /**
- * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code brooklyn:}
- * to Brooklyn {@link EntitySpec} instances.
- * <p>
- * but TODO this should probably be done by {@link BrooklynEntityMatcher}
- * so we have a spec by the time we come to instantiate.
- * (currently privileges "brooklyn.*" key names are checked in both places!)
+ * This generates instances of a template resolver that use a {@link ServiceTypeResolver}
+ * to parse the {@code serviceType} line in the template.
  */
 public class BrooklynComponentTemplateResolver {
 
@@ -118,11 +115,17 @@ public class BrooklynComponentTemplateResolver {
             return findService(context, type);
         }
 
+        // TODO This could be extended to support multiple prefixes per resolver and a 'best-match' algorithm
         protected static ServiceTypeResolver findService(BrooklynClassLoadingContext context, String type) {
-            String prefix = Splitter.on(":").splitToList(type).get(0);
-            ServiceLoader<ServiceTypeResolver> loader = ServiceLoader.load(ServiceTypeResolver.class, context.getManagementContext().getCatalog().getRootClassLoader());
-            for (ServiceTypeResolver resolver : loader) {
-               if (prefix.equalsIgnoreCase(resolver.getTypePrefix())) return resolver;
+            if (type.indexOf(':') != -1) {
+                String prefix = Splitter.on(":").splitToList(type).get(0);
+                ServiceLoader<ServiceTypeResolver> loader = ServiceLoader.load(ServiceTypeResolver.class,
+                        context.getManagementContext().getCatalog().getRootClassLoader());
+                for (ServiceTypeResolver resolver : loader) {
+                   if (prefix.equals(resolver.getTypePrefix())) {
+                       return resolver;
+                   }
+                }
             }
             return null;
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1f6731ef/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
index 3528cee..2fd134a 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/BrooklynServiceTypeResolver.java
@@ -39,7 +39,7 @@ import brooklyn.util.text.Strings;
  */
 public class BrooklynServiceTypeResolver implements ServiceTypeResolver {
 
-    private static final Logger log = LoggerFactory.getLogger(ServiceTypeResolver.class);
+    private static final Logger LOG = LoggerFactory.getLogger(ServiceTypeResolver.class);
 
     @Override
     public String getTypePrefix() { return DEFAULT_TYPE_PREFIX; }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1f6731ef/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceTypeResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceTypeResolver.java
index 4b33649..d082b13 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceTypeResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/CatalogServiceTypeResolver.java
@@ -20,21 +20,43 @@ package io.brooklyn.camp.brooklyn.spi.creation.service;
 
 import io.brooklyn.camp.spi.PlatformComponentTemplate;
 
+import java.util.Map;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import brooklyn.entity.basic.VanillaSoftwareProcess;
+import brooklyn.entity.brooklynnode.BrooklynNode;
 import brooklyn.entity.group.DynamicCluster;
 import brooklyn.entity.group.DynamicRegionsFabric;
+import brooklyn.entity.java.VanillaJavaApp;
 import brooklyn.entity.proxying.EntitySpec;
 
+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 {
 
-    private static final Logger log = LoggerFactory.getLogger(ServiceTypeResolver.class);
+    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","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"; }
@@ -44,13 +66,11 @@ public class CatalogServiceTypeResolver extends BrooklynServiceTypeResolver {
         String type = super.getBrooklynType(serviceType);
         if (type == null) return null;
 
-        // TODO currently a hardcoded list of aliases; would like that to come from mgmt somehow
-        if (type.equals("cluster") || type.equals("Cluster")) return DynamicCluster.class.getName();
-        if (type.equals("fabric") || type.equals("Fabric")) return DynamicRegionsFabric.class.getName();
-        if (type.equals("vanilla") || type.equals("Vanilla")) return VanillaSoftwareProcess.class.getName();
-        if (type.equals("web-app-cluster") || type.equals("WebAppCluster"))
-            // TODO use service discovery; currently included as string to avoid needing a reference to it
-            return "brooklyn.entity.webapp.ControlledDynamicWebAppCluster";
+        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/1f6731ef/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceTypeResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceTypeResolver.java
index 9f266e5..da7be21 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceTypeResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ChefServiceTypeResolver.java
@@ -37,7 +37,7 @@ import brooklyn.util.text.Strings;
  */
 public class ChefServiceTypeResolver extends BrooklynServiceTypeResolver {
 
-    private static final Logger log = LoggerFactory.getLogger(ServiceTypeResolver.class);
+    private static final Logger LOG = LoggerFactory.getLogger(ServiceTypeResolver.class);
 
     @Override
     public String getTypePrefix() { return "chef"; }
@@ -47,7 +47,7 @@ public class ChefServiceTypeResolver extends BrooklynServiceTypeResolver {
         return ChefEntity.class.getName();
     }
 
-    // chef: items are not in catalog
+    /** Chef items are not in the catalog. */
     @Override
     public CatalogItem<Entity, EntitySpec<?>> getCatalogItem(BrooklynComponentTemplateResolver resolver, String serviceType) {
         return null;

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/1f6731ef/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceTypeResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceTypeResolver.java
index 7c30c6a..f348ea8 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceTypeResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/JavaServiceTypeResolver.java
@@ -18,12 +18,21 @@
  */
 package io.brooklyn.camp.brooklyn.spi.creation.service;
 
+import io.brooklyn.camp.spi.PlatformComponentTemplate;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.entity.proxying.EntitySpec;
+
 /**
  * This converts {@link PlatformComponentTemplate} instances whose type is prefixed {@code java:}
  * to Brooklyn {@link EntitySpec} instances.
  */
 public class JavaServiceTypeResolver extends BrooklynServiceTypeResolver {
 
+    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/1f6731ef/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java
index 74c7990..3a96a89 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/service/ServiceTypeResolver.java
@@ -18,17 +18,40 @@
  */
 package io.brooklyn.camp.brooklyn.spi.creation.service;
 
+import java.util.ServiceLoader;
+
 import io.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.entity.Entity;
 import brooklyn.entity.proxying.EntitySpec;
 
+/**
+ * Resolves and decorates {@link EntitySpec entity specifications} based on the {@code serviceType} in a template.
+ * <p>
+ * The {@link #getTypePrefix()} method returns a string that should match the beginning of the
+ * service type. The resolver implementation will use the rest of the service type information
+ * to create and decorate an approprate {@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.
+ *
+ * @see BrooklynServiceTypeResolver
+ * @see ChefServiceTypeResolver
+ */
 public interface ServiceTypeResolver {
 
     String DEFAULT_TYPE_PREFIX = "brooklyn";
 
+    /**
+     * The service type prefix the resolver is responsible for.
+     */
     String getTypePrefix();
 
+    /**
+     * The name of the Java type that Brooklyn will instantiate to create the
+     * service. This can be generated from parts of the service type information
+     * or may be a fixed value.
+     */
     String getBrooklynType(String serviceType);
 
     /**
@@ -38,6 +61,13 @@ public interface ServiceTypeResolver {
      */
     CatalogItem<Entity, EntitySpec<?>> getCatalogItem(BrooklynComponentTemplateResolver resolver, String serviceType);
 
+    /**
+     * Takes the provided {@link EntitySpec} and decorates it appropriately for the service type.
+     * <p>
+     * This includes setting configuration and adding policies, enrichers and initializers.
+     *
+     * @see BrooklynServiceTypeResolver#decorateSpec(BrooklynComponentTemplateResolver, EntitySpec)
+     */
     <T extends Entity> void decorateSpec(BrooklynComponentTemplateResolver resolver, EntitySpec<T> spec);
 
 }