scheu 02/03/28 10:41:17 Modified: java/src/org/apache/axis/encoding/ser BaseDeserializerFactory.java BaseSerializerFactory.java BeanDeserializer.java BeanSerializer.java SimpleDeserializer.java SimpleSerializer.java java/src/org/apache/axis/wsdl/toJava JavaBeanHelperWriter.java Log: The following changes are made: 1) The JavaBeanHelper class now generates getSerializer and getDeserializer methods. These can be overridden by a user who wants to provide custom serialization. The emitted code currently constructs the serializer and directly passes it the "macro media" meta information. 2) The serializer base factories are improved to look for these new getSerializer/getDeserializer methods. (I did not remove the old lookup). I also fixed the exception handling to be more specific. 3) Made some cosmetic improvements to help extend some of these classes. Cheers ! Revision Changes Path 1.2 +121 -33 xml-axis/java/src/org/apache/axis/encoding/ser/BaseDeserializerFactory.java Index: BaseDeserializerFactory.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/BaseDeserializerFactory.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- BaseDeserializerFactory.java 26 Jan 2002 02:40:34 -0000 1.1 +++ BaseDeserializerFactory.java 28 Mar 2002 18:41:16 -0000 1.2 @@ -76,13 +76,15 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; /** * Base class for Axis Deserialization Factory classes for code reuse * * @author Rich Scheuerle <[EMAIL PROTECTED]> */ -public abstract class BaseDeserializerFactory implements DeserializerFactory { +public abstract class BaseDeserializerFactory + implements DeserializerFactory { static Vector mechanisms = null; @@ -91,55 +93,126 @@ protected Deserializer deser = null; protected QName xmlType = null; protected Class javaType = null; - protected Constructor dserClassConstructor = null; + protected Constructor deserClassConstructor = null; + protected Method getDeserializer = null; + protected boolean firstCall = true; /** * Constructor * @param deserClass is the class of the Deserializer - * @param share indicates if deserializers can be shared...i.e. getDeserializerAs - * will always return the same deserializer object if share is true. Sharing is - * only valid for xml primitives. + * @param share indicates if deserializers can be shared. getDeserializerAs + * will always return the same deserializer object if share is true. + * Sharing is only valid for xml primitives. */ public BaseDeserializerFactory(Class deserClass, boolean share) { this.deserClass = deserClass; this.share = share; } - public BaseDeserializerFactory(Class deserClass, boolean share, QName xmlType, Class javaType) { + public BaseDeserializerFactory(Class deserClass, boolean share, + QName xmlType, Class javaType) { this.deserClass = deserClass; this.share = share; this.xmlType = xmlType; this.javaType = javaType; } - public javax.xml.rpc.encoding.Deserializer getDeserializerAs(String mechanismType) + public javax.xml.rpc.encoding.Deserializer + getDeserializerAs(String mechanismType) throws JAXRPCException { // Need to add code to check against mechanisms vector. if (share && deser != null) { return deser; } - // First try to new up the deserializer with qname, class arguments deser = null; - if (javaType != null && xmlType != null) { - try { - if (dserClassConstructor == null) { - dserClassConstructor = - deserClass.getConstructor(new Class[] {Class.class, QName.class}); - } - deser = (Deserializer) - dserClassConstructor.newInstance(new Object[] {javaType, xmlType}); - } catch (Exception e) {} + try { + // Try getting a specialized Deserializer + deser = getSpecialized(mechanismType); + + // Try getting a general purpose Deserializer via constructor + // invocation + if (deser == null) { + deser = getGeneralPurpose(mechanismType); + } + + // If not successfull, try newInstance + if (deser == null) { + deser = (Deserializer) deserClass.newInstance(); + } + } catch (Exception e) { + throw new JAXRPCException(e); } + firstCall = false; + return deser; + } - // If not successfull, try newInstance - if (deser == null) { - try { - deser = (Deserializer) deserClass.newInstance(); - } catch (Exception e) {} + /** + * Obtains a deserializer by invoking <constructor>(javaType, xmlType) + * on the deserClass. + */ + protected Deserializer getGeneralPurpose(String mechanismType) { + if (javaType != null && xmlType != null) { + if (deserClassConstructor == null && firstCall) { + try { + deserClassConstructor = + deserClass.getConstructor( + new Class[] {Class.class, QName.class}); + } catch (NoSuchMethodException e) {} + } + if (deserClassConstructor != null) { + try { + return (Deserializer) + deserClassConstructor.newInstance( + new Object[] {javaType, xmlType}); + } catch (InstantiationException e) { + } catch (IllegalAccessException e) { + } catch (InvocationTargetException e) {} + } } - if (deser == null) { - throw new JAXRPCException(); + return null; + } + + /** + * Obtains a deserializer by invoking getDeserializer method in the + * javaType class or its Helper class. + */ + protected Deserializer getSpecialized(String mechanismType) { + if (javaType != null && xmlType != null) { + if (getDeserializer == null && firstCall) { + try { + getDeserializer = + javaType.getMethod("getDeserialier", + new Class[] {String.class, + Class.class, + QName.class}); + } catch (NoSuchMethodException e) {} + if (getDeserializer == null) { + try { + ClassLoader cl = + Thread.currentThread().getContextClassLoader(); + Class helper = Class.forName( + javaType.getName() + "_Helper", true, cl); + getDeserializer = + helper.getMethod("getDeserializer", + new Class[] {String.class, + Class.class, + QName.class}); + } catch (NoSuchMethodException e) { + } catch (ClassNotFoundException e) {} + } + } + if (getDeserializer != null) { + try { + return (Deserializer) + getDeserializer.invoke( + null, + new Object[] {mechanismType, + javaType, + xmlType}); + } catch (IllegalAccessException e) { + } catch (InvocationTargetException e) {} + } } - return deser; + return null; } /** @@ -165,27 +238,42 @@ * @param QName xmlType * @param Class javaType */ - public static DeserializerFactory createFactory(Class factory, Class javaType, QName xmlType) { + public static DeserializerFactory createFactory(Class factory, + Class javaType, + QName xmlType) { DeserializerFactory df = null; try { - Method method = factory.getMethod("create", new Class[] {Class.class, QName.class}); - df = (DeserializerFactory) method.invoke(null, new Object[] {javaType, xmlType}); - } catch (Exception e) {} + Method method = + factory.getMethod( + "create", + new Class[] {Class.class, QName.class}); + df = (DeserializerFactory) + method.invoke(null, + new Object[] {javaType, xmlType}); + } catch (NoSuchMethodException e) { + } catch (IllegalAccessException e) { + } catch (InvocationTargetException e) {} if (df == null) { try { Constructor constructor = - factory.getConstructor(new Class[] {Class.class, QName.class}); + factory.getConstructor( + new Class[] {Class.class, QName.class}); df = (DeserializerFactory) - constructor.newInstance(new Object[] {javaType, xmlType}); - } catch (Exception e) {} + constructor.newInstance( + new Object[] {javaType, xmlType}); + } catch (NoSuchMethodException e) { + } catch (InstantiationException e) { + } catch (IllegalAccessException e) { + } catch (InvocationTargetException e) {} } if (df == null) { try { df = (DeserializerFactory) factory.newInstance(); - } catch (Exception e) {} + } catch (InstantiationException e) { + } catch (IllegalAccessException e) {} } return df; } 1.4 +126 -36 xml-axis/java/src/org/apache/axis/encoding/ser/BaseSerializerFactory.java Index: BaseSerializerFactory.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/BaseSerializerFactory.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- BaseSerializerFactory.java 20 Mar 2002 16:53:07 -0000 1.3 +++ BaseSerializerFactory.java 28 Mar 2002 18:41:16 -0000 1.4 @@ -77,13 +77,15 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; /** * Base class for Axis Serialization Factory classes for code reuse * * @author Rich Scheuerle <[EMAIL PROTECTED]> */ -public abstract class BaseSerializerFactory implements SerializerFactory { +public abstract class BaseSerializerFactory + implements SerializerFactory { static Vector mechanisms = null; @@ -93,64 +95,137 @@ protected QName xmlType = null; protected Class javaType = null; protected Constructor serClassConstructor = null; + protected Method getSerializer = null; + protected boolean firstCall = true; /** * Constructor * @param serClass is the class of the Serializer - * @param share indicates if serializers can be shared...i.e. getSerializerAs - * will always return the same serializer object if share is true. Sharing is - * only valid for xml primitives. + * @param share indicates if serializers can be shared. getSerializerAs + * will always return the same serializer object if share is true. + * Sharing is only valid for xml primitives. */ public BaseSerializerFactory(Class serClass, boolean share) { this.serClass = serClass; this.share = share; } - public BaseSerializerFactory(Class serClass, boolean share, QName xmlType, Class javaType) { + public BaseSerializerFactory(Class serClass, boolean share, + QName xmlType, Class javaType) { this.serClass = serClass; this.share = share; this.xmlType = xmlType; this.javaType = javaType; } - public javax.xml.rpc.encoding.Serializer getSerializerAs(String mechanismType) + public javax.xml.rpc.encoding.Serializer + getSerializerAs(String mechanismType) throws JAXRPCException { // Need to add code to check against mechanisms vector. if (share && ser != null) { return ser; } - // First try to new up the serializer with qname, class arguments ser = null; + + try { + // Try getting a specialized Serializer + ser = getSpecialized(mechanismType); + + // Try getting a general purpose Serializer via constructor + // invocation + if (ser == null) { + ser = getGeneralPurpose(mechanismType); + } + + // If not successfull, try newInstance + if (ser == null) { + ser = (Serializer) serClass.newInstance(); + } + } catch (Exception e) { + throw new JAXRPCException( + JavaUtils.getMessage("CantGetSerializer", + serClass.getName()), + e); + } + firstCall = false; + return ser; + } + + /** + * Obtains a serializer by invoking <constructor>(javaType, xmlType) + * on the serClass. + */ + protected Serializer getGeneralPurpose(String mechanismType) { if (javaType != null && xmlType != null) { - try { - if (serClassConstructor == null) { + if (serClassConstructor == null && firstCall) { + try { serClassConstructor = - serClass.getConstructor(new Class[] {Class.class, QName.class}); - } - ser = (Serializer) - serClassConstructor.newInstance(new Object[] {javaType, xmlType}); - } catch (Exception e) { - // ignore this error and continue + serClass.getConstructor( + new Class[] {Class.class, QName.class}); + } catch (NoSuchMethodException e) {} } - } - // If not successfull, try newInstance with no arguments - if (ser == null) { - try { - ser = (Serializer) serClass.newInstance(); - } catch (Exception e) { - throw new JAXRPCException( - JavaUtils.getMessage("CantGetSerializer", - serClass.getName()), - e); + if (serClassConstructor != null) { + try { + return (Serializer) + serClassConstructor.newInstance( + new Object[] {javaType, xmlType}); + } catch (InstantiationException e) { + } catch (IllegalAccessException e) { + } catch (InvocationTargetException e) {} } } + return null; + } - return ser; + /** + * Obtains a serializer by invoking getSerializer method in the + * javaType class or its Helper class. + */ + protected Serializer getSpecialized(String mechanismType) { + if (javaType != null && xmlType != null) { + if (getSerializer == null && firstCall) { + try { + getSerializer = + javaType.getMethod("getSerialier", + new Class[] {String.class, + Class.class, + QName.class}); + } catch (NoSuchMethodException e) {} + if (getSerializer == null) { + try { + ClassLoader cl = + Thread.currentThread().getContextClassLoader(); + Class helper = Class.forName( + javaType.getName() + "_Helper", true, cl); + getSerializer = + helper.getMethod("getSerializer", + new Class[] {String.class, + Class.class, + QName.class}); + } catch (NoSuchMethodException e) { + } catch (ClassNotFoundException e) {} + } + } + if (getSerializer != null) { + try { + return (Serializer) + getSerializer.invoke( + null, + new Object[] {mechanismType, + javaType, + xmlType}); + } catch (IllegalAccessException e) { + } catch (InvocationTargetException e) {} + } + } + return null; } /** - * Returns a list of all XML processing mechanism types supported by this SerializerFactory. + * Returns a list of all XML processing mechanism types supported + * by this SerializerFactory. * - * @return List of unique identifiers for the supported XML processing mechanism types + * @return List of unique identifiers for the supported XML + * processing mechanism types */ public Iterator getSupportedMechanismTypes() { if (mechanisms == null) { @@ -170,27 +245,42 @@ * @param QName xmlType * @param Class javaType */ - public static SerializerFactory createFactory(Class factory, Class javaType, QName xmlType) { + public static SerializerFactory createFactory(Class factory, + Class javaType, + QName xmlType) { SerializerFactory sf = null; try { - Method method = factory.getMethod("create", new Class[] {Class.class, QName.class}); - sf = (SerializerFactory) method.invoke(null, new Object[] {javaType, xmlType}); - } catch (Exception e) {} + Method method = + factory.getMethod( + "create", + new Class[] {Class.class, QName.class}); + sf = (SerializerFactory) + method.invoke(null, + new Object[] {javaType, xmlType}); + } catch (NoSuchMethodException e) { + } catch (IllegalAccessException e) { + } catch (InvocationTargetException e) {} if (sf == null) { try { Constructor constructor = - factory.getConstructor(new Class[] {Class.class, QName.class}); + factory.getConstructor( + new Class[] {Class.class, QName.class}); sf = (SerializerFactory) - constructor.newInstance(new Object[] {javaType, xmlType}); - } catch (Exception e) {} + constructor.newInstance( + new Object[] {javaType, xmlType}); + } catch (NoSuchMethodException e) { + } catch (InstantiationException e) { + } catch (IllegalAccessException e) { + } catch (InvocationTargetException e) {} } if (sf == null) { try { sf = (SerializerFactory) factory.newInstance(); - } catch (Exception e) {} + } catch (InstantiationException e) { + } catch (IllegalAccessException e) {} } return sf; } 1.16 +8 -4 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.15 retrieving revision 1.16 diff -u -r1.15 -r1.16 --- BeanDeserializer.java 20 Mar 2002 15:53:44 -0000 1.15 +++ BeanDeserializer.java 28 Mar 2002 18:41:16 -0000 1.16 @@ -101,18 +101,24 @@ QName xmlType; Class javaType; - private HashMap propertyMap = new HashMap(); + protected HashMap propertyMap = new HashMap(); /** Type metadata about this class for XML deserialization */ - private TypeDesc typeDesc = null; + protected TypeDesc typeDesc = null; // This counter is updated to deal with deserialize collection properties protected int collectionIndex = -1; // Construct BeanSerializer for the indicated class/qname public BeanDeserializer(Class javaType, QName xmlType) { + this(javaType, xmlType, TypeDesc.getTypeDescForClass(javaType)); + } + + // Construct BeanSerializer for the indicated class/qname and meta Data + public BeanDeserializer(Class javaType, QName xmlType, TypeDesc typeDesc ) { this.xmlType = xmlType; this.javaType = javaType; + this.typeDesc = typeDesc; // Get a list of the bean properties BeanPropertyDescriptor[] pd = BeanSerializer.getPd(javaType); // loop through properties and grab the names for later @@ -120,8 +126,6 @@ BeanPropertyDescriptor descriptor = pd[i]; propertyMap.put(descriptor.getName(), descriptor); } - - typeDesc = TypeDesc.getTypeDescForClass(javaType); // create a value try { 1.23 +11 -7 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.22 retrieving revision 1.23 diff -u -r1.22 -r1.23 --- BeanSerializer.java 20 Mar 2002 21:43:51 -0000 1.22 +++ BeanSerializer.java 28 Mar 2002 18:41:16 -0000 1.23 @@ -118,17 +118,21 @@ QName xmlType; Class javaType; - private BeanPropertyDescriptor[] propertyDescriptor = null; - private TypeDesc typeDesc = null; + protected BeanPropertyDescriptor[] propertyDescriptor = null; + protected TypeDesc typeDesc = null; // Construct BeanSerializer for the indicated class/qname public BeanSerializer(Class javaType, QName xmlType) { + this(javaType, xmlType, TypeDesc.getTypeDescForClass(javaType)); + } + + // Construct BeanSerializer for the indicated class/qname + public BeanSerializer(Class javaType, QName xmlType, TypeDesc typeDesc) { this.xmlType = xmlType; this.javaType = javaType; + this.typeDesc = typeDesc; propertyDescriptor = getPd(javaType); - - typeDesc = TypeDesc.getTypeDescForClass(javaType); } /** @@ -386,7 +390,7 @@ * @param where location for the generated schema node * @throws Exception */ - private void writeField(Types types, String fieldName, + protected void writeField(Types types, String fieldName, Class fieldType, boolean isUnbounded, Element where) throws Exception { @@ -408,7 +412,7 @@ * @param where location for the generated schema node * @throws Exception */ - private void writeAttribute(Types types, + protected void writeAttribute(Types types, String fieldName, Class fieldType, Element where) throws Exception { @@ -436,7 +440,7 @@ * @param pd the properties of this class * @return attributes for this element, null if none */ - private Attributes getObjectAttributes(Object value, + protected Attributes getObjectAttributes(Object value, Attributes attributes, SerializationContext context) { 1.8 +16 -2 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.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- SimpleDeserializer.java 9 Mar 2002 19:29:48 -0000 1.7 +++ SimpleDeserializer.java 28 Mar 2002 18:41:16 -0000 1.8 @@ -125,10 +125,24 @@ } typeDesc = TypeDesc.getTypeDescForClass(javaType); - } - + } } + public SimpleDeserializer(Class javaType, QName xmlType, TypeDesc typeDesc) { + this.xmlType = xmlType; + this.javaType = javaType; + this.typeDesc = typeDesc; + // if this type is a SimpleType bean, get bean properties + if (SimpleType.class.isAssignableFrom(javaType)) { + this.pd = BeanSerializer.getPd(javaType); + // loop through properties and grab the names for later + for (int i = 0; i < pd.length; i++) { + BeanPropertyDescriptor descriptor = pd[i]; + propertyMap.put(descriptor.getName(), descriptor); + } + } + } + /** * The Factory calls setConstructor. */ 1.9 +10 -0 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.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- SimpleSerializer.java 11 Mar 2002 16:25:31 -0000 1.8 +++ SimpleSerializer.java 28 Mar 2002 18:41:16 -0000 1.9 @@ -108,6 +108,16 @@ typeDesc = TypeDesc.getTypeDescForClass(javaType); } } + public SimpleSerializer(Class javaType, QName xmlType, TypeDesc typeDesc) { + this.xmlType = xmlType; + this.javaType = javaType; + this.typeDesc = typeDesc; + + if (SimpleType.class.isAssignableFrom(javaType)) { + // get the bean properties and the list of attributes from the bean + propertyDescriptor = BeanSerializer.getPd(javaType); + } + } /** * Serialize a primitive or simple value. * If the object to serialize is a primitive, the Object value below 1.2 +74 -12 xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaBeanHelperWriter.java Index: JavaBeanHelperWriter.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaBeanHelperWriter.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- JavaBeanHelperWriter.java 22 Mar 2002 14:38:45 -0000 1.1 +++ JavaBeanHelperWriter.java 28 Mar 2002 18:41:17 -0000 1.2 @@ -67,11 +67,11 @@ * This is Wsdl2java's Helper Type Writer. It writes the <typeName>.java file. */ public class JavaBeanHelperWriter extends JavaWriter { - private TypeEntry type; - private Vector elements; - private Vector attributes; - private TypeEntry extendType; - private HashMap elementMappings = null; + protected TypeEntry type; + protected Vector elements; + protected Vector attributes; + protected TypeEntry extendType; + protected HashMap elementMappings = null; /** * Constructor. @@ -107,7 +107,22 @@ pw.println("public class " + className + " {"); } - // Build elementMappings + writeMetaData(); + writeSerializer(); + writeDeserializer(); + + if (!embeddedCode) { + pw.println("}"); + pw.close(); + } + + } // writeFileBody + + /** + * write MetaData code + */ + protected void writeMetaData() { + // Collect elementMappings if (elements != null) { for (int i = 0; i < elements.size(); i++) { ElementDecl elem = (ElementDecl)elements.get(i); @@ -124,7 +139,6 @@ } } } - // if we have attributes, create metadata function which returns the // list of properties that are attributes instead of elements @@ -186,11 +200,59 @@ pw.println(" }"); pw.println(); } - if (!embeddedCode) { - pw.println("}"); - pw.close(); + } + + /** + * write Serializer getter code and pass in meta data to avoid + * undo introspection. + */ + protected void writeSerializer() { + String typeDesc = null; + if (attributes != null || elementMappings != null) { + typeDesc = "typeDesc"; } - - } // writeFileBody + String ser = " org.apache.axis.encoding.ser.BeanSerializer"; + if (type.isSimpleType()) { + ser = " org.apache.axis.encoding.ser.SimpleSerializer"; + } + pw.println(" /**"); + pw.println(" * Get Custom Serializer"); + pw.println(" */"); + pw.println(" public static org.apache.axis.encoding.Serializer getSerializer("); + pw.println(" String mechType, "); + pw.println(" Class _javaType, "); + pw.println(" javax.xml.rpc.namespace.QName _xmlType) {"); + pw.println(" return "); + pw.println(" new " + ser +"("); + pw.println(" _javaType, _xmlType," + typeDesc + ");"); + pw.println(" };"); + pw.println(); + } + /** + * write Deserializer getter code and pass in meta data to avoid + * undo introspection. + */ + protected void writeDeserializer() { + String typeDesc = null; + if (attributes != null || elementMappings != null) { + typeDesc = "typeDesc"; + } + String dser = " org.apache.axis.encoding.ser.BeanDeserializer"; + if (type.isSimpleType()) { + dser = " org.apache.axis.encoding.ser.SimpleDeserializer"; + } + pw.println(" /**"); + pw.println(" * Get Custom Deserializer"); + pw.println(" */"); + pw.println(" public static org.apache.axis.encoding.Deserializer getDeserializer("); + pw.println(" String mechType, "); + pw.println(" Class _javaType, "); + pw.println(" javax.xml.rpc.namespace.QName _xmlType) {"); + pw.println(" return "); + pw.println(" new " + dser + "("); + pw.println(" _javaType, _xmlType," + typeDesc + ");"); + pw.println(" };"); + pw.println(); + } } // class JavaBeanHelperWriter