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 2014/07/09 23:46:29 UTC

[16/50] git commit: add BrooklynClassLoadingContext and pass it around when we are instantiating, fixing BrooklynComponentTemplateResolver.loadEntitySpec to use new loaders from CatalogItem.

add BrooklynClassLoadingContext and pass it around when we are instantiating,
fixing BrooklynComponentTemplateResolver.loadEntitySpec to use new loaders from CatalogItem.

currently BCLC does not really pull his weight, as he is just used for instantiation and is never combined or kept;
but as we fix deeper bugs in trying to resolve classes from the purview of another,
i think it will become very useful.

(already it should be the case -- but needs testing -- that BCLC allows children to be resolved WRT
the parent's bundle if they are not declared as catalog items)


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

Branch: refs/heads/master
Commit: 37d2004fae1ee22cf207f2ff97e1986c36f66d31
Parents: 5c9b29f
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Sat Jul 5 04:46:26 2014 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Jul 9 22:34:43 2014 +0100

----------------------------------------------------------------------
 .../main/java/brooklyn/catalog/CatalogItem.java |   4 +
 .../BrooklynClassLoadingContext.java            |  19 ++
 .../brooklyn/catalog/internal/CatalogDo.java    |   6 +
 .../catalog/internal/CatalogItemDo.java         |  53 ++---
 .../internal/CatalogItemDtoAbstract.java        |  15 ++
 .../AbstractBrooklynClassLoadingContext.java    |  60 ++++++
 .../BrooklynClassLoadingContextSequential.java  |  85 ++++++++
 .../JavaBrooklynClassLoadingContext.java        |  50 +++++
 .../OsgiBrooklynClassLoadingContext.java        |  64 ++++++
 .../BrooklynAssemblyTemplateInstantiator.java   |  27 ++-
 .../BrooklynComponentTemplateResolver.java      | 117 ++++++-----
 .../creation/BrooklynEntityClassResolver.java   | 141 -------------
 .../BrooklynEntityDecorationResolver.java       |  20 +-
 .../spi/creation/BrooklynEntityMatcher.java     |  12 +-
 .../creation/BrooklynYamlTypeInstantiator.java  | 200 ++++++++++++++++++
 .../spi/creation/BrooklynYamlTypeLoader.java    | 210 -------------------
 .../creation/ChefComponentTemplateResolver.java |  15 +-
 .../BrooklynYamlTypeInstantiatorTest.java       |  76 +++++++
 .../brooklyn/BrooklynYamlTypeLoaderTest.java    |  70 -------
 19 files changed, 709 insertions(+), 535 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/api/src/main/java/brooklyn/catalog/CatalogItem.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/CatalogItem.java b/api/src/main/java/brooklyn/catalog/CatalogItem.java
index c40757c..a110d67 100644
--- a/api/src/main/java/brooklyn/catalog/CatalogItem.java
+++ b/api/src/main/java/brooklyn/catalog/CatalogItem.java
@@ -23,6 +23,9 @@ import java.util.List;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import brooklyn.management.ManagementContext;
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
+
 import com.google.common.annotations.Beta;
 
 @Beta
@@ -66,5 +69,6 @@ public interface CatalogItem<T,SpecT> {
     /** return underlying YAML for this item, if known */ 
     @Nullable public String getPlanYaml();
 
+    BrooklynClassLoadingContext newClassLoadingContext(final ManagementContext mgmt);
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/api/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContext.java b/api/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContext.java
new file mode 100644
index 0000000..e1ba3b5
--- /dev/null
+++ b/api/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContext.java
@@ -0,0 +1,19 @@
+package brooklyn.management.classloading;
+
+import brooklyn.management.ManagementContext;
+import brooklyn.util.guava.Maybe;
+
+/** 
+ * Provides functionality for loading classes based on the current context
+ * (e.g. catalog item, entity, etc). 
+ */
+public interface BrooklynClassLoadingContext {
+
+    public ManagementContext getManagementContext();
+    public Class<?> loadClass(String className);
+    public <T> Class<? extends T> loadClass(String className, Class<T> type);
+    
+    public Maybe<Class<?>> tryLoadClass(String className);
+    public <T> Maybe<Class<? extends T>> tryLoadClass(String className, Class<T> type);
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
index 072a50d..f7dccfa 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogDo.java
@@ -29,6 +29,8 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
 import brooklyn.management.ManagementContext;
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
+import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
 import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.util.exceptions.Exceptions;
 import brooklyn.util.javalang.AggregateClassLoader;
@@ -295,5 +297,9 @@ public class CatalogDo {
         if (parent!=null) return parent.getRootClassLoader();
         return getRecursiveClassLoader();
     }
+    
+    public BrooklynClassLoadingContext newClassLoadingContext() {
+        return new JavaBrooklynClassLoadingContext(mgmt, getRootClassLoader());
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
index 717da09..a9fddc7 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDo.java
@@ -18,17 +18,13 @@
  */
 package brooklyn.catalog.internal;
 
-import java.util.List;
-
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import brooklyn.catalog.CatalogItem;
 import brooklyn.management.ManagementContext;
-import brooklyn.management.ha.OsgiManager;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
+import brooklyn.management.classloading.BrooklynClassLoadingContextSequential;
 
 import com.google.common.base.Preconditions;
 
@@ -100,45 +96,26 @@ public class CatalogItemDo<T,SpecT> implements CatalogItem<T,SpecT> {
     }
 
     /** @deprecated since 0.7.0 this is the legacy mechanism; still needed for policies and apps, but being phased out.
-     * new items should use {@link #getYaml()} */
+     * new items should use {@link #getYaml()} and {@link #newClassLoadingContext(ManagementContext, BrooklynClassLoadingContext)} */
     @Deprecated
     public Class<T> getJavaClass() {
         if (javaClass==null) loadJavaClass(null);
         return javaClass;
     }
     
+    @SuppressWarnings("deprecation")
+    public BrooklynClassLoadingContext newClassLoadingContext(final ManagementContext mgmt) {
+        BrooklynClassLoadingContextSequential result = new BrooklynClassLoadingContextSequential(mgmt);
+        result.add(itemDto.newClassLoadingContext(mgmt));
+        result.addSecondary(catalog.newClassLoadingContext());
+        return result;
+    }
+    
     @SuppressWarnings("unchecked")
-    protected Class<? extends T> loadJavaClass(ManagementContext mgmt) {
-        Maybe<Class<Object>> clazz = null;
-        try {
-            if (javaClass!=null) return javaClass;
-
-            if (mgmt!=null) {
-                Maybe<OsgiManager> osgi = ((ManagementContextInternal)mgmt).getOsgiManager();
-                if (osgi.isPresent() && getLibraries()!=null) {
-                    // TODO getLibraries() should never be null but sometimes it is still
-                    // e.g. run CatalogResourceTest without the above check
-                    List<String> bundles = getLibraries().getBundles();
-                    if (bundles!=null && !bundles.isEmpty()) {
-                        clazz = osgi.get().tryResolveClass(getJavaType(), bundles);
-                        if (clazz.isPresent()) {
-                            return (Class<? extends T>) clazz.get();
-                        }
-                    }
-                }
-            }
-            
-            javaClass = (Class<T>) catalog.getRootClassLoader().loadClass(getJavaType());
-            return javaClass;
-        } catch (Throwable e) {
-            Exceptions.propagateIfFatal(e);
-            if (clazz!=null) {
-                // if OSGi bundles were defined and failed, then prefer to throw its error message
-                clazz.get();
-            }
-            // else throw the java error
-            throw Exceptions.propagate(e);
-        }
+    Class<? extends T> loadJavaClass(final ManagementContext mgmt) {
+        if (javaClass!=null) return javaClass;
+        javaClass = (Class<T>)newClassLoadingContext(mgmt).loadClass(getJavaType());
+        return javaClass;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
index 2a74062..f4fab70 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogItemDtoAbstract.java
@@ -22,6 +22,10 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import brooklyn.catalog.CatalogItem;
+import brooklyn.management.ManagementContext;
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
+import brooklyn.management.classloading.BrooklynClassLoadingContextSequential;
+import brooklyn.management.classloading.OsgiBrooklynClassLoadingContext;
 
 public abstract class CatalogItemDtoAbstract<T,SpecT> implements CatalogItem<T,SpecT> {
 
@@ -109,6 +113,17 @@ public abstract class CatalogItemDtoAbstract<T,SpecT> implements CatalogItem<T,S
             serializer = new CatalogXmlSerializer();
     }
 
+    public BrooklynClassLoadingContext newClassLoadingContext(final ManagementContext mgmt) {
+        BrooklynClassLoadingContextSequential result = new BrooklynClassLoadingContextSequential(mgmt);
+        
+        if (getLibraries()!=null && getLibraries().getBundles()!=null && !getLibraries().getBundles().isEmpty())
+            // TODO getLibraries() should never be null but sometimes it is still
+            // e.g. run CatalogResourceTest without the above check
+            result.add(new OsgiBrooklynClassLoadingContext(mgmt, getLibraries().getBundles()));
+
+        return result;
+    }
+
     public abstract Class<SpecT> getSpecType();
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/core/src/main/java/brooklyn/management/classloading/AbstractBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/AbstractBrooklynClassLoadingContext.java b/core/src/main/java/brooklyn/management/classloading/AbstractBrooklynClassLoadingContext.java
new file mode 100644
index 0000000..dcf4437
--- /dev/null
+++ b/core/src/main/java/brooklyn/management/classloading/AbstractBrooklynClassLoadingContext.java
@@ -0,0 +1,60 @@
+package brooklyn.management.classloading;
+
+import brooklyn.management.ManagementContext;
+import brooklyn.util.guava.Maybe;
+
+import com.google.common.base.Objects;
+
+public abstract class AbstractBrooklynClassLoadingContext implements BrooklynClassLoadingContext {
+
+    protected final ManagementContext mgmt;
+
+    public AbstractBrooklynClassLoadingContext(ManagementContext mgmt) {
+        this.mgmt = mgmt;
+    }
+
+    @Override
+    public ManagementContext getManagementContext() {
+        return mgmt;
+    }
+    
+    @Override
+    public Class<?> loadClass(String className) {
+        return tryLoadClass(className).get();
+    }
+
+    @Override
+    // this is the only one left for subclasses
+    public abstract Maybe<Class<?>> tryLoadClass(String className);
+
+    @Override
+    public <T> Class<? extends T> loadClass(String className, Class<T> type) {
+        return tryLoadClass(className, type).get();
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Override
+    public <T> Maybe<Class<? extends T>> tryLoadClass(String className, Class<T> type) {
+        Maybe<Class<?>> result = tryLoadClass(className);
+        if (result.isAbsent()) return (Maybe)result;
+        Class<?> clazz = result.get();
+        if (type.isAssignableFrom(clazz)) return (Maybe)result;
+        throw new ClassCastException(className+" is not an instance of "+type);
+    }
+
+    @Override
+    public abstract String toString();
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(mgmt);
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof BrooklynClassLoadingContext)) return false;
+        if (!Objects.equal(mgmt, ((BrooklynClassLoadingContext)obj).getManagementContext())) return false;
+        return true;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/core/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContextSequential.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContextSequential.java b/core/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContextSequential.java
new file mode 100644
index 0000000..4b714eb
--- /dev/null
+++ b/core/src/main/java/brooklyn/management/classloading/BrooklynClassLoadingContextSequential.java
@@ -0,0 +1,85 @@
+package brooklyn.management.classloading;
+
+import java.util.List;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Objects;
+
+import brooklyn.management.ManagementContext;
+import brooklyn.util.collections.MutableList;
+import brooklyn.util.collections.MutableSet;
+import brooklyn.util.guava.Maybe;
+
+public final class BrooklynClassLoadingContextSequential extends AbstractBrooklynClassLoadingContext {
+
+    private static final Logger log = LoggerFactory.getLogger(BrooklynClassLoadingContextSequential.class);
+    
+    private final List<BrooklynClassLoadingContext> primaries = MutableList.<BrooklynClassLoadingContext>of();
+    // secondaries used to put java classloader last
+    private final Set<BrooklynClassLoadingContext> secondaries = MutableSet.<BrooklynClassLoadingContext>of();
+
+    public BrooklynClassLoadingContextSequential(ManagementContext mgmt, BrooklynClassLoadingContext ...targets) {
+        super(mgmt);
+        for (BrooklynClassLoadingContext target: targets)
+            add(target);
+    }
+    
+    public void add(BrooklynClassLoadingContext target) {
+        if (target instanceof BrooklynClassLoadingContextSequential) {
+            for (BrooklynClassLoadingContext targetN: ((BrooklynClassLoadingContextSequential)target).primaries )
+                add(targetN);
+            for (BrooklynClassLoadingContext targetN: ((BrooklynClassLoadingContextSequential)target).secondaries )
+                addSecondary(targetN);
+        } else {
+            this.primaries.add( target );
+        }
+    }
+
+    /** @since 0.7.0 only for supporting legacy java-classloading based catalog */
+    @Deprecated
+    public void addSecondary(BrooklynClassLoadingContext target) {
+        if (!(target instanceof JavaBrooklynClassLoadingContext)) {
+            // support for legacy catalog classloader only
+            log.warn("Only Java classloaders should be secondary");
+        }
+        this.secondaries.add( target );
+    }
+    
+    public Maybe<Class<?>> tryLoadClass(String className) {
+        for (BrooklynClassLoadingContext target: primaries) {
+            Maybe<Class<?>> clazz = target.tryLoadClass(className);
+            if (clazz.isPresent())
+                return clazz;
+        }
+        for (BrooklynClassLoadingContext target: secondaries) {
+            Maybe<Class<?>> clazz = target.tryLoadClass(className);
+            if (clazz.isPresent())
+                return clazz;
+        }
+
+        return Maybe.absent("Unable to load "+className+" from "+primaries);
+    }
+
+    @Override
+    public String toString() {
+        return "classload:"+primaries+";"+secondaries;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(super.hashCode(), primaries, secondaries);
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!super.equals(obj)) return false;
+        if (!(obj instanceof BrooklynClassLoadingContextSequential)) return false;
+        if (!Objects.equal(primaries, ((BrooklynClassLoadingContextSequential)obj).primaries)) return false;
+        if (!Objects.equal(secondaries, ((BrooklynClassLoadingContextSequential)obj).secondaries)) return false;
+        return true;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java b/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java
new file mode 100644
index 0000000..8cae3be
--- /dev/null
+++ b/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java
@@ -0,0 +1,50 @@
+package brooklyn.management.classloading;
+
+import com.google.common.base.Objects;
+
+import brooklyn.management.ManagementContext;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+
+public class JavaBrooklynClassLoadingContext extends AbstractBrooklynClassLoadingContext {
+
+    private final ClassLoader loader;
+
+    public JavaBrooklynClassLoadingContext(ManagementContext mgmt, ClassLoader loader) {
+        super(mgmt);
+        this.loader = loader;
+    }
+    
+    public static JavaBrooklynClassLoadingContext newDefault(ManagementContext mgmt) {
+        return new JavaBrooklynClassLoadingContext(mgmt, JavaBrooklynClassLoadingContext.class.getClassLoader());
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public Maybe<Class<?>> tryLoadClass(String className) {
+        try {
+            return (Maybe) Maybe.of(loader.loadClass(className));
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            return Maybe.absent(e);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "java:"+loader;
+    }
+    
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(super.hashCode(), loader);
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!super.equals(obj)) return false;
+        if (!(obj instanceof JavaBrooklynClassLoadingContext)) return false;
+        if (!Objects.equal(loader, ((JavaBrooklynClassLoadingContext)obj).loader)) return false;
+        return true;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java b/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
new file mode 100644
index 0000000..5065078
--- /dev/null
+++ b/core/src/main/java/brooklyn/management/classloading/OsgiBrooklynClassLoadingContext.java
@@ -0,0 +1,64 @@
+package brooklyn.management.classloading;
+
+import java.util.List;
+
+import brooklyn.management.ManagementContext;
+import brooklyn.management.ha.OsgiManager;
+import brooklyn.management.internal.ManagementContextInternal;
+import brooklyn.util.guava.Maybe;
+
+import com.google.common.base.Objects;
+
+public class OsgiBrooklynClassLoadingContext extends AbstractBrooklynClassLoadingContext {
+
+    private final List<String> bundles;
+
+    public OsgiBrooklynClassLoadingContext(ManagementContext mgmt, List<String> bundles) {
+        super(mgmt);
+        this.bundles = bundles;
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public Maybe<Class<?>> tryLoadClass(String className) {
+        Maybe<Class<Object>> clazz = null;
+        Maybe<OsgiManager> osgi = null;
+        if (mgmt!=null) {
+            osgi = ((ManagementContextInternal)mgmt).getOsgiManager();
+            if (osgi.isPresent() && bundles!=null && !bundles.isEmpty()) {
+                clazz = osgi.get().tryResolveClass(className, bundles);
+                if (clazz.isPresent())
+                    return (Maybe)clazz;
+            }
+        }
+        
+        if (clazz!=null) { 
+            // if OSGi bundles were defined and failed, then use its error message
+            return (Maybe)clazz;
+        }
+        // else determine best message
+        if (mgmt==null) return Maybe.absent("No mgmt context available for loading "+className);
+        if (osgi!=null && osgi.isAbsent()) return Maybe.absent("OSGi not available on mgmt for loading "+className);
+        if (bundles==null || bundles.isEmpty())
+            return Maybe.absent("No bundles available for loading "+className);
+        return Maybe.absent("Inconsistent state ("+mgmt+"/"+osgi+"/"+bundles+" loading "+className);
+    }
+
+    @Override
+    public String toString() {
+        return "OSGi:"+bundles;
+    }
+    
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(super.hashCode(), bundles);
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!super.equals(obj)) return false;
+        if (!(obj instanceof OsgiBrooklynClassLoadingContext)) return false;
+        if (!Objects.equal(bundles, ((OsgiBrooklynClassLoadingContext)obj).bundles)) return false;
+        return true;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/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 e1c82bf..13f2180 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
@@ -53,6 +53,8 @@ import brooklyn.entity.trait.Startable;
 import brooklyn.location.Location;
 import brooklyn.management.ManagementContext;
 import brooklyn.management.Task;
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
+import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
 import brooklyn.util.collections.MutableList;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.exceptions.Exceptions;
@@ -167,7 +169,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
         if (Strings.isEmpty(type)) {
             clazz = BasicApplication.class;
         } else {
-            clazz = BrooklynEntityClassResolver.resolveEntity(type, mgmt);
+            clazz = item.newClassLoadingContext(mgmt).loadClass(type, Entity.class);
         }
         
         try {
@@ -284,11 +286,12 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
         // AssemblyTemplates created via PDP, _specifying_ then entities to put in
         final ManagementContext mgmt = getBrooklynManagementContext(platform);
 
-        BrooklynComponentTemplateResolver resolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, template);
+        BrooklynComponentTemplateResolver resolver = BrooklynComponentTemplateResolver.Factory.newInstance(
+            JavaBrooklynClassLoadingContext.newDefault(mgmt), template);
         EntitySpec<? extends Application> app = resolver.resolveSpec(StartableApplication.class, BasicApplicationImpl.class);
         
         // first build the children into an empty shell app
-        buildTemplateServicesAsSpecs(template, app, mgmt);
+        buildTemplateServicesAsSpecs(JavaBrooklynClassLoadingContext.newDefault(mgmt), template, app);
         
         if (shouldUnwrap(template, app)) {
             EntitySpec<? extends Application> oldApp = app;
@@ -335,26 +338,30 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe
         return true;
     }
 
-    private void buildTemplateServicesAsSpecs(AssemblyTemplate template, EntitySpec<? extends Application> root, ManagementContext mgmt) {
+    private void buildTemplateServicesAsSpecs(BrooklynClassLoadingContext loader, AssemblyTemplate template, EntitySpec<? extends Application> root) {
         for (ResolvableLink<PlatformComponentTemplate> ctl: template.getPlatformComponentTemplates().links()) {
             PlatformComponentTemplate appChildComponentTemplate = ctl.resolve();
-            BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, appChildComponentTemplate);
+            BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(loader, appChildComponentTemplate);
             
             EntitySpec<? extends Entity> spec = entityResolver.resolveSpec();
             root.child(spec);
             
-            buildChildrenEntitySpecs(mgmt, spec, entityResolver.getChildren(appChildComponentTemplate.getCustomAttributes()));
+            BrooklynClassLoadingContext newLoader = entityResolver.loader;
+            buildChildrenEntitySpecs(newLoader, spec, entityResolver.getChildren(appChildComponentTemplate.getCustomAttributes()));
         }
     }
 
-    protected void buildChildrenEntitySpecs(ManagementContext mgmt, EntitySpec<?> parent, List<Map<String, Object>> childConfig) {
+    protected void buildChildrenEntitySpecs(BrooklynClassLoadingContext loader, EntitySpec<?> parent, List<Map<String, Object>> childConfig) {
         if (childConfig != null) {
             for (Map<String, Object> childAttrs : childConfig) {
-                BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, childAttrs);
+                BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(loader, childAttrs);
                 EntitySpec<? extends Entity> spec = entityResolver.resolveSpec();
                 parent.child(spec);
-                
-                buildChildrenEntitySpecs(mgmt, spec, entityResolver.getChildren(childAttrs));
+
+                // get the new loader in case the OSGi bundles from parent were added;
+                // not so important now but if we start working with versions this may be important
+                BrooklynClassLoadingContext newLoader = entityResolver.loader;
+                buildChildrenEntitySpecs(newLoader, spec, entityResolver.getChildren(childAttrs));
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/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 f3ba7c9..026350e 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
@@ -32,6 +32,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.annotation.Nullable;
 
+import brooklyn.catalog.CatalogItem;
 import brooklyn.config.ConfigKey;
 import brooklyn.entity.Application;
 import brooklyn.entity.Entity;
@@ -46,6 +47,8 @@ import brooklyn.entity.proxying.EntitySpec;
 import brooklyn.entity.proxying.InternalEntityFactory;
 import brooklyn.location.Location;
 import brooklyn.management.ManagementContext;
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
+import brooklyn.management.classloading.BrooklynClassLoadingContextSequential;
 import brooklyn.management.internal.ManagementContextInternal;
 import brooklyn.util.collections.MutableList;
 import brooklyn.util.collections.MutableSet;
@@ -70,10 +73,11 @@ import com.google.common.collect.Maps;
  */
 public class BrooklynComponentTemplateResolver {
 
+    BrooklynClassLoadingContext loader;
     final ManagementContext mgmt;
     final ConfigBag attrs;
     final Maybe<AbstractResource> template;
-    final BrooklynYamlTypeLoader.Factory loader;
+    final BrooklynYamlTypeInstantiator.Factory yamlLoader;
     AtomicBoolean alreadyBuilt = new AtomicBoolean(false);
 
     public static class Factory {
@@ -91,25 +95,25 @@ public class BrooklynComponentTemplateResolver {
             return null;
         }
 
-        public static BrooklynComponentTemplateResolver newInstance(ManagementContext mgmt, Map<String, Object> childAttrs) {
-            return newInstance(mgmt, ConfigBag.newInstance(childAttrs), null);
+        public static BrooklynComponentTemplateResolver newInstance(BrooklynClassLoadingContext loader, Map<String, Object> childAttrs) {
+            return newInstance(loader, ConfigBag.newInstance(childAttrs), null);
         }
 
-        public static BrooklynComponentTemplateResolver newInstance(ManagementContext mgmt, AbstractResource template) {
-            return newInstance(mgmt, ConfigBag.newInstance(template.getCustomAttributes()), template);
+        public static BrooklynComponentTemplateResolver newInstance(BrooklynClassLoadingContext loader, AbstractResource template) {
+            return newInstance(loader, ConfigBag.newInstance(template.getCustomAttributes()), template);
         }
         
-        public static BrooklynComponentTemplateResolver newInstance(ManagementContext mgmt, String serviceType) {
-            return newInstance(mgmt, ConfigBag.newInstance().configureStringKey("serviceType", serviceType), null);
+        public static BrooklynComponentTemplateResolver newInstance(BrooklynClassLoadingContext loader, String serviceType) {
+            return newInstance(loader, ConfigBag.newInstance().configureStringKey("serviceType", serviceType), null);
         }
         
-        private static BrooklynComponentTemplateResolver newInstance(ManagementContext mgmt, ConfigBag attrs, AbstractResource optionalTemplate) {
+        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(mgmt, attrs, optionalTemplate);
+                return (BrooklynComponentTemplateResolver) rt.getConstructors()[0].newInstance(loader, attrs, optionalTemplate);
             } catch (Exception e) { throw Exceptions.propagate(e); }
         }
 
@@ -126,35 +130,29 @@ public class BrooklynComponentTemplateResolver {
         }
         
         private static String extractServiceTypeAttribute(@Nullable ConfigBag attrs) {
-            return BrooklynYamlTypeLoader.LoaderFromKey.extractTypeName("service", attrs).orNull();
+            return BrooklynYamlTypeInstantiator.InstantiatorFromKey.extractTypeName("service", attrs).orNull();
         }
 
-        public static boolean supportsType(ManagementContext mgmt, String serviceType) {
+        public static boolean supportsType(BrooklynClassLoadingContext loader, String serviceType) {
             Class<? extends BrooklynComponentTemplateResolver> type = computeResolverType(serviceType, null, null);
             if (type!=null) return true;
-            // can't tell by a prefix; try looking it up
-            try {
-                newInstance(mgmt, serviceType).loadEntityClass();
-                return true;
-            } catch (Exception e) {
-                Exceptions.propagateIfFatal(e);
-                return false;
-            }
+            return newInstance(loader, serviceType).canResolve();
         }
     }
 
-    public BrooklynComponentTemplateResolver(ManagementContext mgmt, ConfigBag attrs, AbstractResource optionalTemplate) {
-        this.mgmt = mgmt;
+    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.loader = new BrooklynYamlTypeLoader.Factory(mgmt, this);
+        this.yamlLoader = new BrooklynYamlTypeInstantiator.Factory(loader, this);
     }
     
     protected String getDeclaredType() {
         return Factory.getDeclaredType(null, template.orNull(), attrs);
     }
     
-    protected String getJavaType() {
+    protected String getCatalogIdOrJavaType() {
         String type = getDeclaredType();
         type = Strings.removeFromStart(type, "brooklyn:", "java:");
         
@@ -168,18 +166,42 @@ public class BrooklynComponentTemplateResolver {
         
         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() {
+        return loader.getManagementContext().getCatalog().getCatalogItem(Entity.class, getCatalogIdOrJavaType());
+    }
     
-    @SuppressWarnings("unchecked")
-    public <T extends Entity> Class<T> loadEntityClass() {
-        return (Class<T>) loader.type(getJavaType()).getType(Entity.class);
+    public boolean canResolve() {
+        if (getCatalogItem()!=null) 
+            return true;
+        if (loader.tryLoadClass(getCatalogIdOrJavaType(), Entity.class).isPresent())
+            return true;
+        return false;
     }
 
+    /** returns the entity class, if needed in contexts which scan its statics for example */
+    public Class<? extends Entity> loadEntityClass() {
+        CatalogItem<Entity, EntitySpec<?>> item = getCatalogItem();
+        String typeName = getCatalogIdOrJavaType();
+        if (item!=null) {
+            loader = new BrooklynClassLoadingContextSequential(mgmt, item.newClassLoadingContext(mgmt), loader);
+            typeName = item.getJavaType();
+        }
+        return loader.loadClass(typeName, Entity.class);
+    }
+
+    /** resolves the spec, updating the loader if a catalog item is loaded */
+    @SuppressWarnings("unchecked")
     public <T extends Entity> EntitySpec<T> resolveSpec() {
-        return resolveSpec(this.<T>loadEntityClass(), null);
+        return (EntitySpec<T>)resolveSpec(loadEntityClass(), null);
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
-    public <T extends Entity> EntitySpec<T> resolveSpec(Class<T> type, Class<? extends T> optionalImpl) {
+    public <T extends Entity> EntitySpec<T> resolveSpec(Class<T> type, @Nullable Class<? extends T> optionalImpl) {
         if (alreadyBuilt.getAndSet(true))
             throw new IllegalStateException("Spec can only be used once: "+this);
 
@@ -224,9 +246,9 @@ public class BrooklynComponentTemplateResolver {
     }
 
     protected <T extends Entity> void decorateSpec(EntitySpec<T> spec) {
-        new BrooklynEntityDecorationResolver.PolicySpecResolver(loader).decorate(spec, attrs);
-        new BrooklynEntityDecorationResolver.EnricherSpecResolver(loader).decorate(spec, attrs);
-        new BrooklynEntityDecorationResolver.InitializerResolver(loader).decorate(spec, attrs);
+        new BrooklynEntityDecorationResolver.PolicySpecResolver(yamlLoader).decorate(spec, attrs);
+        new BrooklynEntityDecorationResolver.EnricherSpecResolver(yamlLoader).decorate(spec, attrs);
+        new BrooklynEntityDecorationResolver.InitializerResolver(yamlLoader).decorate(spec, attrs);
         
         configureEntityConfig(spec);
     }
@@ -273,12 +295,12 @@ public class BrooklynComponentTemplateResolver {
         Set<String> keyNamesUsed = new LinkedHashSet<String>();
         for (FlagConfigKeyAndValueRecord r: records) {
             if (r.getFlagMaybeValue().isPresent()) {
-                Object transformed = new SpecialFlagsTransformer(mgmt).transformSpecialFlags(r.getFlagMaybeValue().get(), mgmt);
+                Object transformed = new SpecialFlagsTransformer(loader).transformSpecialFlags(r.getFlagMaybeValue().get());
                 spec.configure(r.getFlagName(), transformed);
                 keyNamesUsed.add(r.getFlagName());
             }
             if (r.getConfigKeyMaybeValue().isPresent()) {
-                Object transformed = new SpecialFlagsTransformer(mgmt).transformSpecialFlags(r.getConfigKeyMaybeValue().get(), mgmt);
+                Object transformed = new SpecialFlagsTransformer(loader).transformSpecialFlags(r.getConfigKeyMaybeValue().get());
                 spec.configure((ConfigKey<Object>)r.getConfigKey(), transformed);
                 keyNamesUsed.add(r.getConfigKey().getName());
             }
@@ -291,35 +313,36 @@ public class BrooklynComponentTemplateResolver {
             // we don't let a flag with the same name as a config key override the config key
             // (that's why we check whether it is used)
             if (!keyNamesUsed.contains(key)) {
-                Object transformed = new SpecialFlagsTransformer(mgmt).transformSpecialFlags(bag.getStringKey(key), mgmt);
+                Object transformed = new SpecialFlagsTransformer(loader).transformSpecialFlags(bag.getStringKey(key));
                 spec.configure(ConfigKeys.newConfigKey(Object.class, key.toString()), transformed);
             }
         }
     }
 
     protected static class SpecialFlagsTransformer implements Function<Object, Object> {
-        final ManagementContext mgmt;
-        public SpecialFlagsTransformer(ManagementContext mgmt) {
-            this.mgmt = mgmt;
+        // TODO this may be large when serialized as it includes the context search bundles
+        final BrooklynClassLoadingContext loader;
+        public SpecialFlagsTransformer(BrooklynClassLoadingContext loader) {
+            this.loader = loader;
         }
         public Object apply(Object input) {
             if (input instanceof Map)
-                return transformSpecialFlags((Map<?, ?>)input, mgmt);
+                return transformSpecialFlags((Map<?, ?>)input);
             else if (input instanceof Set<?>)
-                return MutableSet.of(transformSpecialFlags((Iterable<?>)input, mgmt));
+                return MutableSet.of(transformSpecialFlags((Iterable<?>)input));
             else if (input instanceof List<?>)
-                return MutableList.copyOf(transformSpecialFlags((Iterable<?>)input, mgmt));
+                return MutableList.copyOf(transformSpecialFlags((Iterable<?>)input));
             else if (input instanceof Iterable<?>)
-                return transformSpecialFlags((Iterable<?>)input, mgmt);
+                return transformSpecialFlags((Iterable<?>)input);
             else 
-                return transformSpecialFlags((Object)input, mgmt);
+                return transformSpecialFlags((Object)input);
         }
         
-        protected Map<?, ?> transformSpecialFlags(Map<?, ?> flag, final ManagementContext mgmt) {
+        protected Map<?, ?> transformSpecialFlags(Map<?, ?> flag) {
             return Maps.transformValues(flag, this);
         }
         
-        protected Iterable<?> transformSpecialFlags(Iterable<?> flag, final ManagementContext mgmt) {
+        protected Iterable<?> transformSpecialFlags(Iterable<?> flag) {
             return Iterables.transform(flag, this);
         }
         
@@ -327,15 +350,15 @@ public class BrooklynComponentTemplateResolver {
          * 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.
          */
-        protected Object transformSpecialFlags(Object flag, ManagementContext mgmt) {
+        protected Object transformSpecialFlags(Object flag) {
             if (flag instanceof EntitySpecConfiguration) {
                 EntitySpecConfiguration specConfig = (EntitySpecConfiguration) flag;
                 // TODO: This should called from BrooklynAssemblyTemplateInstantiator.configureEntityConfig
                 // And have transformSpecialFlags(Object flag, ManagementContext mgmt) drill into the Object flag if it's a map or iterable?
                 @SuppressWarnings("unchecked")
-                Map<String, Object> resolvedConfig = (Map<String, Object>)transformSpecialFlags(specConfig.getSpecConfiguration(), mgmt);
+                Map<String, Object> resolvedConfig = (Map<String, Object>)transformSpecialFlags(specConfig.getSpecConfiguration());
                 specConfig.setSpecConfiguration(resolvedConfig);
-                return Factory.newInstance(mgmt, specConfig.getSpecConfiguration()).resolveSpec();
+                return Factory.newInstance(loader, specConfig.getSpecConfiguration()).resolveSpec();
             }
             return flag;
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
deleted file mode 100644
index 8941a19..0000000
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityClassResolver.java
+++ /dev/null
@@ -1,141 +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 static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.NoSuchElementException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.Entity;
-import brooklyn.management.ManagementContext;
-import brooklyn.management.ha.OsgiManager;
-import brooklyn.management.internal.ManagementContextInternal;
-import brooklyn.util.guava.Maybe;
-
-/**
- * Resolves a class name to a <code>Class&lt;? extends Entity&gt;</code> with a given 
- * {@link brooklyn.management.ManagementContext management context}.
- */
-public class BrooklynEntityClassResolver {
-
-    private static final Logger LOG = LoggerFactory.getLogger(BrooklynEntityClassResolver.class);
-
-    /**
-     * Loads the class represented by entityTypeName with the given management context.
-     * Tries the context's catalogue first, then from its root classloader.
-     * @throws java.lang.IllegalStateException if no class extending {@link Entity} is found
-     */
-    public static <T extends Entity> Class<T> resolveEntity(String entityTypeName, ManagementContext mgmt) {
-        return resolveEntity(entityTypeName, mgmt, Collections.<String>emptyList());
-    }
-
-    /**
-     * Loads the class represented by entityTypeName with the given management context.
-     * Tries the context's catalogue first, then from its root classloader.
-     * @throws java.lang.IllegalStateException if no class extending {@link Entity} is found
-     */
-    public static <T extends Entity> Class<T> resolveEntity(String entityTypeName, ManagementContext mgmt, List<String> context) {
-        checkNotNull(mgmt, "management context");
-        Maybe<Class<T>> entityClazz = Maybe.absent("No bundles defined");
-        Maybe<Class<T>> bestError = null;
-        
-        if (context!=null && !context.isEmpty()) {
-            entityClazz = tryLoadEntityFromBundle(entityTypeName, mgmt, context);
-            if (!entityClazz.isPresent()) {
-                LOG.warn("Unable to find class "+entityTypeName+" in suggested bundles "+context+"; continuing other mechanisms");
-                // we should prefer the error message from above if context is non-empty but class can't be found
-                bestError = entityClazz;
-            }
-        }
-        
-
-        if (!entityClazz.isPresent()) {
-            entityClazz = tryLoadEntityFromCatalogue(entityTypeName, mgmt);
-        }
-        if (!entityClazz.isPresent()) {
-            entityClazz = tryLoadFromClasspath(entityTypeName, mgmt);
-        }
-        if (!entityClazz.isPresent()) {
-            LOG.warn("No catalog item for {} and could not load class directly; throwing", entityTypeName);
-            throw new IllegalStateException("Unable to load class "+ entityTypeName +" (extending Entity) from catalogue or classpath: not found");
-        }
-        if (!Entity.class.isAssignableFrom(entityClazz.get())) {
-            LOG.warn("Found class {} on classpath but it is not assignable to {}", entityTypeName, Entity.class);
-            throw new IllegalStateException("Unable to load class "+ entityTypeName +" (extending Entity) from catalogue or classpath: wrong type "+entityClazz.get());
-        }
-        if (!entityClazz.isPresent() && bestError!=null) {
-            // prefer best error if not found
-            bestError.get();
-        }
-        return entityClazz.get();
-    }
-
-    // TODO deprecate the ones below, make them protected or private
-    
-    /** Tries to load the entity with the given class name from the given bundle. */
-    public static <T extends Entity> Maybe<Class<T>> tryLoadEntityFromBundle(String entityTypeName, ManagementContext mgmt, String... bundleUrls) {
-        return tryLoadEntityFromBundle(entityTypeName, mgmt, Arrays.asList(bundleUrls));
-    }
-    public static <T extends Entity> Maybe<Class<T>> tryLoadEntityFromBundle(String entityTypeName, ManagementContext mgmt, Iterable<String> bundleUrls) {
-        LOG.debug("Trying to resolve class {} from bundle {}", entityTypeName, bundleUrls);
-        Maybe<OsgiManager> osgiManager = ((ManagementContextInternal) mgmt).getOsgiManager();
-        if (!osgiManager.isPresentAndNonNull()) {
-            if (LOG.isDebugEnabled())
-                LOG.debug("Asked to resolve class {} from bundles {} but osgi manager is unavailable in context {}",
-                    new Object[]{entityTypeName, bundleUrls, mgmt});
-            return Maybe.absent();
-        }
-        Maybe<Class<T>> clazz = osgiManager.get().tryResolveClass(entityTypeName, bundleUrls);
-        if (!clazz.isPresent() || !Entity.class.isAssignableFrom(clazz.get())) {
-            return Maybe.absent();
-        }
-        return clazz;
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T extends Entity> Maybe<Class<T>> tryLoadEntityFromCatalogue(String entityTypeName, ManagementContext mgmt) {
-        LOG.debug("Trying to resolve class {} from catalog", entityTypeName);
-        try {
-            return (Maybe<Class<T>>)(Maybe<?>) Maybe.<Class<? extends Entity>>of(mgmt.getCatalog().loadClassByType(entityTypeName, Entity.class));
-        } catch (NoSuchElementException e) {
-            LOG.debug("Class {} not found in catalogue classpath", entityTypeName);
-            return Maybe.absent();
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    public static <T> Maybe<Class<T>> tryLoadFromClasspath(String typeName, ManagementContext mgmt) {
-        LOG.debug("Trying to resolve class {} from classpath", typeName);
-        Class<T> clazz;
-        try {
-            clazz = (Class<T>) mgmt.getCatalog().getRootClassLoader().loadClass(typeName);
-        } catch (ClassNotFoundException e) {
-            LOG.debug("Class {} not found on classpath", typeName);
-            return Maybe.absent(new Throwable("Could not find "+typeName+" on classpath"));
-        }
-
-        return Maybe.of(clazz);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/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 d4d08ba..867c775 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
@@ -18,7 +18,7 @@
  */
 package io.brooklyn.camp.brooklyn.spi.creation;
 
-import io.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeLoader.LoaderFromKey;
+import io.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator.InstantiatorFromKey;
 
 import java.util.List;
 import java.util.Map;
@@ -41,10 +41,10 @@ import com.google.common.annotations.Beta;
 @Beta
 public abstract class BrooklynEntityDecorationResolver<DT> {
 
-    public final BrooklynYamlTypeLoader.Factory loader;
+    public final BrooklynYamlTypeInstantiator.Factory instantiator;
     
-    protected BrooklynEntityDecorationResolver(BrooklynYamlTypeLoader.Factory loader) {
-        this.loader = loader;
+    protected BrooklynEntityDecorationResolver(BrooklynYamlTypeInstantiator.Factory instantiator) {
+        this.instantiator = instantiator;
     }
     
     public abstract void decorate(EntitySpec<?> entitySpec, ConfigBag attrs);
@@ -84,7 +84,7 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
 
     public static class PolicySpecResolver extends BrooklynEntityDecorationResolver<PolicySpec<?>> {
         
-        protected PolicySpecResolver(BrooklynYamlTypeLoader.Factory loader) { super(loader); }
+        protected PolicySpecResolver(BrooklynYamlTypeInstantiator.Factory loader) { super(loader); }
         @Override protected String getDecorationKind() { return "Policy"; }
 
         @Override
@@ -99,7 +99,7 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
 
         @Override
         protected void addDecorationFromJsonMap(Map<?, ?> decorationJson, List<PolicySpec<?>> decorations) {
-            LoaderFromKey decoLoader = loader.from(decorationJson).prefix("policy");
+            InstantiatorFromKey decoLoader = instantiator.from(decorationJson).prefix("policy");
             // this pattern of creating a spec could be simplified with a "Configurable" superinterface on *Spec  
             decorations.add(PolicySpec.create(decoLoader.getType(Policy.class))
                 .configure( decoLoader.getConfigMap() ));
@@ -108,7 +108,7 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
 
     public static class EnricherSpecResolver extends BrooklynEntityDecorationResolver<EnricherSpec<?>> {
         
-        protected EnricherSpecResolver(BrooklynYamlTypeLoader.Factory loader) { super(loader); }
+        protected EnricherSpecResolver(BrooklynYamlTypeInstantiator.Factory loader) { super(loader); }
         @Override protected String getDecorationKind() { return "Enricher"; }
 
         @Override
@@ -123,7 +123,7 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
 
         @Override
         protected void addDecorationFromJsonMap(Map<?, ?> decorationJson, List<EnricherSpec<?>> decorations) {
-            LoaderFromKey decoLoader = loader.from(decorationJson).prefix("enricher");
+            InstantiatorFromKey decoLoader = instantiator.from(decorationJson).prefix("enricher");
             decorations.add(EnricherSpec.create(decoLoader.getType(Enricher.class))
                 .configure( decoLoader.getConfigMap() ));
         }
@@ -131,7 +131,7 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
     
     public static class InitializerResolver extends BrooklynEntityDecorationResolver<EntityInitializer> {
         
-        protected InitializerResolver(BrooklynYamlTypeLoader.Factory loader) { super(loader); }
+        protected InitializerResolver(BrooklynYamlTypeInstantiator.Factory loader) { super(loader); }
         @Override protected String getDecorationKind() { return "Entity initializer"; }
 
         @Override
@@ -146,7 +146,7 @@ public abstract class BrooklynEntityDecorationResolver<DT> {
 
         @Override
         protected void addDecorationFromJsonMap(Map<?, ?> decorationJson, List<EntityInitializer> decorations) {
-            decorations.add(loader.from(decorationJson).prefix("initializer").newInstance(EntityInitializer.class));
+            decorations.add(instantiator.from(decorationJson).prefix("initializer").newInstance(EntityInitializer.class));
         }
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
index 7118be9..673e13f 100644
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynEntityMatcher.java
@@ -32,6 +32,7 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.entity.Entity;
 import brooklyn.management.ManagementContext;
+import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
 import brooklyn.util.collections.MutableMap;
 import brooklyn.util.config.ConfigBag;
 import brooklyn.util.exceptions.Exceptions;
@@ -62,9 +63,10 @@ public class BrooklynEntityMatcher implements PdpMatcher {
      * or null if not supported */
     protected String lookupType(Object deploymentPlanItem) {
         if (deploymentPlanItem instanceof Service) {
-            if (!BrooklynComponentTemplateResolver.Factory.supportsType(mgmt, ((Service)deploymentPlanItem).getServiceType()))
+            String serviceType = ((Service)deploymentPlanItem).getServiceType();
+            if (!BrooklynComponentTemplateResolver.Factory.supportsType(JavaBrooklynClassLoadingContext.newDefault(mgmt), serviceType))
                 return null;
-            return ((Service)deploymentPlanItem).getServiceType();
+            return serviceType;
         }
         return null;
     }
@@ -150,7 +152,7 @@ public class BrooklynEntityMatcher implements PdpMatcher {
      * as a custom attribute with type List.
      * @throws java.lang.IllegalArgumentException if map[key] is not an instance of List
      */
-    private void addCustomListAttributeIfNonNull(Builder<? extends PlatformComponentTemplate> builder, Map attrs, String key) {
+    private void addCustomListAttributeIfNonNull(Builder<? extends PlatformComponentTemplate> builder, Map<?,?> attrs, String key) {
         Object items = attrs.remove(key);
         if (items != null) {
             if (items instanceof List) {
@@ -169,7 +171,7 @@ public class BrooklynEntityMatcher implements PdpMatcher {
      * as a custom attribute with type Map.
      * @throws java.lang.IllegalArgumentException if map[key] is not an instance of Map
      */
-    private void addCustomMapAttributeIfNonNull(Builder<? extends PlatformComponentTemplate> builder, Map attrs, String key) {
+    private void addCustomMapAttributeIfNonNull(Builder<? extends PlatformComponentTemplate> builder, Map<?,?> attrs, String key) {
         Object items = attrs.remove(key);
         if (items != null) {
             if (items instanceof Map) {
@@ -190,7 +192,7 @@ public class BrooklynEntityMatcher implements PdpMatcher {
         if (attrs==null || attrs.isEmpty())
             return null;
         try {
-            Class<Entity> type = BrooklynComponentTemplateResolver.Factory.newInstance(mgmt, typeName).loadEntityClass();
+            Class<? extends Entity> type = BrooklynComponentTemplateResolver.Factory.newInstance(JavaBrooklynClassLoadingContext.newDefault(mgmt), typeName).loadEntityClass();
             ConfigBag bag = ConfigBag.newInstance(attrs);
             List<FlagConfigKeyAndValueRecord> values = FlagUtils.findAllFlagsAndConfigKeys(null, type, bag);
             

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
new file mode 100644
index 0000000..ad2b8d7
--- /dev/null
+++ b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeInstantiator.java
@@ -0,0 +1,200 @@
+/*
+ * 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 java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.config.ConfigBag;
+import brooklyn.util.exceptions.Exceptions;
+import brooklyn.util.guava.Maybe;
+import brooklyn.util.javalang.Reflections;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/** Assists in loading types referenced from YAML;
+ * mainly as a way to share logic used in very different contexts. */
+public abstract class BrooklynYamlTypeInstantiator {
+
+    private static final Logger log = LoggerFactory.getLogger(BrooklynYamlTypeInstantiator.class);
+    
+    protected final Factory factory;
+
+    @Beta
+    public static class Factory {
+        final BrooklynClassLoadingContext loader;
+        final Object contextForLogging;
+        
+        public Factory(BrooklynClassLoadingContext loader, Object contextForLogging) {
+            this.loader = loader;
+            this.contextForLogging = contextForLogging;
+        }
+        
+        public InstantiatorFromKey from(Map<?,?> data) {
+            return new InstantiatorFromKey(this, ConfigBag.newInstance(data));
+        }
+        
+        public InstantiatorFromKey from(ConfigBag data) {
+            return new InstantiatorFromKey(this, data);
+        }
+        
+        public InstantiatorFromName type(String typeName) {
+            return new InstantiatorFromName(this, typeName);
+        }
+
+    }
+        
+    public static class InstantiatorFromKey extends BrooklynYamlTypeInstantiator {
+        protected final ConfigBag data;
+        protected String typeKeyPrefix = null;
+        
+        /** Nullable only permitted for instances which do not do loading, e.g. LoaderFromKey#lookup */
+        protected InstantiatorFromKey(@Nullable Factory factory, ConfigBag data) {
+            super(factory);
+            this.data = data;
+        }
+        
+        public static Maybe<String> extractTypeName(String prefix, ConfigBag data) {
+            if (data==null) return Maybe.absent();
+            return new InstantiatorFromKey(null, data).prefix(prefix).getTypeName();
+        }
+        
+        public InstantiatorFromKey prefix(String prefix) {
+            typeKeyPrefix = prefix;
+            return this;
+        }
+
+        public Maybe<String> getTypeName() {
+            Maybe<Object> result = data.getStringKeyMaybe(getPreferredKeyName());
+            if (result.isAbsent() && typeKeyPrefix!=null) {
+                // try alternatives if a prefix was specified
+                result = data.getStringKeyMaybe(typeKeyPrefix+"Type");
+                if (result.isAbsent()) result = data.getStringKeyMaybe("type");
+            }
+            
+            if (result.isAbsent()) return Maybe.absent("Missing key '"+getPreferredKeyName()+"'");
+            
+            if (result.get() instanceof String) return Maybe.of((String)result.get());
+            
+            throw new IllegalArgumentException("Invalid value "+result.get().getClass()+" for "+getPreferredKeyName()+"; "
+                + "expected String, got "+result.get());
+        }
+        
+        protected String getPreferredKeyName() {
+            if (typeKeyPrefix!=null) return typeKeyPrefix+"_type";
+            return "type";
+        }
+        
+        /** as {@link #newInstance(Class)} but inferring the type */
+        public Object newInstance() {
+            return newInstance(null);
+        }
+        
+        /** creates a new instance of the type referred to by this description,
+         * as a subtype of the type supplied here, 
+         * inferring a Map from <code>brooklyn.config</code> key.
+         * TODO in future also picking up recognized flags and config keys (those declared on the type).  
+         * <p>
+         * constructs the object using:
+         * <li> a constructor on the class taking a Map
+         * <li> a no-arg constructor, only if the inferred map is empty  
+         **/
+        public <T> T newInstance(@Nullable Class<T> supertype) {
+            Class<? extends T> type = getType(supertype);
+            Map<String, ?> cfg = getConfigMap();
+            Optional<? extends T> result = Reflections.invokeConstructorWithArgs(type, cfg);
+            if (result.isPresent()) 
+                return result.get();
+            if (cfg.isEmpty()) {
+                result = Reflections.invokeConstructorWithArgs(type);
+                if (result.isPresent()) 
+                    return result.get();
+            }
+            throw new IllegalStateException("No known mechanism for constructing type "+type+" in "+factory.contextForLogging);
+        }
+
+        /** finds the map of config for the type specified;
+         * currently only gets <code>brooklyn.config</code>, returning empty map if none,
+         * but TODO in future should support recognized flags and config keys (those declared on the type),
+         * incorporating code in {@link BrooklynEntityMatcher}.
+         */
+        @SuppressWarnings("unchecked")
+        @Nonnull
+        public Map<String,?> getConfigMap() {
+            MutableMap<String,Object> result = MutableMap.of();
+            Object bc = data.getStringKey("brooklyn.config");
+            if (bc!=null) {
+                if (bc instanceof Map)
+                    result.putAll((Map<? extends String, ?>) bc);
+                else
+                    throw new IllegalArgumentException("brooklyn.config key in "+factory.contextForLogging+" should be a map, not "+bc.getClass()+" ("+bc+")");
+            }
+            return result; 
+        }
+
+    }
+    
+    public static class InstantiatorFromName extends BrooklynYamlTypeInstantiator {
+        protected final String typeName;
+        protected InstantiatorFromName(Factory factory, String typeName) {
+            super(factory);
+            this.typeName = typeName;
+        }
+        
+        public Maybe<String> getTypeName() {
+            return Maybe.fromNullable(typeName);
+        }
+    }
+    
+    protected BrooklynYamlTypeInstantiator(Factory factory) {
+        this.factory = factory;
+    }
+        
+    public abstract Maybe<String> getTypeName();
+    
+    public BrooklynClassLoadingContext getClassLoadingContext() {
+        Preconditions.checkNotNull("No factory set; cannot use this instance for type loading");
+        return factory.loader;
+    }
+    
+    public Class<?> getType() {
+        return getType(Object.class);
+    }
+    
+    public <T> Class<? extends T> getType(@Nonnull Class<T> type) {
+        try {
+            return getClassLoadingContext().loadClass(getTypeName().get(), type);
+//            return loadClass(type, getTypeName().get(), factory.mgmt, factory.contextForLogging);
+        } catch (Exception e) {
+            Exceptions.propagateIfFatal(e);
+            log.warn("Unable to resolve " + type + " " + getTypeName().get() + " (rethrowing) in spec " + factory.contextForLogging);
+            throw Exceptions.propagate(e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeLoader.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeLoader.java b/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeLoader.java
deleted file mode 100644
index f1d387a..0000000
--- a/usage/camp/src/main/java/io/brooklyn/camp/brooklyn/spi/creation/BrooklynYamlTypeLoader.java
+++ /dev/null
@@ -1,210 +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 java.util.Map;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.entity.Entity;
-import brooklyn.management.ManagementContext;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.config.ConfigBag;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.javalang.Reflections;
-import brooklyn.util.osgi.Osgis;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-
-public abstract class BrooklynYamlTypeLoader {
-
-    private static final Logger log = LoggerFactory.getLogger(BrooklynYamlTypeLoader.class);
-    
-    protected final Factory factory;
-
-    @Beta
-    public static class Factory {
-        final ManagementContext mgmt;
-        final Object contextForLogging;
-        
-        public Factory(ManagementContext mgmt, Object contextForLogging) {
-            this.mgmt = mgmt;
-            this.contextForLogging = contextForLogging;
-        }
-        
-        public LoaderFromKey from(Map<?,?> data) {
-            return new LoaderFromKey(this, ConfigBag.newInstance(data));
-        }
-        
-        public LoaderFromKey from(ConfigBag data) {
-            return new LoaderFromKey(this, data);
-        }
-        
-        public LoaderFromName type(String typeName) {
-            return new LoaderFromName(this, typeName);
-        }
-
-    }
-        
-    public static class LoaderFromKey extends BrooklynYamlTypeLoader {
-        protected final ConfigBag data;
-        protected String typeKeyPrefix = null;
-        
-        /** Nullable only permitted for instances which do not do loading, e.g. LoaderFromKey#lookup */
-        protected LoaderFromKey(@Nullable Factory factory, ConfigBag data) {
-            super(factory);
-            this.data = data;
-        }
-        
-        public static Maybe<String> extractTypeName(String prefix, ConfigBag data) {
-            if (data==null) return Maybe.absent();
-            return new LoaderFromKey(null, data).prefix(prefix).getTypeName();
-        }
-        
-        public LoaderFromKey prefix(String prefix) {
-            typeKeyPrefix = prefix;
-            return this;
-        }
-
-        public Maybe<String> getTypeName() {
-            Maybe<Object> result = data.getStringKeyMaybe(getPreferredKeyName());
-            if (result.isAbsent() && typeKeyPrefix!=null) {
-                // try alternatives if a prefix was specified
-                result = data.getStringKeyMaybe(typeKeyPrefix+"Type");
-                if (result.isAbsent()) result = data.getStringKeyMaybe("type");
-            }
-            
-            if (result.isAbsent()) return Maybe.absent("Missing key '"+getPreferredKeyName()+"'");
-            
-            if (result.get() instanceof String) return Maybe.of((String)result.get());
-            
-            throw new IllegalArgumentException("Invalid value "+result.get().getClass()+" for "+getPreferredKeyName()+"; "
-                + "expected String, got "+result.get());
-        }
-        
-        protected String getPreferredKeyName() {
-            if (typeKeyPrefix!=null) return typeKeyPrefix+"_type";
-            return "type";
-        }
-        
-        /** as {@link #newInstance(Class)} but inferring the type */
-        public Object newInstance() {
-            return newInstance(null);
-        }
-        
-        /** creates a new instance of the type referred to by this description,
-         * as a subtype of the type supplied here, 
-         * inferring a Map from <code>brooklyn.config</code> key.
-         * TODO in future also picking up recognized flags and config keys (those declared on the type).  
-         * <p>
-         * constructs the object using:
-         * <li> a constructor on the class taking a Map
-         * <li> a no-arg constructor, only if the inferred map is empty  
-         **/
-        public <T> T newInstance(@Nullable Class<T> supertype) {
-            Class<? extends T> type = getType(supertype);
-            Map<String, ?> cfg = getConfigMap();
-            Optional<? extends T> result = Reflections.invokeConstructorWithArgs(type, cfg);
-            if (result.isPresent()) 
-                return result.get();
-            if (cfg.isEmpty()) {
-                result = Reflections.invokeConstructorWithArgs(type);
-                if (result.isPresent()) 
-                    return result.get();
-            }
-            throw new IllegalStateException("No known mechanism for constructing type "+type+" in "+factory.contextForLogging);
-        }
-
-        /** finds the map of config for the type specified;
-         * currently only gets <code>brooklyn.config</code>, returning empty map if none,
-         * but TODO in future should support recognized flags and config keys (those declared on the type),
-         * incorporating code in {@link BrooklynEntityMatcher}.
-         */
-        @SuppressWarnings("unchecked")
-        @Nonnull
-        public Map<String,?> getConfigMap() {
-            MutableMap<String,Object> result = MutableMap.of();
-            Object bc = data.getStringKey("brooklyn.config");
-            if (bc!=null) {
-                if (bc instanceof Map)
-                    result.putAll((Map<? extends String, ?>) bc);
-                else
-                    throw new IllegalArgumentException("brooklyn.config key in "+factory.contextForLogging+" should be a map, not "+bc.getClass()+" ("+bc+")");
-            }
-            return result; 
-        }
-
-    }
-    
-    public static class LoaderFromName extends BrooklynYamlTypeLoader {
-        protected final String typeName;
-        protected LoaderFromName(Factory factory, String typeName) {
-            super(factory);
-            this.typeName = typeName;
-        }
-        
-        public Maybe<String> getTypeName() {
-            return Maybe.fromNullable(typeName);
-        }
-    }
-    
-    protected BrooklynYamlTypeLoader(Factory factory) {
-        this.factory = factory;
-    }
-        
-    public abstract Maybe<String> getTypeName();
-    
-    public Class<?> getType() {
-        return getType(null);
-    }
-    
-    public <T> Class<? extends T> getType(@Nullable Class<T> type) {
-        Preconditions.checkNotNull("No factory set; cannot use this instance for type loading");
-        return loadClass(type, getTypeName().get(), factory.mgmt, factory.contextForLogging);
-    }
-
-    /**
-     * TODO in future will want OSGi-based resolver here (eg create from osgi:<bundle>: prefix
-     * would use that OSGi mechanism here
-     */
-    @SuppressWarnings("unchecked")
-    private static <T> Class<T> loadClass(@Nullable Class<T> optionalSupertype, String typeName, ManagementContext mgmt, Object otherContext) {
-        try {
-            if (optionalSupertype != null && Entity.class.isAssignableFrom(optionalSupertype))
-                return (Class<T>) BrooklynEntityClassResolver.<Entity>resolveEntity(typeName, mgmt);
-            else
-                return BrooklynEntityClassResolver.<T>tryLoadFromClasspath(typeName, mgmt).get();
-        } catch (Exception e) {
-            Exceptions.propagateIfFatal(e);
-            log.warn("Unable to resolve " + typeName + " in spec " + otherContext);
-            throw Exceptions.propagate(new IllegalStateException("Unable to resolve "
-                    + (optionalSupertype != null ? optionalSupertype.getSimpleName() + " " : "")
-                    + "type '" + typeName + "'", e));
-        }
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/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
index 00e6af4..adb3537 100644
--- 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
@@ -19,24 +19,31 @@
 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.ManagementContext;
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
 import brooklyn.util.config.ConfigBag;
 import brooklyn.util.text.Strings;
 
 public class ChefComponentTemplateResolver extends BrooklynComponentTemplateResolver {
 
-    public ChefComponentTemplateResolver(ManagementContext mgmt, ConfigBag attrs, AbstractResource optionalTemplate) {
-        super(mgmt, attrs, optionalTemplate);
+    public ChefComponentTemplateResolver(BrooklynClassLoadingContext loader, ConfigBag attrs, AbstractResource optionalTemplate) {
+        super(loader, attrs, optionalTemplate);
     }
 
     @Override
-    protected String getJavaType() {
+    protected String getCatalogIdOrJavaType() {
         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) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java
new file mode 100644
index 0000000..3796c00
--- /dev/null
+++ b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/BrooklynYamlTypeInstantiatorTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package io.brooklyn.camp.brooklyn;
+
+import io.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator;
+import io.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator.Factory;
+import io.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiator.InstantiatorFromKey;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import brooklyn.management.classloading.BrooklynClassLoadingContext;
+import brooklyn.management.classloading.JavaBrooklynClassLoadingContext;
+import brooklyn.policy.Policy;
+import brooklyn.policy.ha.ServiceRestarter;
+import brooklyn.util.collections.MutableMap;
+import brooklyn.util.javalang.JavaClassNames;
+import brooklyn.util.time.Duration;
+
+public class BrooklynYamlTypeInstantiatorTest extends AbstractYamlTest {
+
+    protected BrooklynClassLoadingContext loader() {
+        return JavaBrooklynClassLoadingContext.newDefault(mgmt());
+    }
+    
+    @Test
+    public void testLoadPolicySpecProgrammatically() {
+        Factory loader = new BrooklynYamlTypeInstantiator.Factory(loader(), "test:"+JavaClassNames.niceClassAndMethod());
+        InstantiatorFromKey decoL = loader.from(MutableMap.of("some_type", ServiceRestarter.class.getName())).prefix("some");
+        
+        Assert.assertTrue(decoL.getConfigMap().isEmpty());
+        Assert.assertEquals(decoL.getTypeName().get(), ServiceRestarter.class.getName());
+        Assert.assertEquals(decoL.getType(), ServiceRestarter.class);
+        
+        Object sl1 = decoL.newInstance();
+        Assert.assertTrue(sl1 instanceof ServiceRestarter);
+        
+        Policy sl2 = decoL.newInstance(Policy.class);
+        Assert.assertTrue(sl2 instanceof ServiceRestarter);
+    }
+    
+    @Test
+    public void testLoadPolicySpecWithBrooklynConfig() {
+        Factory loader = new BrooklynYamlTypeInstantiator.Factory(loader(), "test:"+JavaClassNames.niceClassAndMethod());
+        InstantiatorFromKey decoL = loader.from(MutableMap.of("some_type", ServiceRestarter.class.getName(),
+            "brooklyn.config", MutableMap.of("failOnRecurringFailuresInThisDuration", Duration.seconds(42)))).prefix("some");
+        Policy sl2 = decoL.newInstance(Policy.class);
+        Assert.assertEquals(sl2.getConfig(ServiceRestarter.FAIL_ON_RECURRING_FAILURES_IN_THIS_DURATION).toSeconds(), 42);
+    }
+
+    @Test(groups = "WIP")
+    public void testLoadPolicySpecWithFlag() {
+        Factory loader = new BrooklynYamlTypeInstantiator.Factory(loader(), "test:"+JavaClassNames.niceClassAndMethod());
+        InstantiatorFromKey decoL = loader.from(MutableMap.of("some_type", ServiceRestarter.class.getName(),
+            "failOnRecurringFailuresInThisDuration", Duration.seconds(42))).prefix("some");
+        Policy sl2 = decoL.newInstance(Policy.class);
+        Assert.assertEquals(sl2.getConfig(ServiceRestarter.FAIL_ON_RECURRING_FAILURES_IN_THIS_DURATION).toSeconds(), 42);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/37d2004f/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/BrooklynYamlTypeLoaderTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/BrooklynYamlTypeLoaderTest.java b/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/BrooklynYamlTypeLoaderTest.java
deleted file mode 100644
index 29ea048..0000000
--- a/usage/camp/src/test/java/io/brooklyn/camp/brooklyn/BrooklynYamlTypeLoaderTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package io.brooklyn.camp.brooklyn;
-
-import io.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeLoader;
-import io.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeLoader.Factory;
-import io.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeLoader.LoaderFromKey;
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-import brooklyn.policy.Policy;
-import brooklyn.policy.ha.ServiceRestarter;
-import brooklyn.util.collections.MutableMap;
-import brooklyn.util.javalang.JavaClassNames;
-import brooklyn.util.time.Duration;
-
-public class BrooklynYamlTypeLoaderTest extends AbstractYamlTest {
-
-    @Test
-    public void testLoadPolicySpecProgrammatically() {
-        Factory loader = new BrooklynYamlTypeLoader.Factory(mgmt(), "test:"+JavaClassNames.niceClassAndMethod());
-        LoaderFromKey decoL = loader.from(MutableMap.of("some_type", ServiceRestarter.class.getName())).prefix("some");
-        
-        Assert.assertTrue(decoL.getConfigMap().isEmpty());
-        Assert.assertEquals(decoL.getTypeName().get(), ServiceRestarter.class.getName());
-        Assert.assertEquals(decoL.getType(), ServiceRestarter.class);
-        
-        Object sl1 = decoL.newInstance();
-        Assert.assertTrue(sl1 instanceof ServiceRestarter);
-        
-        Policy sl2 = decoL.newInstance(Policy.class);
-        Assert.assertTrue(sl2 instanceof ServiceRestarter);
-    }
-    
-    @Test
-    public void testLoadPolicySpecWithBrooklynConfig() {
-        Factory loader = new BrooklynYamlTypeLoader.Factory(mgmt(), "test:"+JavaClassNames.niceClassAndMethod());
-        LoaderFromKey decoL = loader.from(MutableMap.of("some_type", ServiceRestarter.class.getName(),
-            "brooklyn.config", MutableMap.of("failOnRecurringFailuresInThisDuration", Duration.seconds(42)))).prefix("some");
-        Policy sl2 = decoL.newInstance(Policy.class);
-        Assert.assertEquals(sl2.getConfig(ServiceRestarter.FAIL_ON_RECURRING_FAILURES_IN_THIS_DURATION).toSeconds(), 42);
-    }
-
-    @Test(groups = "WIP")
-    public void testLoadPolicySpecWithFlag() {
-        Factory loader = new BrooklynYamlTypeLoader.Factory(mgmt(), "test:"+JavaClassNames.niceClassAndMethod());
-        LoaderFromKey decoL = loader.from(MutableMap.of("some_type", ServiceRestarter.class.getName(),
-            "failOnRecurringFailuresInThisDuration", Duration.seconds(42))).prefix("some");
-        Policy sl2 = decoL.newInstance(Policy.class);
-        Assert.assertEquals(sl2.getConfig(ServiceRestarter.FAIL_ON_RECURRING_FAILURES_IN_THIS_DURATION).toSeconds(), 42);
-    }
-
-}