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.Message;
029: import org.apache.axis2.jaxws.message.Protocol;
030: import org.apache.axis2.jaxws.message.factory.MessageFactory;
031: import org.apache.axis2.jaxws.registry.FactoryRegistry;
032: import org.apache.axis2.jaxws.runtime.description.marshal.MarshalServiceRuntimeDescription;
033: import org.apache.axis2.jaxws.utility.ConvertUtils;
034: import org.apache.commons.logging.Log;
035: import org.apache.commons.logging.LogFactory;
036:
037: import javax.xml.namespace.QName;
038: import javax.xml.ws.WebServiceException;
039: import java.lang.annotation.Annotation;
040: import java.util.List;
041: import java.util.TreeSet;
042:
043: /**
044: * The Doc/Lit Wrapped Minimal Marshaller is used when 1) The web service is Doc/Lit mininal, and 2)
045: * JAXB artifacts are missing (i.e. we don't have ObjectFactories)
046: */
047: public class DocLitBareMinimalMethodMarshaller implements
048: MethodMarshaller {
049:
050: private static Log log = LogFactory
051: .getLog(DocLitBareMinimalMethodMarshaller.class);
052:
053: public DocLitBareMinimalMethodMarshaller() {
054: super ();
055: }
056:
057: public Object demarshalResponse(Message message,
058: Object[] signatureArgs, OperationDescription operationDesc)
059: throws WebServiceException {
060:
061: EndpointInterfaceDescription ed = operationDesc
062: .getEndpointInterfaceDescription();
063: EndpointDescription endpointDesc = ed.getEndpointDescription();
064:
065: // Note all exceptions are caught and rethrown with a WebServiceException
066: try {
067: // Sample Document message
068: // ..
069: // <soapenv:body>
070: // <m:return ... >...</m:param>
071: // </soapenv:body>
072: //
073: // Important points.
074: // 1) There is no operation element in the message
075: // 2) The data blocks are located underneath the operation element.
076: // 3) The name of the data blocks (m:param) are defined by the schema.
077: // (SOAP indicates that the name of the element is not important, but
078: // for document processing, we will assume that the name corresponds to
079: // a schema root element)
080: // 4) The type of the data block is defined by schema; thus in most cases
081: // an xsi:type will not be present
082: ParameterDescription[] pds = operationDesc
083: .getParameterDescriptions();
084: MarshalServiceRuntimeDescription marshalDesc = MethodMarshallerUtils
085: .getMarshalDesc(endpointDesc);
086: TreeSet<String> packages = marshalDesc.getPackages();
087:
088: // Get the return value.
089: Class returnType = operationDesc.getResultActualType();
090: Object returnValue = null;
091: boolean hasReturnInBody = false;
092: if (returnType != void.class) {
093: // Use "byJavaType" unmarshalling if necessary
094: Class byJavaType = null;
095: if (MethodMarshallerUtils.isNotJAXBRootElement(
096: returnType, marshalDesc)) {
097: byJavaType = returnType;
098: }
099: // If the webresult is in the header, we need the name of the header so that we can find it.
100: Element returnElement = null;
101: if (operationDesc.isResultHeader()) {
102: returnElement = MethodMarshallerUtils
103: .getReturnElement(
104: packages,
105: message,
106: byJavaType,
107: operationDesc.isListType(),
108: true,
109: operationDesc
110: .getResultTargetNamespace(),
111: operationDesc.getResultName(),
112: MethodMarshallerUtils
113: .numOutputBodyParams(pds) > 0);
114:
115: } else {
116: returnElement = MethodMarshallerUtils
117: .getReturnElement(
118: packages,
119: message,
120: byJavaType,
121: operationDesc.isListType(),
122: false,
123: null,
124: null,
125: MethodMarshallerUtils
126: .numOutputBodyParams(pds) > 0);
127: hasReturnInBody = true;
128: }
129: //TODO should we allow null if the return is a header?
130: //Validate input parameters for operation and make sure no input parameters are null.
131: //As per JAXWS Specification section 3.6.2.3 if a null value is passes as an argument
132: //to a method then an implementation MUST throw WebServiceException.
133: returnValue = returnElement.getTypeValue();
134: if (ConvertUtils.isConvertable(returnValue, returnType)) {
135: returnValue = ConvertUtils.convert(returnValue,
136: returnType);
137: }
138: }
139:
140: // We want to use "by Java Type" unmarshalling for
141: // allall non-JAXB objects
142: Class[] javaTypes = new Class[pds.length];
143: for (int i = 0; i < pds.length; i++) {
144: ParameterDescription pd = pds[i];
145: Class type = pd.getParameterActualType();
146: if (MethodMarshallerUtils.isNotJAXBRootElement(type,
147: marshalDesc)) {
148: javaTypes[i] = type;
149: }
150: }
151:
152: // Unmarshall the ParamValues from the Message
153: List<PDElement> pvList = MethodMarshallerUtils
154: .getPDElements(pds, message, packages, false, // output
155: hasReturnInBody, javaTypes); // byJavaType unmarshalling
156:
157: // Populate the response Holders
158: MethodMarshallerUtils.updateResponseSignatureArgs(pds,
159: pvList, signatureArgs);
160:
161: return returnValue;
162: } catch (Exception e) {
163: throw ExceptionFactory.makeWebServiceException(e);
164: }
165: }
166:
167: public Object[] demarshalRequest(Message message,
168: OperationDescription operationDesc)
169: throws WebServiceException {
170:
171: EndpointInterfaceDescription ed = operationDesc
172: .getEndpointInterfaceDescription();
173: EndpointDescription endpointDesc = ed.getEndpointDescription();
174:
175: // Note all exceptions are caught and rethrown with a WebServiceException
176: try {
177: // Sample Document message
178: // ..
179: // <soapenv:body>
180: // <m:param .. >...</m:param>
181: // </soapenv:body>
182: //
183: // Important points.
184: // 1) There is no operation element under the body.
185: // 2) The data blocks are located underneath the body.
186: // 3) The name of the data blocks (m:param) are defined by the schema
187: // 4) The type of the data block (data:foo) is defined by schema (and probably
188: // is not present in the message
189: ParameterDescription[] pds = operationDesc
190: .getParameterDescriptions();
191: MarshalServiceRuntimeDescription marshalDesc = MethodMarshallerUtils
192: .getMarshalDesc(endpointDesc);
193: TreeSet<String> packages = marshalDesc.getPackages();
194:
195: // We want to use "by Java Type" unmarshalling for
196: // allall non-JAXB objects
197: Class[] javaTypes = new Class[pds.length];
198: for (int i = 0; i < pds.length; i++) {
199: ParameterDescription pd = pds[i];
200: Class type = pd.getParameterActualType();
201: // If it is not a JAXB Root Element
202: if (MethodMarshallerUtils.isNotJAXBRootElement(type,
203: marshalDesc)) {
204: javaTypes[i] = type;
205: }
206: }
207:
208: // Unmarshal the ParamValues from the message
209: List<PDElement> pvList = MethodMarshallerUtils
210: .getPDElements(pds, message, packages, true, // input
211: false, javaTypes); // never unmarshal by type for doc/lit bare
212:
213: // Build the signature arguments
214: Object[] sigArguments = MethodMarshallerUtils
215: .createRequestSignatureArgs(pds, pvList);
216: return sigArguments;
217: } catch (Exception e) {
218: throw ExceptionFactory.makeWebServiceException(e);
219: }
220: }
221:
222: public Message marshalResponse(Object returnObject,
223: Object[] signatureArgs, OperationDescription operationDesc,
224: Protocol protocol) throws WebServiceException {
225:
226: EndpointInterfaceDescription ed = operationDesc
227: .getEndpointInterfaceDescription();
228: EndpointDescription endpointDesc = ed.getEndpointDescription();
229:
230: // We want to respond with the same protocol as the request,
231: // It the protocol is null, then use the Protocol defined by the binding
232: if (protocol == null) {
233: protocol = Protocol.getProtocolForBinding(endpointDesc
234: .getBindingType());
235: }
236:
237: // Note all exceptions are caught and rethrown with a WebServiceException
238: try {
239: // Sample Document message
240: // ..
241: // <soapenv:body>
242: // <m:return ... >...</m:param>
243: // </soapenv:body>
244: //
245: // Important points.
246: // 1) There is no operation element in the message
247: // 2) The data blocks are located underneath the operation element.
248: // 3) The name of the data blocks (m:param) are defined by the schema.
249: // (SOAP indicates that the name of the element is not important, but
250: // for document processing, we will assume that the name corresponds to
251: // a schema root element)
252: // 4) The type of the data block is defined by schema; thus in most cases
253: // an xsi:type will not be present
254:
255: // Get the operation information
256: ParameterDescription[] pds = operationDesc
257: .getParameterDescriptions();
258: MarshalServiceRuntimeDescription marshalDesc = MethodMarshallerUtils
259: .getMarshalDesc(endpointDesc);
260: TreeSet<String> packages = marshalDesc.getPackages();
261:
262: // Create the message
263: MessageFactory mf = (MessageFactory) FactoryRegistry
264: .getFactory(MessageFactory.class);
265: Message m = mf.create(protocol);
266:
267: // Put the return object onto the message
268: Class returnType = operationDesc.getResultActualType();
269: if (returnType != void.class) {
270:
271: // Use byJavaType marshalling if necessary
272: Class byJavaType = null;
273: if (MethodMarshallerUtils.isNotJAXBRootElement(
274: returnType, marshalDesc)) {
275: byJavaType = returnType;
276: }
277:
278: Element returnElement = null;
279: QName returnQName = new QName(operationDesc
280: .getResultTargetNamespace(), operationDesc
281: .getResultName());
282: if (marshalDesc.getAnnotationDesc(returnType)
283: .hasXmlRootElement()) {
284: returnElement = new Element(returnObject,
285: returnQName);
286: } else {
287: returnElement = new Element(returnObject,
288: returnQName, returnType);
289: }
290: MethodMarshallerUtils.toMessage(returnElement,
291: returnType, operationDesc.isListType(),
292: marshalDesc, m, byJavaType, operationDesc
293: .isResultHeader());
294: }
295:
296: // Convert the holder objects into a list of JAXB objects for marshalling
297: List<PDElement> pdeList = MethodMarshallerUtils
298: .getPDElements(marshalDesc, pds, signatureArgs,
299: false, // output
300: false, false);
301:
302: // We want to use "by Java Type" marshalling for
303: // all body elements and all non-JAXB objects
304: for (PDElement pde : pdeList) {
305: ParameterDescription pd = pde.getParam();
306: Class type = pd.getParameterActualType();
307: if (MethodMarshallerUtils.isNotJAXBRootElement(type,
308: marshalDesc)) {
309: pde.setByJavaTypeClass(type);
310: }
311: }
312:
313: // Put values onto the message
314: MethodMarshallerUtils.toMessage(pdeList, m, packages);
315:
316: return m;
317: } catch (Exception e) {
318: throw ExceptionFactory.makeWebServiceException(e);
319: }
320: }
321:
322: public Message marshalRequest(Object[] signatureArguments,
323: OperationDescription operationDesc)
324: throws WebServiceException {
325:
326: EndpointInterfaceDescription ed = operationDesc
327: .getEndpointInterfaceDescription();
328: EndpointDescription endpointDesc = ed.getEndpointDescription();
329: Protocol protocol = Protocol.getProtocolForBinding(endpointDesc
330: .getClientBindingID());
331:
332: // Note all exceptions are caught and rethrown with a WebServiceException
333: try {
334: // Sample Document message
335: // ..
336: // <soapenv:body>
337: // <m:param .. >...</m:param>
338: // </soapenv:body>
339: //
340: // Important points.
341: // 1) There is no operation element under the body.
342: // 2) The data blocks are located underneath the body.
343: // 3) The name of the data blocks (m:param) are defined by the schema
344: // 4) The type of the data block (data:foo) is defined by schema (and probably
345: // is not present in the message
346:
347: // Get the operation information
348: ParameterDescription[] pds = operationDesc
349: .getParameterDescriptions();
350: MarshalServiceRuntimeDescription marshalDesc = MethodMarshallerUtils
351: .getMarshalDesc(endpointDesc);
352: TreeSet<String> packages = marshalDesc.getPackages();
353:
354: // Create the message
355: MessageFactory mf = (MessageFactory) FactoryRegistry
356: .getFactory(MessageFactory.class);
357: Message m = mf.create(protocol);
358:
359: // The input object represent the signature arguments.
360: // Signature arguments are both holders and non-holders
361: // Convert the signature into a list of JAXB objects for marshalling
362: List<PDElement> pdeList = MethodMarshallerUtils
363: .getPDElements(marshalDesc, pds,
364: signatureArguments, true, // input
365: false, false);
366:
367: // We want to use "by Java Type" marshalling for
368: // all body elements and all non-JAXB objects
369: for (PDElement pde : pdeList) {
370: ParameterDescription pd = pde.getParam();
371: Class type = pd.getParameterActualType();
372: if (MethodMarshallerUtils.isNotJAXBRootElement(type,
373: marshalDesc)) {
374: pde.setByJavaTypeClass(type);
375: }
376: }
377:
378: // Put values onto the message...marshalling by type
379: MethodMarshallerUtils.toMessage(pdeList, m, packages);
380:
381: return m;
382: } catch (Exception e) {
383: throw ExceptionFactory.makeWebServiceException(e);
384: }
385: }
386:
387: public Message marshalFaultResponse(Throwable throwable,
388: OperationDescription operationDesc, Protocol protocol)
389: throws WebServiceException {
390:
391: EndpointInterfaceDescription ed = operationDesc
392: .getEndpointInterfaceDescription();
393: EndpointDescription endpointDesc = ed.getEndpointDescription();
394: MarshalServiceRuntimeDescription marshalDesc = MethodMarshallerUtils
395: .getMarshalDesc(endpointDesc);
396:
397: // We want to respond with the same protocol as the request,
398: // It the protocol is null, then use the Protocol defined by the binding
399: if (protocol == null) {
400: protocol = Protocol.getProtocolForBinding(endpointDesc
401: .getBindingType());
402: }
403:
404: // Note all exceptions are caught and rethrown with a WebServiceException
405: try {
406: // Create the message
407: MessageFactory mf = (MessageFactory) FactoryRegistry
408: .getFactory(MessageFactory.class);
409: Message m = mf.create(protocol);
410:
411: // Put the fault onto the message
412: MethodMarshallerUtils.marshalFaultResponse(throwable,
413: marshalDesc, operationDesc, m);
414: return m;
415: } catch (Exception e) {
416: throw ExceptionFactory.makeWebServiceException(e);
417: }
418: }
419:
420: public Throwable demarshalFaultResponse(Message message,
421: OperationDescription operationDesc)
422: throws WebServiceException {
423:
424: EndpointInterfaceDescription ed = operationDesc
425: .getEndpointInterfaceDescription();
426: EndpointDescription endpointDesc = ed.getEndpointDescription();
427: MarshalServiceRuntimeDescription marshalDesc = MethodMarshallerUtils
428: .getMarshalDesc(endpointDesc);
429:
430: // Note all exceptions are caught and rethrown with a WebServiceException
431: try {
432: Throwable t = MethodMarshallerUtils.demarshalFaultResponse(
433: operationDesc, marshalDesc, message);
434: return t;
435: } catch (Exception e) {
436: throw ExceptionFactory.makeWebServiceException(e);
437: }
438: }
439:
440: }
|