001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.axis2.jaxws.marshaller.impl.alt;
020:
021: import org.apache.axis2.jaxws.ExceptionFactory;
022: import org.apache.axis2.jaxws.description.EndpointDescription;
023: import org.apache.axis2.jaxws.description.EndpointInterfaceDescription;
024: import org.apache.axis2.jaxws.description.OperationDescription;
025: import org.apache.axis2.jaxws.description.ParameterDescription;
026: import org.apache.axis2.jaxws.i18n.Messages;
027: import org.apache.axis2.jaxws.marshaller.MethodMarshaller;
028: import org.apache.axis2.jaxws.message.Block;
029: import org.apache.axis2.jaxws.message.Message;
030: import org.apache.axis2.jaxws.message.Protocol;
031: import org.apache.axis2.jaxws.message.databinding.JAXBBlockContext;
032: import org.apache.axis2.jaxws.message.factory.JAXBBlockFactory;
033: import org.apache.axis2.jaxws.message.factory.MessageFactory;
034: import org.apache.axis2.jaxws.registry.FactoryRegistry;
035: import org.apache.axis2.jaxws.runtime.description.marshal.MarshalServiceRuntimeDescription;
036: import org.apache.axis2.jaxws.utility.ConvertUtils;
037: import org.apache.axis2.jaxws.wrapper.JAXBWrapperTool;
038: import org.apache.axis2.jaxws.wrapper.impl.JAXBWrapperToolImpl;
039: import org.apache.commons.logging.Log;
040: import org.apache.commons.logging.LogFactory;
041:
042: import javax.jws.WebParam.Mode;
043: import javax.xml.bind.JAXBElement;
044: import javax.xml.namespace.QName;
045: import javax.xml.ws.WebServiceException;
046: import java.util.ArrayList;
047: import java.util.HashMap;
048: import java.util.List;
049: import java.util.Map;
050: import java.util.TreeSet;
051:
052: public class DocLitWrappedMethodMarshaller implements MethodMarshaller {
053:
054: private static Log log = LogFactory
055: .getLog(DocLitWrappedMethodMarshaller.class);
056:
057: public DocLitWrappedMethodMarshaller() {
058: super ();
059: }
060:
061: public Object demarshalResponse(Message message,
062: Object[] signatureArgs, OperationDescription operationDesc)
063: throws WebServiceException {
064: // Note all exceptions are caught and rethrown with a WebServiceException
065:
066: EndpointInterfaceDescription ed = operationDesc
067: .getEndpointInterfaceDescription();
068: EndpointDescription endpointDesc = ed.getEndpointDescription();
069:
070: try {
071: // Sample Document message
072: // ..
073: // <soapenv:body>
074: // <m:operationResponse ... >
075: // <param>hello</param>
076: // </m:operationResponse>
077: // </soapenv:body>
078: //
079: // Important points.
080: // 1) There is no operation element in the message
081: // 2) The data blocks are located underneath the body element.
082: // 3) The name of the data block (m:operationResponse) is defined by the schema.
083: // It matches the operation name + "Response", and it has a corresponding JAXB element.
084: // This element is called the wrapper element
085: // 4) The parameters are (param) are child elements of the wrapper element.
086: ParameterDescription[] pds = operationDesc
087: .getParameterDescriptions();
088: MarshalServiceRuntimeDescription marshalDesc = MethodMarshallerUtils
089: .getMarshalDesc(endpointDesc);
090: TreeSet<String> packages = marshalDesc.getPackages();
091: String packagesKey = marshalDesc.getPackagesKey();
092:
093: // Determine if a returnValue is expected.
094: // The return value may be an child element
095: // The wrapper element
096: // or null
097: Object returnValue = null;
098: Class returnType = operationDesc.getResultActualType();
099: boolean isChildReturn = !operationDesc
100: .isJAXWSAsyncClientMethod()
101: && (operationDesc.getResultPartName() != null);
102: boolean isNoReturn = (returnType == void.class);
103:
104: // In usage=WRAPPED, there will be a single JAXB block inside the body.
105: // Get this block
106: JAXBBlockContext blockContext = new JAXBBlockContext(
107: packages, packagesKey);
108: JAXBBlockFactory factory = (JAXBBlockFactory) FactoryRegistry
109: .getFactory(JAXBBlockFactory.class);
110: Block block = message.getBodyBlock(blockContext, factory);
111: Object wrapperObject = block.getBusinessObject(true);
112:
113: // The child elements are within the object that
114: // represents the type
115: if (wrapperObject instanceof JAXBElement) {
116: wrapperObject = ((JAXBElement) wrapperObject)
117: .getValue();
118: }
119:
120: // Use the wrapper tool to get the child objects.
121: JAXBWrapperTool wrapperTool = new JAXBWrapperToolImpl();
122:
123: // Get the list of names for the output parameters
124: List<String> names = new ArrayList<String>();
125: List<ParameterDescription> pdList = new ArrayList<ParameterDescription>();
126: for (int i = 0; i < pds.length; i++) {
127: ParameterDescription pd = pds[i];
128: if (pd.getMode() == Mode.OUT
129: || pd.getMode() == Mode.INOUT) {
130: names.add(pd.getParameterName());
131: pdList.add(pd);
132: }
133: }
134:
135: // The return name is added as the last name
136: if (isChildReturn && !isNoReturn) {
137: names.add(operationDesc.getResultPartName());
138: }
139:
140: // Get the child objects
141: Object[] objects = wrapperTool.unWrap(wrapperObject, names,
142: marshalDesc.getPropertyDescriptorMap(wrapperObject
143: .getClass()));
144:
145: // Now create a list of paramValues so that we can populate the signature
146: List<PDElement> pvList = new ArrayList<PDElement>();
147: for (int i = 0; i < pdList.size(); i++) {
148: ParameterDescription pd = pdList.get(i);
149: Object value = objects[i];
150: // The object in the PDElement must be an element
151: Element element = null;
152: QName qName = new QName(pd.getTargetNamespace(), pd
153: .getPartName());
154: if (!marshalDesc.getAnnotationDesc(
155: pd.getParameterActualType())
156: .hasXmlRootElement()) {
157: element = new Element(value, qName, pd
158: .getParameterActualType());
159:
160: } else {
161: element = new Element(value, qName);
162: }
163: pvList.add(new PDElement(pd, element, null));
164: }
165:
166: // Populate the response Holders in the signature
167: MethodMarshallerUtils.updateResponseSignatureArgs(pds,
168: pvList, signatureArgs);
169:
170: // Now get the return value
171: if (isNoReturn) {
172: returnValue = null;
173: } else if (isChildReturn) {
174: returnValue = objects[objects.length - 1];
175: // returnValue may be incompatible with JAX-WS signature
176: if (ConvertUtils.isConvertable(returnValue, returnType)) {
177: returnValue = ConvertUtils.convert(returnValue,
178: returnType);
179: } else {
180: String objectClass = (returnValue == null) ? "null"
181: : returnValue.getClass().getName();
182: throw ExceptionFactory
183: .makeWebServiceException(Messages
184: .getMessage("convertProblem",
185: objectClass, returnType
186: .getName()));
187: }
188: } else {
189: returnValue = wrapperObject;
190: }
191:
192: return returnValue;
193: } catch (Exception e) {
194: throw ExceptionFactory.makeWebServiceException(e);
195: }
196: }
197:
198: public Object[] demarshalRequest(Message message,
199: OperationDescription operationDesc)
200: throws WebServiceException {
201:
202: EndpointInterfaceDescription ed = operationDesc
203: .getEndpointInterfaceDescription();
204: EndpointDescription endpointDesc = ed.getEndpointDescription();
205:
206: // Note all exceptions are caught and rethrown with a WebServiceException
207: try {
208: // Sample Document message
209: // ..
210: // <soapenv:body>
211: // <m:operation>
212: // <param>hello</param>
213: // </m:operation>
214: // </soapenv:body>
215: //
216: // Important points.
217: // 1) There is no operation element under the body.
218: // 2) The data blocks are located underneath the body.
219: // 3) The name of the data block (m:operation) is defined by the schema and match the name of the operation.
220: // This is called the wrapper element. The wrapper element has a corresponding JAXB element pojo.
221: // 4) The parameters (m:param) are child elements of the wrapper element.
222: ParameterDescription[] pds = operationDesc
223: .getParameterDescriptions();
224: MarshalServiceRuntimeDescription marshalDesc = MethodMarshallerUtils
225: .getMarshalDesc(endpointDesc);
226: TreeSet<String> packages = marshalDesc.getPackages();
227: String packagesKey = marshalDesc.getPackagesKey();
228:
229: // In usage=WRAPPED, there will be a single JAXB block inside the body.
230: // Get this block
231: JAXBBlockContext blockContext = new JAXBBlockContext(
232: packages, packagesKey);
233: JAXBBlockFactory factory = (JAXBBlockFactory) FactoryRegistry
234: .getFactory(JAXBBlockFactory.class);
235: Block block = message.getBodyBlock(blockContext, factory);
236: Object wrapperObject = block.getBusinessObject(true);
237:
238: // The child elements are within the object that
239: // represents the type
240: if (wrapperObject instanceof JAXBElement) {
241: wrapperObject = ((JAXBElement) wrapperObject)
242: .getValue();
243: }
244:
245: // Use the wrapper tool to get the child objects.
246: JAXBWrapperTool wrapperTool = new JAXBWrapperToolImpl();
247:
248: // Get the list of names for the input parameters
249: List<String> names = new ArrayList<String>();
250: List<ParameterDescription> pdList = new ArrayList<ParameterDescription>();
251: for (int i = 0; i < pds.length; i++) {
252: ParameterDescription pd = pds[i];
253: if (pd.getMode() == Mode.IN
254: || pd.getMode() == Mode.INOUT) {
255: names.add(pd.getParameterName());
256: pdList.add(pd);
257: }
258:
259: }
260:
261: // Get the child objects
262: Object[] objects = wrapperTool.unWrap(wrapperObject, names,
263: marshalDesc.getPropertyDescriptorMap(wrapperObject
264: .getClass()));
265:
266: // Now create a list of paramValues
267: List<PDElement> pvList = new ArrayList<PDElement>();
268: for (int i = 0; i < pdList.size(); i++) {
269: ParameterDescription pd = pdList.get(i);
270: Object value = objects[i];
271: // The object in the PDElement must be an element
272: Element element = null;
273: QName qName = new QName(pd.getTargetNamespace(), pd
274: .getPartName());
275: if (!marshalDesc.getAnnotationDesc(
276: pd.getParameterActualType())
277: .hasXmlRootElement()) {
278: element = new Element(value, qName, pd
279: .getParameterActualType());
280: } else {
281: element = new Element(value, qName);
282: }
283: pvList.add(new PDElement(pd, element, null));
284: }
285:
286: // Build the signature arguments
287: Object[] sigArguments = MethodMarshallerUtils
288: .createRequestSignatureArgs(pds, pvList);
289:
290: return sigArguments;
291: } catch (Exception e) {
292: throw ExceptionFactory.makeWebServiceException(e);
293: }
294: }
295:
296: public Message marshalResponse(Object returnObject,
297: Object[] signatureArgs, OperationDescription operationDesc,
298: Protocol protocol) throws WebServiceException {
299:
300: EndpointInterfaceDescription ed = operationDesc
301: .getEndpointInterfaceDescription();
302: EndpointDescription endpointDesc = ed.getEndpointDescription();
303: MarshalServiceRuntimeDescription marshalDesc = MethodMarshallerUtils
304: .getMarshalDesc(endpointDesc);
305: TreeSet<String> packages = marshalDesc.getPackages();
306: String packagesKey = marshalDesc.getPackagesKey();
307:
308: // We want to respond with the same protocol as the request,
309: // It the protocol is null, then use the Protocol defined by the binding
310: if (protocol == null) {
311: protocol = Protocol.getProtocolForBinding(endpointDesc
312: .getBindingType());
313: }
314:
315: // Note all exceptions are caught and rethrown with a WebServiceException
316: try {
317: // Sample Document message
318: // ..
319: // <soapenv:body>
320: // <m:operationResponse ... >
321: // <param>hello</param>
322: // </m:operationResponse>
323: // </soapenv:body>
324: //
325: // Important points.
326: // 1) There is no operation element in the message
327: // 2) The data blocks are located underneath the body element.
328: // 3) The name of the data block (m:operationResponse) is defined by the schema.
329: // It matches the operation name + "Response", and it has a corresponding JAXB element.
330: // This element is called the wrapper element
331: // 4) The parameters are (param) are child elements of the wrapper element.
332:
333: // Get the operation information
334: ParameterDescription[] pds = operationDesc
335: .getParameterDescriptions();
336:
337: // Create the message
338: MessageFactory mf = marshalDesc.getMessageFactory();
339: Message m = mf.create(protocol);
340:
341: // In usage=WRAPPED, there will be a single block in the body.
342: // The signatureArguments represent the child elements of that block
343: // The first step is to convert the signature arguments into a list
344: // of parameter values
345: List<PDElement> pdeList = MethodMarshallerUtils
346: .getPDElements(marshalDesc, pds, signatureArgs,
347: false, // output
348: true, false);
349:
350: // Now we want to create a single JAXB element that contains the
351: // ParameterValues. We will use the wrapper tool to do this.
352: // Create the inputs to the wrapper tool
353: ArrayList<String> nameList = new ArrayList<String>();
354: Map<String, Object> objectList = new HashMap<String, Object>();
355:
356: for (PDElement pde : pdeList) {
357: String name = pde.getParam().getParameterName();
358:
359: // The object list contains type rendered objects
360: Object value = pde.getElement().getTypeValue();
361: nameList.add(name);
362: objectList.put(name, value);
363: }
364:
365: // Add the return object to the nameList and objectList
366: Class returnType = operationDesc.getResultActualType();
367: if (returnType != void.class) {
368: String name = operationDesc.getResultName();
369: nameList.add(name);
370: objectList.put(name, returnObject);
371: }
372:
373: // Now create the single JAXB element
374: String wrapperName = marshalDesc
375: .getResponseWrapperClassName(operationDesc);
376: Class cls = MethodMarshallerUtils.loadClass(wrapperName);
377: JAXBWrapperTool wrapperTool = new JAXBWrapperToolImpl();
378: Object object = wrapperTool.wrap(cls, nameList, objectList,
379: marshalDesc.getPropertyDescriptorMap(cls));
380:
381: QName wrapperQName = new QName(operationDesc
382: .getResponseWrapperTargetNamespace(), operationDesc
383: .getResponseWrapperLocalName());
384:
385: // Make sure object can be rendered as an element
386: if (!marshalDesc.getAnnotationDesc(cls).hasXmlRootElement()) {
387: object = new JAXBElement(wrapperQName, cls, object);
388: }
389:
390: // Put the object into the message
391: JAXBBlockFactory factory = (JAXBBlockFactory) FactoryRegistry
392: .getFactory(JAXBBlockFactory.class);
393:
394: Block block = factory.createFrom(object,
395: new JAXBBlockContext(packages, packagesKey),
396: wrapperQName);
397: m.setBodyBlock(block);
398:
399: return m;
400: } catch (Exception e) {
401: throw ExceptionFactory.makeWebServiceException(e);
402: }
403: }
404:
405: public Message marshalRequest(Object[] signatureArguments,
406: OperationDescription operationDesc)
407: throws WebServiceException {
408:
409: EndpointInterfaceDescription ed = operationDesc
410: .getEndpointInterfaceDescription();
411: EndpointDescription endpointDesc = ed.getEndpointDescription();
412: Protocol protocol = Protocol.getProtocolForBinding(endpointDesc
413: .getClientBindingID());
414: MarshalServiceRuntimeDescription marshalDesc = MethodMarshallerUtils
415: .getMarshalDesc(endpointDesc);
416: TreeSet<String> packages = marshalDesc.getPackages();
417: String packagesKey = marshalDesc.getPackagesKey();
418:
419: // Note all exceptions are caught and rethrown with a WebServiceException
420: try {
421: // Sample Document message
422: // ..
423: // <soapenv:body>
424: // <m:operation>
425: // <param>hello</param>
426: // </m:operation>
427: // </soapenv:body>
428: //
429: // Important points.
430: // 1) There is no operation element under the body.
431: // 2) The data blocks are located underneath the body.
432: // 3) The name of the data block (m:operation) is defined by the schema and match the name of the operation.
433: // This is called the wrapper element. The wrapper element has a corresponding JAXB element pojo.
434: // 4) The parameters (m:param) are child elements of the wrapper element.
435:
436: // Get the operation information
437: ParameterDescription[] pds = operationDesc
438: .getParameterDescriptions();
439:
440: // Create the message
441: MessageFactory mf = marshalDesc.getMessageFactory();
442: Message m = mf.create(protocol);
443:
444: // In usage=WRAPPED, there will be a single block in the body.
445: // The signatureArguments represent the child elements of that block
446: // The first step is to convert the signature arguments into list
447: // of parameter values
448: List<PDElement> pvList = MethodMarshallerUtils
449: .getPDElements(marshalDesc, pds,
450: signatureArguments, true, // input
451: true, false);
452:
453: // Now we want to create a single JAXB element that contains the
454: // ParameterValues. We will use the wrapper tool to do this.
455: // Create the inputs to the wrapper tool
456: ArrayList<String> nameList = new ArrayList<String>();
457: Map<String, Object> objectList = new HashMap<String, Object>();
458:
459: for (PDElement pv : pvList) {
460: String name = pv.getParam().getParameterName();
461:
462: // The object list contains type rendered objects
463: Object value = pv.getElement().getTypeValue();
464: nameList.add(name);
465: objectList.put(name, value);
466: }
467:
468: // Now create the single JAXB element
469: String wrapperName = marshalDesc
470: .getRequestWrapperClassName(operationDesc);
471: Class cls = MethodMarshallerUtils.loadClass(wrapperName);
472: JAXBWrapperTool wrapperTool = new JAXBWrapperToolImpl();
473: Object object = wrapperTool.wrap(cls, nameList, objectList,
474: marshalDesc.getPropertyDescriptorMap(cls));
475:
476: QName wrapperQName = new QName(operationDesc
477: .getRequestWrapperTargetNamespace(), operationDesc
478: .getRequestWrapperLocalName());
479:
480: // Make sure object can be rendered as an element
481: if (!marshalDesc.getAnnotationDesc(cls).hasXmlRootElement()) {
482: object = new JAXBElement(wrapperQName, cls, object);
483: }
484:
485: // Put the object into the message
486: JAXBBlockFactory factory = (JAXBBlockFactory) FactoryRegistry
487: .getFactory(JAXBBlockFactory.class);
488:
489: Block block = factory.createFrom(object,
490: new JAXBBlockContext(packages, packagesKey),
491: wrapperQName);
492: m.setBodyBlock(block);
493:
494: return m;
495: } catch (Exception e) {
496: throw ExceptionFactory.makeWebServiceException(e);
497: }
498: }
499:
500: public Message marshalFaultResponse(Throwable throwable,
501: OperationDescription operationDesc, Protocol protocol)
502: throws WebServiceException {
503:
504: EndpointInterfaceDescription ed = operationDesc
505: .getEndpointInterfaceDescription();
506: EndpointDescription endpointDesc = ed.getEndpointDescription();
507: MarshalServiceRuntimeDescription marshalDesc = MethodMarshallerUtils
508: .getMarshalDesc(endpointDesc);
509: TreeSet<String> packages = marshalDesc.getPackages();
510:
511: // We want to respond with the same protocol as the request,
512: // It the protocol is null, then use the Protocol defined by the binding
513: if (protocol == null) {
514: protocol = Protocol.getProtocolForBinding(endpointDesc
515: .getBindingType());
516: }
517:
518: // Note all exceptions are caught and rethrown with a WebServiceException
519: try {
520: // Create the message
521: MessageFactory mf = (MessageFactory) FactoryRegistry
522: .getFactory(MessageFactory.class);
523: Message m = mf.create(protocol);
524:
525: // Put the fault onto the message
526: MethodMarshallerUtils.marshalFaultResponse(throwable,
527: marshalDesc, operationDesc, m);
528: return m;
529: } catch (Exception e) {
530: throw ExceptionFactory.makeWebServiceException(e);
531: }
532: }
533:
534: public Throwable demarshalFaultResponse(Message message,
535: OperationDescription operationDesc)
536: throws WebServiceException {
537:
538: EndpointInterfaceDescription ed = operationDesc
539: .getEndpointInterfaceDescription();
540: EndpointDescription endpointDesc = ed.getEndpointDescription();
541: MarshalServiceRuntimeDescription marshalDesc = MethodMarshallerUtils
542: .getMarshalDesc(endpointDesc);
543:
544: // Note all exceptions are caught and rethrown with a WebServiceException
545: try {
546: Throwable t = MethodMarshallerUtils.demarshalFaultResponse(
547: operationDesc, marshalDesc, message);
548: return t;
549: } catch (Exception e) {
550: throw ExceptionFactory.makeWebServiceException(e);
551: }
552: }
553:
554: }
|