scheu 2002/09/25 11:27:03 Modified: java/src/org/apache/axis/encoding DefaultTypeMappingImpl.java SerializationContextImpl.java java/src/org/apache/axis/encoding/ser BaseSerializerFactory.java Log: Follow-on fix for 12886. (xsi:type needs to be sent if the prefered xmlType does not match the actual type) Changes: * Changed the getSerializer(javaType, preferedXMLType) method to have an extra actualXMLType QNameHolder parameter. The getSerializer method returns the actual xmlType via this parameter. * If the actual xmlType is different than the prefered xmlType, the xsi:type attribute is set with the actual xmlType. (Same logic that Glen had in his fix.) * The getSerializer method determines the actual xmlType by querying the BaseSerializerFactory. If this fails, a less performant solution is used (using the same strategy as Glen's fix). * getXMLType() and getJavaType() access methods are added to the BaseSerializerFactory. * Testing revealed a bug in DefaultTypeMappingImpl. The wrong QName was being used for org.apache.axis.types.Day. This is also fixed. Revision Changes Path 1.57 +2 -2 xml-axis/java/src/org/apache/axis/encoding/DefaultTypeMappingImpl.java Index: DefaultTypeMappingImpl.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/DefaultTypeMappingImpl.java,v retrieving revision 1.56 retrieving revision 1.57 diff -u -r1.56 -r1.57 --- DefaultTypeMappingImpl.java 25 Sep 2002 16:29:47 -0000 1.56 +++ DefaultTypeMappingImpl.java 25 Sep 2002 18:27:03 -0000 1.57 @@ -314,9 +314,9 @@ ); myRegister(Constants.XSD_DAY, org.apache.axis.types.Day.class, new SimplePrimitiveSerializerFactory(org.apache.axis.types.Day.class, - Constants.XSD_YEARMONTH), + Constants.XSD_DAY), new SimpleDeserializerFactory(org.apache.axis.types.Day.class, - Constants.XSD_YEARMONTH) + Constants.XSD_DAY) ); myRegister(Constants.XSD_MONTHDAY, org.apache.axis.types.MonthDay.class, new SimplePrimitiveSerializerFactory(org.apache.axis.types.MonthDay.class, 1.74 +49 -15 xml-axis/java/src/org/apache/axis/encoding/SerializationContextImpl.java Index: SerializationContextImpl.java =================================================================== RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/SerializationContextImpl.java,v retrieving revision 1.73 retrieving revision 1.74 diff -u -r1.73 -r1.74 --- SerializationContextImpl.java 25 Sep 2002 03:21:08 -0000 1.73 +++ SerializationContextImpl.java 25 Sep 2002 18:27:03 -0000 1.74 @@ -65,6 +65,7 @@ import org.apache.axis.soap.SOAPConstants; import org.apache.axis.wsdl.symbolTable.SymbolTable; import org.apache.axis.wsdl.symbolTable.SchemaUtils; +import org.apache.axis.encoding.ser.BaseSerializerFactory; import org.apache.axis.enum.Style; import org.apache.axis.handlers.soap.SOAPService; import org.apache.axis.attachments.Attachments; @@ -90,6 +91,7 @@ import org.xml.sax.helpers.AttributesImpl; import javax.xml.namespace.QName; +import javax.xml.rpc.holders.QNameHolder; import javax.xml.rpc.JAXRPCException; import java.io.IOException; import java.io.Writer; @@ -845,7 +847,7 @@ forceSer = mri.value; // Now serialize the value. - // The sendType parameter is set to true for interop purposes. + // The sendType parameter is defaulted for interop purposes. // Some of the remote services do not know how to // ascertain the type in these circumstances (though Axis does). serialize(multirefQName, attrs, mri.value, @@ -1199,17 +1201,28 @@ } // Try getting a serializer for the prefered xmlType - Serializer ser = getSerializer(javaType, xmlType); + QNameHolder actualXMLType = new QNameHolder(); + Serializer ser = getSerializer(javaType, xmlType, + actualXMLType); if ( ser != null ) { - // Send the xmlType if indicated. - QName actualType = ((TypeMappingImpl)tm).getXMLType(javaType, - xmlType); - - if (shouldSendType || (xmlType != null && - (!actualType.equals(xmlType)))) - attributes = setTypeAttribute(attributes, actualType); - + // Send the xmlType if indicated or if + // the actual xmlType is different than the + // prefered xmlType + if (shouldSendType || + (xmlType != null && + actualXMLType.value != null && + (!xmlType.equals(actualXMLType.value)))) { + attributes = setTypeAttribute(attributes, + actualXMLType.value); + } + + // ----------------- + // NOTE: I have seen doc/lit tests that use + // the type name as the element name in multi-ref cases + // (for example <soapenc:Array ... >) + // In such cases the xsi:type is not passed along. + // ----------------- // The multiref QName is our own fake name. // It may be beneficial to set the name to the // type name, but I didn't see any improvements @@ -1264,20 +1277,26 @@ * getSerializer * Attempts to get a serializer for the indicated javaType and xmlType. * @param javaType is the type of the object - * @param xmlType is the preferred qname type. + * @param preferXmlType is the preferred qname type. + * @param actualXmlType is set to a QNameHolder or null. + * If a QNameHolder, the actual xmlType is returned. * @return found class/serializer or null **/ - private Serializer getSerializer(Class javaType, QName xmlType) { + private Serializer getSerializer(Class javaType, QName preferXMLType, + QNameHolder actualXMLType) { SerializerFactory serFactory = null ; TypeMapping tm = getTypeMapping(); + if (actualXMLType != null) { + actualXMLType.value = null; + } while (javaType != null) { - serFactory = (SerializerFactory) tm.getSerializer(javaType, xmlType); + serFactory = (SerializerFactory) tm.getSerializer(javaType, preferXMLType); if (serFactory != null) break; // Walk my interfaces... - serFactory = getSerializerFactoryFromInterface(javaType, xmlType, tm); + serFactory = getSerializerFactoryFromInterface(javaType, preferXMLType, tm); // Finally, head to my superclass if (serFactory != null) @@ -1290,13 +1309,28 @@ Serializer ser = null; if ( serFactory != null ) { ser = (Serializer) serFactory.getSerializerAs(Constants.AXIS_SAX); + + if (actualXMLType != null) { + // Get the actual qname xmlType from the factory. + // If not found via the factory, fall back to a less + // performant solution. + if (serFactory instanceof BaseSerializerFactory) { + actualXMLType.value = + ((BaseSerializerFactory) serFactory).getXMLType(); + } + if (actualXMLType.value == null) { + actualXMLType.value = + ((TypeMappingImpl) tm).getXMLType(javaType, + preferXMLType); + } + } } return ser; } public String getValueAsString(Object value, QName xmlType) throws IOException { - Serializer ser = getSerializer(value.getClass(), xmlType); + Serializer ser = getSerializer(value.getClass(), xmlType, null); if (!(ser instanceof SimpleValueSerializer)) { throw new IOException( Messages.getMessage("needSimpleValueSer", 1.16 +16 -0 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.15 retrieving revision 1.16 diff -u -r1.15 -r1.16 --- BaseSerializerFactory.java 18 Sep 2002 16:10:35 -0000 1.15 +++ BaseSerializerFactory.java 25 Sep 2002 18:27:03 -0000 1.16 @@ -250,7 +250,23 @@ } return mechanisms.iterator(); } + + /** + * get xmlType + * @return xmlType QName for this factory + */ + public QName getXMLType() { + return xmlType; + } + /** + * get javaType + * @return javaType Class for this factory + */ + public Class getJavaType() { + return javaType; + } + /** * Utility method that intospects on a factory class to decide how to * create the factory. Tries in the following order: