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 <claus.ib...@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); } + }