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