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; }