You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2017/09/27 20:04:05 UTC

[2/3] brooklyn-server git commit: Adds TypeCoercion utility ‘registerInstanceForClassnameAdapter’

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 <al...@gmail.com>
Authored: Tue Sep 19 15:20:02 2017 +0100
Committer: Aled Sage <al...@gmail.com>
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 {
+    }
 }