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 2013/03/07 12:07:32 UTC
svn commit: r1453773 - in /camel/trunk/camel-core/src:
main/java/org/apache/camel/spi/ main/java/org/apache/camel/util/
test/java/org/apache/camel/util/
Author: davsclaus
Date: Thu Mar 7 11:07:31 2013
New Revision: 1453773
URL: http://svn.apache.org/r1453773
Log:
CAMEL-6130: Setting refernece parameters on endpoints improved to provide class type when looking up in Registry. This fixes lookup with OSGi where the OSGi Service Registry mandates registering the service with its class type. Thanks to Aaron Whiteside for the patch and his hard work on this.
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/spi/Registry.java
camel/trunk/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/spi/Registry.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/spi/Registry.java?rev=1453773&r1=1453772&r2=1453773&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/spi/Registry.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/spi/Registry.java Thu Mar 7 11:07:31 2013
@@ -79,7 +79,7 @@ public interface Registry {
Object lookup(String name);
/**
- * Looks up a service in the registry, returning the service or <tt>null</tt> if it could not be found.
+ * Looks up a service in the registry, returning the service or <tt>null</tt> if it could not be found. cha
*
* @param name the name of the service
* @param type the type of the required service
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java?rev=1453773&r1=1453772&r2=1453773&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java Thu Mar 7 11:07:31 2013
@@ -16,6 +16,7 @@
*/
package org.apache.camel.util;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -29,6 +30,7 @@ import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
+import org.apache.camel.NoTypeConversionAvailableException;
import org.apache.camel.PollingConsumer;
import org.apache.camel.Processor;
import org.apache.camel.ResolveEndpointFailedException;
@@ -260,6 +262,7 @@ public final class EndpointHelper {
* @param parameters parameters
* @throws Exception is thrown if setting property fails
*/
+ @SuppressWarnings("unchecked")
public static void setReferenceProperties(CamelContext context, Object bean, Map<String, Object> parameters) throws Exception {
Iterator<Map.Entry<String, Object>> it = parameters.entrySet().iterator();
while (it.hasNext()) {
@@ -268,18 +271,41 @@ public final class EndpointHelper {
Object v = entry.getValue();
String value = v != null ? v.toString() : null;
if (value != null && isReferenceParameter(value)) {
- // For backwards-compatibility reasons, no mandatory lookup is done here
- Object ref = resolveReferenceParameter(context, value, Object.class, false);
- if (ref != null) {
- boolean hit = IntrospectionSupport.setProperty(context.getTypeConverter(), bean, name, ref);
- if (hit) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Configured property: {} on bean: {} with value: {}", new Object[]{name, bean, ref});
+ List<Method> candidates = IntrospectionSupport.findSetterMethodsOrderedByParameterType(bean.getClass(), name, false);
+
+ Exception typeConversionFailed = null;
+ for (Method setter : candidates) {
+ Class parameterType = setter.getParameterTypes()[0];
+ // For backwards-compatibility reasons, no mandatory lookup is done here
+ Object ref = resolveReferenceParameter(context, value, parameterType, false);
+ if (ref != null) {
+ try {
+ boolean hit = IntrospectionSupport.setProperty(context.getTypeConverter(), bean, setter, ref);
+
+ if (hit) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Configured property: {} on bean: {} with value: {}", new Object[]{name, bean, ref});
+ }
+ // must remove as its a valid option and we could configure it
+ it.remove();
+ typeConversionFailed = null;
+ break;
+ }
+ } catch (NoTypeConversionAvailableException e) {
+ typeConversionFailed = e;
+ } catch (IllegalArgumentException e) {
+ typeConversionFailed = e;
}
- // must remove as its a valid option and we could configure it
- it.remove();
}
}
+
+ if (typeConversionFailed != null) {
+ // we did not find a setter method to use, and if we did try to use a type converter then throw
+ // this kind of exception as the caused by will hint this error
+ throw new IllegalArgumentException("Could not find a suitable setter for property: " + name
+ + " as there isn't a setter method with same type: " + value.getClass().getCanonicalName()
+ + " nor type conversion possible: " + typeConversionFailed.getMessage());
+ }
}
}
}
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java?rev=1453773&r1=1453772&r2=1453773&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java Thu Mar 7 11:07:31 2013
@@ -25,9 +25,11 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -69,6 +71,28 @@ public final class IntrospectionSupport
EXCLUDED_METHODS.addAll(Arrays.asList(Proxy.class.getMethods()));
}
+ private static final Set<Class> PRIMITIVE_CLASSES = new HashSet<Class>();
+
+ static {
+ PRIMITIVE_CLASSES.add(String.class);
+ PRIMITIVE_CLASSES.add(Character.class);
+ PRIMITIVE_CLASSES.add(Boolean.class);
+ PRIMITIVE_CLASSES.add(Byte.class);
+ PRIMITIVE_CLASSES.add(Short.class);
+ PRIMITIVE_CLASSES.add(Integer.class);
+ PRIMITIVE_CLASSES.add(Long.class);
+ PRIMITIVE_CLASSES.add(Float.class);
+ PRIMITIVE_CLASSES.add(Double.class);
+ PRIMITIVE_CLASSES.add(char.class);
+ PRIMITIVE_CLASSES.add(boolean.class);
+ PRIMITIVE_CLASSES.add(byte.class);
+ PRIMITIVE_CLASSES.add(short.class);
+ PRIMITIVE_CLASSES.add(int.class);
+ PRIMITIVE_CLASSES.add(long.class);
+ PRIMITIVE_CLASSES.add(float.class);
+ PRIMITIVE_CLASSES.add(double.class);
+ }
+
/**
* Structure of an introspected class.
*/
@@ -415,47 +439,52 @@ public final class IntrospectionSupport
}
public static boolean setProperty(TypeConverter typeConverter, Object target, String name, Object value, boolean allowBuilderPattern) throws Exception {
- try {
- Class<?> clazz = target.getClass();
- // find candidates of setter methods as there can be overloaded setters
- Set<Method> setters = findSetterMethods(typeConverter, clazz, name, value, allowBuilderPattern);
- if (setters.isEmpty()) {
- return false;
- }
+ Class<?> clazz = target.getClass();
+ // find candidates of setter methods as there can be overloaded setters
+ Set<Method> setters = findSetterMethods(clazz, name, value, allowBuilderPattern);
+ if (setters.isEmpty()) {
+ return false;
+ }
- // loop and execute the best setter method
- Exception typeConversionFailed = null;
- for (Method setter : setters) {
- // If the type is null or it matches the needed type, just use the value directly
- if (value == null || setter.getParameterTypes()[0].isAssignableFrom(value.getClass())) {
- setter.invoke(target, value);
- return true;
- } else {
- // We need to convert it
- try {
- // ignore exceptions as there could be another setter method where we could type convert successfully
- Object convertedValue = convert(typeConverter, setter.getParameterTypes()[0], value);
- setter.invoke(target, convertedValue);
- return true;
- } catch (NoTypeConversionAvailableException e) {
- typeConversionFailed = e;
- } catch (IllegalArgumentException e) {
- typeConversionFailed = e;
- }
- if (LOG.isTraceEnabled()) {
- LOG.trace("Setter \"{}\" with parameter type \"{}\" could not be used for type conversions of {}",
- new Object[]{setter, setter.getParameterTypes()[0], value});
- }
- }
+ // loop and execute the best setter method
+ Exception typeConversionFailed = null;
+ for (Method setter : setters) {
+ try {
+ return setProperty(typeConverter, target, setter, value);
+ // ignore exceptions as there could be another setter method where we could type convert successfully
+ } catch (NoTypeConversionAvailableException e) {
+ typeConversionFailed = e;
+ } catch (IllegalArgumentException e) {
+ typeConversionFailed = e;
+ }
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Setter \"{}\" with parameter type \"{}\" could not be used for type conversions of {}",
+ new Object[]{setter, setter.getParameterTypes()[0], value});
}
+ }
+
+ if (typeConversionFailed != null) {
// we did not find a setter method to use, and if we did try to use a type converter then throw
// this kind of exception as the caused by will hint this error
- if (typeConversionFailed != null) {
- throw new IllegalArgumentException("Could not find a suitable setter for property: " + name
- + " as there isn't a setter method with same type: " + value.getClass().getCanonicalName()
- + " nor type conversion possible: " + typeConversionFailed.getMessage());
+ throw new IllegalArgumentException("Could not find a suitable setter for property: " + name
+ + " as there isn't a setter method with same type: " + value.getClass().getCanonicalName()
+ + " nor type conversion possible: " + typeConversionFailed.getMessage());
+ } else {
+ return false;
+ }
+ }
+
+ public static boolean setProperty(TypeConverter typeConverter, Object target, Method setter, Object value) throws Exception {
+ try {
+ // If the type is null or it matches the needed type, just use the value directly
+ if (value == null || setter.getParameterTypes()[0].isAssignableFrom(value.getClass())) {
+ setter.invoke(target, value);
+ return true;
} else {
- return false;
+ // We need to convert it
+ Object convertedValue = convert(typeConverter, setter.getParameterTypes()[0], value);
+ setter.invoke(target, convertedValue);
+ return true;
}
} catch (InvocationTargetException e) {
// lets unwrap the exception
@@ -469,9 +498,10 @@ public final class IntrospectionSupport
}
}
}
-
+
public static boolean setProperty(TypeConverter typeConverter, Object target, String name, Object value) throws Exception {
- return setProperty(typeConverter, target, name, value, false);
+ // allow build pattern as a setter as well
+ return setProperty(typeConverter, target, name, value, true);
}
public static boolean setProperty(Object target, String name, Object value, boolean allowBuilderPattern) throws Exception {
@@ -479,7 +509,8 @@ public final class IntrospectionSupport
}
public static boolean setProperty(Object target, String name, Object value) throws Exception {
- return setProperty(target, name, value, false);
+ // allow build pattern as a setter as well
+ return setProperty(target, name, value, true);
}
private static Object convert(TypeConverter typeConverter, Class<?> type, Object value)
@@ -502,8 +533,8 @@ public final class IntrospectionSupport
}
return null;
}
-
- private static Set<Method> findSetterMethods(TypeConverter typeConverter, Class<?> clazz, String name, Object value, boolean allowBuilderPattern) {
+
+ public static Set<Method> findSetterMethods(Class<?> clazz, String name, boolean allowBuilderPattern) {
Set<Method> candidates = new LinkedHashSet<Method>();
// Build the method name.
@@ -514,12 +545,11 @@ public final class IntrospectionSupport
Method objectSetMethod = null;
Method[] methods = clazz.getMethods();
for (Method method : methods) {
- Class<?> params[] = method.getParameterTypes();
- if (method.getName().equals(name) && params.length == 1) {
- Class<?> paramType = params[0];
- if (paramType.equals(Object.class)) {
+ if (method.getName().equals(name) && isSetter(method, allowBuilderPattern)) {
+ Class<?> params[] = method.getParameterTypes();
+ if (params[0].equals(Object.class)) {
objectSetMethod = method;
- } else if (typeConverter != null || isSetter(method, allowBuilderPattern) || paramType.isInstance(value)) {
+ } else {
candidates.add(method);
}
}
@@ -529,6 +559,11 @@ public final class IntrospectionSupport
}
clazz = clazz.getSuperclass();
}
+ return candidates;
+ }
+
+ private static Set<Method> findSetterMethods(Class<?> clazz, String name, Object value, boolean allowBuilderPattern) {
+ Set<Method> candidates = findSetterMethods(clazz, name, allowBuilderPattern);
if (candidates.isEmpty()) {
return candidates;
@@ -552,5 +587,22 @@ public final class IntrospectionSupport
return candidates;
}
}
-
+
+ public static List<Method> findSetterMethodsOrderedByParameterType(Class<?> target, String propertyName, boolean allowBuilderPattern) {
+ List<Method> answer = new LinkedList<Method>();
+ List<Method> primitives = new LinkedList<Method>();
+ Set<Method> setters = findSetterMethods(target, propertyName, allowBuilderPattern);
+ for (Method setter : setters) {
+ Class parameterType = setter.getParameterTypes()[0];
+ if (PRIMITIVE_CLASSES.contains(parameterType)) {
+ primitives.add(setter);
+ } else {
+ answer.add(setter);
+ }
+ }
+ // primitives get added last
+ answer.addAll(primitives);
+ return answer;
+ }
+
}
Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java?rev=1453773&r1=1453772&r2=1453773&view=diff
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java (original)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java Thu Mar 7 11:07:31 2013
@@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -375,5 +376,15 @@ public class IntrospectionSupportTest ex
assertEquals(1, params.size());
assertEquals("yes", params.get("bar"));
}
+
+ public void testFindSetterMethodsOrderedByParameterType() throws Exception {
+ List<Method> setters = IntrospectionSupport.findSetterMethodsOrderedByParameterType(MyOverloadedBean.class, "bean", false);
+
+ assertNotNull(setters);
+ assertEquals(2, setters.size());
+
+ assertEquals(ExampleBean.class, setters.get(0).getParameterTypes()[0]);
+ assertEquals(String.class, setters.get(1).getParameterTypes()[0]);
+ }
}