001: /**
002: * $Id: XMapSerializer.java,v 1.2 2003/12/01 10:47:40 vv138407 Exp $
003: * Copyright 2003 Sun Microsystems, Inc. All
004: * rights reserved. Use of this product is subject
005: * to license terms. Federal Acquisitions:
006: * Commercial Software -- Government Users
007: * Subject to Standard License Terms and
008: * Conditions.
009: *
010: * Sun, Sun Microsystems, the Sun logo, and Sun ONE
011: * are trademarks or registered trademarks of Sun Microsystems,
012: * Inc. in the United States and other countries.
013: */package com.sun.portal.providers.simplewebservice.rpc;
014:
015: import java.util.Iterator;
016: import java.util.Map;
017: import java.util.HashMap;
018: import javax.xml.namespace.QName;
019:
020: import com.sun.xml.rpc.util.StructMap;
021: import com.sun.xml.rpc.util.JAXRPCClassFactory;
022: import com.sun.xml.rpc.util.exception.LocalizableExceptionAdapter;
023: import com.sun.xml.rpc.encoding.DeserializationException;
024: import com.sun.xml.rpc.encoding.SOAPInstanceBuilder;
025: import com.sun.xml.rpc.encoding.ObjectSerializerBase;
026: import com.sun.xml.rpc.encoding.Initializable;
027: import com.sun.xml.rpc.encoding.JAXRPCSerializer;
028: import com.sun.xml.rpc.encoding.JAXRPCDeserializer;
029: import com.sun.xml.rpc.encoding.InternalTypeMappingRegistry;
030: import com.sun.xml.rpc.encoding.SOAPSerializationContext;
031: import com.sun.xml.rpc.encoding.SOAPDeserializationState;
032: import com.sun.xml.rpc.encoding.SOAPDeserializationContext;
033: import com.sun.xml.rpc.encoding.xsd.XSDConstants;
034: import com.sun.xml.rpc.streaming.XMLReader;
035: import com.sun.xml.rpc.streaming.XMLWriter;
036: import com.sun.xml.rpc.streaming.XMLReaderUtil;
037: import com.sun.xml.rpc.streaming.Attributes;
038: import com.sun.xml.rpc.wsdl.document.soap.SOAPConstants;
039: import com.sun.xml.rpc.processor.modeler.rmi.SOAPSimpleTypeCreatorBase;
040:
041: import com.sun.portal.providers.simplewebservice.ParameterDescriptor;
042: import com.sun.portal.providers.simplewebservice.util.XList;
043:
044: public class XMapSerializer extends ObjectSerializerBase implements
045: Initializable {
046:
047: private static final String old_XSD_URI = "http://www.w3.org/1999/XMLSchema";
048: private static final String old_XSI_URI = "http://www.w3.org/1999/XMLSchema-instance";
049:
050: protected ParameterDescriptor paramDesc = null;
051: protected InternalTypeMappingRegistry registry = null;
052: protected Map javaToXmlType = new HashMap();
053:
054: public XMapSerializer(QName type, boolean encodeType,
055: boolean isNullable, String encodingStyle,
056: ParameterDescriptor paramDesc) {
057:
058: super (type, encodeType, isNullable, encodingStyle);
059: SOAPSimpleTypeCreatorBase base = JAXRPCClassFactory
060: .newInstance().createSOAPSimpleTypeCreator();
061: base.initializeJavaToXmlTypeMap(javaToXmlType);
062: // SOAPSimpleTypeCreator typeCreator = new SOAPSimpleTypeCreator();
063: // typeCreator.initializeJavaToXmlTypeMap(javaToXmlType);
064: this .paramDesc = paramDesc;
065: }
066:
067: public void initialize(InternalTypeMappingRegistry registry)
068: throws Exception {
069: this .registry = registry;
070: }
071:
072: protected void doSerializeInstance(Object instance,
073: XMLWriter writer, SOAPSerializationContext context)
074: throws Exception {
075:
076: StructMap struct = (StructMap) instance;
077: Iterator eachKey = struct.keys().iterator();
078: Iterator eachValue = struct.values().iterator();
079: JAXRPCSerializer serializer = null;
080:
081: while (eachKey.hasNext()) {
082: Object value = eachValue.next();
083: QName key = (QName) eachKey.next();
084:
085: if (value != null) {
086: Class boxedClass = getBoxedClassFor(value.getClass());
087:
088: if (boxedClass == null) {
089: boxedClass = value.getClass();
090:
091: QName xmlType = getXMLTypeFromParamDesc(key);
092:
093: serializer = (JAXRPCSerializer) registry
094: .getSerializer(
095: SOAPConstants.NS_SOAP_ENCODING,
096: xmlType);
097: } else {
098: serializer = (JAXRPCSerializer) registry
099: .getSerializer(
100: SOAPConstants.NS_SOAP_ENCODING,
101: boxedClass, (QName) javaToXmlType
102: .get(boxedClass));
103: }
104: serializer.serialize(value, key, null, writer, context);
105: } else {
106: serializeNull(key, writer, context);
107: }
108: }
109:
110: }
111:
112: protected Object doDeserialize(SOAPDeserializationState state,
113: XMLReader reader, SOAPDeserializationContext context)
114: throws Exception {
115:
116: StructMap instance = new StructMap();
117: Object member;
118: XMapBuilder builder = null;
119: boolean isComplete = true;
120:
121: int memberIndex = 0;
122:
123: while (reader.nextElementContent() != XMLReader.END) {
124: QName key = reader.getName();
125:
126: if (!getNullStatus(reader)) {
127: QName xmlType = this .getType(reader);
128:
129: if (xmlType == null) {
130: xmlType = getXMLTypeFromParamDesc(key);
131: }
132:
133: JAXRPCDeserializer deserializer = null;
134:
135: if (xmlType != null) {
136: if (isOldXSDNamespace(xmlType.getNamespaceURI())) {
137: xmlType = getNewSimpleTypeQName(xmlType
138: .getLocalPart());
139: }
140: }
141:
142: deserializer = (JAXRPCDeserializer) registry
143: .getDeserializer(encodingStyle, xmlType);
144:
145: member = deserializer.deserialize(key, reader, context);
146:
147: if (member instanceof SOAPDeserializationState) {
148:
149: if (builder == null) {
150: builder = new XMapBuilder(instance);
151: }
152: state = registerWithMemberState(instance, state,
153: member, memberIndex, builder);
154: isComplete = false;
155: }
156:
157: instance.put(key, member);
158: } else {
159: instance.put(key, null);
160: }
161: memberIndex++;
162: }
163: return (isComplete ? (Object) instance : (Object) state);
164: }
165:
166: private static Class getBoxedClassFor(Class possiblePrimitiveType) {
167: if (possiblePrimitiveType == null)
168: return null;
169:
170: if (possiblePrimitiveType == java.lang.Boolean.class)
171: return boolean.class;
172: else if (possiblePrimitiveType == java.lang.Byte.class)
173: return byte.class;
174: else if (possiblePrimitiveType == java.lang.Double.class)
175: return double.class;
176: else if (possiblePrimitiveType == java.lang.Float.class)
177: return float.class;
178: else if (possiblePrimitiveType == java.lang.Integer.class)
179: return int.class;
180: else if (possiblePrimitiveType == java.lang.Long.class)
181: return long.class;
182: else if (possiblePrimitiveType == java.lang.Short.class)
183: return short.class;
184: else if (possiblePrimitiveType == java.lang.String.class)
185: return String.class;
186:
187: if (possiblePrimitiveType.isPrimitive())
188: return possiblePrimitiveType;
189:
190: return null;
191: }
192:
193: /* .
194: * .
195: * .
196: * <boolean_4 xsi:type="xsd:boolean">false</boolean_4>
197: * <TestNestedComplexType_5 href="#ID1"/></ans1:get2LevelNestedComplexType>
198: *
199: * <ans2:TestNestedComplexType xmlns:ans2="http://com.sun.portal.providers.simplewebservice.test.service/types/TestSWS2"
200: * id="ID1"
201: * xsi:type="ans2:TestNestedComplexType">
202: * <booleanData xsi:type="xsd:boolean">false</booleanData>
203: * <intData xsi:type="xsd:int">131129</intData>
204: * <longData xsi:type="xsd:long">131129</longData>
205: * <stringData xsi:type="xsd:string">Test data sent from client</stringData>
206: * <testComplexType href="#ID2"/></ans2:TestNestedComplexType>
207: *
208: * For a case like above, getType(reader) returns null, when parsing
209: * <TestNestedComplexType_5 href="#ID1"/>. The registry throws a deserialization
210: * error. Workaround for this case. This is a JAXRPC bug that will
211: * arise once JAXRPC bug 4848627 is fixed.
212: */
213:
214: protected QName getXMLTypeFromParamDesc(QName paramName) {
215: XList list = (XList) this .paramDesc.getValue();
216:
217: for (int i = 0; i < list.size(); i++) {
218: ParameterDescriptor param = (ParameterDescriptor) list
219: .get(i);
220:
221: if (param.getName().equals(paramName.getLocalPart())) {
222: XList childList = (XList) param.getValue();
223:
224: return new QName(childList.getTargetNameSpace(),
225: childList.getComplexTypeName());
226: }
227: }
228: return null;
229: }
230:
231: /*
232: * Google's response XML has http://www.w3.org/1999/XMLSchema-instance,
233: * although the WSDL indicates http://www.w3.org/2001/XMLSchema-instance.
234: * Hence overriding the method in SerializerBase.
235: */
236: public static QName getType(XMLReader reader) throws Exception {
237: QName type = null;
238:
239: Attributes attrs = reader.getAttributes();
240: String typeVal = attrs.getValue(XSDConstants.URI_XSI, "type");
241:
242: if (typeVal == null)
243: typeVal = attrs.getValue(old_XSI_URI, "type");
244:
245: if (typeVal != null) {
246: type = XMLReaderUtil.decodeQName(reader, typeVal);
247: }
248: return type;
249: }
250:
251: /*
252: * Google's response XML has http://www.w3.org/1999/XMLSchema,
253: * although the WSDL indicates http://www.w3.org/2001/XMLSchema.
254: * Hence creating a 'map' method to get the new QName, with the
255: * the newer namespace URI. This ensures that the registry.getDeserializer
256: * call returns the serializer instead of null.
257: */
258: private QName getNewSimpleTypeQName(String oldTypeName) {
259: Class className = null;
260:
261: if ("boolean".equals(oldTypeName))
262: className = boolean.class;
263: else if ("byte".equals(oldTypeName))
264: className = byte.class;
265: else if ("short".equals(oldTypeName))
266: className = short.class;
267: else if ("int".equals(oldTypeName))
268: className = int.class;
269: else if ("long".equals(oldTypeName))
270: className = long.class;
271: else if ("float".equals(oldTypeName))
272: className = float.class;
273: else if ("double".equals(oldTypeName))
274: className = double.class;
275: else if ("string".equals(oldTypeName))
276: className = String.class;
277: else if ("String".equals(oldTypeName))
278: className = String.class;
279:
280: if (className != null)
281: className = getBoxedClassFor(className);
282:
283: return (QName) javaToXmlType.get(className);
284: }
285:
286: /*
287: * Used with getNewSimpleTypeQName. See comments for getNewSimpleTypeQName.
288: */
289: private boolean isOldXSDNamespace(String oldTypeNamespace) {
290: if (oldTypeNamespace.equals(old_XSD_URI))
291: return true;
292:
293: return false;
294: }
295:
296: protected class XMapBuilder implements SOAPInstanceBuilder {
297:
298: StructMap instance;
299:
300: XMapBuilder(StructMap instance) {
301: this .instance = instance;
302: }
303:
304: public int memberGateType(int memberIndex) {
305: return (SOAPInstanceBuilder.GATES_INITIALIZATION | SOAPInstanceBuilder.REQUIRES_CREATION);
306: }
307:
308: public void construct() {
309: return;
310: }
311:
312: public void setMember(int index, Object memberValue) {
313: try {
314: instance.set(index, memberValue);
315: } catch (Exception e) {
316: throw new DeserializationException(
317: "nestedSerializationError",
318: new LocalizableExceptionAdapter(e));
319: }
320: }
321:
322: public void initialize() {
323: return;
324: }
325:
326: public void setInstance(Object instance) {
327: instance = (StructMap) instance;
328: }
329:
330: public Object getInstance() {
331: return instance;
332: }
333: }
334: }
|