Adds TypeCoercion utility âregisterInstanceForClassnameAdapterâ Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/854c3517 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/854c3517 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/854c3517
Branch: refs/heads/master Commit: 854c35172ab057f2d0aa50a47941a15701b6dd11 Parents: 2a63d8e Author: Aled Sage <[email protected]> Authored: Tue Sep 19 15:20:02 2017 +0100 Committer: Aled Sage <[email protected]> Committed: Thu Sep 21 09:09:34 2017 +0100 ---------------------------------------------------------------------- .../core/mgmt/internal/LocalUsageManager.java | 31 ++++---------------- .../brooklyn/util/core/flags/TypeCoercions.java | 21 +++++++++++++ .../util/core/internal/TypeCoercionsTest.java | 31 ++++++++++++++++++++ 3 files changed, 58 insertions(+), 25 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/854c3517/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalUsageManager.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalUsageManager.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalUsageManager.java index 5403b47..41c5dc4 100644 --- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalUsageManager.java +++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalUsageManager.java @@ -51,8 +51,6 @@ import org.apache.brooklyn.core.mgmt.usage.UsageManager; import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.flags.TypeCoercions; import org.apache.brooklyn.util.exceptions.Exceptions; -import org.apache.brooklyn.util.guava.Maybe; -import org.apache.brooklyn.util.javalang.Reflections; import org.apache.brooklyn.util.time.Duration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -136,29 +134,6 @@ public class LocalUsageManager implements UsageManager { } } - // Register a coercion from String->UsageListener, so that USAGE_LISTENERS defined in brooklyn.properties - // will be instantiated, given their class names. - static { - TypeCoercions.registerAdapter(String.class, UsageListener.class, new Function<String, UsageListener>() { - @Override public UsageListener apply(String input) { - Class<?> clazz; - try { - clazz = new ClassLoaderUtils(this.getClass()).loadClass(input); - } catch (ClassNotFoundException e) { - throw new IllegalStateException("Failed to load usage listener class: " + input, e); - } - Maybe<Object> result = Reflections.invokeConstructorFromArgs(clazz); - if (result.isPresentAndNonNull() && result.get() instanceof UsageListener) { - return (UsageListener) result.get(); - } else if (result.isPresent()) { - throw new IllegalStateException("Object is not a UsageListener: " + result.get()); - } else { - throw new IllegalStateException("Failed to create UsageListener from class name '"+input+"' using no-arg constructor"); - } - } - }); - } - @VisibleForTesting public static final String APPLICATION_USAGE_KEY = "usage-application"; @@ -180,6 +155,12 @@ public class LocalUsageManager implements UsageManager { public LocalUsageManager(LocalManagementContext managementContext) { this.managementContext = checkNotNull(managementContext, "managementContext"); + // Register a coercion from String->UsageListener, so that USAGE_LISTENERS defined in brooklyn.properties + // will be instantiated, given their class names. + TypeCoercions.BrooklynCommonAdaptorTypeCoercions.registerInstanceForClassnameAdapter( + new ClassLoaderUtils(this.getClass(), managementContext), + UsageListener.class); + // Although changing listeners to Collection<UsageListener> is valid at compile time // the collection will contain any objects that could not be coerced by the function // declared above. Generally this means any string declared in brooklyn.properties http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/854c3517/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java b/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java index 9bc25e2..a2dc398 100644 --- a/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java +++ b/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java @@ -28,6 +28,7 @@ import org.apache.brooklyn.api.sensor.AttributeSensor; import org.apache.brooklyn.api.sensor.Sensor; import org.apache.brooklyn.core.internal.BrooklynInitialization; import org.apache.brooklyn.core.mgmt.BrooklynTaskTags; +import org.apache.brooklyn.core.mgmt.usage.UsageListener; import org.apache.brooklyn.core.sensor.Sensors; import org.apache.brooklyn.util.JavaGroovyEquivalents; import org.apache.brooklyn.util.core.ClassLoaderUtils; @@ -267,6 +268,26 @@ public class TypeCoercions { }); } + public static <T> void registerInstanceForClassnameAdapter(ClassLoaderUtils loader, Class<T> supertype) { + TypeCoercions.registerAdapter(String.class, supertype, new Function<String, T>() { + @Override public T apply(String input) { + Class<?> clazz; + try { + clazz = loader.loadClass(input); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Failed to load " + supertype.getSimpleName() + " class " + input, e); + } + Maybe<Object> result = Reflections.invokeConstructorFromArgs(clazz); + if (result.isPresentAndNonNull() && supertype.isInstance(result.get())) { + return (T) result.get(); + } else if (result.isPresent()) { + throw new IllegalStateException("Object is not a " + supertype.getSimpleName()+": " + result.get()); + } else { + throw new IllegalStateException("Failed to create "+supertype.getSimpleName()+" from class name '"+input+"' using no-arg constructor"); + } + } + }); + } } public static TypeCoercer asTypeCoercer() { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/854c3517/core/src/test/java/org/apache/brooklyn/util/core/internal/TypeCoercionsTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/brooklyn/util/core/internal/TypeCoercionsTest.java b/core/src/test/java/org/apache/brooklyn/util/core/internal/TypeCoercionsTest.java index 48dcc56..2d451c8 100644 --- a/core/src/test/java/org/apache/brooklyn/util/core/internal/TypeCoercionsTest.java +++ b/core/src/test/java/org/apache/brooklyn/util/core/internal/TypeCoercionsTest.java @@ -20,6 +20,7 @@ package org.apache.brooklyn.util.core.internal; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; import java.math.BigDecimal; import java.math.BigInteger; @@ -31,10 +32,12 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; import org.apache.brooklyn.core.entity.lifecycle.Lifecycle; import org.apache.brooklyn.test.Asserts; import org.apache.brooklyn.util.collections.MutableSet; +import org.apache.brooklyn.util.core.ClassLoaderUtils; import org.apache.brooklyn.util.core.flags.TypeCoercions; import org.apache.brooklyn.util.javalang.coerce.ClassCoercionException; import org.apache.brooklyn.util.text.StringPredicates; @@ -362,6 +365,29 @@ public class TypeCoercionsTest { assertEquals(TypeCoercions.function(Double.class).apply("1"), Double.valueOf(1)); } + @Test + public void testCoerceInstanceForClassnameAdapter() { + List<String> loaderCalls = new CopyOnWriteArrayList<>(); + ClassLoaderUtils loader = new ClassLoaderUtils(getClass()) { + @Override + public Class<?> loadClass(String name) throws ClassNotFoundException { + loaderCalls.add(name); + return super.loadClass(name); + } + }; + + TypeCoercions.BrooklynCommonAdaptorTypeCoercions.registerInstanceForClassnameAdapter(loader, MyInterface.class); + MyInterface val = TypeCoercions.coerce(MyClazz.class.getName(), MyInterface.class); + assertTrue(val instanceof MyClazz, "val="+val); + assertEquals(loaderCalls, ImmutableList.of(MyClazz.class.getName())); + } + + @Test(expectedExceptions = org.apache.brooklyn.util.javalang.coerce.ClassCoercionException.class) + public void testInvalidCoerceInstanceForClassnameAdapterThrows() { + TypeCoercions.BrooklynCommonAdaptorTypeCoercions.registerInstanceForClassnameAdapter(new ClassLoaderUtils(getClass()), MyInterface.class); + TypeCoercions.coerce("wrongClassNameDoesNotExist", MyInterface.class); + } + public static class WithAs { String value; public WithAs(Object x) { value = ""+x; } @@ -379,4 +405,9 @@ public class TypeCoercionsTest { } } + public static interface MyInterface { + } + + public static class MyClazz implements MyInterface { + } }
