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/03/10 13:51:13 UTC

[1/5] brooklyn-server git commit: Add typeCoercion (String->TimeZone; number->Date)

Repository: brooklyn-server
Updated Branches:
  refs/heads/master 025a3d82d -> ea18d9ab0


Add typeCoercion (String->TimeZone; number->Date)

Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/acfcb91c
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/acfcb91c
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/acfcb91c

Branch: refs/heads/master
Commit: acfcb91c311c177670629b54bd9d70a843e95611
Parents: 59624f5
Author: Aled Sage <al...@gmail.com>
Authored: Wed Mar 8 21:03:02 2017 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Mar 8 23:45:40 2017 +0000

----------------------------------------------------------------------
 .../coerce/CommonAdaptorTypeCoercions.java       | 19 +++++++++++++++++++
 .../util/javalang/coerce/TypeCoercionsTest.java  | 13 +++++++++++++
 2 files changed, 32 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/acfcb91c/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
index 94c93e9..03745e6 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
@@ -28,6 +28,7 @@ import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TimeZone;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
@@ -258,6 +259,24 @@ public class CommonAdaptorTypeCoercions {
                 return QuorumChecks.of(input);
             }
         });
+        registerAdapter(String.class, TimeZone.class, new Function<String,TimeZone>() {
+            @Override
+            public TimeZone apply(final String input) {
+                return TimeZone.getTimeZone(input);
+            }
+        });
+        registerAdapter(Long.class, Date.class, new Function<Long,Date>() {
+            @Override
+            public Date apply(final Long input) {
+                return new Date(input);
+            }
+        });
+        registerAdapter(Integer.class, Date.class, new Function<Integer,Date>() {
+            @Override
+            public Date apply(final Integer input) {
+                return new Date(input);
+            }
+        });
     }
     
     @SuppressWarnings("rawtypes")

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/acfcb91c/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercionsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercionsTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercionsTest.java
index 0492ac5..1a3d560 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercionsTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercionsTest.java
@@ -28,9 +28,11 @@ import java.net.URI;
 import java.net.URL;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TimeZone;
 
 import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.util.collections.MutableSet;
@@ -168,6 +170,17 @@ public class TypeCoercionsTest {
     }
 
     @Test
