allow access to catalog classloader without populating catalog

required changes to how catalog is initialized, but i think it's a bit cleaner 
now (overwriting other changes in this PR).
(lots of files touched, unfortunately, but not a lot different here.)


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

Branch: refs/heads/master
Commit: ddbb43c604b57c8ef522f7e99d6e1f45517292bc
Parents: 21707da
Author: Alex Heneveld <alex.henev...@cloudsoftcorp.com>
Authored: Wed May 6 16:37:20 2015 +0100
Committer: Alex Heneveld <alex.henev...@cloudsoftcorp.com>
Committed: Fri May 8 18:22:22 2015 +0100

----------------------------------------------------------------------
 .../java/brooklyn/catalog/BrooklynCatalog.java  |   4 +-
 .../brooklyn/management/ManagementContext.java  |   5 +
 .../catalog/internal/BasicBrooklynCatalog.java  |  11 +-
 .../catalog/internal/CatalogInitialization.java | 108 ++++++++-----------
 .../brooklyn/entity/rebind/RebindIteration.java |   6 +-
 .../entity/rebind/RebindManagerImpl.java        |   4 +-
 .../persister/BrooklynPersistenceUtils.java     |   4 +-
 .../location/basic/BasicLocationRegistry.java   |   2 +-
 .../JavaBrooklynClassLoadingContext.java        |   2 +-
 .../ha/HighAvailabilityManagerImpl.java         |   2 +-
 .../internal/AbstractManagementContext.java     |  36 +++----
 .../internal/ManagementContextInternal.java     |   8 --
 .../NonDeploymentManagementContext.java         |  21 ++--
 .../location/jclouds/JcloudsLocation.java       |   4 +-
 .../BrooklynComponentTemplateResolver.java      |   7 +-
 .../brooklyn/launcher/BrooklynLauncher.java     |   9 +-
 .../rest/resources/ApplicationResource.java     |   2 +-
 .../brooklyn/rest/resources/EntityResource.java |   2 +-
 .../rest/util/BrooklynRestResourceUtils.java    |   4 +
 .../util/javalang/AggregateClassLoader.java     |  24 ++++-
 20 files changed, 130 insertions(+), 135 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java 
