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/23 19:30:48 UTC
[camel] 02/18: 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 13557
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 7afdee74a7667e3d2c26605266a4219abdbb2c28
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed May 22 21:53:23 2019 +0200
CAMEL-13557: Add property binding support to make it convenient to configure components and whatnot.
---
.../apache/camel/support/IntrospectionSupport.java | 65 ++---------------
.../camel/support/PropertyBindingSupport.java | 84 ++++++++++++++++++++--
2 files changed, 85 insertions(+), 64 deletions(-)
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 28a1e3f..02d2f47 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
@@ -516,65 +516,10 @@ public final class IntrospectionSupport {
*/
public static boolean setProperty(CamelContext context, TypeConverter typeConverter, Object target, String name, Object value, String refName,
boolean allowBuilderPattern) throws Exception {
- return setProperty(context, typeConverter, target, name, value, refName, allowBuilderPattern, false);
- }
- /**
- * This method supports two modes to set a property:
- *
- * 1. Setting a property that has already been resolved, this is the case when {@code context} and {@code refName} are
- * NULL and {@code value} is non-NULL.
- *
- * 2. Setting a property that has not yet been resolved, the property will be resolved based on the suitable methods
- * 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.
- */
- public static boolean setProperty(CamelContext context, TypeConverter typeConverter, 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) {
- String[] parts = name.split("\\.");
- Object newTarget = target;
- Class<?> newClass = clazz;
- // we should only iterate until until 2nd last so we use -1 in the for loop
- for (int i = 0; i < parts.length - 1; i++) {
- String part = parts[i];
- 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);
- if (newSetters.size() == 1) {
- Method method = newSetters.iterator().next();
- Class<?> parameterType = method.getParameterTypes()[0];
- if (parameterType != null && org.apache.camel.util.ObjectHelper.hasDefaultPublicNoArgConstructor(parameterType)) {
- Object instance = context.getInjector().newInstance(parameterType);
- if (instance != null) {
- org.apache.camel.support.ObjectHelper.invokeMethod(method, newTarget, instance);
- newTarget = instance;
- newClass = newTarget.getClass();
- }
- }
- }
- } else {
- newTarget = prop;
- newClass = newTarget.getClass();
- }
- }
- // okay we found a nested property, then lets change to use that
- target = newTarget;
- clazz = newTarget.getClass();
- name = parts[parts.length - 1];
- if (value instanceof String) {
- if (EndpointHelper.isReferenceParameter(value.toString())) {
- // okay its a reference so swap to lookup this
- refName = value.toString();
- value = null;
- }
- }
- }
-
// we need to lookup the value from the registry
if (context != null && refName != null && value == null) {
setters = findSetterMethodsOrderedByParameterType(clazz, name, allowBuilderPattern);
@@ -676,7 +621,7 @@ public final class IntrospectionSupport {
}
}
- private static boolean isPropertyPlaceholder(CamelContext context, Object value) {
+ static boolean isPropertyPlaceholder(CamelContext context, Object value) {
if (context != null) {
PropertiesComponent pc = context.getPropertiesComponent(false);
if (pc != null) {
@@ -711,7 +656,7 @@ public final class IntrospectionSupport {
return setProperty(target, name, value, true);
}
- private static Object convert(TypeConverter typeConverter, Class<?> type, Object value)
+ static Object convert(TypeConverter typeConverter, Class<?> type, Object value)
throws URISyntaxException, NoTypeConversionAvailableException {
if (typeConverter != null) {
return typeConverter.mandatoryConvertTo(type, value);
@@ -760,7 +705,7 @@ public final class IntrospectionSupport {
return candidates;
}
- private static Set<Method> findSetterMethods(Class<?> clazz, String name, Object value, boolean allowBuilderPattern) {
+ static Set<Method> findSetterMethods(Class<?> clazz, String name, Object value, boolean allowBuilderPattern) {
Set<Method> candidates = findSetterMethods(clazz, name, allowBuilderPattern);
if (candidates.isEmpty()) {
@@ -786,7 +731,7 @@ public final class IntrospectionSupport {
}
}
- protected static List<Method> findSetterMethodsOrderedByParameterType(Class<?> target, String propertyName, boolean allowBuilderPattern) {
+ static List<Method> findSetterMethodsOrderedByParameterType(Class<?> target, String propertyName, boolean allowBuilderPattern) {
List<Method> answer = new LinkedList<>();
List<Method> primitives = new LinkedList<>();
Set<Method> setters = findSetterMethods(target, propertyName, allowBuilderPattern);
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 b9d98bf..38b2d10 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
@@ -16,20 +16,34 @@
*/
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 java.util.Map;
+import static org.apache.camel.support.IntrospectionSupport.findSetterMethods;
+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)</li>
- * <li>reference by id - Values can refer to other beans by their id using # syntax</li>
+ * <li>nested - Properties can be nested using the dot syntax (OGNL), 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}.
*/
public final class PropertyBindingSupport {
+ private static final Pattern SECRETS = Pattern.compile(".*(passphrase|password|secretKey).*", Pattern.CASE_INSENSITIVE);
+ private static final Logger LOG = LoggerFactory.getLogger(PropertyBindingSupport.class);
+
private PropertyBindingSupport() {
}
@@ -42,6 +56,68 @@ public final class PropertyBindingSupport {
}
public static boolean bindProperty(CamelContext camelContext, Object target, String name, Object value) throws Exception {
- return IntrospectionSupport.setProperty(camelContext, camelContext.getTypeConverter(), target, name, value, null, true, true);
+ return setProperty(camelContext, camelContext.getTypeConverter(), target, name, value, null, true, true);
+ }
+
+ /**
+ * This method supports two modes to set a property:
+ *
+ * 1. Setting a property that has already been resolved, this is the case when {@code context} and {@code refName} are
+ * NULL and {@code value} is non-NULL.
+ *
+ * 2. Setting a property that has not yet been resolved, the property will be resolved based on the suitable methods
+ * 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,
+ 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) {
+ String[] parts = name.split("\\.");
+ Object newTarget = target;
+ Class<?> newClass = clazz;
+ // we should only iterate until until 2nd last so we use -1 in the for loop
+ for (int i = 0; i < parts.length - 1; i++) {
+ String part = parts[i];
+ 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);
+ if (newSetters.size() == 1) {
+ Method method = newSetters.iterator().next();
+ Class<?> parameterType = method.getParameterTypes()[0];
+ if (parameterType != null && org.apache.camel.util.ObjectHelper.hasDefaultPublicNoArgConstructor(parameterType)) {
+ Object instance = context.getInjector().newInstance(parameterType);
+ if (instance != null) {
+ org.apache.camel.support.ObjectHelper.invokeMethod(method, newTarget, instance);
+ newTarget = instance;
+ newClass = newTarget.getClass();
+ }
+ }
+ }
+ } else {
+ newTarget = prop;
+ newClass = newTarget.getClass();
+ }
+ }
+ // okay we found a nested property, then lets change to use that
+ target = newTarget;
+ clazz = newTarget.getClass();
+ name = parts[parts.length - 1];
+ if (value instanceof String) {
+ if (EndpointHelper.isReferenceParameter(value.toString())) {
+ // okay its a reference so swap to lookup this
+ refName = value.toString();
+ value = null;
+ }
+ }
+ }
+
+ // TODO: At this point we can likely just call IntrospectionSupport directly
+ return IntrospectionSupport.setProperty(context, context.getTypeConverter(), target, name, value, refName, true);
}
+
}