Handle wrapped ClassNotFoundException And try not to wrap it!
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/77357873 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/77357873 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/77357873 Branch: refs/heads/master Commit: 77357873a1feec996cd6b3f8e98f01e6999c70ea Parents: 2654305 Author: Aled Sage <[email protected]> Authored: Thu Jul 7 23:05:38 2016 +0100 Committer: Aled Sage <[email protected]> Committed: Sat Jul 9 10:58:36 2016 +0100 ---------------------------------------------------------------------- ...ssLoaderFromBrooklynClassLoadingContext.java | 11 ++-- .../brooklyn/util/core/ClassLoaderUtils.java | 23 ++++--- ...aderFromBrooklynClassLoadingContextTest.java | 65 ++++++++++++++++++++ 3 files changed, 87 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/77357873/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContext.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContext.java index f36e2ac..35d3b05 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContext.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContext.java @@ -21,6 +21,7 @@ package org.apache.brooklyn.core.mgmt.classloading; import java.net.URL; import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; +import org.apache.brooklyn.util.guava.Maybe; public class ClassLoaderFromBrooklynClassLoadingContext extends ClassLoader { @@ -36,15 +37,15 @@ public class ClassLoaderFromBrooklynClassLoadingContext extends ClassLoader { } @Override - public Class<?> findClass(String className) throws ClassNotFoundException { - Class<?> result = clc.loadClass(className); - if (result!=null) return result; + protected Class<?> findClass(String className) throws ClassNotFoundException { + Maybe<Class<?>> result = clc.tryLoadClass(className); + if (result.isPresent()) return result.get(); // last resort. see comment in XStream CompositeClassLoader ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if (contextClassLoader != null) { - result = contextClassLoader.loadClass(className); - if (result!=null) return result; + Class<?> result2 = contextClassLoader.loadClass(className); + if (result2 != null) return result2; } return null; } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/77357873/core/src/main/java/org/apache/brooklyn/util/core/ClassLoaderUtils.java ---------------------------------------------------------------------- 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 b46f68d..b6d39e9 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 @@ -172,13 +172,7 @@ public class ClassLoaderUtils { try { return loader.loadClass(className); } catch (IllegalStateException e) { - ClassNotFoundException cnfe = Exceptions.getFirstThrowableOfType(e, ClassNotFoundException.class); - NoClassDefFoundError ncdfe = Exceptions.getFirstThrowableOfType(e, NoClassDefFoundError.class); - if (cnfe == null && ncdfe == null) { - throw e; - } else { - // ignore, fall back to Class.forName(...) - } + propagateIfCauseNotClassNotFound(e); } } else { log.warn("Entity " + entity + " refers to non-existent catalog item " + catalogItemId + ". Trying to load class " + name); @@ -196,12 +190,16 @@ public class ClassLoaderUtils { // Note that Class.forName(name, false, classLoader) doesn't seem to like us returning a // class with a different name from that intended (e.g. stripping off an OSGi prefix). return classLoader.loadClass(className); + } catch (IllegalStateException e) { + propagateIfCauseNotClassNotFound(e); } catch (ClassNotFoundException e) { } if (mgmt != null) { try { return mgmt.getCatalogClassLoader().loadClass(name); + } catch (IllegalStateException e) { + propagateIfCauseNotClassNotFound(e); } catch (ClassNotFoundException e) { } } @@ -214,6 +212,17 @@ public class ClassLoaderUtils { } } + protected void propagateIfCauseNotClassNotFound(IllegalStateException e) { + // TODO loadClass() should not throw IllegalStateException; should throw ClassNotFoundException without wrapping. + ClassNotFoundException cnfe = Exceptions.getFirstThrowableOfType(e, ClassNotFoundException.class); + NoClassDefFoundError ncdfe = Exceptions.getFirstThrowableOfType(e, NoClassDefFoundError.class); + if (cnfe == null && ncdfe == null) { + throw e; + } else { + // ignore, try next way of loading + } + } + public Class<?> loadClass(String symbolicName, @Nullable String version, String className) throws ClassNotFoundException { Framework framework = getFramework(); if (framework != null) { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/77357873/core/src/test/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContextTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContextTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContextTest.java new file mode 100644 index 0000000..997ff5c --- /dev/null +++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/classloading/ClassLoaderFromBrooklynClassLoadingContextTest.java @@ -0,0 +1,65 @@ +/* + * Copyright 2016 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.brooklyn.core.mgmt.classloading; + +import org.apache.brooklyn.api.catalog.CatalogItem; +import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; +import org.apache.brooklyn.api.typereg.OsgiBundleWithUrl; +import org.apache.brooklyn.core.entity.Entities; +import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; +import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.entity.stock.BasicApplication; +import org.apache.brooklyn.test.Asserts; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; + +public class ClassLoaderFromBrooklynClassLoadingContextTest { + + private LocalManagementContext mgmt; + private CatalogItem<?, ?> item; + private ClassLoaderFromBrooklynClassLoadingContext loader; + + @BeforeMethod(alwaysRun=true) + @SuppressWarnings("deprecation") + public void setUp() throws Exception { + mgmt = LocalManagementContextForTests.builder(true).disableOsgi(false).build(); + item = mgmt.getCatalog().addItem(BasicApplication.class); + + BrooklynClassLoadingContext clc = new OsgiBrooklynClassLoadingContext(mgmt, item.getCatalogItemId(), ImmutableList.<OsgiBundleWithUrl>of()); + loader = new ClassLoaderFromBrooklynClassLoadingContext(clc); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (mgmt != null) { + Entities.destroyAll(mgmt); + mgmt = null; + } + } + + @Test + public void testLoadNonExistantClassThrowsClassNotFound() throws Exception { + try { + loader.loadClass("my.clazz.does.not.Exist"); + Asserts.shouldHaveFailedPreviously(); + } catch (ClassNotFoundException e) { + // success; + } + } +}