b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
index 7c36c0e..82b865d 100644
--- a/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
+++ b/api/src/main/java/brooklyn/catalog/BrooklynCatalog.java
@@ -69,7 +69,9 @@ public interface BrooklynCatalog {
     public void persist(CatalogItem<?, ?> catalogItem);
 
     /** @return The classloader which should be used to load classes and 
entities;
-     * this includes all the catalog's classloaders in the right order */
+     * this includes all the catalog's classloaders in the right order.
+     * This is a wrapper which will update as the underlying catalog items 
change,
+     * so it is safe for callers to keep a handle on this. */
     public ClassLoader getRootClassLoader();
 
     /** creates a spec for the given catalog item, throwing exceptions if any 
problems */

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/api/src/main/java/brooklyn/management/ManagementContext.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/brooklyn/management/ManagementContext.java 
b/api/src/main/java/brooklyn/management/ManagementContext.java
index 12ead70..b34dba1 100644
--- a/api/src/main/java/brooklyn/management/ManagementContext.java
+++ b/api/src/main/java/brooklyn/management/ManagementContext.java
@@ -197,6 +197,11 @@ public interface ManagementContext {
     /** Record of configured Brooklyn entities (and templates and policies) 
which can be loaded */
     BrooklynCatalog getCatalog();
 
+    /** Returns the class loader to be used to load items. 
+     * Temporary routine while catalog supports classloader-based and 
OSGi-based classloading. */
+    @Beta
+    ClassLoader getCatalogClassLoader();
+
     LocationManager getLocationManager();
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java 
b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
index 375b29e..2e31532 100644
--- a/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
+++ b/core/src/main/java/brooklyn/catalog/internal/BasicBrooklynCatalog.java
@@ -112,6 +112,7 @@ public class BasicBrooklynCatalog implements 
BrooklynCatalog {
     private CatalogDo catalog;
     private volatile CatalogDo manualAdditionsCatalog;
     private volatile LoadedClassLoader manualAdditionsClasses;
+    private final AggregateClassLoader rootClassLoader = 
AggregateClassLoader.newInstanceWithNoLoaders();
 
     public BasicBrooklynCatalog(ManagementContext mgmt) {
         this(mgmt, CatalogDto.newNamedInstance("empty catalog", "empty 
catalog", "empty catalog, expected to be reset later"));
@@ -143,6 +144,7 @@ public class BasicBrooklynCatalog implements 
BrooklynCatalog {
         catalog.load(mgmt, null);
         CatalogUtils.logDebugOrTraceIfRebinding(log, "Reloaded catalog for 
"+this+", now switching");
         this.catalog = catalog;
+        resetRootClassLoader();
         this.manualAdditionsCatalog = null;
 
         // Inject management context into and persist all the new entries.
@@ -295,7 +297,14 @@ public class BasicBrooklynCatalog implements 
BrooklynCatalog {
     
     @Override
     public ClassLoader getRootClassLoader() {
-        return catalog.getRootClassLoader();
+        if (rootClassLoader.isEmpty() && catalog!=null) {
+            resetRootClassLoader();
+        }
+        return rootClassLoader;
+    }
+
+    private void resetRootClassLoader() {
+        rootClassLoader.reset(ImmutableList.of(catalog.getRootClassLoader()));
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java 
b/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
index 69dc877..1710384 100644
--- a/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
+++ b/core/src/main/java/brooklyn/catalog/internal/CatalogInitialization.java
@@ -21,12 +21,10 @@ package brooklyn.catalog.internal;
 import java.io.File;
 import java.util.Collection;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.CatalogItem;
 import brooklyn.config.BrooklynServerConfig;
 import brooklyn.management.ManagementContext;
@@ -45,6 +43,7 @@ import brooklyn.util.text.Strings;
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 
 @Beta
@@ -79,12 +78,14 @@ public class CatalogInitialization implements 
ManagementContextInjectable {
 
     boolean disallowLocal = false;
     List<Function<CatalogInitialization, Void>> callbacks = MutableList.of();
-    AtomicInteger runCount = new AtomicInteger();
+    boolean hasRunBestEffort = false, hasRunOfficial = false, isPopulating = 
false;
     
     ManagementContext managementContext;
     boolean isStartingUp = false;
     boolean failOnStartupErrors = false;
     
+    Object mutex = new Object();
+    
     public CatalogInitialization(String initialUri, boolean reset, String 
additionUri, boolean force) {
         this.initialUri = initialUri;
         this.reset = reset;
@@ -115,36 +116,31 @@ public class CatalogInitialization implements 
ManagementContextInjectable {
         return reset;
     }
 
-    public int getRunCount() {
-        return runCount.get();
-    }
-    
-    public boolean hasRun() {
-        return getRunCount()>0;
-    }
+    public boolean hasRunOfficial() { return hasRunOfficial; }
+    public boolean hasRunIncludingBestEffort() { return hasRunOfficial || 
hasRunBestEffort; }
 
     /** makes or updates the mgmt catalog, based on the settings in this class 
*/
     public void populateCatalog(boolean needsInitial, 
Collection<CatalogItem<?, ?>> optionalItemsForResettingCatalog) {
         try {
-            BasicBrooklynCatalog catalog;
-            Maybe<BrooklynCatalog> cm = 
((ManagementContextInternal)managementContext).getCatalogIfSet();
-            if (cm.isAbsent()) {
-                if (hasRun()) {
-                    log.warn("Catalog initialization has already run but 
management context has no catalog; re-creating");
-                }
-                catalog = new BasicBrooklynCatalog(managementContext);
-                setCatalog(managementContext, catalog, "Replacing catalog with 
newly populated catalog", true);
-            } else {
-                if (!hasRun()) {
-                    log.warn("Catalog initialization has not properly run but 
management context has a catalog; re-populating, possibly overwriting items 
installed during earlier access (it may have been an early web request)");
+            isPopulating = true;
+            synchronized (mutex) {
+                BasicBrooklynCatalog catalog = (BasicBrooklynCatalog) 
managementContext.getCatalog();
+                if (!catalog.getCatalog().isLoaded()) {
+                    catalog.load();
+                } else {
+                    if (hasRunOfficial || hasRunBestEffort) {
+                        // an indication that something caused it to load 
early; not severe, but unusual
+                        log.warn("Catalog initialization has not properly run 
but management context has a catalog; re-populating, possibly overwriting items 
installed during earlier access (it may have been an early web request)");
+                        catalog.reset(ImmutableList.<CatalogItem<?,?>>of());
+                    }
                 }
-                catalog = (BasicBrooklynCatalog) cm.get();
-            }
+                hasRunOfficial = true;
 
-            populateCatalog(catalog, needsInitial, true, 
optionalItemsForResettingCatalog);
-            
+                populateCatalog(catalog, needsInitial, true, 
optionalItemsForResettingCatalog);
+            }
         } finally {
-            runCount.incrementAndGet();
+            hasRunOfficial = true;
+            isPopulating = false;
         }
     }
 
@@ -170,7 +166,7 @@ public class CatalogInitialization implements 
ManagementContextInjectable {
     
     protected void populateInitial(BasicBrooklynCatalog catalog) {
         if (disallowLocal) {
-            if (!hasRun()) {
+            if (!hasRunOfficial()) {
                 log.debug("CLI initial catalog not being read with 
disallow-local mode set.");
             }
             return;
@@ -278,24 +274,27 @@ public class CatalogInitialization implements 
ManagementContextInjectable {
         return problem;
     }
 
+    boolean hasRunAdditions = false;
     protected void populateAdditions(BasicBrooklynCatalog catalog) {
         if (Strings.isNonBlank(additionsUri)) {
             if (disallowLocal) {
-                if (!hasRun()) {
+                if (!hasRunAdditions) {
                     log.warn("CLI additions supplied but not supported in 
disallow-local mode; ignoring.");
                 }
                 return;
             }   
-            if (!hasRun()) {
+            if (!hasRunAdditions) {
                 log.debug("Adding to catalog from CLI: "+additionsUri+" 
(force: "+force+")");
             }
             Iterable<? extends CatalogItem<?, ?>> items = catalog.addItems(
                 new ResourceUtils(this).getResourceAsString(additionsUri), 
force);
             
-            if (!hasRun())
+            if (!hasRunAdditions)
                 log.debug("Added to catalog from CLI: "+items);
             else
                 log.debug("Added to catalog from CLI: count 
"+Iterables.size(items));
+            
+            hasRunAdditions = true;
         }
     }
 
@@ -332,43 +331,22 @@ public class CatalogInitialization implements 
ManagementContextInjectable {
 
     /** makes the catalog, warning if persistence is on and hasn't run yet 
      * (as the catalog will be subsequently replaced) */
-    @Beta
-    public BrooklynCatalog getCatalogPopulatingBestEffort() {
-        Maybe<BrooklynCatalog> cm = 
((ManagementContextInternal)managementContext).getCatalogIfSet();
-        if (cm.isPresent()) return cm.get();
-
-        BrooklynCatalog oldC = setCatalog(managementContext, new 
BasicBrooklynCatalog(managementContext),
-            "Request to make local catalog early, but someone else has created 
it, reverting to that", false);
-        if (oldC==null) {
-            // our catalog was added, so run population
-            // NB: we need the catalog to be saved already so that we can run 
callbacks
-            populateCatalog((BasicBrooklynCatalog) 
managementContext.getCatalog(), true, true, null);
-        }
-        
-        return managementContext.getCatalog();
-    }
-
-    /** Sets the catalog in the given management context, warning and choosing 
appropriately if one already exists. 
-     * Returns any previously existing catalog (whether or not changed). */
-    @Beta
-    public static BrooklynCatalog setCatalog(ManagementContext 
managementContext, BrooklynCatalog catalog, String messageIfAlready, boolean 
preferNew) {
-        Maybe<BrooklynCatalog> cm;
-        synchronized (managementContext) {
-            cm = 
((ManagementContextInternal)managementContext).getCatalogIfSet();
-            if (cm.isAbsent()) {
-                
((ManagementContextInternal)managementContext).setCatalog(catalog);
-                return null;
-            }
-            if (preferNew) {
-                // set to null first to prevent errors
-                
((ManagementContextInternal)managementContext).setCatalog(null);
-                
((ManagementContextInternal)managementContext).setCatalog(catalog);
+    public void populateBestEffort(BasicBrooklynCatalog catalog) {
+        synchronized (mutex) {
+            if (hasRunOfficial || hasRunBestEffort || isPopulating) return;
+            // if a thread calls back in to this, ie calling to it from a 
getCatalog() call while populating,
+            // it will own the mutex and observe isRunningBestEffort, 
returning quickly 
+            isPopulating = true;
+            try {
+                if (isStartingUp) {
+                    log.warn("Catalog access requested when not yet 
initialized; populating best effort rather than through recommended pathway. 
Catalog data may be replaced subsequently.");
+                }
+                populateCatalog(catalog, true, true, null);
+            } finally {
+                hasRunBestEffort = true;
+                isPopulating = false;
             }
         }
-        if (Strings.isNonBlank(messageIfAlready)) {
-            log.warn(messageIfAlready);
-        }
-        return cm.get();
     }
 
     public void setStartingUp(boolean isStartingUp) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java 
b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
index 13d02e8..3355851 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindIteration.java
@@ -350,7 +350,7 @@ public abstract class RebindIteration {
         Collection<CatalogItem<?,?>> itemsForResettingCatalog = null;
         boolean needsInitialCatalog;
         if (rebindManager.persistCatalogItemsEnabled) {
-            if (!catInit.hasRun() && catInit.isInitialResetRequested()) {
+            if (!catInit.hasRunOfficial() && 
catInit.isInitialResetRequested()) {
                 String message = "RebindManager resetting catalog on first run 
(catalog persistence enabled, but reset explicitly specified). ";
                 if (catalogItems.isEmpty()) {
                     message += "Catalog was empty anyway.";
@@ -371,7 +371,7 @@ public abstract class RebindIteration {
                     itemsForResettingCatalog = rebindContext.getCatalogItems();
                     needsInitialCatalog = false;
                 } else {
-                    if (catInit.hasRun()) {
+                    if (catInit.hasRunOfficial()) {
                         logRebindingDebug("RebindManager will re-add any new 
items (persisted state empty)");
                         needsInitialCatalog = false;
                     } else {
@@ -381,7 +381,7 @@ public abstract class RebindIteration {
                 }
             }
         } else {
-            if (catInit.hasRun()) {
+            if (catInit.hasRunOfficial()) {
                 logRebindingDebug("RebindManager skipping catalog init because 
it has already run (catalog persistence disabled)");
                 needsInitialCatalog = false;
             } else {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java 
b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
index a31c1de..71d5218 100644
--- a/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
+++ b/core/src/main/java/brooklyn/entity/rebind/RebindManagerImpl.java
@@ -371,7 +371,7 @@ public class RebindManagerImpl implements RebindManager {
         
     public void rebindPartialActive(CompoundTransformer transformer, 
Iterator<BrooklynObject> objectsToRebind) {
         final ClassLoader classLoader = 
-            managementContext.getCatalog().getRootClassLoader();
+            managementContext.getCatalogClassLoader();
         // TODO we might want different exception handling for partials;
         // failure at various points should leave proxies in a sensible state,
         // either pointing at old or at new, though this is relatively 
untested,
@@ -474,7 +474,7 @@ public class RebindManagerImpl implements RebindManager {
     @Override
     public List<Application> rebind(ClassLoader classLoaderO, 
RebindExceptionHandler exceptionHandlerO, ManagementNodeState modeO) {
         final ClassLoader classLoader = classLoaderO!=null ? classLoaderO :
-            managementContext.getCatalog().getRootClassLoader();
+            managementContext.getCatalogClassLoader();
         final RebindExceptionHandler exceptionHandler = 
exceptionHandlerO!=null ? exceptionHandlerO :
             RebindExceptionHandlerImpl.builder()
                 .danglingRefFailureMode(danglingRefFailureMode)

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java
 
b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java
index 24a2d38..8a76833 100644
--- 
a/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java
+++ 
b/core/src/main/java/brooklyn/entity/rebind/persister/BrooklynPersistenceUtils.java
@@ -107,7 +107,7 @@ public class BrooklynPersistenceUtils {
         BrooklynMementoPersisterToObjectStore persister = new 
BrooklynMementoPersisterToObjectStore(
             destinationObjectStore,
             
((ManagementContextInternal)managementContext).getBrooklynProperties(),
-            managementContext.getCatalog().getRootClassLoader());
+            managementContext.getCatalogClassLoader());
         PersistenceExceptionHandler exceptionHandler = 
PersistenceExceptionHandlerImpl.builder().build();
         persister.enableWriteAccess();
         persister.checkpoint(memento, exceptionHandler);
@@ -117,7 +117,7 @@ public class BrooklynPersistenceUtils {
             PersistenceObjectStore destinationObjectStore) {
         if (optionalPlaneRecord != null) {
             ManagementPlaneSyncRecordPersisterToObjectStore 
managementPersister = new ManagementPlaneSyncRecordPersisterToObjectStore(
-                    managementContext, destinationObjectStore, 
managementContext.getCatalog().getRootClassLoader());
+                    managementContext, destinationObjectStore, 
managementContext.getCatalogClassLoader());
             managementPersister.checkpoint(optionalPlaneRecord);
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/core/src/main/java/brooklyn/location/basic/BasicLocationRegistry.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/location/basic/BasicLocationRegistry.java 
b/core/src/main/java/brooklyn/location/basic/BasicLocationRegistry.java
index c59298b..2b1980c 100644
--- a/core/src/main/java/brooklyn/location/basic/BasicLocationRegistry.java
+++ b/core/src/main/java/brooklyn/location/basic/BasicLocationRegistry.java
@@ -149,7 +149,7 @@ public class BasicLocationRegistry implements 
LocationRegistry {
     }
 
     protected void findServices() {
-        ServiceLoader<LocationResolver> loader = 
ServiceLoader.load(LocationResolver.class, 
mgmt.getCatalog().getRootClassLoader());
+        ServiceLoader<LocationResolver> loader = 
ServiceLoader.load(LocationResolver.class, mgmt.getCatalogClassLoader());
         for (LocationResolver r: loader) {
             registerResolver(r);
         }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/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
index 29e07af..ebc2329 100644
--- 
a/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java
+++ 
b/core/src/main/java/brooklyn/management/classloading/JavaBrooklynClassLoadingContext.java
@@ -69,7 +69,7 @@ public class JavaBrooklynClassLoadingContext extends 
AbstractBrooklynClassLoadin
     
     private ClassLoader getClassLoader() {
         if (loader != null) return loader;
-        if (mgmt!=null) return mgmt.getCatalog().getRootClassLoader();
+        if (mgmt!=null) return mgmt.getCatalogClassLoader();
         return JavaBrooklynClassLoadingContext.class.getClassLoader();
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java 
b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
index b004f6b..70bb13d 100644
--- a/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
+++ b/core/src/main/java/brooklyn/management/ha/HighAvailabilityManagerImpl.java
@@ -814,7 +814,7 @@ public class HighAvailabilityManagerImpl implements 
HighAvailabilityManager {
         setInternalNodeState(ManagementNodeState.MASTER);
         publishPromotionToMaster();
         try {
-            
managementContext.getRebindManager().rebind(managementContext.getCatalog().getRootClassLoader(),
 null, getInternalNodeState());
+            
managementContext.getRebindManager().rebind(managementContext.getCatalogClassLoader(),
 null, getInternalNodeState());
         } catch (Exception e) {
             LOG.error("Management node 
"+managementContext.getManagementNodeId()+" enountered problem during rebind 
when promoting self to master; demoting to FAILED and rethrowing: "+e);
             demoteTo(ManagementNodeState.FAILED);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
 
b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
index 8ff6dfc..1cbe312 100644
--- 
a/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
+++ 
b/core/src/main/java/brooklyn/management/internal/AbstractManagementContext.java
@@ -148,7 +148,7 @@ public abstract class AbstractManagementContext implements 
ManagementContextInte
 
     protected BrooklynProperties configMap;
     protected BasicLocationRegistry locationRegistry;
-    protected volatile BasicBrooklynCatalog catalog;
+    protected final BasicBrooklynCatalog catalog;
     protected ClassLoader baseClassLoader;
     protected Iterable<URL> baseClassPathForScanning;
 
@@ -183,7 +183,9 @@ public abstract class AbstractManagementContext implements 
ManagementContextInte
             datagridFactory = loadDataGridFactory(brooklynProperties);
         }
         DataGrid datagrid = datagridFactory.newDataGrid(this);
-         
+
+        this.catalog = new BasicBrooklynCatalog(this);
+        
         this.storage = new BrooklynStorageImpl(datagrid);
         this.rebindManager = new RebindManagerImpl(this); // TODO leaking 
"this" reference; yuck
         this.highAvailabilityManager = new HighAvailabilityManagerImpl(this); 
// TODO leaking "this" reference; yuck
@@ -359,28 +361,20 @@ public abstract class AbstractManagementContext 
implements ManagementContextInte
     }
 
     @Override
-    public Maybe<BrooklynCatalog> getCatalogIfSet() {
-        return Maybe.<BrooklynCatalog>fromNullable(catalog);
-    }
-
-    @Override
-    public void setCatalog(BrooklynCatalog catalog) {
-        if (this.catalog!=null && catalog!=null) {
-            // should only happen if process has accessed catalog before 
rebind/startup populated it
-            log.warn("Replacing catalog in management context; new catalog is: 
"+catalog);
+    public BrooklynCatalog getCatalog() {
+        if (!getCatalogInitialization().hasRunIncludingBestEffort()) {
+            // catalog init is needed; normally this will be done from start 
sequence,
+            // but if accessed early -- and in tests -- we will load it here
+            getCatalogInitialization().injectManagementContext(this);
+            getCatalogInitialization().populateBestEffort(catalog);
         }
-        this.catalog = (BasicBrooklynCatalog) catalog;
+        return catalog;
     }
-
+    
     @Override
-    public BrooklynCatalog getCatalog() {
-        if (catalog!=null) 
-            return catalog;
-        
-        // catalog init is needed; normally this will be done from start 
sequence,
-        // but if accessed early -- and in tests -- we will load it here
-        // TODO log if in launcher mode
-        return getCatalogInitialization().getCatalogPopulatingBestEffort();
+    public ClassLoader getCatalogClassLoader() {
+        // catalog does not have to be initialized
+        return catalog.getRootClassLoader();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
 
b/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
index d5123a6..20f9113 100644
--- 
a/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
+++ 
b/core/src/main/java/brooklyn/management/internal/ManagementContextInternal.java
@@ -24,7 +24,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
 
-import brooklyn.catalog.BrooklynCatalog;
 import brooklyn.catalog.internal.CatalogInitialization;
 import brooklyn.config.BrooklynProperties;
 import brooklyn.entity.Effector;
@@ -119,11 +118,4 @@ public interface ManagementContextInternal extends 
ManagementContext {
     @Beta
     void setCatalogInitialization(CatalogInitialization catalogInitialization);
 
-    @Beta
-    public Maybe<BrooklynCatalog> getCatalogIfSet();
-    
-    /** For use from {@link CatalogInitialization} to set the catalog */
-    @Beta
-    public void setCatalog(BrooklynCatalog catalog);
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
 
b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
index 77eb4de..00639a5 100644
--- 
a/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
+++ 
b/core/src/main/java/brooklyn/management/internal/NonDeploymentManagementContext.java
@@ -35,7 +35,6 @@ import org.slf4j.LoggerFactory;
 
 import brooklyn.basic.BrooklynObject;
 import brooklyn.catalog.BrooklynCatalog;
-import brooklyn.catalog.internal.BasicBrooklynCatalog;
 import brooklyn.catalog.internal.CatalogInitialization;
 import brooklyn.config.BrooklynProperties;
 import brooklyn.config.StringConfigMap;
@@ -75,7 +74,6 @@ import brooklyn.mementos.BrooklynMementoRawData;
 import brooklyn.util.guava.Maybe;
 import brooklyn.util.time.Duration;
 
-import com.google.common.annotations.Beta;
 import com.google.common.base.Objects;
 
 public class NonDeploymentManagementContext implements 
ManagementContextInternal {
@@ -324,6 +322,12 @@ public class NonDeploymentManagementContext implements 
ManagementContextInternal
     }
     
     @Override
+    public ClassLoader getCatalogClassLoader() {
+        checkInitialManagementContextReal();
+        return initialManagementContext.getCatalogClassLoader();
+    }
+    
+    @Override
     public EntitlementManager getEntitlementManager() {
         return entitlementManager;
     }
@@ -462,19 +466,6 @@ public class NonDeploymentManagementContext implements 
ManagementContextInternal
         
initialManagementContext.setCatalogInitialization(catalogInitialization);
     }
 
-    @Override
-    public Maybe<BrooklynCatalog> getCatalogIfSet() {
-        checkInitialManagementContextReal();
-        return initialManagementContext.getCatalogIfSet();
-    }
-    
-    /** For use from {@link CatalogInitialization} to set the catalog */
-    @Beta @Override
-    public void setCatalog(BrooklynCatalog catalog) {
-        checkInitialManagementContextReal();
-        initialManagementContext.setCatalog(catalog);
-    }
-    
     /**
      * For when the initial management context is not "real"; the 
changeListener is a no-op, but everything else forbidden.
      * 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
----------------------------------------------------------------------
diff --git 
a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
 
b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
index 698731b..45019d5 100644
--- 
a/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
+++ 
b/locations/jclouds/src/main/java/brooklyn/location/jclouds/JcloudsLocation.java
@@ -321,7 +321,7 @@ public class JcloudsLocation extends 
AbstractCloudMachineProvisioningLocation im
     protected CloudMachineNamer getCloudMachineNamer(ConfigBag config) {
         String namerClass = 
config.get(LocationConfigKeys.CLOUD_MACHINE_NAMER_CLASS);
         if (Strings.isNonBlank(namerClass)) {
-            Optional<CloudMachineNamer> cloudNamer = 
Reflections.invokeConstructorWithArgs(getManagementContext().getCatalog().getRootClassLoader(),
 namerClass, config);
+            Optional<CloudMachineNamer> cloudNamer = 
Reflections.invokeConstructorWithArgs(getManagementContext().getCatalogClassLoader(),
 namerClass, config);
             if (cloudNamer.isPresent()) {
                 return cloudNamer.get();
             } else {
@@ -341,7 +341,7 @@ public class JcloudsLocation extends 
AbstractCloudMachineProvisioningLocation im
         @SuppressWarnings("deprecation")
         String customizersSupplierType = 
setup.get(JCLOUDS_LOCATION_CUSTOMIZERS_SUPPLIER_TYPE);
 
-        ClassLoader catalogClassLoader = 
getManagementContext().getCatalog().getRootClassLoader();
+        ClassLoader catalogClassLoader = 
getManagementContext().getCatalogClassLoader();
         List<JcloudsLocationCustomizer> result = new 
ArrayList<JcloudsLocationCustomizer>();
         if (customizer != null) result.add(customizer);
         if (customizers != null) result.addAll(customizers);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/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 618d4a3..492ef65 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,7 +28,6 @@ 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;
@@ -121,7 +120,7 @@ public class BrooklynComponentTemplateResolver {
             if (type.indexOf(':') != -1) {
                 String prefix = Splitter.on(":").splitToList(type).get(0);
                 ServiceLoader<ServiceTypeResolver> loader = 
ServiceLoader.load(ServiceTypeResolver.class,
-                        
context.getManagementContext().getCatalog().getRootClassLoader());
+                        
context.getManagementContext().getCatalogClassLoader());
                 for (ServiceTypeResolver resolver : loader) {
                    if (prefix.equals(resolver.getTypePrefix())) {
                        return resolver;
@@ -220,7 +219,7 @@ public class BrooklynComponentTemplateResolver {
         return spec;
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @SuppressWarnings({ "unchecked" })
     protected <T extends Entity> EntitySpec<T> createSpec(Set<String> 
encounteredCatalogTypes) {
         CatalogItem<Entity, EntitySpec<?>> item = 
getServiceTypeResolver().getCatalogItem(this, getDeclaredType());
         if (encounteredCatalogTypes==null) encounteredCatalogTypes = 
MutableSet.of();
@@ -258,6 +257,7 @@ public class BrooklynComponentTemplateResolver {
         }
     }
     
+    @SuppressWarnings("unchecked")
     protected <T extends Entity> EntitySpec<T> createSpecFromJavaType() {
         Class<T> type = (Class<T>) loadEntityClass();
         
@@ -267,6 +267,7 @@ public class BrooklynComponentTemplateResolver {
         } else {
             // If this is a concrete class, particularly for an Application 
class, we want the proxy
             // to expose all interfaces it implements.
+            @SuppressWarnings("rawtypes")
             Class interfaceclazz = (Application.class.isAssignableFrom(type)) 
? Application.class : Entity.class;
             List<Class<?>> additionalInterfaceClazzes = 
Reflections.getAllInterfaces(type);
             spec = 
EntitySpec.create(interfaceclazz).impl(type).additionalInterfaces(additionalInterfaceClazzes);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
----------------------------------------------------------------------
diff --git 
a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java 
b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
index 71f53a5..3a87087 100644
--- a/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
+++ b/usage/launcher/src/main/java/brooklyn/launcher/BrooklynLauncher.java
@@ -598,7 +598,7 @@ public class BrooklynLauncher {
         try {
             // run cat init now if it hasn't yet been run; 
             // will also run if there was an ignored error in catalog above, 
allowing it to fail startup here if requested
-            if (catInit!=null && !catInit.hasRun()) {
+            if (catInit!=null && !catInit.hasRunOfficial()) {
                 LOG.debug("Loading catalog as part of launcher (persistence 
did not run it)");
                 catInit.populateCatalog(true, null);
             }
@@ -792,7 +792,7 @@ public class BrooklynLauncher {
                 BrooklynMementoPersisterToObjectStore persister = new 
BrooklynMementoPersisterToObjectStore(
                     objectStore,
                     
((ManagementContextInternal)managementContext).getBrooklynProperties(),
-                    managementContext.getCatalog().getRootClassLoader());
+                    managementContext.getCatalogClassLoader());
                 PersistenceExceptionHandler persistenceExceptionHandler = 
PersistenceExceptionHandlerImpl.builder().build();
                 ((RebindManagerImpl) 
rebindManager).setPeriodicPersistPeriod(persistPeriod);
                 rebindManager.setPersister(persister, 
persistenceExceptionHandler);
@@ -816,7 +816,8 @@ public class BrooklynLauncher {
             HighAvailabilityManager haManager = 
managementContext.getHighAvailabilityManager();
             ManagementPlaneSyncRecordPersister persister =
                 new 
ManagementPlaneSyncRecordPersisterToObjectStore(managementContext,
-                    objectStore, 
managementContext.getCatalog().getRootClassLoader());
+                    objectStore,
+                    managementContext.getCatalogClassLoader());
             
((HighAvailabilityManagerImpl)haManager).setHeartbeatTimeout(haHeartbeatTimeoutOverride);
             
((HighAvailabilityManagerImpl)haManager).setPollPeriod(haHeartbeatPeriodOverride);
             haManager.setPersister(persister);
@@ -866,7 +867,7 @@ public class BrooklynLauncher {
         else
             LOG.info("Management node (no HA) rebinding to entities on file 
system in "+persistenceDir);
 
-        ClassLoader classLoader = 
managementContext.getCatalog().getRootClassLoader();
+        ClassLoader classLoader = managementContext.getCatalogClassLoader();
         try {
             rebindManager.rebind(classLoader, null, 
ManagementNodeState.MASTER);
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/usage/rest-server/src/main/java/brooklyn/rest/resources/ApplicationResource.java
----------------------------------------------------------------------
diff --git 
a/usage/rest-server/src/main/java/brooklyn/rest/resources/ApplicationResource.java
 
b/usage/rest-server/src/main/java/brooklyn/rest/resources/ApplicationResource.java
index 27a93a9..0144d56 100644
--- 
a/usage/rest-server/src/main/java/brooklyn/rest/resources/ApplicationResource.java
+++ 
b/usage/rest-server/src/main/java/brooklyn/rest/resources/ApplicationResource.java
@@ -404,7 +404,7 @@ public class ApplicationResource extends 
AbstractBrooklynRestResource implements
     private void checkEntityTypeIsValid(String type) {
         if (CatalogUtils.getCatalogItemOptionalVersion(mgmt(), type) == null) {
             try {
-                brooklyn().getCatalog().getRootClassLoader().loadClass(type);
+                brooklyn().getCatalogClassLoader().loadClass(type);
             } catch (ClassNotFoundException e) {
                 log.debug("Class not found for type '" + type + "'; reporting 
404", e);
                 throw WebResourceUtils.notFound("Undefined type '%s'", type);

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityResource.java
----------------------------------------------------------------------
diff --git 
a/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityResource.java 
b/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityResource.java
index 5572121..3e94068 100644
--- 
a/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityResource.java
+++ 
b/usage/rest-server/src/main/java/brooklyn/rest/resources/EntityResource.java
@@ -170,7 +170,7 @@ public class EntityResource extends 
AbstractBrooklynRestResource implements Enti
             // paths (ie non-protocol) and
             // NB, for security, file URL's are NOT served
             MediaType mime = 
WebResourceUtils.getImageMediaTypeFromExtension(Files.getFileExtension(url));
-            Object content = 
ResourceUtils.create(brooklyn().getCatalog().getRootClassLoader()).getResourceFromUrl(url);
+            Object content = 
ResourceUtils.create(brooklyn().getCatalogClassLoader()).getResourceFromUrl(url);
             return Response.ok(content, mime).build();
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
----------------------------------------------------------------------
diff --git 
a/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
 
b/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
index 2dbed30..c3499b8 100644
--- 
a/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
+++ 
b/usage/rest-server/src/main/java/brooklyn/rest/util/BrooklynRestResourceUtils.java
@@ -95,6 +95,10 @@ public class BrooklynRestResourceUtils {
         return mgmt.getCatalog();
     }
     
+    public ClassLoader getCatalogClassLoader() {
+        return mgmt.getCatalogClassLoader();
+    }
+    
     public LocationRegistry getLocationRegistry() {
         return mgmt.getLocationRegistry();
     }

http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/ddbb43c6/utils/common/src/main/java/brooklyn/util/javalang/AggregateClassLoader.java
----------------------------------------------------------------------
diff --git 
a/utils/common/src/main/java/brooklyn/util/javalang/AggregateClassLoader.java 
b/utils/common/src/main/java/brooklyn/util/javalang/AggregateClassLoader.java
index 07af10a..1a5dd93 100644
--- 
a/utils/common/src/main/java/brooklyn/util/javalang/AggregateClassLoader.java
+++ 
b/utils/common/src/main/java/brooklyn/util/javalang/AggregateClassLoader.java
@@ -20,6 +20,7 @@ package brooklyn.util.javalang;
 
 import java.io.IOException;
 import java.net.URL;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
@@ -34,7 +35,7 @@ import com.google.common.collect.Sets;
  * exposing more info, a few conveniences, and a nice toString */
 public class AggregateClassLoader extends ClassLoader {
 
-    private final List<ClassLoader> classLoaders = new 
CopyOnWriteArrayList<ClassLoader>();
+    private final CopyOnWriteArrayList<ClassLoader> classLoaders = new 
CopyOnWriteArrayList<ClassLoader>();
 
     private AggregateClassLoader() {
         //Don't pass load requests to the app classloader,
@@ -69,8 +70,25 @@ public class AggregateClassLoader extends ClassLoader {
         if (classLoader != null) classLoaders.add(index, classLoader);
     }
     
-    /** Returns the _live_ (and modifiable) list of classloaders 
-     * @return */ 
+    /** Resets the classloader shown here to be the given set */
+    public void reset(Collection<? extends ClassLoader> newClassLoaders) {
+        synchronized (classLoaders) {
+            int count = classLoaders.size();
+            classLoaders.addAll(newClassLoaders);
+            for (int i=0; i<count; i++) {
+                classLoaders.remove(0);
+            }
+        }
+    }
+
+    /** True if nothing is in the list here */
+    public boolean isEmpty() {
+        return classLoaders.isEmpty();
+    }
+    
+    /** Returns the _live_ (and modifiable) list of classloaders; dangerous 
and discouraged. 
+     * @deprecated since 0.7.0 */
+    @Deprecated
     public List<ClassLoader> getList() {
         return classLoaders;
     }


Reply via email to