Author: davsclaus
Date: Thu Mar 7 13:37:02 2013
New Revision: 1453859
URL: http://svn.apache.org/r1453859
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/branches/camel-2.10.x/ (props changed)
camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/spi/Registry.java
camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
camel/branches/camel-2.10.x/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java
Propchange: camel/branches/camel-2.10.x/
------------------------------------------------------------------------------
Merged /camel/trunk:r1453773
Propchange: camel/branches/camel-2.10.x/
------------------------------------------------------------------------------
Binary property 'svnmerge-integrated' - no diff available.
Modified:
camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/spi/Registry.java
URL:
http://svn.apache.org/viewvc/camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/spi/Registry.java?rev=1453859&r1=1453858&r2=1453859&view=diff
==============================================================================
---
camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/spi/Registry.java
(original)
+++
camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/spi/Registry.java
Thu Mar 7 13:37:02 2013
@@ -36,7 +36,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/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
URL:
http://svn.apache.org/viewvc/camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java?rev=1453859&r1=1453858&r2=1453859&view=diff
==============================================================================
---
camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
(original)
+++
camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/EndpointHelper.java
Thu Mar 7 13:37:02 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/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
URL:
http://svn.apache.org/viewvc/camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java?rev=1453859&r1=1453858&r2=1453859&view=diff
==============================================================================
---
camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
(original)
+++
camel/branches/camel-2.10.x/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
Thu Mar 7 13:37:02 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;
@@ -56,6 +58,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);
+ }
+
/**
* Utility classes should not have a public constructor.
*/
@@ -308,47 +332,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
@@ -362,9 +391,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 {
@@ -372,7 +402,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)
@@ -390,8 +421,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.
@@ -402,12 +433,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);
}
}
@@ -417,6 +447,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;
@@ -440,5 +475,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/branches/camel-2.10.x/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java
URL:
http://svn.apache.org/viewvc/camel/branches/camel-2.10.x/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java?rev=1453859&r1=1453858&r2=1453859&view=diff
==============================================================================
---
camel/branches/camel-2.10.x/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java
(original)
+++
camel/branches/camel-2.10.x/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java
Thu Mar 7 13:37:02 2013
@@ -22,6 +22,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -356,5 +357,15 @@ public class IntrospectionSupportTest ex
assertEquals(false, IntrospectionSupport.isGetter(setupSomething));
assertEquals(false, IntrospectionSupport.isSetter(setupSomething));
}
+
+ 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]);
+ }
}