You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xbean-scm@geronimo.apache.org by da...@apache.org on 2008/03/20 02:36:31 UTC
svn commit: r639106 - in
/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe:
ObjectRecipe.java ReflectionUtil.java
Author: dain
Date: Wed Mar 19 18:36:22 2008
New Revision: 639106
URL: http://svn.apache.org/viewvc?rev=639106&view=rev
Log:
Multiple setters and a field may be valid for a property so try each until the value can be successfully converted to setter/field type and then set
Modified:
geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java
geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java
Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java?rev=639106&r1=639105&r2=639106&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ObjectRecipe.java Wed Mar 19 18:36:22 2008
@@ -367,24 +367,41 @@
private void setProperty(Object instance, Class clazz, Property propertyName, Object propertyValue) {
- Member member;
+ List<Member> members = new ArrayList<Member>();
try {
if (propertyName instanceof SetterProperty){
- member = new MethodMember(ReflectionUtil.findSetter(clazz, propertyName.name, propertyValue, options));
+ List<Method> setters = ReflectionUtil.findAllSetters(clazz, propertyName.name, propertyValue, options);
+ for (Method setter : setters) {
+ MethodMember member = new MethodMember(setter);
+ members.add(member);
+ }
} else if (propertyName instanceof FieldProperty){
- member = new FieldMember(ReflectionUtil.findField(clazz, propertyName.name, propertyValue, options));
+ FieldMember member = new FieldMember(ReflectionUtil.findField(clazz, propertyName.name, propertyValue, options));
+ members.add(member);
} else {
+ // add setter members
+ MissingAccessorException noSetter = null;
try {
- member = new MethodMember(ReflectionUtil.findSetter(clazz, propertyName.name, propertyValue, options));
- } catch (MissingAccessorException noSetter) {
+ List<Method> setters = ReflectionUtil.findAllSetters(clazz, propertyName.name, propertyValue, options);
+ for (Method setter : setters) {
+ MethodMember member = new MethodMember(setter);
+ members.add(member);
+ }
+ } catch (MissingAccessorException e) {
+ noSetter = e;
if (!options.contains(Option.FIELD_INJECTION)) {
throw noSetter;
}
+ }
+ if (options.contains(Option.FIELD_INJECTION)) {
try {
- member = new FieldMember(ReflectionUtil.findField(clazz, propertyName.name, propertyValue, options));
+ FieldMember member = new FieldMember(ReflectionUtil.findField(clazz, propertyName.name, propertyValue, options));
+ members.add(member);
} catch (MissingAccessorException noField) {
- throw (noField.getMatchLevel() > noSetter.getMatchLevel())? noField: noSetter;
+ if (members.isEmpty()) {
+ throw (noSetter == null || noField.getMatchLevel() > noSetter.getMatchLevel())? noField: noSetter;
+ }
}
}
}
@@ -396,19 +413,42 @@
throw e;
}
- try {
- propertyValue = RecipeHelper.convert(member.getType(), propertyValue, false);
- member.setValue(instance, propertyValue);
- } catch (Exception e) {
- Throwable t = e;
- if (e instanceof InvocationTargetException) {
- InvocationTargetException invocationTargetException = (InvocationTargetException) e;
- if (invocationTargetException.getCause() != null) {
- t = invocationTargetException.getCause();
+ ConstructionException conversionException = null;
+ for (Member member : members) {
+ // convert the value to type of setter/field
+ try {
+ propertyValue = RecipeHelper.convert(member.getType(), propertyValue, false);
+ } catch (Exception e) {
+ // save off first conversion exception, in case setting failed
+ if (conversionException == null) {
+ String valueType = propertyValue == null ? "null" : propertyValue.getClass().getName();
+ String memberType = member.getType() instanceof Class ? ((Class) member.getType()).getName() : member.getType().toString();
+ conversionException = new ConstructionException("Unable to convert property value" +
+ " from " + valueType +
+ " to " + memberType +
+ " for injection " + member, e);
}
+ continue;
}
- throw new ConstructionException("Error setting property: " + member, t);
+ try {
+ // set value
+ member.setValue(instance, propertyValue);
+ } catch (Exception e) {
+ Throwable t = e;
+ if (e instanceof InvocationTargetException) {
+ InvocationTargetException invocationTargetException = (InvocationTargetException) e;
+ if (invocationTargetException.getCause() != null) {
+ t = invocationTargetException.getCause();
+ }
+ }
+ throw new ConstructionException("Error setting property: " + member, t);
+ }
+
+ // value set successfully
+ return;
}
+
+ throw conversionException;
}
private Factory findFactory(Type expectedType) {
Modified: geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java?rev=639106&r1=639105&r2=639106&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java (original)
+++ geronimo/xbean/trunk/xbean-reflect/src/main/java/org/apache/xbean/recipe/ReflectionUtil.java Wed Mar 19 18:36:22 2008
@@ -34,6 +34,8 @@
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
+import java.util.LinkedList;
+import java.util.LinkedHashSet;
import static org.apache.xbean.recipe.RecipeHelper.isAssignableFrom;
@@ -149,6 +151,21 @@
}
public static Method findSetter(Class typeClass, String propertyName, Object propertyValue, Set<Option> options) {
+ List<Method> setters = findAllSetters(typeClass, propertyName, propertyValue, options);
+ return setters.get(0);
+ }
+
+ /**
+ * Finds all valid setters for the property. Due to automatic type conversion there may be more than one possible
+ * setter that could be used to set the property. The setters that do not require type converstion will be a the
+ * head of the returned list of setters.
+ * @param typeClass the class to search for setters
+ * @param propertyName the name of the property
+ * @param propertyValue the value that must be settable either directly or after conversion
+ * @param options controls which setters are considered valid
+ * @return the valid setters; never null or empty
+ */
+ public static List<Method> findAllSetters(Class typeClass, String propertyName, Object propertyValue, Set<Option> options) {
if (typeClass == null) throw new NullPointerException("typeClass is null");
if (propertyName == null) throw new NullPointerException("name is null");
if (propertyName.length() == 0) throw new IllegalArgumentException("name is an empty string");
@@ -187,6 +204,9 @@
boolean allowStatic = options.contains(Option.STATIC_PROPERTIES);
boolean caseInsesnitive = options.contains(Option.CASE_INSENSITIVE_PROPERTIES);
+
+ LinkedList<Method> validSetters = new LinkedList<Method>();
+
List<Method> methods = new ArrayList<Method>(Arrays.asList(typeClass.getMethods()));
methods.addAll(Arrays.asList(typeClass.getDeclaredMethods()));
for (Method method : methods) {
@@ -263,11 +283,22 @@
setAccessible(method);
}
- return method;
+ if (RecipeHelper.isInstance(methodParameterType, propertyValue)) {
+ // This setter requires no conversion, which means there can not be a conversion error.
+ // Therefore this setter is perferred and put a the head of the list
+ validSetters.addFirst(method);
+ } else {
+ validSetters.add(method);
+ }
}
}
+ if (!validSetters.isEmpty()) {
+ // remove duplicate methods (can happen with inheritance)
+ return new ArrayList<Method>(new LinkedHashSet<Method>(validSetters));
+ }
+
if (missException != null) {
throw missException;
} else {