You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2019/05/24 10:12:44 UTC
[camel] 04/27: CAMEL-13557: Add property binding support to make it
convenient to configure components and whatnot.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 21f7433b2a3b89ffa65dad9bc66d818d4c89176c
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu May 23 06:03:42 2019 +0200
CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot.
---
.../camel/support/IntrospectionSupportTest.java | 90 +++++++++++++++++++++-
.../camel/support/PropertyBindingSupportTest.java | 13 ++++
.../apache/camel/support/IntrospectionSupport.java | 21 +++--
.../camel/support/PropertyBindingSupport.java | 21 ++---
4 files changed, 122 insertions(+), 23 deletions(-)
diff --git a/core/camel-core/src/test/java/org/apache/camel/support/IntrospectionSupportTest.java b/core/camel-core/src/test/java/org/apache/camel/support/IntrospectionSupportTest.java
index b2b87f5..874fe41 100644
--- a/core/camel-core/src/test/java/org/apache/camel/support/IntrospectionSupportTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/support/IntrospectionSupportTest.java
@@ -134,7 +134,95 @@ public class IntrospectionSupportTest extends ContextTestSupport {
return this;
}
}
-
+
+ @Test
+ public void testBuilderPatternWith() throws Exception {
+ MyBuilderPatternWithBean builderBean = new MyBuilderPatternWithBean();
+ IntrospectionSupport.setProperty(context.getTypeConverter(), builderBean, "name", "Donald");
+ IntrospectionSupport.setProperty(context.getTypeConverter(), builderBean, "age", "33");
+ IntrospectionSupport.setProperty(context.getTypeConverter(), builderBean, "gold-customer", "true");
+ assertEquals("Donald", builderBean.getName());
+ assertEquals(33, builderBean.getAge());
+ assertTrue(builderBean.isGoldCustomer());
+ }
+
+ public class MyBuilderPatternWithBean {
+ private String name;
+ private int age;
+ private boolean goldCustomer;
+
+ public MyBuilderPatternWithBean withName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public MyBuilderPatternWithBean withAge(int age) {
+ this.age = age;
+ return this;
+ }
+
+ public MyBuilderPatternWithBean withGoldCustomer(boolean goldCustomer) {
+ this.goldCustomer = goldCustomer;
+ return this;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public boolean isGoldCustomer() {
+ return goldCustomer;
+ }
+ }
+
+ @Test
+ public void testBuilderPattern() throws Exception {
+ MyBuilderPatternBean builderBean = new MyBuilderPatternBean();
+ IntrospectionSupport.setProperty(context.getTypeConverter(), builderBean, "name", "Goofy");
+ IntrospectionSupport.setProperty(context.getTypeConverter(), builderBean, "age", "34");
+ IntrospectionSupport.setProperty(context.getTypeConverter(), builderBean, "gold-customer", "true");
+ assertEquals("Goofy", builderBean.getName());
+ assertEquals(34, builderBean.getAge());
+ assertTrue(builderBean.isGoldCustomer());
+ }
+
+ public class MyBuilderPatternBean {
+ private String name;
+ private int age;
+ private boolean goldCustomer;
+
+ public MyBuilderPatternBean name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public MyBuilderPatternBean age(int age) {
+ this.age = age;
+ return this;
+ }
+
+ public MyBuilderPatternBean goldCustomer(boolean goldCustomer) {
+ this.goldCustomer = goldCustomer;
+ return this;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public boolean isGoldCustomer() {
+ return goldCustomer;
+ }
+ }
+
@Test
public void testIsSetterBuilderPatternSupport() throws Exception {
Method setter = MyBuilderBean.class.getMethod("setName", String.class);
diff --git a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java
index c55745f..86118be 100644
--- a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportTest.java
@@ -44,12 +44,14 @@ public class PropertyBindingSupportTest extends ContextTestSupport {
PropertyBindingSupport.bindProperty(context, foo, "name", "James");
PropertyBindingSupport.bindProperty(context, foo, "bar.age", "33");
PropertyBindingSupport.bindProperty(context, foo, "bar.rider", "true");
+ PropertyBindingSupport.bindProperty(context, foo, "bar.gold-customer", "true");
PropertyBindingSupport.bindProperty(context, foo, "bar.work.id", "123");
PropertyBindingSupport.bindProperty(context, foo, "bar.work.name", "Acme");
assertEquals("James", foo.getName());
assertEquals(33, foo.getBar().getAge());
assertTrue(foo.getBar().isRider());
+ assertTrue(foo.getBar().isGoldCustomer());
assertEquals(123, foo.getBar().getWork().getId());
assertEquals("Acme", foo.getBar().getWork().getName());
}
@@ -60,12 +62,14 @@ public class PropertyBindingSupportTest extends ContextTestSupport {
PropertyBindingSupport.bindProperty(context, foo, "name", "James");
PropertyBindingSupport.bindProperty(context, foo, "bar.age", "33");
+ PropertyBindingSupport.bindProperty(context, foo, "bar.gold-customer", "true");
PropertyBindingSupport.bindProperty(context, foo, "bar.rider", "true");
PropertyBindingSupport.bindProperty(context, foo, "bar.work", "#myWork");
assertEquals("James", foo.getName());
assertEquals(33, foo.getBar().getAge());
assertTrue(foo.getBar().isRider());
+ assertTrue(foo.getBar().isGoldCustomer());
assertEquals(456, foo.getBar().getWork().getId());
assertEquals("Acme", foo.getBar().getWork().getName());
}
@@ -95,6 +99,7 @@ public class PropertyBindingSupportTest extends ContextTestSupport {
private int age;
private boolean rider;
private Company work; // has no default value but Camel can automatic create one if there is a setter
+ private boolean goldCustomer;
public int getAge() {
return age;
@@ -119,6 +124,14 @@ public class PropertyBindingSupportTest extends ContextTestSupport {
public void setWork(Company work) {
this.work = work;
}
+
+ public boolean isGoldCustomer() {
+ return goldCustomer;
+ }
+
+ public void setGoldCustomer(boolean goldCustomer) {
+ this.goldCustomer = goldCustomer;
+ }
}
public static class Company {
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/IntrospectionSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/IntrospectionSupport.java
index 02d2f47..8e4ea5f 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/IntrospectionSupport.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/IntrospectionSupport.java
@@ -195,9 +195,14 @@ public final class IntrospectionSupport {
Class<?> type = method.getReturnType();
int parameterCount = method.getParameterCount();
- // is it a getXXX method
- if (name.startsWith("set") && name.length() >= 4 && Character.isUpperCase(name.charAt(3))) {
- return parameterCount == 1 && (type.equals(Void.TYPE) || (allowBuilderPattern && method.getDeclaringClass().isAssignableFrom(type)));
+ // is it a setXXX method
+ boolean validName = name.startsWith("set") && name.length() >= 4 && Character.isUpperCase(name.charAt(3));
+ if (validName) {
+ return parameterCount == 1 && type.equals(Void.TYPE);
+ }
+ // or if its a builder method
+ if (allowBuilderPattern && parameterCount == 1 && method.getDeclaringClass().isAssignableFrom(type)) {
+ return true;
}
return false;
@@ -680,15 +685,19 @@ public final class IntrospectionSupport {
public static Set<Method> findSetterMethods(Class<?> clazz, String name, boolean allowBuilderPattern) {
Set<Method> candidates = new LinkedHashSet<>();
- // Build the method name.
- name = "set" + StringHelper.capitalize(name, true);
+ // Build the method name
+ String builderName = "with" + StringHelper.capitalize(name, true);
+ String builderName2 = StringHelper.capitalize(name, true);
+ builderName2 = Character.toLowerCase(builderName2.charAt(0)) + builderName2.substring(1);
+ String setName = "set" + StringHelper.capitalize(name, true);
while (clazz != Object.class) {
// Since Object.class.isInstance all the objects,
// here we just make sure it will be add to the bottom of the set.
Method objectSetMethod = null;
Method[] methods = clazz.getMethods();
for (Method method : methods) {
- if (method.getName().equals(name) && isSetter(method, allowBuilderPattern)) {
+ boolean validName = method.getName().equals(setName) || allowBuilderPattern && method.getName().equals(builderName) || allowBuilderPattern && method.getName().equals(builderName2);
+ if (validName && isSetter(method, allowBuilderPattern)) {
Class<?>[] params = method.getParameterTypes();
if (params[0].equals(Object.class)) {
objectSetMethod = method;
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
index 85a98a1..66bb0b4 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/PropertyBindingSupport.java
@@ -17,15 +17,10 @@
package org.apache.camel.support;
import java.lang.reflect.Method;
-import java.util.Collection;
import java.util.Map;
import java.util.Set;
-import java.util.regex.Pattern;
import org.apache.camel.CamelContext;
-import org.apache.camel.TypeConverter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import static org.apache.camel.support.IntrospectionSupport.findSetterMethods;
import static org.apache.camel.support.IntrospectionSupport.getOrElseProperty;
@@ -34,7 +29,7 @@ import static org.apache.camel.support.IntrospectionSupport.getOrElseProperty;
* A convenient support class for binding String valued properties to an instance which
* uses a set of conventions:
* <ul>
- * <li>nested - Properties can be nested using the dot syntax (OGNL), eg foo.bar=123</li>
+ * <li>nested - Properties can be nested using the dot syntax (OGNL and builder pattern using with as prefix), eg foo.bar=123</li>
* <li>reference by id - Values can refer to other beans in the registry by prefixing with # syntax, eg #myBean</li>
* </ul>
* This implementations reuses parts of {@link IntrospectionSupport}.
@@ -42,10 +37,6 @@ import static org.apache.camel.support.IntrospectionSupport.getOrElseProperty;
public final class PropertyBindingSupport {
// TODO: Add support for auto binding to singleton instance by type from registry (boolean on|off)
- // TODO: builder pattern with naming prefix: withXXX
-
- private static final Pattern SECRETS = Pattern.compile(".*(passphrase|password|secretKey).*", Pattern.CASE_INSENSITIVE);
- private static final Logger LOG = LoggerFactory.getLogger(PropertyBindingSupport.class);
private PropertyBindingSupport() {
}
@@ -59,7 +50,7 @@ public final class PropertyBindingSupport {
}
public static boolean bindProperty(CamelContext camelContext, Object target, String name, Object value) throws Exception {
- return setProperty(camelContext, camelContext.getTypeConverter(), target, name, value, null, true, true);
+ return setProperty(camelContext, target, name, value, null, true, true);
}
/**
@@ -72,10 +63,9 @@ public final class PropertyBindingSupport {
* found matching the property name on the {@code target} bean. For this mode to be triggered the parameters
* {@code context} and {@code refName} must NOT be NULL, and {@code value} MUST be NULL.
*/
- private static boolean setProperty(CamelContext context, TypeConverter typeConverter, Object target, String name, Object value, String refName,
+ private static boolean setProperty(CamelContext context, Object target, String name, Object value, String refName,
boolean allowBuilderPattern, boolean allowNestedProperties) throws Exception {
Class<?> clazz = target.getClass();
- Collection<Method> setters;
// if name has dot then we need to OGNL walk it
if (allowNestedProperties && name.indexOf('.') > 0) {
@@ -88,7 +78,7 @@ public final class PropertyBindingSupport {
Object prop = getOrElseProperty(newTarget, part, null);
if (prop == null) {
// okay is there a setter so we can create a new instance and set it automatic
- Set<Method> newSetters = findSetterMethods(newClass, part, true);
+ Set<Method> newSetters = findSetterMethods(newClass, part, allowBuilderPattern);
if (newSetters.size() == 1) {
Method method = newSetters.iterator().next();
Class<?> parameterType = method.getParameterTypes()[0];
@@ -119,8 +109,7 @@ public final class PropertyBindingSupport {
}
}
- // TODO: At this point we can likely just call IntrospectionSupport directly
- return IntrospectionSupport.setProperty(context, context.getTypeConverter(), target, name, value, refName, true);
+ return IntrospectionSupport.setProperty(context, context.getTypeConverter(), target, name, value, refName, allowBuilderPattern);
}
}