scheu 02/04/19 17:22:25
Modified: java/src/org/apache/axis/description TypeDesc.java
java/src/org/apache/axis/encoding/ser BeanDeserializer.java
BeanPropertyTarget.java BeanSerializer.java
SimpleDeserializer.java SimpleSerializer.java
java/src/org/apache/axis/utils BeanPropertyDescriptor.java
BeanUtils.java
java/test/encoding AttributeBean.java TestAttributes.java
Log:
There has been some discussion and bugs related to the serialization and
deserialization of beans that do not have
getter/setters but instead have public fields.
This change fixes the following bug:
http://nagoya.apache.org/bugzilla/show_bug.cgi?id=7869
Changes to utils.BeanPropertyDescriptor:
* Add constructor to set BPD with a java.lang.reflect.Field.
So now a BPD can be constructed with a Field or
it can be constructed with a read/write Method pair.
* Get rid of the public getReadMethod/getWriteMethod methods.
* Instead have set/get methods which will use the methods
if available or use the field.
* Have isReadable, isWriteable, isIndexed methods to query the BPD.
Changes to utils.BeanUtils
* Add the BPD's for public fields that do not have getters/setters.
Changes to encoding/ser/BeanPropertyTarget
* Change the getWriteMethod calls to use the new BPD.set calls
...simplifies this code.
Changes to encoding/ser/BeanSerializer & BeanDeserializer etc.
* Similar changes to remove getWriteMethod and getReadMethod calls
and use the set/get and other query methods.
This also simplifies the code.
Also changed the test/encoding/AttributeBean to have an element
which does not have getters/setters. This tests serialization
and deserialization.
Revision Changes Path
1.11 +4 -2 xml-axis/java/src/org/apache/axis/description/TypeDesc.java
Index: TypeDesc.java
===================================================================
RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/description/TypeDesc.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- TypeDesc.java 16 Apr 2002 20:26:32 -0000 1.10
+++ TypeDesc.java 20 Apr 2002 00:22:24 -0000 1.11
@@ -69,7 +69,9 @@
* @author Glen Daniels ([EMAIL PROTECTED])
*/
public class TypeDesc {
- public static Class [] noClasses = new Class [] {};
+ public static final Class [] noClasses = new Class [] {};
+ public static final Object[] noObjects = new Object[] {};
+
public TypeDesc(Class javaClass) {
this.javaClass = javaClass;
@@ -105,7 +107,7 @@
}
if (getTypeDesc != null) {
return (TypeDesc)getTypeDesc.invoke(null,
- BeanSerializer.noArgs);
+ noObjects);
}
} catch (Exception e) {
}
1.20 +23 -21
xml-axis/java/src/org/apache/axis/encoding/ser/BeanDeserializer.java
Index: BeanDeserializer.java
===================================================================
RCS file:
/home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/BeanDeserializer.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- BeanDeserializer.java 16 Apr 2002 18:56:16 -0000 1.19
+++ BeanDeserializer.java 20 Apr 2002 00:22:24 -0000 1.20
@@ -229,16 +229,20 @@
dSer.setDefaultType(tm.getTypeQName(type));
}
- if (propDesc.getWriteMethod().getParameterTypes().length == 1) {
- // Success! Register the target and deserializer.
- collectionIndex = -1;
- dSer.registerValueTarget(new BeanPropertyTarget(value, propDesc));
- } else {
- // Success! This is a collection of properties so use the index
- collectionIndex++;
- dSer.registerValueTarget(new BeanPropertyTarget(value,
- propDesc,
- collectionIndex));
+ if (propDesc.isWriteable()) {
+ if (!propDesc.isIndexed()) {
+ // Success! Register the target and deserializer.
+ collectionIndex = -1;
+ dSer.registerValueTarget(
+ new BeanPropertyTarget(value, propDesc));
+ } else {
+ // Success! This is a collection of properties so use the index
+ collectionIndex++;
+ dSer.registerValueTarget(
+ new BeanPropertyTarget(value,
+ propDesc,
+ collectionIndex));
+ }
}
return (SOAPHandler)dSer;
}
@@ -277,7 +281,7 @@
BeanPropertyDescriptor bpd =
(BeanPropertyDescriptor) propertyMap.get(fieldName);
if (bpd != null) {
- if (bpd.getWriteMethod() == null ) continue ;
+ if (!bpd.isWriteable() || bpd.isIndexed() ) continue ;
// determine the QName for this child element
TypeMapping tm = context.getTypeMapping();
@@ -298,16 +302,14 @@
bpd.getName(),
type.toString()));
- if (bpd.getWriteMethod().getParameterTypes().length == 1) {
- // Success! Create an object from the string and set
- // it in the bean
- try {
- Object val = ((SimpleDeserializer)dSer).
- makeValue(attributes.getValue(i));
- bpd.getWriteMethod().invoke(value, new Object[] {val} );
- } catch (Exception e) {
- throw new SAXException(e);
- }
+ // Success! Create an object from the string and set
+ // it in the bean
+ try {
+ Object val = ((SimpleDeserializer)dSer).
+ makeValue(attributes.getValue(i));
+ bpd.set(value, val);
+ } catch (Exception e) {
+ throw new SAXException(e);
}
} // if
1.6 +5 -5
xml-axis/java/src/org/apache/axis/encoding/ser/BeanPropertyTarget.java
Index: BeanPropertyTarget.java
===================================================================
RCS file:
/home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/BeanPropertyTarget.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- BeanPropertyTarget.java 16 Apr 2002 18:56:16 -0000 1.5
+++ BeanPropertyTarget.java 20 Apr 2002 00:22:24 -0000 1.6
@@ -99,17 +99,17 @@
public void set(Object value) throws SAXException {
try {
if (index < 0)
- pd.getWriteMethod().invoke(object, new Object[] {value});
+ pd.set(object, value);
else
- pd.getWriteMethod().invoke(object, new Object[] {new
Integer(index), value});
+ pd.set(object, index, value);
} catch (Exception e) {
- Class type = pd.getReadMethod().getReturnType();
+ Class type = pd.getType();
value = JavaUtils.convert(value, type);
try {
if (index < 0)
- pd.getWriteMethod().invoke(object, new Object[] {value});
+ pd.set(object, value);
else
- pd.getWriteMethod().invoke(object, new Object[] {new
Integer(index), value});
+ pd.set(object, index, value);
} catch (Exception ex) {
String field= pd.getName();
int i = 0;
1.28 +12 -15
xml-axis/java/src/org/apache/axis/encoding/ser/BeanSerializer.java
Index: BeanSerializer.java
===================================================================
RCS file:
/home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/BeanSerializer.java,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- BeanSerializer.java 16 Apr 2002 18:56:16 -0000 1.27
+++ BeanSerializer.java 20 Apr 2002 00:22:24 -0000 1.28
@@ -97,8 +97,6 @@
protected static Log log =
LogFactory.getLog(BeanSerializer.class.getName());
- public static final Object[] noArgs = new Object[] {}; // For convenience
-
QName xmlType;
Class javaType;
@@ -169,15 +167,16 @@
qname = new QName("", propName);
}
- Method readMethod = propertyDescriptor[i].getReadMethod();
- // if there is a read method for a property
- if(readMethod != null) {
- Class baseJavaType = readMethod.getReturnType();
+ // Read the value from the property
+ if(propertyDescriptor[i].isReadable()) {
+ Class baseJavaType = propertyDescriptor[i].getType();
Class javaType;
- if (readMethod.getParameterTypes().length == 0) {
+ if (!propertyDescriptor[i].isIndexed()) {
// Normal case: serialize the value
- Object propValue = readMethod.invoke(value,noArgs);
- javaType = (propValue == null || baseJavaType.isPrimitive())
+ Object propValue =
+ propertyDescriptor[i].get(value);
+ javaType = (propValue == null ||
+ baseJavaType.isPrimitive())
? baseJavaType : propValue.getClass();
context.serialize(qname,
null,
@@ -189,8 +188,7 @@
Object propValue = null;
try {
propValue =
- readMethod.invoke(value,
- new Object[] { new Integer(j) });
+ propertyDescriptor[i].get(value, j);
j++;
} catch (Exception e) {
j = -1;
@@ -408,11 +406,10 @@
qname = new QName("", propName);
}
- Method readMethod = propertyDescriptor[i].getReadMethod();
- if (readMethod != null &&
- readMethod.getParameterTypes().length == 0) {
+ if (propertyDescriptor[i].isReadable() &&
+ !propertyDescriptor[i].isIndexed()) {
// add to our attributes
- Object propValue = readMethod.invoke(value,noArgs);
+ Object propValue = propertyDescriptor[i].get(value);
// If the property value does not exist, don't serialize
// the attribute. In the future, the decision to serializer
// the attribute may be more sophisticated. For example, don't
1.12 +14 -19
xml-axis/java/src/org/apache/axis/encoding/ser/SimpleDeserializer.java
Index: SimpleDeserializer.java
===================================================================
RCS file:
/home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/SimpleDeserializer.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- SimpleDeserializer.java 16 Apr 2002 18:56:16 -0000 1.11
+++ SimpleDeserializer.java 20 Apr 2002 00:22:24 -0000 1.12
@@ -280,7 +280,7 @@
BeanPropertyDescriptor bpd =
(BeanPropertyDescriptor) propertyMap.get(fieldName);
if (bpd != null) {
- if (bpd.getWriteMethod() == null ) continue ;
+ if (!bpd.isWriteable() || bpd.isIndexed() ) continue ;
// determine the QName for this child element
TypeMapping tm = context.getTypeMapping();
@@ -301,21 +301,18 @@
bpd.getName(),
type.toString()));
- if (bpd.getWriteMethod().getParameterTypes().length == 1) {
- // Success! Create an object from the string and save
- // it in our attribute map for later.
- if (attributeMap == null) {
- attributeMap = new HashMap();
- }
- try {
- Object val = ((SimpleDeserializer)dSer).
- makeValue(attributes.getValue(i));
- attributeMap.put(fieldName, val);
- } catch (Exception e) {
- throw new SAXException(e);
- }
+ // Success! Create an object from the string and save
+ // it in our attribute map for later.
+ if (attributeMap == null) {
+ attributeMap = new HashMap();
+ }
+ try {
+ Object val = ((SimpleDeserializer)dSer).
+ makeValue(attributes.getValue(i));
+ attributeMap.put(fieldName, val);
+ } catch (Exception e) {
+ throw new SAXException(e);
}
-
} // if
} // attribute loop
} // onStartElement
@@ -338,11 +335,9 @@
BeanPropertyDescriptor bpd =
(BeanPropertyDescriptor) propertyMap.get(name);
- if (bpd.getWriteMethod() == null) continue;
+ if (!bpd.isWriteable() || bpd.isIndexed()) continue;
try {
- if (bpd.getWriteMethod().getParameterTypes().length == 1) {
- bpd.getWriteMethod().invoke(value, new Object[] {val} );
- }
+ bpd.set(value, val );
} catch (Exception e) {
throw new SAXException(e);
}
1.12 +3 -5
xml-axis/java/src/org/apache/axis/encoding/ser/SimpleSerializer.java
Index: SimpleSerializer.java
===================================================================
RCS file:
/home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/SimpleSerializer.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- SimpleSerializer.java 18 Apr 2002 19:02:31 -0000 1.11
+++ SimpleSerializer.java 20 Apr 2002 00:22:24 -0000 1.12
@@ -193,12 +193,10 @@
qname = new QName("", propName);
}
- Method readMethod = propertyDescriptor[i].getReadMethod();
- if (readMethod != null &&
- readMethod.getParameterTypes().length == 0) {
+ if (propertyDescriptor[i].isReadable() &&
+ !propertyDescriptor[i].isIndexed()) {
// add to our attributes
- Object propValue = readMethod.
- invoke(value,BeanSerializer.noArgs);
+ Object propValue = propertyDescriptor[i].get(value);
// If the property value does not exist, don't serialize
// the attribute. In the future, the decision to serializer
// the attribute may be more sophisticated. For example, don't
1.2 +150 -9
xml-axis/java/src/org/apache/axis/utils/BeanPropertyDescriptor.java
Index: BeanPropertyDescriptor.java
===================================================================
RCS file:
/home/cvs/xml-axis/java/src/org/apache/axis/utils/BeanPropertyDescriptor.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- BeanPropertyDescriptor.java 16 Apr 2002 18:56:16 -0000 1.1
+++ BeanPropertyDescriptor.java 20 Apr 2002 00:22:25 -0000 1.2
@@ -64,10 +64,14 @@
import org.apache.commons.logging.LogFactory;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
/**
* This class is essentially a copy of the PropertyDescriptor information, except
* that the values in it can be modified.
+ * Updated this to include fields that don't have getter/setters.
* @author Rich Scheuerle <[EMAIL PROTECTED]>
**/
public class BeanPropertyDescriptor
@@ -75,19 +79,156 @@
protected static Log log =
LogFactory.getLog(BeanPropertyDescriptor.class.getName());
- private String name;
- private Method getter;
- private Method setter;
-
- public BeanPropertyDescriptor(String _name, Method _getter, Method _setter) {
+ private String name = null;
+ private Method getter = null;
+ private Method setter = null;
+ private Field field = null;
+ private static final Object[] noArgs = new Object[] {};
+
+ /**
+ * Construct a BPD with getter/setter methods
+ * Both must be set
+ */
+ public BeanPropertyDescriptor(String _name,
+ Method _getter,
+ Method _setter) {
name = _name;
getter = _getter;
setter = _setter;
+ if (_getter == null || _setter == null || _name == null) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Construct a BPD with a field
+ * Both must be set
+ */
+ public BeanPropertyDescriptor(String _name,
+ Field _field) {
+ name = _name;
+ field = _field;
+ if (_field == null || _name == null) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Query if property is readable
+ */
+ public boolean isReadable() {
+ return (getter != null ||
+ field != null);
+ }
+ /**
+ * Query if property is writeable
+ */
+ public boolean isWriteable() {
+ return (setter != null ||
+ field != null);
+ }
+ /**
+ * Query if property is indexed.
+ * Indexed properties require valid setters/getters
+ */
+ public boolean isIndexed() {
+ return (getter != null &&
+ getter.getParameterTypes().length == 1 &&
+ setter != null &&
+ setter.getParameterTypes().length == 2);
}
- public Method getReadMethod() { return getter; }
- public Method getWriteMethod() { return setter; }
+
+ /**
+ * Get the property value
+ */
+ public Object get(Object obj)
+ throws InvocationTargetException, IllegalAccessException {
+ if (isIndexed()) {
+ throw new IllegalArgumentException();
+ }
+ if (getter != null) {
+ return getter.invoke(obj, noArgs);
+ } else if (field != null) {
+ return field.get(obj);
+ }
+ return null;
+ }
+ /**
+ * Set the property value
+ */
+ public void set(Object obj, Object newValue)
+ throws InvocationTargetException, IllegalAccessException {
+ if (isIndexed()) {
+ throw new IllegalArgumentException();
+ }
+ if (setter != null) {
+ setter.invoke(obj, new Object[] {newValue});
+ } else if (field != null) {
+ field.set(obj, newValue);
+ }
+ }
+ /**
+ * Get an indexed property
+ */
+ public Object get(Object obj, int i)
+ throws InvocationTargetException, IllegalAccessException {
+ if (!isIndexed()) {
+ throw new IllegalArgumentException();
+ }
+ if (getter != null) {
+ return getter.invoke(obj, new Object[] { new Integer(i)});
+ } else if (field != null) {
+ return Array.get(field.get(obj), i);
+ }
+ return null;
+ }
+ /**
+ * Get an indexed property value
+ */
+ public void set(Object obj, int i, Object newValue)
+ throws InvocationTargetException, IllegalAccessException {
+ if (!isIndexed()) {
+ throw new IllegalArgumentException();
+ }
+ if (setter != null) {
+ setter.invoke(obj, new Object[] {new Integer(i), newValue});
+ } else if (field != null) {
+ Array.set(field.get(obj),i, newValue);
+ }
+ }
+
+ /**
+ * Get the name of a property
+ */
public String getName() {return name;}
- public Class getType() {return getter.getReturnType(); }
-}
+ /**
+ * Get the type of a property
+ */
+ public Class getType() {
+ if (getter != null) {
+ return getter.getReturnType();
+ } else {
+ return field.getType();
+ }
+ }
+ /**
+ * Get the read Method.
+ * (This is package visibility so that Bean Utils
+ * can access this information. The other methods
+ * should be used during serialization/deserialization.)
+ */
+ Method getReadMethod() {
+ return getter;
+ }
+ /**
+ * Get the write Method.
+ * (This is package visibility so that Bean Utils
+ * can access this information. The other methods
+ * should be used during serialization/deserialization.)
+ */
+ Method getWriteMethod() {
+ return setter;
+ }
+}
1.2 +49 -6 xml-axis/java/src/org/apache/axis/utils/BeanUtils.java
Index: BeanUtils.java
===================================================================
RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/utils/BeanUtils.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- BeanUtils.java 16 Apr 2002 18:56:16 -0000 1.1
+++ BeanUtils.java 20 Apr 2002 00:22:25 -0000 1.2
@@ -62,6 +62,8 @@
import java.beans.Introspector;
import java.util.Vector;
import java.lang.reflect.Method;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
public class BeanUtils {
@@ -140,10 +142,14 @@
PropertyDescriptor[] rawPd, Class cls) {
BeanPropertyDescriptor[] myPd = new BeanPropertyDescriptor[rawPd.length];
+ int index1 = 0;
for (int i=0; i < rawPd.length; i++) {
- myPd[i] = new BeanPropertyDescriptor(rawPd[i].getName(),
- rawPd[i].getReadMethod(),
- rawPd[i].getWriteMethod());
+ if (rawPd[i].getReadMethod() != null &&
+ rawPd[i].getWriteMethod() != null) {
+ myPd[index1++] = new BeanPropertyDescriptor(rawPd[i].getName(),
+
rawPd[i].getReadMethod(),
+
rawPd[i].getWriteMethod());
+ }
}
try {
@@ -151,7 +157,7 @@
int index = 0;
// Build a new pd array
- // defined by the order of the get methods.
+ // defined by the order of the set methods.
BeanPropertyDescriptor[] newPd = new
BeanPropertyDescriptor[rawPd.length];
Method[] methods = cls.getMethods();
for (int i=0; i < methods.length; i++) {
@@ -159,7 +165,8 @@
if (method.getName().startsWith("set")) {
boolean found = false;
for (int j=0; j < myPd.length && !found; j++) {
- if (myPd[j].getWriteMethod() != null &&
+ if (myPd[j] != null &&
+ myPd[j].getWriteMethod() != null &&
myPd[j].getWriteMethod().equals(method)) {
found = true;
newPd[index] = myPd[j];
@@ -199,7 +206,8 @@
methods[j].getParameterTypes()[0] == int.class &&
methods[i].getParameterTypes()[0] == int.class) {
for (int k=0; k < myPd.length; k++) {
- if (myPd[k].getReadMethod() != null &&
+ if (myPd[k] != null &&
+ myPd[k].getReadMethod() != null &&
myPd[k].getWriteMethod() != null &&
myPd[k].getReadMethod().getName().equals(methods[j].getName()) &&
myPd[k].getWriteMethod().getName().equals(methods[i].getName())) {
@@ -212,6 +220,41 @@
}
}
}
+ ArrayList pd = new ArrayList();
+ for (int i=0; i < myPd.length; i++) {
+ if (myPd[i] != null) {
+ pd.add(myPd[i]);
+ }
+ }
+ // Now look for public fields
+ Field fields[] = cls.getFields();
+ if (fields != null && fields.length > 0) {
+ // See if the field is in the list of properties
+ // add it if not.
+ for (int i=0; i < fields.length; i++) {
+ Field f = fields[i];
+ String fName = f.getName();
+ boolean found = false;
+ for (int j=0; j<pd.size() && !found; j++) {
+ String pName =
+ ((BeanPropertyDescriptor)pd.get(i)).getName();
+ if (pName.length() == fName.length() &&
+ pName.substring(0,1).equalsIgnoreCase(
+ fName.substring(0,1))) {
+ found = pName.length() == 1 ||
+ pName.substring(1).equals(fName.substring(1));
+ }
+ }
+ if (!found) {
+ pd.add(new BeanPropertyDescriptor(f.getName(), f));
+ }
+ }
+ }
+ myPd = new BeanPropertyDescriptor[pd.size()];
+ for (int i=0; i <pd.size(); i++) {
+ myPd[i] = (BeanPropertyDescriptor) pd.get(i);
+ }
+
} catch (Exception e) {
// Don't process Property Descriptors if problems occur
return myPd;
1.5 +11 -4 xml-axis/java/test/encoding/AttributeBean.java
Index: AttributeBean.java
===================================================================
RCS file: /home/cvs/xml-axis/java/test/encoding/AttributeBean.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- AttributeBean.java 3 Apr 2002 06:09:55 -0000 1.4
+++ AttributeBean.java 20 Apr 2002 00:22:25 -0000 1.5
@@ -68,17 +68,18 @@
public class AttributeBean extends ParentBean {
private int age;
private float iD;
+ public String company; // element without getter/setter
private java.lang.String name; // attribute
private boolean male; // attribute
- public AttributeBean() {
- }
+ public AttributeBean() {}
- public AttributeBean(int age, float iD, java.lang.String name, boolean male) {
+ public AttributeBean(int age, float iD, String name, String company, boolean
male) {
this.age = age;
this.iD = iD;
this.name = name;
this.male = male;
+ this.company = company;
}
public int getAge() {
@@ -128,8 +129,14 @@
if (other.getName() != null) {
return false;
}
+ }else if (!name.equals(other.getName())) {
+ return false;
}
- if (!name.equals(other.getName())) {
+ if (company == null) {
+ if (company != null) {
+ return false;
+ }
+ } else if (!company.equals(other.company)) {
return false;
}
if (getParentFloat() != other.getParentFloat())
1.5 +1 -1 xml-axis/java/test/encoding/TestAttributes.java
Index: TestAttributes.java
===================================================================
RCS file: /home/cvs/xml-axis/java/test/encoding/TestAttributes.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- TestAttributes.java 3 Apr 2002 06:09:55 -0000 1.4
+++ TestAttributes.java 20 Apr 2002 00:22:25 -0000 1.5
@@ -69,6 +69,7 @@
bean.setAge(35);
bean.setID(1.15F);
bean.setMale(true);
+ bean.company = "Majesty's Secret Service";
bean.setName("James Bond");
RPCParam arg = new RPCParam("", "struct", bean);
@@ -115,7 +116,6 @@
Object obj = ((RPCParam)params.get(0)).getValue();
assertTrue("Deserialized param not an AttributeBean!",
(obj instanceof AttributeBean));
-
AttributeBean deserBean = (AttributeBean)obj;
assertTrue("Deserialized bean not equal to expected values!",
(bean.equals(deserBean)));