Author: davsclaus Date: Mon Jun 7 09:55:32 2010 New Revision: 952173 URL: http://svn.apache.org/viewvc?rev=952173&view=rev Log: CAMEL-2642: IntrospectionSupport being consistent with getProperty and getProperties. Also getProperties now return all types of properties. Work in progress.
Added: camel/trunk/camel-core/src/test/java/org/apache/camel/util/AnotherExampleBean.java - copied, changed from r952104, camel/trunk/camel-core/src/test/java/org/apache/camel/util/jndi/ExampleBean.java Modified: 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/util/IntrospectionSupport.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java?rev=952173&r1=952172&r2=952173&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 Mon Jun 7 09:55:32 2010 @@ -20,12 +20,16 @@ import java.beans.PropertyEditor; import java.beans.PropertyEditorManager; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -44,6 +48,14 @@ public final class IntrospectionSupport private static final transient Log LOG = LogFactory.getLog(IntrospectionSupport.class); private static final Pattern GETTER_PATTERN = Pattern.compile("(get|is)[A-Z].*"); private static final Pattern SETTER_PATTERN = Pattern.compile("set[A-Z].*"); + private static final List<Method> EXCLUDED_METHODS = new ArrayList<Method>(); + + static { + // exclude all java.lang.Object methods as we dont want to invoke them + EXCLUDED_METHODS.addAll(Arrays.asList(Object.class.getMethods())); + // exclude all java.lang.reflect.Proxy methods as we dont want to invoke them + EXCLUDED_METHODS.addAll(Arrays.asList(Proxy.class.getMethods())); + } /** * Utility classes should not have a public constructor. @@ -85,6 +97,20 @@ public final class IntrospectionSupport return name; } + public static String getSetterShorthandName(Method method) { + if (!isSetter(method)) { + return method.getName(); + } + + String name = method.getName(); + if (name.startsWith("set")) { + name = name.substring(3); + name = name.substring(0, 1).toLowerCase() + name.substring(1); + } + + return name; + } + public static boolean isSetter(Method method) { String name = method.getName(); Class<?> type = method.getReturnType(); @@ -100,8 +126,7 @@ public final class IntrospectionSupport /** * Will inspect the target for properties. * <p/> - * <b>Notice:</b> only properties which is convertable to String will be selected, - * other properties will be skipped. + * Notice a property must have both a getter/setter method to be included. * * @param target the target bean * @param properties the map to fill in found properties @@ -120,34 +145,44 @@ public final class IntrospectionSupport Class clazz = target.getClass(); Method[] methods = clazz.getMethods(); for (Method method : methods) { - String name = method.getName(); - Class type = method.getReturnType(); - Class params[] = method.getParameterTypes(); - if (name.startsWith("get") && params.length == 0 && type != null && isSettableType(type)) { - try { + if (EXCLUDED_METHODS.contains(method)) { + continue; + } + try { + // must be properties which have setters + if (isGetter(method) && hasSetter(target, method)) { Object value = method.invoke(target); - if (value == null) { - continue; - } - - // TODO: Why must the found property be convertable to String? - String strValue = convertToString(value, type); - if (strValue == null) { - continue; - } - - name = name.substring(3, 4).toLowerCase() + name.substring(4); - properties.put(optionPrefix + name, strValue); + String name = getGetterShorthandName(method); + properties.put(optionPrefix + name, value); rc = true; - } catch (Exception ignore) { - // ignore } + } catch (Exception e) { + // ignore } } return rc; } + public static boolean hasSetter(Object target, Method getter) { + String name = getGetterShorthandName(getter); + + Class clazz = target.getClass(); + Method[] methods = clazz.getMethods(); + for (Method method : methods) { + if (EXCLUDED_METHODS.contains(method)) { + continue; + } + if (isSetter(method)) { + if (name.equals(getSetterShorthandName(method))) { + return true; + } + } + } + + return false; + } + public static boolean hasProperties(Map<String, Object> properties, String optionPrefix) { ObjectHelper.notNull(properties, "properties"); @@ -177,7 +212,23 @@ public final class IntrospectionSupport } public static Method getPropertyGetter(Class<?> type, String propertyName) throws NoSuchMethodException { - return type.getMethod("get" + ObjectHelper.capitalize(propertyName)); + if (isPropertyIsGetter(type, propertyName)) { + return type.getMethod("is" + ObjectHelper.capitalize(propertyName)); + } else { + return type.getMethod("get" + ObjectHelper.capitalize(propertyName)); + } + } + + public static boolean isPropertyIsGetter(Class<?> type, String propertyName) { + try { + Method method = type.getMethod("is" + ObjectHelper.capitalize(propertyName)); + if (method != null) { + return method.getReturnType().isAssignableFrom(boolean.class) || method.getReturnType().isAssignableFrom(Boolean.class); + } + } catch (NoSuchMethodException e) { + // ignore + } + return false; } public static boolean setProperties(Object target, Map<String, Object> properties, String optionPrefix) throws Exception { @@ -227,7 +278,7 @@ public final class IntrospectionSupport for (Iterator<Map.Entry<String, Object>> iter = properties.entrySet().iterator(); iter.hasNext();) { Map.Entry<String, Object> entry = iter.next(); - if (setProperty(typeConverter, target, (String)entry.getKey(), entry.getValue())) { + if (setProperty(typeConverter, target, entry.getKey(), entry.getValue())) { iter.remove(); rc = true; } @@ -317,6 +368,7 @@ public final class IntrospectionSupport return null; } + @Deprecated private static String convertToString(Object value, Class<?> type) throws URISyntaxException { PropertyEditor editor = PropertyEditorManager.findEditor(type); if (editor != null) { @@ -329,6 +381,7 @@ public final class IntrospectionSupport return null; } + @Deprecated private static Set<Method> findSetterMethods(TypeConverter typeConverter, Class<?> clazz, String name, Object value) { Set<Method> candidates = new LinkedHashSet<Method>(); @@ -383,6 +436,7 @@ public final class IntrospectionSupport } } + @Deprecated private static boolean isSettableType(Class<?> clazz) { // TODO: Why limit to what the JDK property editor can set? if (PropertyEditorManager.findEditor(clazz) != null) { Copied: camel/trunk/camel-core/src/test/java/org/apache/camel/util/AnotherExampleBean.java (from r952104, camel/trunk/camel-core/src/test/java/org/apache/camel/util/jndi/ExampleBean.java) URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/util/AnotherExampleBean.java?p2=camel/trunk/camel-core/src/test/java/org/apache/camel/util/AnotherExampleBean.java&p1=camel/trunk/camel-core/src/test/java/org/apache/camel/util/jndi/ExampleBean.java&r1=952104&r2=952173&rev=952173&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/util/jndi/ExampleBean.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/util/AnotherExampleBean.java Mon Jun 7 09:55:32 2010 @@ -14,18 +14,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.util.jndi; +package org.apache.camel.util; + +import java.util.Collection; +import java.util.Date; /** * @version $Revision$ */ -public class ExampleBean { +public class AnotherExampleBean { private String id; private String name; private double price; + private Date date; + private Collection children; + private Boolean goldCustomer; + private boolean little; public String toString() { - return "ExampleBean[name: " + name + " price: " + price + " id: " + id + "]"; + return "AnotherExampleBean[name: " + name + " price: " + price + " id: " + id + "]"; } public String getName() { @@ -43,7 +50,7 @@ public class ExampleBean { public void setPrice(double price) { this.price = price; } - + public String getId() { return id; } @@ -51,4 +58,36 @@ public class ExampleBean { public void setId(String id) { this.id = id; } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public Collection getChildren() { + return children; + } + + public void setChildren(Collection children) { + this.children = children; + } + + public Boolean isGoldCustomer() { + return goldCustomer; + } + + public void setGoldCustomer(Boolean goldCustomer) { + this.goldCustomer = goldCustomer; + } + + public boolean isLittle() { + return little; + } + + public void setLittle(boolean little) { + this.little = little; + } } \ No newline at end of file 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=952173&r1=952172&r2=952173&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 Mon Jun 7 09:55:32 2010 @@ -17,7 +17,10 @@ package org.apache.camel.util; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -26,7 +29,7 @@ import org.apache.camel.ContextTestSuppo import org.apache.camel.util.jndi.ExampleBean; /** - * Unit test for IntrospectionSupport + * Unit test for IntrospectionSupport */ public class IntrospectionSupportTest extends ContextTestSupport { @@ -98,50 +101,100 @@ public class IntrospectionSupportTest ex Map<String, Object> map = new HashMap<String, Object>(); IntrospectionSupport.getProperties(bean, map, null); - assertEquals(2, map.size()); + assertEquals(3, map.size()); assertEquals("Claus", map.get("name")); String price = map.get("price").toString(); assertTrue(price.startsWith("10")); + + assertEquals(null, map.get("id")); + } + + public void testAnotherGetProperties() throws Exception { + AnotherExampleBean bean = new AnotherExampleBean(); + bean.setId("123"); + bean.setName("Claus"); + bean.setPrice(10.0); + Date date = new Date(0); + bean.setDate(date); + bean.setGoldCustomer(true); + bean.setLittle(true); + Collection children = new ArrayList(); + bean.setChildren(children); + + Map<String, Object> map = new HashMap<String, Object>(); + IntrospectionSupport.getProperties(bean, map, null); + assertEquals(7, map.size()); + + assertEquals("Claus", map.get("name")); + String price = map.get("price").toString(); + assertTrue(price.startsWith("10")); + assertSame(date, map.get("date")); + assertSame(children, map.get("children")); + assertEquals(Boolean.TRUE, map.get("goldCustomer")); + assertEquals(Boolean.TRUE, map.get("little")); + assertEquals("123", map.get("id")); } public void testGetPropertiesOptionPrefix() throws Exception { ExampleBean bean = new ExampleBean(); bean.setName("Claus"); bean.setPrice(10.0); + bean.setId("123"); Map<String, Object> map = new HashMap<String, Object>(); IntrospectionSupport.getProperties(bean, map, "bean."); - assertEquals(2, map.size()); + assertEquals(3, map.size()); assertEquals("Claus", map.get("bean.name")); String price = map.get("bean.price").toString(); assertTrue(price.startsWith("10")); + assertEquals("123", map.get("bean.id")); } public void testGetProperty() throws Exception { ExampleBean bean = new ExampleBean(); + bean.setId("123"); bean.setName("Claus"); bean.setPrice(10.0); Object name = IntrospectionSupport.getProperty(bean, "name"); assertEquals("Claus", name); } - + + public void testAnotherGetProperty() throws Exception { + AnotherExampleBean bean = new AnotherExampleBean(); + bean.setName("Claus"); + bean.setPrice(10.0); + Date date = new Date(0); + bean.setDate(date); + bean.setGoldCustomer(true); + bean.setLittle(true); + Collection children = new ArrayList(); + bean.setChildren(children); + + Object name = IntrospectionSupport.getProperty(bean, "name"); + assertEquals("Claus", name); + assertSame(date, IntrospectionSupport.getProperty(bean, "date")); + assertSame(children, IntrospectionSupport.getProperty(bean, "children")); + assertEquals(Boolean.TRUE, IntrospectionSupport.getProperty(bean, "goldCustomer")); + assertEquals(Boolean.TRUE, IntrospectionSupport.getProperty(bean, "little")); + } + public void testGetPropertyLocaleIndependend() throws Exception { Locale oldLocale = Locale.getDefault(); Locale.setDefault(new Locale("tr", "TR")); - + try { ExampleBean bean = new ExampleBean(); bean.setName("Claus"); bean.setPrice(10.0); bean.setId("1"); - + Object name = IntrospectionSupport.getProperty(bean, "name"); Object id = IntrospectionSupport.getProperty(bean, "id"); Object price = IntrospectionSupport.getProperty(bean, "price"); - + assertEquals("Claus", name); assertEquals(10.0, price); assertEquals("1", id); @@ -162,11 +215,11 @@ public class IntrospectionSupportTest ex public void testIsGetter() throws Exception { ExampleBean bean = new ExampleBean(); - Method name = bean.getClass().getMethod("getName", (Class<?>[])null); + Method name = bean.getClass().getMethod("getName", (Class<?>[]) null); assertEquals(true, IntrospectionSupport.isGetter(name)); assertEquals(false, IntrospectionSupport.isSetter(name)); - Method price = bean.getClass().getMethod("getPrice", (Class<?>[])null); + Method price = bean.getClass().getMethod("getPrice", (Class<?>[]) null); assertEquals(true, IntrospectionSupport.isGetter(price)); assertEquals(false, IntrospectionSupport.isSetter(price)); } @@ -186,19 +239,19 @@ public class IntrospectionSupportTest ex public void testOtherIsGetter() throws Exception { OtherExampleBean bean = new OtherExampleBean(); - Method customerId = bean.getClass().getMethod("getCustomerId", (Class<?>[])null); + Method customerId = bean.getClass().getMethod("getCustomerId", (Class<?>[]) null); assertEquals(true, IntrospectionSupport.isGetter(customerId)); assertEquals(false, IntrospectionSupport.isSetter(customerId)); - Method goldCustomer = bean.getClass().getMethod("isGoldCustomer", (Class<?>[])null); + Method goldCustomer = bean.getClass().getMethod("isGoldCustomer", (Class<?>[]) null); assertEquals(true, IntrospectionSupport.isGetter(goldCustomer)); assertEquals(false, IntrospectionSupport.isSetter(goldCustomer)); - Method silverCustomer = bean.getClass().getMethod("isSilverCustomer", (Class<?>[])null); + Method silverCustomer = bean.getClass().getMethod("isSilverCustomer", (Class<?>[]) null); assertEquals(true, IntrospectionSupport.isGetter(silverCustomer)); assertEquals(false, IntrospectionSupport.isSetter(silverCustomer)); - Method company = bean.getClass().getMethod("getCompany", (Class<?>[])null); + Method company = bean.getClass().getMethod("getCompany", (Class<?>[]) null); assertEquals(true, IntrospectionSupport.isGetter(company)); assertEquals(false, IntrospectionSupport.isSetter(company));