Repository: brooklyn-server
Updated Branches:
  refs/heads/master 374e01f41 -> a36b6412d


Test+fix DeferredSuppliers in $brooklyn:object


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

Branch: refs/heads/master
Commit: fed6e511649ba825ce567405dfc758f046139e14
Parents: 374e01f
Author: Aled Sage <aled.s...@gmail.com>
Authored: Mon Aug 15 12:57:07 2016 +0100
Committer: Aled Sage <aled.s...@gmail.com>
Committed: Tue Aug 16 10:45:19 2016 +0100

----------------------------------------------------------------------
 .../spi/dsl/methods/BrooklynDslCommon.java      |  51 +++--
 .../brooklyn/camp/brooklyn/ObjectsYamlTest.java | 227 +++++++++++++++++++
 .../brooklyn/util/javalang/Reflections.java     |   7 +-
 3 files changed, 261 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/fed6e511/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 d6dfddd..fc8424b 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
@@ -47,6 +47,7 @@ import 
org.apache.brooklyn.core.mgmt.internal.ExternalConfigSupplierRegistry;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider;
 import org.apache.brooklyn.core.sensor.DependentConfiguration;
+import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.ClassLoaderUtils;
 import org.apache.brooklyn.util.core.config.ConfigBag;
@@ -68,6 +69,7 @@ import com.google.common.base.Objects;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 
 /** static import functions which can be used in `$brooklyn:xxx` contexts */
 public class BrooklynDslCommon {
@@ -350,7 +352,7 @@ public class BrooklynDslCommon {
                 Map<String, Object> config) {
             this.typeName = checkNotNull(typeName, "typeName");
             this.type = null;
-            this.constructorArgs = constructorArgs;
+            this.constructorArgs = checkNotNull(constructorArgs, 
"constructorArgs");
             this.factoryMethodName = null;
             this.factoryMethodArgs = ImmutableList.of();
             this.fields = MutableMap.copyOf(fields);
@@ -364,7 +366,7 @@ public class BrooklynDslCommon {
                 Map<String, Object> config) {
             this.typeName = null;
             this.type = checkNotNull(type, "type");
-            this.constructorArgs = constructorArgs;
+            this.constructorArgs = checkNotNull(constructorArgs, 
"constructorArgs");
             this.factoryMethodName = null;
             this.factoryMethodArgs = ImmutableList.of();
             this.fields = MutableMap.copyOf(fields);
@@ -381,7 +383,7 @@ public class BrooklynDslCommon {
             this.type = null;
             this.constructorArgs = ImmutableList.of();
             this.factoryMethodName = factoryMethodName;
-            this.factoryMethodArgs = factoryMethodArgs;
+            this.factoryMethodArgs = checkNotNull(factoryMethodArgs, 
"factoryMethodArgs");
             this.fields = MutableMap.copyOf(fields);
             this.config = MutableMap.copyOf(config);
         }
@@ -396,7 +398,7 @@ public class BrooklynDslCommon {
             this.type = checkNotNull(type, "type");
             this.constructorArgs = ImmutableList.of();
             this.factoryMethodName = factoryMethodName;
-            this.factoryMethodArgs = factoryMethodArgs;
+            this.factoryMethodArgs = checkNotNull(factoryMethodArgs, 
"factoryMethodArgs");
             this.fields = MutableMap.copyOf(fields);
             this.config = MutableMap.copyOf(config);
         }
@@ -416,7 +418,7 @@ public class BrooklynDslCommon {
             final Class<?> clazz = type;
 
             List<TaskAdaptable<Object>> tasks = Lists.newLinkedList();
-            for (Object value : Iterables.concat(fields.values(), 
config.values())) {
+            for (Object value : Iterables.concat(fields.values(), 
config.values(), constructorArgs, factoryMethodArgs)) {
                 if (value instanceof TaskAdaptable) {
                     tasks.add((TaskAdaptable<Object>) value);
                 } else if (value instanceof TaskFactory) {
@@ -428,28 +430,31 @@ public class BrooklynDslCommon {
             return DependentConfiguration.transformMultiple(flags, new 
Function<List<Object>, Object>() {
                         @Override
                         public Object apply(List<Object> input) {
-                            Iterator<Object> values = input.iterator();
-                            for (String name : fields.keySet()) {
-                                Object value = fields.get(name);
-                                if (value instanceof TaskAdaptable || value 
instanceof TaskFactory) {
-                                    fields.put(name, values.next());
-                                } else if (value instanceof DeferredSupplier) {
-                                    fields.put(name, ((DeferredSupplier<?>) 
value).get());
+                            final Iterator<Object> taskValues = 
input.iterator();
+                            Function<Object, Object> resolver = new 
Function<Object, Object>() {
+                                @Override public Object apply(Object value) {
+                                    return requiresTask(value) ? 
taskValues.next() : resolveValue(value);
                                 }
-                            }
-                            for (String name : config.keySet()) {
-                                Object value = config.get(name);
-                                if (value instanceof TaskAdaptable || value 
instanceof TaskFactory) {
-                                    config.put(name, values.next());
-                                } else if (value instanceof DeferredSupplier) {
-                                    config.put(name, ((DeferredSupplier<?>) 
value).get());
-                                }
-                            }
+                            };
+                            Map<String, Object> resolvedFields = 
MutableMap.copyOf(Maps.transformValues(fields, resolver));
+                            Map<String, Object> resolvedConfig = 
MutableMap.copyOf(Maps.transformValues(config, resolver));
+                            List<Object> resolvedConstructorArgs = 
MutableList.copyOf(Lists.transform(constructorArgs, resolver));
+                            List<Object> resolvedFactoryMethodArgs = 
MutableList.copyOf(Lists.transform(factoryMethodArgs, resolver));
+
                             if (factoryMethodName == null) {
-                                return create(clazz, constructorArgs, fields, 
config);
+                                return create(clazz, resolvedConstructorArgs, 
resolvedFields, resolvedConfig);
                             } else {
-                                return create(clazz, factoryMethodName, 
factoryMethodArgs, fields, config);
+                                return create(clazz, factoryMethodName, 
resolvedFactoryMethodArgs, resolvedFields, resolvedConfig);
+                            }
+                        }
+                        protected boolean requiresTask(Object value) {
+                            return (value instanceof TaskAdaptable || value 
instanceof TaskFactory);
+                        }
+                        protected Object resolveValue(Object value) {
+                            if (value instanceof DeferredSupplier) {
+                                return ((DeferredSupplier<?>) value).get();
                             }
+                            return value;
                         }
                     }, tasks);
         }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/fed6e511/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 ca4f91b..c372a72 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
@@ -18,6 +18,8 @@
  */
 package org.apache.brooklyn.camp.brooklyn;
 
+import static org.testng.Assert.assertEquals;
+
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -39,7 +41,10 @@ import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Charsets;
 import com.google.common.collect.Lists;
+import com.google.common.hash.HashCode;
+import com.google.common.hash.Hashing;
 
 @Test
 public class ObjectsYamlTest extends AbstractYamlTest {
@@ -54,6 +59,11 @@ public class ObjectsYamlTest extends AbstractYamlTest {
         private Object object;
 
         // Factory method.
+        public static TestObject newTestObjectWithNoArgs() {
+            return new TestObject("myDefaultFirst", 1, "myDefaultThird");
+        }
+
+        // Factory method.
         public static TestObject newTestObject(String string, Integer number, 
Object object) {
             return new TestObject(string + "-suffix", number + 1, object);
         }
@@ -84,6 +94,17 @@ public class ObjectsYamlTest extends AbstractYamlTest {
         }
     }
 
+    // TODO Copy of org.apache.brooklyn.rest.security.PasswordHasher; but this 
module does not
+    // have access to brooklyn-rest-resources (and would create a circular 
reference to do so)
+    public static class PasswordHasher {
+        public static String sha256(String salt, String password) {
+            if (salt == null) salt = "";
+            byte[] bytes = (salt + password).getBytes(Charsets.UTF_8);
+            HashCode hash = Hashing.sha256().hashBytes(bytes);
+            return hash.toString();
+        }
+    }
+
     public static class ConfigurableObject implements Configurable {
         public static final ConfigKey<Integer> INTEGER = 
ConfigKeys.newIntegerConfigKey("config.number");
         @SetFromFlag("object")
@@ -339,6 +360,212 @@ public class ObjectsYamlTest extends AbstractYamlTest {
         Assert.assertTrue(testObjectObject instanceof SimpleTestPojo, 
"Expected a SimpleTestPojo: "+testObjectObject);
     }
 
+    @Test
+    public void testBrooklynObjectWithFactoryMethodNoArgs() throws Exception {
+        Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+            "  brooklyn.config:",
+            "    test.confObject:",
+            "      $brooklyn:object:",
+            "        type: "+ObjectsYamlTest.class.getName()+"$TestObject",
+            "        factoryMethod.name: newTestObjectWithNoArgs");
+
+        TestObject testObject = (TestObject) 
testEntity.getConfig(TestEntity.CONF_OBJECT);
+        assertEquals(testObject.getString(), "myDefaultFirst");
+        assertEquals(testObject.getNumber(), Integer.valueOf(1));
+        assertEquals(testObject.getObject(), "myDefaultThird");
+    }
+
+    @Test
+    public void testFieldsAsDeferredSuppliers() throws Exception {
+        // all fields as deferred suppliers
+        {
+            Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+                "  brooklyn.config:",
+                "    mystring: myval",
+                "    myint: 123",
+                "    test.confObject:",
+                "      $brooklyn:object:",
+                "        type: "+ObjectsYamlTest.class.getName()+"$TestObject",
+                "        object.fields:",
+                "          number: $brooklyn:config(\"myint\")",
+                "          string: $brooklyn:config(\"mystring\")");
+    
+            TestObject testObject = (TestObject) 
testEntity.getConfig(TestEntity.CONF_OBJECT);
+            Assert.assertEquals(testObject.getNumber(), Integer.valueOf(123));
+            Assert.assertEquals(testObject.getString(), "myval");
+        }
+        
+        // Only first field as deferred supplier
+        {
+            Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+                    "  brooklyn.config:",
+                    "    mystring: myval",
+                    "    myint: 123",
+                    "    test.confObject:",
+                    "      $brooklyn:object:",
+                    "        type: 
"+ObjectsYamlTest.class.getName()+"$TestObject",
+                    "        object.fields:",
+                    "          number: $brooklyn:config(\"myint\")",
+                    "          string: myval");
+    
+                TestObject testObject = (TestObject) 
testEntity.getConfig(TestEntity.CONF_OBJECT);
+                Assert.assertEquals(testObject.getNumber(), 
Integer.valueOf(123));
+                Assert.assertEquals(testObject.getString(), "myval");
+        }
+        
+        // Only second field as deferred supplier
+        {
+            Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+                    "  brooklyn.config:",
+                    "    mystring: myval",
+                    "    myint: 123",
+                    "    test.confObject:",
+                    "      $brooklyn:object:",
+                    "        type: 
"+ObjectsYamlTest.class.getName()+"$TestObject",
+                    "        object.fields:",
+                    "          number: 7",
+                    "          string: $brooklyn:config(\"mystring\")");
+    
+                TestObject testObject = (TestObject) 
testEntity.getConfig(TestEntity.CONF_OBJECT);
+                Assert.assertEquals(testObject.getNumber(), 
Integer.valueOf(7));
+                Assert.assertEquals(testObject.getString(), "myval");
+        }
+    }
+
+    @Test
+    public void testConfigAsDeferredSuppliers() throws Exception {
+        // all fields as deferred suppliers
+        {
+            Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+                "  brooklyn.config:",
+                "    mystring: myval",
+                "    myint: 123",
+                "    mydouble: 1.4",
+                "    test.confObject:",
+                "      $brooklyn:object:",
+                "        type: 
"+ObjectsYamlTest.class.getName()+"$ConfigurableObject",
+                "        object.fields:",
+                "          double: $brooklyn:config(\"mydouble\")",
+                "        brooklyn.config:",
+                "          flag: $brooklyn:config(\"mystring\")",
+                "          config.number: $brooklyn:config(\"myint\")");
+    
+            ConfigurableObject testObject = (ConfigurableObject) 
testEntity.getConfig(TestEntity.CONF_OBJECT);
+            assertEquals(testObject.getDouble(), Double.valueOf(1.4));
+            assertEquals(testObject.getString(), "myval");
+            assertEquals(testObject.getNumber(), Integer.valueOf(123));
+        }
+        
+        // Only only fields (and not config) as deferred supplier
+        {
+            Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+                    "  brooklyn.config:",
+                    "    mystring: myval",
+                    "    myint: 123",
+                    "    mydouble: 1.4",
+                    "    test.confObject:",
+                    "      $brooklyn:object:",
+                    "        type: 
"+ObjectsYamlTest.class.getName()+"$ConfigurableObject",
+                    "        object.fields:",
+                    "          double: $brooklyn:config(\"mydouble\")",
+                    "        brooklyn.config:",
+                    "          flag: myval",
+                    "          config.number: 123");
+        
+                ConfigurableObject testObject = (ConfigurableObject) 
testEntity.getConfig(TestEntity.CONF_OBJECT);
+                assertEquals(testObject.getDouble(), Double.valueOf(1.4));
+                assertEquals(testObject.getString(), "myval");
+                assertEquals(testObject.getNumber(), Integer.valueOf(123));
+        }
+        
+        // Only config (and not fields) as deferred supplier
+        {
+            Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+                    "  brooklyn.config:",
+                    "    mystring: myval",
+                    "    myint: 123",
+                    "    mydouble: 1.4",
+                    "    test.confObject:",
+                    "      $brooklyn:object:",
+                    "        type: 
"+ObjectsYamlTest.class.getName()+"$ConfigurableObject",
+                    "        object.fields:",
+                    "          double: 1.4",
+                    "        brooklyn.config:",
+                    "          flag: $brooklyn:config(\"mystring\")",
+                    "          config.number: $brooklyn:config(\"myint\")");
+        
+                ConfigurableObject testObject = (ConfigurableObject) 
testEntity.getConfig(TestEntity.CONF_OBJECT);
+                assertEquals(testObject.getDouble(), Double.valueOf(1.4));
+                assertEquals(testObject.getString(), "myval");
+                assertEquals(testObject.getNumber(), Integer.valueOf(123));
+        }
+    }
+
+    @Test
+    public void testConstructorArgsAsDeferredSuppliers() throws Exception {
+        Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+                "  brooklyn.config:",
+                "    mystring: myval",
+                "    myint: 123",
+                "    mydouble: 1.4",
+                "    test.confObject:",
+                "      $brooklyn:object:",
+                "        type: "+ObjectsYamlTest.class.getName()+"$TestObject",
+                "        constructor.args:",
+                "        - $brooklyn:config(\"mystring\")",
+                "        - $brooklyn:config(\"myint\")",
+                "        - myThirdParam");
+
+        TestObject testObject = (TestObject) 
testEntity.getConfig(TestEntity.CONF_OBJECT);
+        assertEquals(testObject.getNumber(), Integer.valueOf(123));
+        assertEquals(testObject.getString(), "myval");
+        assertEquals(testObject.getObject(), "myThirdParam");
+    }
+    
+    @Test
+    public void testFactorArgsAsDeferredSuppliers() throws Exception {
+        Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+                "  brooklyn.config:",
+                "    mystring: myval",
+                "    myint: 123",
+                "    mydouble: 1.4",
+                "    test.confObject:",
+                "      $brooklyn:object:",
+                "        type: "+ObjectsYamlTest.class.getName()+"$TestObject",
+                "        factoryMethod.name: newTestObject",
+                "        factoryMethod.args:",
+                "        - $brooklyn:config(\"mystring\")",
+                "        - $brooklyn:config(\"myint\")",
+                "        - myThirdParam");
+
+        TestObject testObject = (TestObject) 
testEntity.getConfig(TestEntity.CONF_OBJECT);
+        assertEquals(testObject.getNumber(), Integer.valueOf(124)); // factory 
method adds one
+        assertEquals(testObject.getString(), "myval-suffix");
+        assertEquals(testObject.getObject(), "myThirdParam");
+    }
+
+    @Test
+    public void testCallingPasswordHasher() throws Exception {
+        Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+            "  brooklyn.config:",
+            "    brooklyn.password: mypassword",
+            "    brooklyn.password.sha256:",
+            "    brooklyn.password.salt: $brooklyn:entityId()",
+            "    brooklyn.password.sha256:",
+            "      $brooklyn:object:",
+            "        type: "+PasswordHasher.class.getName(),
+            "        factoryMethod.name: sha256",
+            "        factoryMethod.args:",
+            "        - $brooklyn:config(\"brooklyn.password.salt\")",
+            "        - $brooklyn:config(\"brooklyn.password\")");
+
+        String salt = (String) 
testEntity.config().get(ConfigKeys.newConfigKey(Object.class, 
"brooklyn.password.salt"));
+        String sha256 = (String) 
testEntity.config().get(ConfigKeys.newConfigKey(Object.class, 
"brooklyn.password.sha256"));
+
+        assertEquals(salt, testEntity.getId());
+        assertEquals(sha256, PasswordHasher.sha256(salt, "mypassword"));
+    }
+
     @Override
     protected Logger getLogger() {
         return log;

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/fed6e511/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 37f3fe6..5af8ae9 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
@@ -57,6 +57,7 @@ import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
 /**
@@ -891,7 +892,11 @@ public class Reflections {
             }
         }
         
-        return Maybe.absent("Method not found matching given args");
+        List<String> argTypes = Lists.newArrayList();
+        for (Object arg : args) {
+            argTypes.add(arg == null ? "<null>" : 
arg.getClass().getSimpleName());
+        }
+        return Maybe.absent("Method '"+method+"' not found matching given args 
of type "+argTypes);
     }
 
     /** true iff all args match the corresponding types */

Reply via email to