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));