You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by lb...@apache.org on 2020/08/12 10:37:05 UTC
[camel] branch master updated: Inprove PropertyBindingSupport
(CAMEL-15396, CAMEL-15397)
This is an automated email from the ASF dual-hosted git repository.
lburgazzoli pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/master by this push:
new ab54bed Inprove PropertyBindingSupport (CAMEL-15396, CAMEL-15397)
ab54bed is described below
commit ab54bed173977fa8d386a330002f2119b3441a3b
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Tue Aug 11 17:20:12 2020 +0200
Inprove PropertyBindingSupport (CAMEL-15396, CAMEL-15397)
This PR adds support for arrays in PropertyBindingSupport and fix issues when binding to list when properties have gaps.
See tests in:
- PropertyBindingSupportArrayTest
- PropertyBindingSupportListTest
---
.../camel/support/IntrospectionSupportTest.java | 30 ++++++
...t.java => PropertyBindingSupportArrayTest.java} | 110 +++++++++++++++------
.../support/PropertyBindingSupportListTest.java | 51 +++++++++-
.../support/PropertyBindingSupportMapTest.java | 2 +-
.../apache/camel/support/IntrospectionSupport.java | 55 +++++++++--
.../camel/support/PropertyBindingSupport.java | 63 +++++++++++-
.../camel/support/PropertyConfigurerHelper.java | 70 +++++++++++++
7 files changed, 336 insertions(+), 45 deletions(-)
diff --git a/core/camel-core/src/test/java/org/apache/camel/support/IntrospectionSupportTest.java b/core/camel-core/src/test/java/org/apache/camel/support/IntrospectionSupportTest.java
index 07fbe38..18ae51e 100644
--- a/core/camel-core/src/test/java/org/apache/camel/support/IntrospectionSupportTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/support/IntrospectionSupportTest.java
@@ -564,4 +564,34 @@ public class IntrospectionSupportTest extends ContextTestSupport {
assertEquals(ExampleBean.class, setters.get(0).getParameterTypes()[0]);
assertEquals(String.class, setters.get(1).getParameterTypes()[0]);
}
+
+
+ @Test
+ public void testArray() throws Exception {
+ MyBeanWithArray target = new MyBeanWithArray();
+ IntrospectionSupport.setProperty(context.getTypeConverter(), target, "names[0]", "James");
+ IntrospectionSupport.setProperty(context.getTypeConverter(), target, "names[1]", "Claus");
+ assertEquals("James", target.getNames()[0]);
+ assertEquals("Claus", target.getNames()[1]);
+
+ IntrospectionSupport.setProperty(context.getTypeConverter(), target, "names[0]", "JamesX");
+ assertEquals("JamesX", target.getNames()[0]);
+
+ IntrospectionSupport.setProperty(context.getTypeConverter(), target, "names[2]", "Andrea");
+ assertEquals("JamesX", target.getNames()[0]);
+ assertEquals("Claus", target.getNames()[1]);
+ assertEquals("Andrea", target.getNames()[2]);
+ }
+
+ public class MyBeanWithArray {
+ private String[] names = new String[10];
+
+ public String[] getNames() {
+ return names;
+ }
+
+ public void setNames(String[] names) {
+ this.names = names;
+ }
+ }
}
diff --git a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportListTest.java b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportArrayTest.java
similarity index 59%
copy from core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportListTest.java
copy to core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportArrayTest.java
index 83a1acc..88bf95b 100644
--- a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportListTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportArrayTest.java
@@ -17,7 +17,6 @@
package org.apache.camel.support;
import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -26,12 +25,15 @@ import org.apache.camel.ContextTestSupport;
import org.apache.camel.PropertyBindingException;
import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.*;
+import static org.apache.camel.util.CollectionHelper.mapOf;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
/**
* Unit test for PropertyBindingSupport
*/
-public class PropertyBindingSupportListTest extends ContextTestSupport {
+public class PropertyBindingSupportArrayTest extends ContextTestSupport {
@Override
protected CamelContext createCamelContext() throws Exception {
@@ -55,7 +57,7 @@ public class PropertyBindingSupportListTest extends ContextTestSupport {
}
@Test
- public void testPropertiesList() throws Exception {
+ public void testPropertiesArray() throws Exception {
Foo foo = new Foo();
Map<String, Object> prop = new LinkedHashMap<>();
@@ -72,15 +74,40 @@ public class PropertyBindingSupportListTest extends ContextTestSupport {
assertEquals(33, foo.getBar().getAge());
assertTrue(foo.getBar().isRider());
assertTrue(foo.getBar().isGoldCustomer());
- assertEquals(2, foo.getBar().getWorks().size());
- assertEquals(123, foo.getBar().getWorks().get(0).getId());
- assertEquals("Acme", foo.getBar().getWorks().get(0).getName());
- assertEquals(456, foo.getBar().getWorks().get(1).getId());
- assertEquals("Acme 2", foo.getBar().getWorks().get(1).getName());
+ assertEquals(2, foo.getBar().getWorks().length);
+ assertEquals(123, foo.getBar().getWorks()[0].getId());
+ assertEquals("Acme", foo.getBar().getWorks()[0].getName());
+ assertEquals(456, foo.getBar().getWorks()[1].getId());
+ assertEquals("Acme 2", foo.getBar().getWorks()[1].getName());
}
@Test
- public void testPropertiesListNested() throws Exception {
+ public void testPropertiesArrayWithGaps() throws Exception {
+ Foo foo = new Foo();
+
+ Map<String, Object> prop = new LinkedHashMap<>();
+ prop.put("name", "James");
+ prop.put("bar.age", "33");
+ prop.put("bar.{{committer}}", "true");
+ prop.put("bar.gold-customer", "true");
+ prop.put("bar.works[5]", "#bean:company1");
+ prop.put("bar.works[9]", "#bean:company2");
+
+ PropertyBindingSupport.build().bind(context, foo, prop);
+
+ assertEquals("James", foo.getName());
+ assertEquals(33, foo.getBar().getAge());
+ assertTrue(foo.getBar().isRider());
+ assertTrue(foo.getBar().isGoldCustomer());
+ assertEquals(10, foo.getBar().getWorks().length);
+ assertEquals(123, foo.getBar().getWorks()[5].getId());
+ assertEquals("Acme", foo.getBar().getWorks()[5].getName());
+ assertEquals(456, foo.getBar().getWorks()[9].getId());
+ assertEquals("Acme 2", foo.getBar().getWorks()[9].getName());
+ }
+
+ @Test
+ public void testPropertiesArrayNested() throws Exception {
Foo foo = new Foo();
Map<String, Object> prop = new LinkedHashMap<>();
@@ -99,15 +126,36 @@ public class PropertyBindingSupportListTest extends ContextTestSupport {
assertEquals(33, foo.getBar().getAge());
assertTrue(foo.getBar().isRider());
assertTrue(foo.getBar().isGoldCustomer());
- assertEquals(2, foo.getBar().getWorks().size());
- assertEquals(666, foo.getBar().getWorks().get(0).getId());
- assertEquals("Acme", foo.getBar().getWorks().get(0).getName());
- assertEquals(456, foo.getBar().getWorks().get(1).getId());
- assertEquals("I changed this", foo.getBar().getWorks().get(1).getName());
+ assertEquals(2, foo.getBar().getWorks().length);
+ assertEquals(666, foo.getBar().getWorks()[0].getId());
+ assertEquals("Acme", foo.getBar().getWorks()[0].getName());
+ assertEquals(456, foo.getBar().getWorks()[1].getId());
+ assertEquals("I changed this", foo.getBar().getWorks()[1].getName());
}
@Test
- public void testPropertiesListFirst() throws Exception {
+ public void testPropertiesArrayNestedSimple() throws Exception {
+ Foo foo = new Foo();
+
+ PropertyBindingSupport.build().bind(context, foo, mapOf(
+ "bar.works[0].id", "666",
+ "bar.works[1].name", "I changed this"
+ ));
+
+ assertEquals(666, foo.bar.works[0].getId());
+ assertEquals("I changed this", foo.bar.works[1].getName());
+
+ PropertyBindingSupport.build().bind(context, foo, mapOf(
+ "bar.works[0].id", "999",
+ "bar.works[1].name", "I changed this again"
+ ));
+
+ assertEquals(999, foo.bar.works[0].getId());
+ assertEquals("I changed this again", foo.bar.works[1].getName());
+ }
+
+ @Test
+ public void testPropertiesArrayFirst() throws Exception {
Bar bar = new Bar();
Map<String, Object> prop = new LinkedHashMap<>();
@@ -118,15 +166,15 @@ public class PropertyBindingSupportListTest extends ContextTestSupport {
PropertyBindingSupport.build().bind(context, bar, prop);
- assertEquals(2, bar.getWorks().size());
- assertEquals(666, bar.getWorks().get(0).getId());
- assertEquals("Acme", bar.getWorks().get(0).getName());
- assertEquals(456, bar.getWorks().get(1).getId());
- assertEquals("I changed this", bar.getWorks().get(1).getName());
+ assertEquals(2, bar.getWorks().length);
+ assertEquals(666, bar.getWorks()[0].getId());
+ assertEquals("Acme", bar.getWorks()[0].getName());
+ assertEquals(456, bar.getWorks()[1].getId());
+ assertEquals("I changed this", bar.getWorks()[1].getName());
}
@Test
- public void testPropertiesNotList() throws Exception {
+ public void testPropertiesNotArray() throws Exception {
Foo foo = new Foo();
Map<String, Object> prop = new LinkedHashMap<>();
@@ -140,13 +188,13 @@ public class PropertyBindingSupportListTest extends ContextTestSupport {
} catch (PropertyBindingException e) {
assertEquals("bar.gold-customer[]", e.getPropertyName());
IllegalArgumentException iae = assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
- assertTrue(iae.getMessage().startsWith("Cannot set property: gold-customer[] as either a Map/List because target bean is not a Map or List type"));
+ assertTrue(iae.getMessage().startsWith("Cannot set property: gold-customer[] as either a Map/List/array because target bean is not a Map, List or array type"));
}
}
public static class Foo {
- private String name;
- private Bar bar = new Bar();
+ String name;
+ Bar bar = new Bar();
public String getName() {
return name;
@@ -166,10 +214,10 @@ public class PropertyBindingSupportListTest extends ContextTestSupport {
}
public static class Bar {
- private int age;
- private boolean rider;
- private List<Company> works; // should auto-create this via the setter
- private boolean goldCustomer;
+ int age;
+ boolean rider;
+ Company[] works; // should auto-create this via the setter
+ boolean goldCustomer;
public int getAge() {
return age;
@@ -187,11 +235,11 @@ public class PropertyBindingSupportListTest extends ContextTestSupport {
this.rider = rider;
}
- public List<Company> getWorks() {
+ public Company[] getWorks() {
return works;
}
- public void setWorks(List<Company> works) {
+ public void setWorks(Company[] works) {
this.works = works;
}
diff --git a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportListTest.java b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportListTest.java
index 83a1acc..11c4892 100644
--- a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportListTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportListTest.java
@@ -26,7 +26,10 @@ import org.apache.camel.ContextTestSupport;
import org.apache.camel.PropertyBindingException;
import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.*;
+import static org.apache.camel.util.CollectionHelper.mapOf;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
/**
* Unit test for PropertyBindingSupport
@@ -80,6 +83,31 @@ public class PropertyBindingSupportListTest extends ContextTestSupport {
}
@Test
+ public void testPropertiesListWithGaps() throws Exception {
+ Foo foo = new Foo();
+
+ Map<String, Object> prop = new LinkedHashMap<>();
+ prop.put("name", "James");
+ prop.put("bar.age", "33");
+ prop.put("bar.{{committer}}", "true");
+ prop.put("bar.gold-customer", "true");
+ prop.put("bar.works[5]", "#bean:company1");
+ prop.put("bar.works[9]", "#bean:company2");
+
+ PropertyBindingSupport.build().bind(context, foo, prop);
+
+ assertEquals("James", foo.getName());
+ assertEquals(33, foo.getBar().getAge());
+ assertTrue(foo.getBar().isRider());
+ assertTrue(foo.getBar().isGoldCustomer());
+ assertEquals(10, foo.getBar().getWorks().size());
+ assertEquals(123, foo.getBar().getWorks().get(5).getId());
+ assertEquals("Acme", foo.getBar().getWorks().get(5).getName());
+ assertEquals(456, foo.getBar().getWorks().get(9).getId());
+ assertEquals("Acme 2", foo.getBar().getWorks().get(9).getName());
+ }
+
+ @Test
public void testPropertiesListNested() throws Exception {
Foo foo = new Foo();
@@ -107,6 +135,25 @@ public class PropertyBindingSupportListTest extends ContextTestSupport {
}
@Test
+ public void testPropertiesListNestedWithType() throws Exception {
+ Foo foo = new Foo();
+
+ // use CollectionHelper::mapOf to avoid insertion ordered iteration
+ PropertyBindingSupport.build().bind(context, foo, mapOf(
+ "bar.works[0]", "#class:" + Company.class.getName(),
+ "bar.works[0].name", "first",
+ "bar.works[1]", "#class:" + Company.class.getName(),
+ "bar.works[1].name", "second"
+ ));
+
+ assertEquals(2, foo.getBar().getWorks().size());
+ assertEquals(0, foo.getBar().getWorks().get(0).getId());
+ assertEquals("first", foo.getBar().getWorks().get(0).getName());
+ assertEquals(0, foo.getBar().getWorks().get(1).getId());
+ assertEquals("second", foo.getBar().getWorks().get(1).getName());
+ }
+
+ @Test
public void testPropertiesListFirst() throws Exception {
Bar bar = new Bar();
@@ -140,7 +187,7 @@ public class PropertyBindingSupportListTest extends ContextTestSupport {
} catch (PropertyBindingException e) {
assertEquals("bar.gold-customer[]", e.getPropertyName());
IllegalArgumentException iae = assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
- assertTrue(iae.getMessage().startsWith("Cannot set property: gold-customer[] as either a Map/List because target bean is not a Map or List type"));
+ assertTrue(iae.getMessage().startsWith("Cannot set property: gold-customer[] as either a Map/List/array because target bean is not a Map, List or array type"));
}
}
diff --git a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportMapTest.java b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportMapTest.java
index 3f18035..4b3b688 100644
--- a/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportMapTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/support/PropertyBindingSupportMapTest.java
@@ -139,7 +139,7 @@ public class PropertyBindingSupportMapTest extends ContextTestSupport {
} catch (PropertyBindingException e) {
assertEquals("bar.gold-customer[foo]", e.getPropertyName());
IllegalArgumentException iae = assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
- assertTrue(iae.getMessage().startsWith("Cannot set property: gold-customer[foo] as either a Map/List because target bean is not a Map or List type"));
+ assertTrue(iae.getMessage().startsWith("Cannot set property: gold-customer[foo] as either a Map/List/array because target bean is not a Map, List or array type"));
}
}
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 178e193..5dcefab 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
@@ -16,6 +16,7 @@
*/
package org.apache.camel.support;
+import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@@ -199,7 +200,7 @@ public final class IntrospectionSupport {
return false;
}
-
+
public static boolean isSetter(Method method) {
return isSetter(method, false);
}
@@ -471,7 +472,7 @@ public final class IntrospectionSupport {
}
}
}
-
+
return rc;
}
@@ -621,6 +622,8 @@ public final class IntrospectionSupport {
obj = new LinkedHashMap<>();
} else if (Collection.class.isAssignableFrom(returnType)) {
obj = new ArrayList<>();
+ } else if (returnType.isArray()) {
+ obj = Array.newInstance(returnType.getComponentType(), 0);
}
} else {
// fallback as map type
@@ -646,15 +649,53 @@ public final class IntrospectionSupport {
value = CamelContextHelper.lookup(context, s);
}
if (isNotEmpty(lookupKey)) {
- int idx = Integer.valueOf(lookupKey);
- list.add(idx, value);
+ int idx = Integer.parseInt(lookupKey);
+ if (idx < list.size()) {
+ list.set(idx, value);
+ } else if (idx == list.size()) {
+ list.add(value);
+ } else {
+ // If the list implementation is based on an array, we
+ // can increase tha capacity to the required value to
+ // avoid potential re-allocation weh invoking List::add.
+ //
+ // Note that ArrayList is the default List impl that
+ // is automatically created if the property is null.
+ if (list instanceof ArrayList) {
+ ((ArrayList) list).ensureCapacity(idx + 1);
+ }
+ while (list.size() < idx) {
+ list.add(null);
+ }
+ list.add(idx, value);
+ }
} else {
list.add(value);
}
return true;
+ } else if (obj.getClass().isArray() && lookupKey != null) {
+ if (context != null && refName != null && value == null) {
+ String s = StringHelper.replaceAll(refName, "#", "");
+ value = CamelContextHelper.lookup(context, s);
+ }
+ int idx = Integer.parseInt(lookupKey);
+ int size = Array.getLength(obj);
+ if (idx >= size) {
+ obj = Arrays.copyOf((Object[])obj, idx + 1);
+
+ // replace array
+ boolean hit = IntrospectionSupport.setProperty(context, target, key, obj);
+ if (!hit) {
+ throw new IllegalArgumentException("Cannot set property: " + name + " as an array because target bean has no setter method for the array");
+ }
+ }
+
+ Array.set(obj, idx, value);
+
+ return true;
} else {
// not a map or list
- throw new IllegalArgumentException("Cannot set property: " + name + " as either a Map/List because target bean is not a Map or List type: " + target);
+ throw new IllegalArgumentException("Cannot set property: " + name + " as either a Map/List/array because target bean is not a Map, List or array type: " + target);
}
}
@@ -799,7 +840,7 @@ public final class IntrospectionSupport {
// allow build pattern as a setter as well
return setProperty(context, typeConverter, target, name, value, null, true, false, false);
}
-
+
public static boolean setProperty(TypeConverter typeConverter, Object target, String name, Object value) throws Exception {
// allow build pattern as a setter as well
return setProperty(null, typeConverter, target, name, value, null, true, false, false);
@@ -873,7 +914,7 @@ public final class IntrospectionSupport {
// find the best match if possible
LOG.trace("Found {} suitable setter methods for setting {}", candidates.size(), name);
// prefer to use the one with the same instance if any exists
- for (Method method : candidates) {
+ for (Method method : candidates) {
if (method.getParameterTypes()[0].isInstance(value)) {
LOG.trace("Method {} is the best candidate as it has parameter with same instance type", method);
// retain only this method in the answer
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 650b0f4..5a8308b 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,10 +16,12 @@
*/
package org.apache.camel.support;
+import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
@@ -35,6 +37,7 @@ import org.apache.camel.CamelContext;
import org.apache.camel.Component;
import org.apache.camel.ExtendedCamelContext;
import org.apache.camel.PropertyBindingException;
+import org.apache.camel.spi.BeanIntrospection;
import org.apache.camel.spi.GeneratedPropertyConfigurer;
import org.apache.camel.spi.PropertyConfigurer;
import org.apache.camel.spi.PropertyConfigurerGetter;
@@ -778,17 +781,37 @@ public final class PropertyBindingSupport {
// use configurer if possible
Object answer = null;
- GeneratedPropertyConfigurer configurer = context.adapt(ExtendedCamelContext.class).getConfigurerResolver().resolvePropertyConfigurer(target.getClass().getSimpleName(), context);
+ Class<?> type = null;
+
+ GeneratedPropertyConfigurer configurer = PropertyConfigurerHelper.resolvePropertyConfigurer(context, target);
if (configurer instanceof PropertyConfigurerGetter) {
- answer = ((PropertyConfigurerGetter) configurer).getOptionValue(target, key, ignoreCase);
+ answer = ((PropertyConfigurerGetter)configurer).getOptionValue(target, key, ignoreCase);
if (answer == null) {
answer = defaultValue;
}
}
if (answer == null) {
+ BeanIntrospection introspection = context.adapt(ExtendedCamelContext.class).getBeanIntrospection();
// fallback to reflection based
- answer = context.adapt(ExtendedCamelContext.class).getBeanIntrospection().getOrElseProperty(target, key, defaultValue, ignoreCase);
+ answer = introspection.getOrElseProperty(target, key, defaultValue, ignoreCase);
+ if (answer == null) {
+ try {
+ Method method = introspection.getPropertyGetter(target.getClass(), key, ignoreCase);
+ if (method != null) {
+ type = method.getReturnType();
+ }
+ } catch (NoSuchMethodException e) {
+ // ignore
+ }
+ }
+ }
+
+ if (answer != null) {
+ type = answer.getClass();
+ } else if (configurer instanceof PropertyConfigurerGetter) {
+ type = (Class<?>)((PropertyConfigurerGetter)configurer).getAllOptions(target).get(key);
}
+
if (answer instanceof Map && lookupKey != null) {
Map map = (Map) answer;
answer = map.getOrDefault(lookupKey, defaultValue);
@@ -804,6 +827,38 @@ public final class PropertyBindingSupport {
answer = list.get(list.size() - 1);
}
}
+ } else if (type != null && type.isArray() && lookupKey != null) {
+ int idx = Integer.parseInt(lookupKey);
+ int size = answer != null ? Array.getLength(answer) : 0;
+ if (idx >= size) {
+ answer = answer != null ? Arrays.copyOf((Object[]) answer, idx + 1) : Array.newInstance(Object.class, idx + 1);
+ }
+
+ Object result = Array.get(answer, idx);
+ if (result == null) {
+ result = context.getInjector().newInstance(type.getComponentType());
+ Array.set(answer, idx, result);
+ }
+
+ if (idx >= size) {
+ // replace array
+ if (configurer != null) {
+ configurer.configure(context, target, key, answer, true);
+ } else {
+ // fallback to reflection
+ boolean hit;
+ try {
+ hit = IntrospectionSupport.setProperty(context.getTypeConverter(), target, key, answer);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Cannot set property: " + key + " as an array because target bean has no setter method for the array");
+ }
+ if (!hit) {
+ throw new IllegalArgumentException("Cannot set property: " + key + " as an array because target bean has no setter method for the array");
+ }
+ }
+ }
+
+ answer = result;
}
return answer != null ? answer : defaultValue;
@@ -1035,7 +1090,7 @@ public final class PropertyBindingSupport {
continue;
}
// must be a public static method that returns something
- if (!Modifier.isStatic(method.getModifiers())
+ if (!Modifier.isStatic(method.getModifiers())
|| !Modifier.isPublic(method.getModifiers())
|| method.getReturnType() == Void.TYPE) {
continue;
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/PropertyConfigurerHelper.java b/core/camel-support/src/main/java/org/apache/camel/support/PropertyConfigurerHelper.java
new file mode 100644
index 0000000..df104d5
--- /dev/null
+++ b/core/camel-support/src/main/java/org/apache/camel/support/PropertyConfigurerHelper.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.support;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Helper class for dealing with configurers.
+ *
+ * @see org.apache.camel.spi.PropertyConfigurer
+ * @see org.apache.camel.spi.PropertyConfigurerGetter
+ */
+public final class PropertyConfigurerHelper {
+
+ private PropertyConfigurerHelper() {
+ }
+
+ /**
+ * Resolves the given configurer.
+ *
+ * @param context the camel context
+ * @param target the target object for which we need a {@link org.apache.camel.spi.PropertyConfigurer}
+ * @return the resolved configurer, or <tt>null</tt> if no configurer could be found
+ */
+ public static GeneratedPropertyConfigurer resolvePropertyConfigurer(CamelContext context, Object target) {
+ ObjectHelper.notNull(target, "target");
+ ObjectHelper.notNull(context, "context");
+
+ return context.adapt(ExtendedCamelContext.class)
+ .getConfigurerResolver()
+ .resolvePropertyConfigurer(target.getClass().getSimpleName(), context);
+ }
+
+ /**
+ * Resolves the given configurer.
+ *
+ * @param context the camel context
+ * @param target the target object for which we need a {@link org.apache.camel.spi.PropertyConfigurer}
+ * @param type the specific type of {@link org.apache.camel.spi.PropertyConfigurer}
+ * @return the resolved configurer, or <tt>null</tt> if no configurer could be found
+ */
+ public static <T> T resolvePropertyConfigurer(CamelContext context, Object target, Class<T> type) {
+ ObjectHelper.notNull(target, "target");
+ ObjectHelper.notNull(context, "context");
+
+ GeneratedPropertyConfigurer configurer = resolvePropertyConfigurer(context, target);
+ if (type.isInstance(configurer)) {
+ return type.cast(configurer);
+ }
+
+ return null;
+ }
+}