You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2021/12/03 14:07:34 UTC
[brooklyn-server] branch master updated: don't allow bundles to be activated to provide classes we need
This is an automated email from the ASF dual-hosted git repository.
heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
The following commit(s) were added to refs/heads/master by this push:
new d48d92b don't allow bundles to be activated to provide classes we need
d48d92b is described below
commit d48d92b4727d462571a62a6969e6020e1408bbf7
Author: Alex Heneveld <al...@cloudsoftcorp.com>
AuthorDate: Fri Dec 3 14:04:45 2021 +0000
don't allow bundles to be activated to provide classes we need
this prevents persisted bundles being upgraded from being resolved (and failing sometimes)
where they (might) contain a class being referenced by the initial catalog
add'l fix for fix 2d20fffa2407e4da48fe6edeebc3335e140edccb from 2021-09-14
---
.../catalog/internal/CatalogInitialization.java | 5 +-
.../brooklyn/util/core/ClassLoaderUtils.java | 21 ++++--
.../brooklyn/util/core/ClassLoaderUtilsTest.java | 81 +++++++++++-----------
3 files changed, 63 insertions(+), 44 deletions(-)
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
index b65e1c7..8ff5180 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
@@ -258,6 +258,9 @@ public class CatalogInitialization implements ManagementContextInjectable {
// so that OSGi unique IDs might be picked up when initial catalog is populated
Map<InstallableManagedBundle, OsgiBundleInstallationResult> persistenceInstalls = installPersistedBundlesDontStart(persistedState.getBundles(), exceptionHandler, rebindLogger);
+ // now we install and start the bundles from the catalog;
+ // 2021-12-03 now this only will look for classes in active bundles, so it won't resolve persisted bundles
+ // and we can safely filter them out later
populateInitialCatalogImpl(true);
final Maybe<OsgiManager> maybesOsgiManager = managementContext.getOsgiManager();
@@ -274,7 +277,7 @@ public class CatalogInitialization implements ManagementContextInjectable {
PersistedCatalogState filteredPersistedState = filterBundlesAndCatalogInPersistedState(persistedState, rebindLogger);
- // previously we effectively installed here, after populating; but now we do it before and then uninstall if needed, to preserve IDs
+ // 2021-09-14 previously we effectively installed here, after populating; but now we do it earlier and then uninstall if needed, to preserve IDs
// Map<InstallableManagedBundle, OsgiBundleInstallationResult> persistenceInstalls = installPersistedBundlesDontStart(filteredPersistedState.getBundles(), exceptionHandler, rebindLogger);
try {
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java b/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java
index c8011b9..5d446d5 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java
@@ -40,6 +40,7 @@ import org.apache.brooklyn.core.mgmt.ha.OsgiManager;
import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
import org.apache.brooklyn.core.typereg.BundleUpgradeParser.CatalogUpgrades;
import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.core.LoaderDispatcher.ClassLoaderDispatcher;
import org.apache.brooklyn.util.core.LoaderDispatcher.MultipleResourceLoaderDispatcher;
import org.apache.brooklyn.util.core.LoaderDispatcher.ResourceLoaderDispatcher;
@@ -457,14 +458,26 @@ public class ClassLoaderUtils {
}
List<Bundle> bundles = Osgis.bundleFinder(framework)
.satisfying(createBundleMatchingPredicate())
+ .satisfying(b -> b.getState() == Bundle.ACTIVE) // 2021-12-03 we now require them to be started, to prevent activation of persisted bundles too early
.findAll();
+ Map<Bundle,Throwable> errors = MutableMap.of();
for (Bundle b : bundles) {
- Maybe<T> item = dispatcher.tryLoadFrom(b, className);
- if (item.isPresent()) {
- return item;
+ try {
+ Maybe<T> item = dispatcher.tryLoadFrom(b, className);
+ if (item.isPresent()) {
+ return item;
+ }
+ } catch (Exception e) {
+ // silently ignore
+ log.debug("Skipping bundle "+b+" for search of "+className+" due to: "+e);
+ if (log.isTraceEnabled()) log.trace("Stack trace details", e);
+ errors.put(b, e);
}
}
- return Maybe.absentNull();
+ return Maybe.absent(() -> {
+ if (errors.isEmpty()) return new IllegalStateException("Unable to find class '"+className+"' in whitelisted bundles");
+ return Exceptions.propagate("Unable to find class '"+className+"' in whitelisted bundles, with errors in bundles "+errors.keySet(), errors.values());
+ });
}
protected WhiteListBundlePredicate createBundleMatchingPredicate() {
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/ClassLoaderUtilsTest.java b/core/src/test/java/org/apache/brooklyn/util/core/ClassLoaderUtilsTest.java
index 1a6da26..db90666 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/ClassLoaderUtilsTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/ClassLoaderUtilsTest.java
@@ -108,7 +108,7 @@ public class ClassLoaderUtilsTest {
TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), bundlePath);
mgmt = LocalManagementContextForTests.builder(true).enableOsgiReusable().build();
- Bundle bundle = installBundle(mgmt, bundleUrl);
+ Bundle bundle = installBundle(mgmt, bundleUrl, false /* this works without starting it */);
@SuppressWarnings("unchecked")
Class<? extends Entity> clazz = (Class<? extends Entity>) bundle.loadClass(classname);
Entity entity = createSimpleEntity(bundleUrl, clazz);
@@ -129,153 +129,154 @@ public class ClassLoaderUtilsTest {
String bundlePath = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
String bundleUrl = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL;
String classname = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_ENTITY;
-
+
TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), bundlePath);
mgmt = LocalManagementContextForTests.builder(true).enableOsgiReusable().build();
- Bundle bundle = installBundle(mgmt, bundleUrl);
+ Bundle bundle = installBundle(mgmt, bundleUrl, false /* this works without starting it */);
Class<?> clazz = bundle.loadClass(classname);
Entity entity = createSimpleEntity(bundleUrl, clazz);
-
+
String whiteList = bundle.getSymbolicName()+":"+bundle.getVersion();
System.setProperty(ClassLoaderUtils.WHITE_LIST_KEY, whiteList);
-
+
ClassLoaderUtils cluEntity = new ClassLoaderUtils(getClass(), entity);
BundledName resource = new BundledName(classname).toResource();
BundledName bn = new BundledName(resource.bundle, resource.version, "/" + resource.name);
Asserts.assertSize(cluEntity.getResources(bn.toString()), 1);
}
-
+
@Test
public void testVariousLoadersLoadClassInOsgiWhiteList() throws Exception {
String bundlePath = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
String bundleUrl = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL;
String classname = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_ENTITY;
-
+
TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), bundlePath);
mgmt = LocalManagementContextForTests.builder(true).enableOsgiReusable().build();
- Bundle bundle = installBundle(mgmt, bundleUrl);
+ Bundle bundle = installBundle(mgmt, bundleUrl, true);
+
Class<?> clazz = bundle.loadClass(classname);
Entity entity = createSimpleEntity(bundleUrl, clazz);
-
+
String whiteList = bundle.getSymbolicName()+":"+bundle.getVersion();
System.setProperty(ClassLoaderUtils.WHITE_LIST_KEY, whiteList);
-
+
ClassLoaderUtils cluMgmt = new ClassLoaderUtils(getClass(), mgmt);
ClassLoaderUtils cluClass = new ClassLoaderUtils(clazz);
ClassLoaderUtils cluEntity = new ClassLoaderUtils(getClass(), entity);
-
+
assertLoadSucceeds(classname, clazz, cluMgmt, cluClass, cluEntity);
assertLoadSucceeds(bundle.getSymbolicName() + ":" + classname, clazz, cluMgmt, cluClass, cluEntity);
}
-
+
@Test
public void testLoadClassInOsgiWhiteListWithInvalidBundlePresent() throws Exception {
String bundlePath = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH;
String bundleUrl = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL;
String classname = OsgiTestResources.BROOKLYN_TEST_OSGI_ENTITIES_SIMPLE_ENTITY;
-
+
TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), bundlePath);
mgmt = LocalManagementContextForTests.builder(true).enableOsgiReusable().build();
- Bundle bundle = installBundle(mgmt, bundleUrl);
-
+ Bundle bundle = installBundle(mgmt, bundleUrl, true);
+
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
JarOutputStream target = new JarOutputStream(buffer, manifest);
target.close();
-
+
OsgiManager osgiManager = ((ManagementContextInternal)mgmt).getOsgiManager().get();
Framework framework = osgiManager.getFramework();
Bundle installedBundle = framework.getBundleContext().installBundle("stream://invalid", new ByteArrayInputStream(buffer.toByteArray()));
assertNotNull(installedBundle);
-
+
Class<?> clazz = bundle.loadClass(classname);
Entity entity = createSimpleEntity(bundleUrl, clazz);
-
+
String whileList = bundle.getSymbolicName()+":"+bundle.getVersion();
System.setProperty(ClassLoaderUtils.WHITE_LIST_KEY, whileList);
-
+
ClassLoaderUtils cluMgmt = new ClassLoaderUtils(getClass(), mgmt);
ClassLoaderUtils cluClass = new ClassLoaderUtils(clazz);
ClassLoaderUtils cluEntity = new ClassLoaderUtils(getClass(), entity);
-
+
assertLoadSucceeds(classname, clazz, cluMgmt, cluClass, cluEntity);
assertLoadSucceeds(bundle.getSymbolicName() + ":" + classname, clazz, cluMgmt, cluClass, cluEntity);
}
-
+
@Test
public void testLoadClassInOsgiCore() throws Exception {
Class<?> clazz = BasicEntity.class;
String classname = clazz.getName();
-
+
mgmt = LocalManagementContextForTests.builder(true).enableOsgiReusable().build();
Bundle bundle = getBundle(mgmt, "org.apache.brooklyn.core");
String url = bundle.getLocation();
// NB: the above will be a system:file: url when running tests against target/classes/ -- but
// OSGi manager will accept that if running in dev mode
Entity entity = createSimpleEntity(url, clazz);
-
+
ClassLoaderUtils cluMgmt = new ClassLoaderUtils(getClass(), mgmt);
ClassLoaderUtils cluClass = new ClassLoaderUtils(clazz);
ClassLoaderUtils cluNone = new ClassLoaderUtils(getClass());
ClassLoaderUtils cluEntity = new ClassLoaderUtils(getClass(), entity);
-
+
assertLoadSucceeds(classname, clazz, cluMgmt, cluClass, cluNone, cluEntity);
assertLoadSucceeds(classname, clazz, cluMgmt, cluClass, cluNone, cluEntity);
assertLoadSucceeds(bundle.getSymbolicName() + ":" + classname, clazz, cluMgmt, cluClass, cluNone, cluEntity);
assertLoadSucceeds(bundle.getSymbolicName() + ":" + bundle.getVersion() + ":" + classname, clazz, cluMgmt, cluClass, cluNone, cluEntity);
}
-
+
@Test
public void testLoadClassInOsgiApi() throws Exception {
Class<?> clazz = Entity.class;
String classname = clazz.getName();
-
+
mgmt = LocalManagementContextForTests.builder(true).enableOsgiReusable().build();
Bundle bundle = getBundle(mgmt, "org.apache.brooklyn.api");
-
+
ClassLoaderUtils cluMgmt = new ClassLoaderUtils(getClass(), mgmt);
ClassLoaderUtils cluClass = new ClassLoaderUtils(clazz);
ClassLoaderUtils cluNone = new ClassLoaderUtils(getClass());
-
+
assertLoadSucceeds(classname, clazz, cluMgmt, cluClass, cluNone);
assertLoadSucceeds(classname, clazz, cluMgmt, cluClass, cluNone);
assertLoadSucceeds(bundle.getSymbolicName() + ":" + classname, clazz, cluMgmt, cluClass, cluNone);
assertLoadSucceeds(bundle.getSymbolicName() + ":" + bundle.getVersion() + ":" + classname, clazz, cluMgmt, cluClass, cluNone);
}
-
+
@Test
public void testIsBundleWhiteListed() throws Exception {
mgmt = LocalManagementContextForTests.builder(true).enableOsgiReusable().build();
ClassLoaderUtils clu = new ClassLoaderUtils(getClass(), mgmt);
-
+
assertTrue(clu.isBundleWhiteListed(getBundle(mgmt, "org.apache.brooklyn.core")));
assertTrue(clu.isBundleWhiteListed(getBundle(mgmt, "org.apache.brooklyn.api")));
assertFalse(clu.isBundleWhiteListed(getBundle(mgmt, "com.google.guava")));
}
-
+
/**
- * When two guava versions installed, want us to load from the *brooklyn* version rather than
+ * When two guava versions installed, want us to load from the *brooklyn* version rather than
* a newer version that happens to be in Karaf.
*/
@Test(groups={"Integration"})
public void testLoadsFromRightGuavaVersion() throws Exception {
mgmt = LocalManagementContextForTests.builder(true).enableOsgiReusable().build();
ClassLoaderUtils clu = new ClassLoaderUtils(getClass(), mgmt);
-
+
String bundleUrl = MavenRetriever.localUrl(MavenArtifact.fromCoordinate("com.google.guava:guava:jar:18.0"));
- Bundle bundle = installBundle(mgmt, bundleUrl);
+ Bundle bundle = installBundle(mgmt, bundleUrl, false /* this works without starting */);
String bundleName = bundle.getSymbolicName();
-
+
String classname = bundleName + ":" + ImmutableList.class.getName();
assertLoadSucceeds(clu, classname, ImmutableList.class);
}
-
+
@Test
public void testLoadBrooklynClass() throws Exception {
mgmt = LocalManagementContextForTests.builder(true).enableOsgiReusable().build();
@@ -310,11 +311,13 @@ public class ClassLoaderUtilsTest {
Asserts.expectedFailureContains(nested, "not found to load");
}
}
-
- private Bundle installBundle(ManagementContext mgmt, String bundleUrl) throws Exception {
+
+ private Bundle installBundle(ManagementContext mgmt, String bundleUrl, boolean start) throws Exception {
OsgiManager osgiManager = ((ManagementContextInternal)mgmt).getOsgiManager().get();
Framework framework = osgiManager.getFramework();
- return Osgis.install(framework, bundleUrl);
+ Bundle result = Osgis.install(framework, bundleUrl);
+ if (start) result.start();
+ return result;
}
private Bundle getBundle(ManagementContext mgmt, final String symbolicName) throws Exception {