+    public void testCoerceStringToTimeZone() {
+        assertEquals(coerce("UTC", TimeZone.class).getID(), TimeZone.getTimeZone("UTC").getID());
+    }
+
+    @Test
+    public void testCoerceNumberToDate() {
+        assertEquals(coerce(1000L, Date.class), new Date(1000));
+        assertEquals(coerce(1000, Date.class), new Date(1000));
+    }
+
+    @Test
     public void testCoerceStringToEnum() {
         assertEquals(coerce("LOWERCASE", PerverseEnum.class), PerverseEnum.lowercase);
         assertEquals(coerce("CAMELCASE", PerverseEnum.class), PerverseEnum.camelCase);


[4/5] brooklyn-server git commit: $brooklyn:object - support coercing args

Posted by al...@apache.org.
$brooklyn:object - support coercing args

Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/7ddca12d
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/7ddca12d
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/7ddca12d

Branch: refs/heads/master
Commit: 7ddca12d489796bd916b1f8b70586b93dbdaabfa
Parents: acfcb91
Author: Aled Sage <al...@gmail.com>
Authored: Wed Mar 8 22:11:16 2017 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Mar 8 23:45:41 2017 +0000

----------------------------------------------------------------------
 .../spi/dsl/methods/BrooklynDslCommon.java      |  5 +-
 .../brooklyn/camp/brooklyn/ObjectsYamlTest.java | 18 +++++
 .../brooklyn/util/core/flags/TypeCoercions.java | 14 ++++
 .../brooklyn/util/javalang/Reflections.java     | 77 ++++++++++++++++----
 .../brooklyn/util/javalang/ReflectionsTest.java | 21 +++++-
 5 files changed, 120 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7ddca12d/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
index 2bc8878..9fbab0e 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
@@ -63,6 +63,7 @@ import org.apache.brooklyn.util.core.task.Tasks;
 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.javalang.coerce.TypeCoercer;
 import org.apache.brooklyn.util.net.Urls;
 import org.apache.commons.beanutils.BeanUtils;
 import org.slf4j.Logger;
@@ -70,6 +71,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Function;
 import com.google.common.base.Objects;
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -697,7 +699,8 @@ public class BrooklynDslCommon {
 
         public static Object create(Class<?> type, String factoryMethodName, List<?> factoryMethodArgs, Map<String,?> fields, Map<String,?> config) {
             try {
-                Object bean = Reflections.invokeMethodFromArgs(type, factoryMethodName, factoryMethodArgs).get();
+                Optional<TypeCoercer> coercer = Optional.of(TypeCoercions.asTypeCoercer());
+                Object bean = Reflections.invokeMethodFromArgs(type, factoryMethodName, factoryMethodArgs, false, coercer).get();
                 BeanUtils.populate(bean, fields);
 
                 if (config.size() > 0) {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7ddca12d/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
index 01aa477..ec9937c 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
@@ -40,6 +40,7 @@ import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
 import org.apache.brooklyn.util.core.flags.TypeCoercions;
+import org.apache.brooklyn.util.time.Time;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
@@ -397,6 +398,23 @@ public class ObjectsYamlTest extends AbstractYamlTest {
         assertEquals(testObject.getNumber(), Integer.valueOf(1));
         assertEquals(testObject.getObject(), "myDefaultThird");
     }
+    
+    @Test
+    public void testBrooklynObjectWithFactoryMethodWithArgCoercion() throws Exception {
+        Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+            "  brooklyn.config:",
+            "    test.confObject:",
+            "      $brooklyn:object:",
+            "        type: " + Time.class.getName(),
+            "        factoryMethod.name: makeDateString",
+            "        factoryMethod.args:",
+            "        - 1000",
+            "        - yyyy-MM-dd'T'HH:mm:ss",
+            "        - UTC");
+
+        String val = (String) testEntity.getConfig(TestEntity.CONF_OBJECT);
+        assertEquals(val, "1970-01-01T00:00:01");
+    }
 
     @Test
     public void testFieldsAsDeferredSuppliers() throws Exception {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7ddca12d/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 923a082..29d8d4b 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
@@ -254,4 +254,18 @@ public class TypeCoercions {
         }
         
     }
+
+    public static TypeCoercer asTypeCoercer() {
+        return new TypeCoercer() {
+            @Override public <T> T coerce(Object input, Class<T> type) {
+                return TypeCoercions.coerce(input, type);
+            }
+            @Override public <T> Maybe<T> tryCoerce(Object input, Class<T> type) {
+                return TypeCoercions.tryCoerce(input, type);
+            }
+            @Override public <T> Maybe<T> tryCoerce(Object input, TypeToken<T> type) {
+                return TypeCoercions.tryCoerce(input, type);
+            }
+        };
+    }
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7ddca12d/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
index fba72b5..abcaf47 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/Reflections.java
@@ -48,6 +48,7 @@ import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.javalang.coerce.TypeCoercer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -840,19 +841,33 @@ public class Reflections {
     public static Maybe<Object> invokeMethodFromArgs(Object clazzOrInstance, String method, List<?> args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
         return invokeMethodFromArgs(clazzOrInstance, method, args, false);
     }
+    
     /** as {@link #invokeMethodFromArgs(Object, String, List)} but giving control over whether to set it accessible */
     public static Maybe<Object> invokeMethodFromArgs(Object clazzOrInstance, String method, List<?> args, boolean setAccessible) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+        return invokeMethodFromArgs(clazzOrInstance, method, args, setAccessible, Optional.<TypeCoercer>absent());
+    }
+    
+    /** as {@link #invokeMethodFromArgs(Object, String, List)} but giving control over whether to set it accessible */
+    public static Maybe<Object> invokeMethodFromArgs(Object clazzOrInstance, String method, List<?> args, boolean setAccessible, Optional<? extends TypeCoercer> coercer) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
         Maybe<Method> maybeMethod = getMethodFromArgs(clazzOrInstance, method, args);
+        if (coercer.isPresent() && maybeMethod.isAbsent()) {
+            maybeMethod = getMethodFromArgs(clazzOrInstance, method, args, coercer);
+        }
         if (maybeMethod.isAbsent()) {
             return Maybe.absent(Maybe.getException(maybeMethod));
         }
         Method m = maybeMethod.get();
 
-        return Maybe.of(invokeMethodFromArgs(clazzOrInstance, m, args, setAccessible));
+        return Maybe.of(invokeMethodFromArgs(clazzOrInstance, m, args, setAccessible, coercer));
     }
 
     /** searches for the given method on the given clazz or instance, doing reasonably good matching on args etc */
     public static Maybe<Method> getMethodFromArgs(Object clazzOrInstance, String method, List<?> args) {
+        return getMethodFromArgs(clazzOrInstance, method, args, Optional.<TypeCoercer>absent());
+    }
+    
+    /** searches for the given method on the given clazz or instance, doing reasonably good matching on args etc */
+    public static Maybe<Method> getMethodFromArgs(Object clazzOrInstance, String method, List<?> args, Optional<? extends TypeCoercer> coercer) {
         Preconditions.checkNotNull(clazzOrInstance, "clazz or instance");
         Preconditions.checkNotNull(method, "method");
         Preconditions.checkNotNull(args, "args to "+method);
@@ -870,12 +885,11 @@ public class Reflections {
             if (method.equals(m.getName())) {
                 Class<?>[] parameterTypes = m.getParameterTypes();
                 if (m.isVarArgs()) {
-                    if (typesMatchUpTo(argsArray, parameterTypes, parameterTypes.length-1)) {
+                    if (typesMatchUpTo(argsArray, parameterTypes, parameterTypes.length-1, coercer)) {
                         Class<?> varargType = parameterTypes[parameterTypes.length-1].getComponentType();
                         boolean varargsMatch = true;
                         for (int i=parameterTypes.length-1; i<argsArray.length; i++) {
-                            if (!Boxing.boxedType(varargType).isInstance(argsArray[i]) ||
-                                    (varargType.isPrimitive() && argsArray[i]==null)) {
+                            if (!typeMatches(argsArray[i], varargType, coercer)) {
                                 varargsMatch = false;
                                 break;
                             }
@@ -885,7 +899,7 @@ public class Reflections {
                         }
                     }
                 }
-                if (typesMatch(argsArray, parameterTypes)) {
+                if (typesMatch(argsArray, parameterTypes, coercer)) {
                     return Maybe.of(m);
                 }
             }
@@ -910,6 +924,12 @@ public class Reflections {
     /** as {@link #invokeMethodFromArgs(Object, Method, List)} but giving control over whether to set it accessible */
     public static Object invokeMethodFromArgs(Object clazzOrInstance, Method m, List<?> args, boolean setAccessible)
             throws IllegalAccessException, InvocationTargetException {
+        return invokeMethodFromArgs(clazzOrInstance, m, args, setAccessible, Optional.<TypeCoercer>absent());
+    }
+
+    /** as {@link #invokeMethodFromArgs(Object, Method, List)} but giving control over whether to set it accessible */
+    public static Object invokeMethodFromArgs(Object clazzOrInstance, Method m, List<?> args, boolean setAccessible, Optional<? extends TypeCoercer> coercer)
+            throws IllegalAccessException, InvocationTargetException {
         Preconditions.checkNotNull(clazzOrInstance, "clazz or instance");
         Preconditions.checkNotNull(m, "method");
         Preconditions.checkNotNull(args, "args to "+m);
@@ -928,38 +948,69 @@ public class Reflections {
             Class<?> varargType = parameterTypes[parameterTypes.length-1].getComponentType();
             Object varargs = Array.newInstance(varargType, argsArray.length+1 - parameterTypes.length);
             for (int i=parameterTypes.length-1; i<argsArray.length; i++) {
-                Boxing.setInArray(varargs, i+1-parameterTypes.length, argsArray[i], varargType);
+                Object arg = coercer.isPresent() ? coercer.get().coerce(argsArray[i], varargType) : argsArray[i];
+                Boxing.setInArray(varargs, i+1-parameterTypes.length, arg, varargType);
             }
             Object[] newArgsArray = new Object[parameterTypes.length];
-            System.arraycopy(argsArray, 0, newArgsArray, 0, parameterTypes.length-1);
+            for (int i = 0; i < parameterTypes.length - 1; i++) {
+                Object arg = coercer.isPresent() ? coercer.get().coerce(argsArray[i], parameterTypes[i]) : argsArray[i];
+                newArgsArray[i] = arg;
+            }
             newArgsArray[parameterTypes.length-1] = varargs;
             if (setAccessible) m.setAccessible(true);
             return m.invoke(instance, newArgsArray);
         } else {
+            Object[] newArgsArray;
+            if (coercer.isPresent()) {
+                newArgsArray = new Object[parameterTypes.length];
+                for (int i = 0; i < parameterTypes.length; i++) {
+                    Object arg = coercer.get().coerce(argsArray[i], parameterTypes[i]);
+                    newArgsArray[i] = arg;
+                }
+            } else {
+                newArgsArray = argsArray;
+            }
             if (setAccessible) m.setAccessible(true);
-            return m.invoke(instance, argsArray);
+            return m.invoke(instance, newArgsArray);
         }
     }
 
     /** true iff all args match the corresponding types */
     public static boolean typesMatch(Object[] argsArray, Class<?>[] parameterTypes) {
+        return typesMatch(argsArray, parameterTypes, Optional.<TypeCoercer>absent());
+    }
+    
+    /** true iff all args match the corresponding types */
+    public static boolean typesMatch(Object[] argsArray, Class<?>[] parameterTypes, Optional<? extends TypeCoercer> coercer) {
         if (argsArray.length != parameterTypes.length)
             return false;
-        return typesMatchUpTo(argsArray, parameterTypes, argsArray.length);
+        return typesMatchUpTo(argsArray, parameterTypes, argsArray.length, coercer);
     }
-    
+
     /** true iff the initial N args match the corresponding types */
     public static boolean typesMatchUpTo(Object[] argsArray, Class<?>[] parameterTypes, int lengthRequired) {
+        return typesMatchUpTo(argsArray, parameterTypes, lengthRequired, Optional.<TypeCoercer>absent());
+    }
+    
+    /** true iff the initial N args match the corresponding types */
+    public static boolean typesMatchUpTo(Object[] argsArray, Class<?>[] parameterTypes, int lengthRequired, Optional<? extends TypeCoercer> coercer) {
         if (argsArray.length < lengthRequired || parameterTypes.length < lengthRequired)
             return false;
         for (int i=0; i<lengthRequired; i++) {
-            if (argsArray[i]==null) continue;
-            if (Boxing.boxedType(parameterTypes[i]).isInstance(argsArray[i])) continue;
-            return false;
+            if (!typeMatches(argsArray[i], parameterTypes[i], coercer)) return false;
         }
         return true;
     }
 
+    /** true iff the initial N args match the corresponding types */
+    public static boolean typeMatches(Object arg, Class<?> parameterType, Optional<? extends TypeCoercer> coercer) {
+        if (parameterType.isPrimitive() && arg == null) return false;
+        if (arg == null) return true;
+        if (Boxing.boxedType(parameterType).isInstance(arg)) return true;
+        if (coercer.isPresent() && coercer.get().tryCoerce(arg, parameterType).isPresent()) return true;
+        return false;
+    }
+
     /**
      * Gets all the interfaces implemented by the given type, including its parent classes.
      *

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/7ddca12d/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
index 52aee8c..ba4b1d3 100644
--- a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/ReflectionsTest.java
@@ -26,10 +26,13 @@ import java.lang.reflect.Method;
 import java.util.Arrays;
 import java.util.List;
 
-import org.apache.brooklyn.util.javalang.Reflections;
+import org.apache.brooklyn.util.javalang.coerce.CommonAdaptorTypeCoercions;
+import org.apache.brooklyn.util.javalang.coerce.TypeCoercer;
+import org.apache.brooklyn.util.javalang.coerce.TypeCoercerExtensible;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
@@ -129,6 +132,22 @@ public class ReflectionsTest {
     }
     
     @Test
+    public void testInvocationCoercingArgs() throws Exception {
+        TypeCoercerExtensible rawCoercer = TypeCoercerExtensible.newDefault();
+        new CommonAdaptorTypeCoercions(rawCoercer).registerAllAdapters();
+        Optional<TypeCoercer> coercer = Optional.<TypeCoercer>of(rawCoercer);
+        
+        Method m1Short = CI1.class.getMethod("m1", String.class, int.class);
+        Method m1Long = CI1.class.getMethod("m1", String.class, int.class, int.class, int[].class);
+        Assert.assertEquals(m1Short.invoke(null, "hello", 1), "hello1");
+        Assert.assertEquals(m1Long.invoke(null, "hello", 1, 2, new int[] { 3, 4}), "hello10");
+        
+        Assert.assertEquals(Reflections.invokeMethodFromArgs(CI1.class, "m1", Arrays.<Object>asList('a', "2"), false, coercer).get(), "a2");
+        Assert.assertEquals(Reflections.invokeMethodFromArgs(CI1.class, "m1", Arrays.<Object>asList('a', "3", "4", "5"), false, coercer).get(), "a12");
+        Assert.assertEquals(Reflections.invokeMethodFromArgs(CI1.class, "m1", Arrays.<Object>asList('a', (byte)3, (byte)4, (byte)5), false, coercer).get(), "a12");
+    }
+    
+    @Test
     public void testMethodInvocation() throws Exception {
         Method m1Short = CI1.class.getMethod("m1", String.class, int.class);
         Method m1Long = CI1.class.getMethod("m1", String.class, int.class, int.class, int[].class);


[3/5] brooklyn-server git commit: $brooklyn:object: support explicit “deferred”

Posted by al...@apache.org.
$brooklyn:object: support explicit \u201cdeferred\u201d

YAML authors can specify \u201cdeferred\u201d, to force the object to only be
constructed when the config is being retrieved.


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/b2fd0e81
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/b2fd0e81
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/b2fd0e81

Branch: refs/heads/master
Commit: b2fd0e81761b30e963ffe12ae6108565d5f2ed1a
Parents: 2fe2ba0
Author: Aled Sage <al...@gmail.com>
Authored: Wed Mar 8 20:37:41 2017 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Mar 8 23:45:40 2017 +0000

----------------------------------------------------------------------
 .../spi/dsl/methods/BrooklynDslCommon.java      |   4 +-
 .../brooklyn/camp/brooklyn/ObjectsYamlTest.java | 101 +++++++++++++++++++
 2 files changed, 104 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b2fd0e81/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
index 2836895..2bc8878 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
@@ -56,6 +56,7 @@ import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.ClassLoaderUtils;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.core.flags.FlagUtils;
+import org.apache.brooklyn.util.core.flags.TypeCoercions;
 import org.apache.brooklyn.util.core.task.DeferredSupplier;
 import org.apache.brooklyn.util.core.task.ImmediateSupplier;
 import org.apache.brooklyn.util.core.task.Tasks;
@@ -292,6 +293,7 @@ public class BrooklynDslCommon {
         List<Object> factoryMethodArgs = (List<Object>) config.getStringKeyMaybe("factoryMethod.args").or(ImmutableList.of());
         Map<String,Object> objectFields = (Map<String, Object>) config.getStringKeyMaybe("object.fields").or(MutableMap.of());
         Map<String,Object> brooklynConfig = (Map<String, Object>) config.getStringKeyMaybe(BrooklynCampReservedKeys.BROOKLYN_CONFIG).or(MutableMap.of());
+        boolean deferred = TypeCoercions.coerce(config.getStringKeyMaybe("deferred").or(Boolean.FALSE), Boolean.class);
 
         String mappedTypeName = DeserializingClassRenamesProvider.INSTANCE.findMappedName(typeName);
         Class<?> type;
@@ -302,7 +304,7 @@ public class BrooklynDslCommon {
             return new DslObject(mappedTypeName, constructorArgs, objectFields, brooklynConfig);
         }
 
-        if (resolved(constructorArgs) && resolved(factoryMethodArgs) && resolved(objectFields.values()) && resolved(brooklynConfig.values())) {
+        if (!deferred && resolved(constructorArgs) && resolved(factoryMethodArgs) && resolved(objectFields.values()) && resolved(brooklynConfig.values())) {
             if (factoryMethodName == null) {
                 return DslObject.create(type, constructorArgs, objectFields, brooklynConfig);
             } else {

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b2fd0e81/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
index b15097d..01aa477 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.camp.brooklyn;
 
 import static org.testng.Assert.assertEquals;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -34,6 +35,7 @@ import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
 import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
@@ -45,6 +47,7 @@ import org.testng.annotations.Test;
 
 import com.google.common.base.Charsets;
 import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.hash.HashCode;
@@ -586,6 +589,104 @@ public class ObjectsYamlTest extends AbstractYamlTest {
         assertEquals(sha256, PasswordHasher.sha256(salt, "mypassword"));
     }
 
+    @Test
+    public void testBrooklynObjectEvaluatedImmediatelyOnlyOnce() throws Exception {
+        CallRecorder.clear();
+        Entity entity = setupAndCheckTestEntityInBasicYamlWith(
+            "  brooklyn.config:",
+            "    test.confObject:",
+            "      $brooklyn:object:",
+            "        type: "+CallRecorder.class.getName(),
+            "        factoryMethod.name: call",
+            "        factoryMethod.args:",
+            "        - myval");
+        
+        // Nothing has called config().get() yet; but expect it to have been evaluated immediate, on entity construction
+        assertEquals(CallRecorder.getCalls(), ImmutableList.of("myval"));
+
+        // The config value is set to the result of that single call; getting the config will not invoke it again
+        Object val = entity.config().get(TestEntity.CONF_OBJECT);
+        assertEquals(val, "myval");
+        assertEquals(CallRecorder.getCalls(), ImmutableList.of("myval"));
+    }
+
+    @Test
+    public void testBrooklynObjectEvaluationDeferredIfRequired() throws Exception {
+        CallRecorder.clear();
+        Entity entity = setupAndCheckTestEntityInBasicYamlWith(
+            "  brooklyn.config:",
+            "    anotherConfig: myval",
+            "    test.confObject:",
+            "      $brooklyn:object:",
+            "        type: "+CallRecorder.class.getName(),
+            "        factoryMethod.name: call",
+            "        factoryMethod.args:",
+            "        - $brooklyn:config(\"anotherConfig\")");
+        
+        // The value is a DeferredSupplier; nothing in the blueprint will have called config().get() yet.
+        // However, verification will have called it! Therefore not doing:
+        //   assertEquals(CallRecorder.getCalls(), ImmutableList.of());
+        CallRecorder.clear();
+
+        // Retrieving the config value causes it to be resolved
+        Object val = entity.config().get(TestEntity.CONF_OBJECT);
+        assertEquals(val, "myval");
+        assertEquals(CallRecorder.getCalls(), ImmutableList.of("myval"));
+        
+        // Retrieving the config value a second time will resolve it again
+        Object val2 = entity.config().get(TestEntity.CONF_OBJECT);
+        assertEquals(val2, "myval");
+        assertEquals(CallRecorder.getCalls(), ImmutableList.of("myval", "myval"));
+    }
+
+    @Test
+    public void testBrooklynObjectEvaluationExplicitlyDeferred() throws Exception {
+        CallRecorder.clear();
+        Entity entity = setupAndCheckTestEntityInBasicYamlWith(
+            "  brooklyn.config:",
+            "    test.confObject:",
+            "      $brooklyn:object:",
+            "        deferred: true",
+            "        type: "+CallRecorder.class.getName(),
+            "        factoryMethod.name: call",
+            "        factoryMethod.args:",
+            "        - myval");
+        
+        // The value is a DeferredSupplier; nothing in the blueprint will have called config().get() yet.
+        // However, verification will have called it! Therefore not doing:
+        //   assertEquals(CallRecorder.getCalls(), ImmutableList.of());
+        CallRecorder.clear();
+
+        // Retrieving the config value causes it to be resolved
+        Object val = entity.config().get(TestEntity.CONF_OBJECT);
+        assertEquals(val, "myval");
+        assertEquals(CallRecorder.getCalls(), ImmutableList.of("myval"));
+        
+        // Retrieving the config value a second time will resolve it again
+        Object val2 = entity.config().get(TestEntity.CONF_OBJECT);
+        assertEquals(val2, "myval");
+        assertEquals(CallRecorder.getCalls(), ImmutableList.of("myval", "myval"));
+    }
+
+    public static class CallRecorder {
+        private static final List<String> calls = Collections.synchronizedList(Lists.<String>newArrayList());
+        
+        public static String call(String val) {
+            calls.add(val);
+            return val;
+        }
+        
+        public static void clear() {
+            calls.clear();
+        }
+        
+        public static List<String> getCalls() {
+            synchronized (calls) {
+                return MutableList.copyOf(calls);
+            }
+        }
+    }
+
     @Override
     protected Logger getLogger() {
         return log;


[5/5] brooklyn-server git commit: This closes #586

Posted by al...@apache.org.
This closes #586


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/ea18d9ab
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/ea18d9ab
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/ea18d9ab

Branch: refs/heads/master
Commit: ea18d9ab0e2cdb75a6c0fdf57b8c33b118900cf9
Parents: 025a3d8 7ddca12
Author: Aled Sage <al...@gmail.com>
Authored: Fri Mar 10 13:50:59 2017 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Fri Mar 10 13:50:59 2017 +0000

----------------------------------------------------------------------
 .../spi/dsl/methods/BrooklynDslCommon.java      |   9 +-
 .../brooklyn/camp/brooklyn/ObjectsYamlTest.java | 119 +++++++++++++++++++
 .../brooklyn/util/core/flags/TypeCoercions.java |  14 +++
 .../brooklyn/test/framework/TestHttpCall.java   |   6 +
 .../test/framework/TestHttpCallImpl.java        |   7 +-
 .../test/framework/TestHttpCallTest.java        |  26 ++++
 .../brooklyn/util/javalang/Reflections.java     |  77 ++++++++++--
 .../coerce/CommonAdaptorTypeCoercions.java      |  19 +++
 .../brooklyn/util/javalang/ReflectionsTest.java |  21 +++-
 .../util/javalang/coerce/TypeCoercionsTest.java |  13 ++
 10 files changed, 292 insertions(+), 19 deletions(-)
----------------------------------------------------------------------



[2/5] brooklyn-server git commit: TestHttpCall: support “maxAttempts” config

Posted by al...@apache.org.
TestHttpCall: support \u201cmaxAttempts\u201d config

Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/59624f52
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/59624f52
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/59624f52

Branch: refs/heads/master
Commit: 59624f52cbb2fc89cf5fcbba400a221db72c8028
Parents: b2fd0e8
Author: Aled Sage <al...@gmail.com>
Authored: Wed Mar 8 20:49:19 2017 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Wed Mar 8 23:45:40 2017 +0000

----------------------------------------------------------------------
 .../brooklyn/test/framework/TestHttpCall.java   |  6 +++++
 .../test/framework/TestHttpCallImpl.java        |  7 +++---
 .../test/framework/TestHttpCallTest.java        | 26 ++++++++++++++++++++
 3 files changed, 36 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/59624f52/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java
index 31dac5d..3e4867b 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCall.java
@@ -24,6 +24,7 @@ import org.apache.brooklyn.api.entity.ImplementedBy;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
+import org.apache.brooklyn.util.time.Duration;
 import org.apache.http.client.methods.HttpDelete;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpHead;
@@ -63,6 +64,11 @@ public interface TestHttpCall extends BaseTest {
     ConfigKey<HttpAssertionTarget> ASSERTION_TARGET = ConfigKeys.newConfigKey(HttpAssertionTarget.class, "applyAssertionTo",
         "The HTTP field to apply the assertion to [body,status]", HttpAssertionTarget.body);
 
+    /**
+     * The duration to wait for an assertion to succeed or fail before throwing an exception.
+     */
+    ConfigKey<Integer> MAX_ATTEMPTS = ConfigKeys.newIntegerConfigKey("maxAttempts", "Maximum number of attempts");
+
     enum HttpMethod {
         GET(HttpGet.class),
         POST(HttpPost.class),

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/59624f52/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
----------------------------------------------------------------------
diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
index 9f51c0e..69bed81 100644
--- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
+++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestHttpCallImpl.java
@@ -29,6 +29,7 @@ import org.apache.brooklyn.api.location.Location;
 import org.apache.brooklyn.core.entity.lifecycle.Lifecycle;
 import org.apache.brooklyn.core.entity.lifecycle.ServiceStateLogic;
 import org.apache.brooklyn.test.framework.TestFrameworkAssertions.AssertionOptions;
+import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.http.HttpTool;
@@ -39,7 +40,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 
 /**
@@ -65,6 +65,7 @@ public class TestHttpCallImpl extends TargetableTestComponentImpl implements Tes
             final String body = config().get(TARGET_BODY);
             final List<Map<String, Object>> assertions = getAssertions(this, ASSERTIONS);
             final Duration timeout = getConfig(TIMEOUT);
+            final Integer maxAttempts = getConfig(MAX_ATTEMPTS);
             final Duration backoffToPeriod = getConfig(BACKOFF_TO_PERIOD);
             final HttpAssertionTarget target = getRequiredConfig(ASSERTION_TARGET);
             final boolean trustAll = getRequiredConfig(TRUST_ALL);
@@ -72,7 +73,7 @@ public class TestHttpCallImpl extends TargetableTestComponentImpl implements Tes
                 throw new RuntimeException(String.format("The entity [%s] cannot have child entities", getClass().getName()));
             }
             
-            doRequestAndCheckAssertions(ImmutableMap.of("timeout", timeout, "backoffToPeriod", backoffToPeriod), 
+            doRequestAndCheckAssertions(MutableMap.of("timeout", timeout, "backoffToPeriod", backoffToPeriod, "maxAttempts", maxAttempts), 
                     assertions, target, method, url, headers, trustAll, body);
             setUpAndRunState(true, Lifecycle.RUNNING);
 
@@ -87,7 +88,7 @@ public class TestHttpCallImpl extends TargetableTestComponentImpl implements Tes
         }
     }
 
-    private void doRequestAndCheckAssertions(Map<String, Duration> flags, List<Map<String, Object>> assertions,
+    private void doRequestAndCheckAssertions(Map<String, ?> flags, List<Map<String, Object>> assertions,
                                              HttpAssertionTarget target, final HttpMethod method, final String url, final Map<String, String> headers, final boolean trustAll, final String body) {
         switch (target) {
             case body:

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/59624f52/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestHttpCallTest.java
----------------------------------------------------------------------
diff --git a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestHttpCallTest.java b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestHttpCallTest.java
index 99638a4..9c58e4b 100644
--- a/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestHttpCallTest.java
+++ b/test-framework/src/test/java/org/apache/brooklyn/test/framework/TestHttpCallTest.java
@@ -18,6 +18,8 @@
  */
 package org.apache.brooklyn.test.framework;
 
+import static org.testng.Assert.assertTrue;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -28,8 +30,10 @@ import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.location.LocationSpec;
 import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
 import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
+import org.apache.brooklyn.test.Asserts;
 import org.apache.brooklyn.test.http.TestHttpRequestHandler;
 import org.apache.brooklyn.test.http.TestHttpServer;
+import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.text.Identifiers;
 import org.apache.brooklyn.util.time.Duration;
 import org.apache.http.HttpException;
@@ -41,6 +45,7 @@ import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Stopwatch;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
@@ -172,6 +177,27 @@ public class TestHttpCallTest extends BrooklynAppUnitTestSupport {
         app.start(ImmutableList.of(loc));
     }
 
+    @Test(groups = "Integration")
+    public void testMaxAttempts() {
+        app.addChild(EntitySpec.create(TestHttpCall.class)
+                .configure(TestHttpCall.TARGET_URL, server.getUrl() + "/201")
+                .configure(TestHttpCall.TIMEOUT, Duration.minutes(1))
+                .configure(TestHttpCall.MAX_ATTEMPTS, 1)
+                .configure(TestSensor.ASSERTIONS, newAssertion("isEqualTo", "Wrong")));
+        Stopwatch stopwatch = Stopwatch.createStarted();
+        try {
+            app.start(ImmutableList.of(loc));
+            Asserts.shouldHaveFailedPreviously();
+        } catch (Exception e) {
+            AssertionError ae = Exceptions.getFirstThrowableOfType(e, AssertionError.class);
+            if (ae == null || !ae.toString().contains("body expected isEqualTo Wrong")) {
+                throw e;
+            }
+        }
+        Duration duration = Duration.of(stopwatch);
+        assertTrue(duration.isShorterThan(Asserts.DEFAULT_LONG_TIMEOUT), "duration="+duration);
+    }
+
     private List<Map<String, Object>> newAssertion(final String assertionKey, final Object assertionValue) {
         final List<Map<String, Object>> result = new ArrayList<>();
         result.add(ImmutableMap.of(assertionKey, assertionValue));