| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.apache.axis2.rpc.receivers; |
| |
| import org.apache.axiom.om.OMAbstractFactory; |
| import org.apache.axiom.om.OMElement; |
| import org.apache.axiom.om.OMNamespace; |
| import org.apache.axiom.om.OMText; |
| import org.apache.axiom.om.OMXMLBuilderFactory; |
| import org.apache.axiom.om.OMXMLParserWrapper; |
| import org.apache.axiom.soap.SOAPEnvelope; |
| import org.apache.axiom.soap.SOAPFactory; |
| import org.apache.axiom.util.base64.Base64Utils; |
| import org.apache.axis2.AxisFault; |
| import org.apache.axis2.context.MessageContext; |
| import org.apache.axis2.databinding.typemapping.SimpleTypeMapper; |
| import org.apache.axis2.databinding.utils.BeanUtil; |
| import org.apache.axis2.databinding.utils.Constants; |
| import org.apache.axis2.databinding.utils.reader.NullXMLStreamReader; |
| import org.apache.axis2.description.AxisMessage; |
| import org.apache.axis2.description.AxisService; |
| import org.apache.axis2.description.Parameter; |
| import org.apache.axis2.description.java2wsdl.TypeTable; |
| import org.apache.axis2.engine.ObjectSupplier; |
| import org.apache.axis2.util.StreamWrapper; |
| |
| import javax.activation.DataHandler; |
| import javax.xml.datatype.XMLGregorianCalendar; |
| import javax.xml.namespace.QName; |
| import javax.xml.stream.XMLStreamReader; |
| import java.lang.reflect.Array; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| public class RPCUtil { |
| |
| |
| public static void processResponse(SOAPFactory fac, Object resObject, |
| OMElement bodyContent, |
| OMNamespace ns, |
| SOAPEnvelope envelope, |
| Method method, |
| boolean qualified, |
| TypeTable typeTable) { |
| if (resObject != null) { |
| //simple type |
| if (resObject instanceof OMElement) { |
| OMElement result = (OMElement) resObject; |
| bodyContent = fac.createOMElement( |
| method.getName() + "Response", ns); |
| OMElement resWrapper; |
| if (qualified) { |
| resWrapper = fac.createOMElement(Constants.RETURN_WRAPPER, ns.getNamespaceURI(), |
| ns.getPrefix()); |
| } else { |
| resWrapper = fac.createOMElement(Constants.RETURN_WRAPPER, null); |
| } |
| resWrapper.addChild(result); |
| bodyContent.addChild(resWrapper); |
| } else if (SimpleTypeMapper.isDomDocument(resObject.getClass())){ |
| OMElement doc = BeanUtil.convertDOMtoOM(fac, resObject); |
| bodyContent = fac.createOMElement(method.getName() + "Response", ns); |
| OMElement child; |
| if (qualified) { |
| child = fac.createOMElement(Constants.RETURN_WRAPPER, ns); |
| } else { |
| child = fac.createOMElement(Constants.RETURN_WRAPPER, null); |
| } |
| child.addChild(doc); |
| bodyContent.addChild(child); |
| } else if (SimpleTypeMapper.isSimpleType(resObject)) { |
| bodyContent = fac.createOMElement( |
| method.getName() + "Response", ns); |
| OMElement child; |
| if (qualified) { |
| child = fac.createOMElement(Constants.RETURN_WRAPPER, ns); |
| } else { |
| child = fac.createOMElement(Constants.RETURN_WRAPPER, null); |
| } |
| child.addChild(fac.createOMText(child, SimpleTypeMapper.getStringValue(resObject))); |
| addInstanceTypeInfo(fac, child, method, resObject, typeTable); |
| bodyContent.addChild(child); |
| |
| } else if (resObject instanceof XMLGregorianCalendar) { |
| bodyContent = fac.createOMElement( |
| method.getName() + "Response", ns); |
| OMElement child; |
| if (qualified) { |
| child = fac.createOMElement(Constants.RETURN_WRAPPER, ns); |
| } else { |
| child = fac.createOMElement(Constants.RETURN_WRAPPER, null); |
| } |
| child.addChild(fac.createOMText(child, ((XMLGregorianCalendar)resObject).toXMLFormat())); |
| addInstanceTypeInfo(fac, child, method, resObject, typeTable); |
| bodyContent.addChild(child); |
| |
| } else { |
| bodyContent = fac.createOMElement( |
| method.getName() + "Response", ns); |
| // Java Beans |
| QName returnWrapper; |
| if (qualified) { |
| returnWrapper = new QName(ns.getNamespaceURI(), Constants.RETURN_WRAPPER, ns.getPrefix()); |
| } else { |
| returnWrapper = new QName(Constants.RETURN_WRAPPER); |
| } |
| XMLStreamReader xr = BeanUtil.getPullParser(resObject, |
| returnWrapper, typeTable, qualified, false); |
| OMXMLParserWrapper stAXOMBuilder = |
| OMXMLBuilderFactory.createStAXOMBuilder( |
| OMAbstractFactory.getOMFactory(), new StreamWrapper(xr)); |
| OMElement documentElement = stAXOMBuilder.getDocumentElement(); |
| if (documentElement != null) { |
| bodyContent.addChild(documentElement); |
| } |
| } |
| } |
| if (bodyContent != null) { |
| envelope.getBody().addChild(bodyContent); |
| } |
| } |
| |
| public static void processObjectAsDocLitBare(SOAPFactory fac, |
| Object resObject, |
| OMElement bodyContent, |
| OMNamespace ns, |
| Method method, |
| SOAPEnvelope envelope, |
| boolean qualified, |
| TypeTable typeTable, |
| String partName) { |
| if (resObject instanceof OMElement) { |
| OMElement result = (OMElement) resObject; |
| bodyContent = fac.createOMElement( |
| partName, ns); |
| bodyContent.addChild(result); |
| } else if(SimpleTypeMapper.isDomDocument(resObject.getClass())){ |
| bodyContent = fac.createOMElement( |
| partName, ns); |
| bodyContent.addChild(BeanUtil.convertDOMtoOM(fac, resObject)); |
| } else if (SimpleTypeMapper.isSimpleType(resObject)) { |
| bodyContent = fac.createOMElement( |
| partName, ns); |
| addInstanceTypeInfo(fac, bodyContent, method, resObject, typeTable); |
| bodyContent.addChild(fac.createOMText(bodyContent, |
| SimpleTypeMapper.getStringValue(resObject))); |
| } else { |
| QName returnWrapper = new QName(ns.getNamespaceURI(), partName, ns.getPrefix()); |
| XMLStreamReader xr = BeanUtil.getPullParser(resObject, |
| returnWrapper, typeTable, qualified, true); |
| OMXMLParserWrapper stAXOMBuilder = |
| OMXMLBuilderFactory.createStAXOMBuilder( |
| OMAbstractFactory.getOMFactory(), new StreamWrapper(xr)); |
| OMElement documentElement = stAXOMBuilder.getDocumentElement(); |
| if (documentElement != null) { |
| envelope.getBody().addChild(documentElement); |
| } |
| } |
| if (bodyContent != null) { |
| envelope.getBody().addChild(bodyContent); |
| } |
| } |
| |
| public static void processObjectAsDocLitBare(SOAPFactory fac, |
| Object resObject, OMElement bodyContent, OMNamespace ns, |
| SOAPEnvelope envelope, boolean qualified, TypeTable typeTable, |
| String partName) { |
| processObjectAsDocLitBare(fac, resObject, bodyContent, ns, null, |
| envelope, qualified, typeTable, partName); |
| |
| } |
| |
| public static Object[] processRequest(OMElement methodElement, |
| Method method, ObjectSupplier objectSupplier, String[] parameterNames) |
| throws AxisFault { |
| Class[] parameters = method.getParameterTypes(); |
| return BeanUtil.deserialize(methodElement, parameters, objectSupplier, parameterNames, method); |
| } |
| |
| public static Object[] processRequest(OMElement methodElement, |
| Method method, ObjectSupplier objectSupplier) |
| throws AxisFault { |
| return processRequest(methodElement, method, objectSupplier, null); |
| } |
| |
| public static Object invokeServiceClass(AxisMessage inAxisMessage, |
| Method method, |
| Object implObject, |
| String messageNameSpace, |
| OMElement methodElement, |
| MessageContext inMessage) throws AxisFault, |
| IllegalAccessException, InvocationTargetException { |
| |
| //POJO was not WS-I complient since it does generate an empty soap message for in comming |
| //soap envelope when no input parameters are set. But now we have fixed this to include the |
| // the operation name wrapper. |
| // this causes problems with the clients generated with the earlier wsdls. in order to |
| // keep the back word compatibility we need to add this check. |
| |
| if ((inAxisMessage.getElementQName() == null) || (methodElement == null)) { |
| // method accept empty SOAPbody |
| return method.invoke(implObject); |
| } else { |
| QName elementQName = inAxisMessage.getElementQName(); |
| messageNameSpace = elementQName.getNamespaceURI(); |
| OMNamespace namespace = methodElement.getNamespace(); |
| if (messageNameSpace != null) { |
| if (namespace == null) { |
| throw new AxisFault("namespace mismatch require " + |
| messageNameSpace + |
| " found none"); |
| } |
| if (!messageNameSpace.equals(namespace.getNamespaceURI())) { |
| throw new AxisFault("namespace mismatch require " + |
| messageNameSpace + |
| " found " + methodElement.getNamespace().getNamespaceURI()); |
| } |
| } else if (namespace != null) { |
| throw new AxisFault( |
| "namespace mismatch. Axis Operation expects non-namespace " + |
| "qualified element. But received a namespace qualified element"); |
| } |
| Object[] objectArray; |
| if (inAxisMessage.isWrapped()) { |
| Parameter namesParameter = inMessage.getAxisService().getParameter(method.getName()); |
| String[] parameterNames = null; |
| if (namesParameter != null){ |
| parameterNames = (String[]) namesParameter.getValue(); |
| } |
| objectArray = RPCUtil.processRequest(methodElement, |
| method, inMessage.getAxisService().getObjectSupplier(), parameterNames); |
| } else { |
| objectArray = RPCUtil.processRequest((OMElement) methodElement.getParent(), |
| method, inMessage.getAxisService().getObjectSupplier()); |
| } |
| return method.invoke(implObject, objectArray); |
| |
| } |
| } |
| |
| public static OMElement getResponseElement(QName resname, |
| Object[] objs, |
| boolean qualified, |
| TypeTable typeTable) { |
| if (qualified) { |
| return BeanUtil.getOMElement(resname, objs, |
| new QName(resname.getNamespaceURI(), |
| Constants.RETURN_WRAPPER, |
| resname.getPrefix()), |
| qualified, |
| typeTable); |
| } else { |
| return BeanUtil.getOMElement(resname, objs, |
| new QName(Constants.RETURN_WRAPPER), qualified, |
| typeTable); |
| } |
| } |
| |
| public static void processResonseAsDocLitBare(Object resObject, |
| AxisService service, |
| Method method, |
| SOAPEnvelope envelope, |
| SOAPFactory fac, |
| OMNamespace ns, |
| OMElement bodyContent, |
| MessageContext outMessage |
| ) throws Exception { |
| QName elementQName = outMessage.getAxisMessage().getElementQName(); |
| String partName = outMessage.getAxisMessage().getPartName(); |
| if (resObject == null) { |
| processNullReturns(service, envelope, partName); |
| } else { |
| if (resObject instanceof Object[]) { |
| QName resName = new QName(elementQName.getNamespaceURI(), |
| partName, |
| elementQName.getPrefix()); |
| OMElement bodyChild = RPCUtil.getResponseElement(resName, |
| (Object[]) resObject, |
| service.isElementFormDefault(), |
| service.getTypeTable()); |
| envelope.getBody().addChild(bodyChild); |
| } else { |
| if (resObject.getClass().isArray()) { |
| int length = Array.getLength(resObject); |
| Object objArray[]; |
| if (resObject instanceof byte[]) { |
| objArray = new Object[1]; |
| objArray[0] = Base64Utils.encode((byte[]) resObject); |
| } else { |
| objArray = new Object[length]; |
| for (int i = 0; i < length; i++) { |
| objArray[i] = Array.get(resObject, i); |
| } |
| } |
| |
| QName resName = new QName(elementQName.getNamespaceURI(), |
| partName, |
| elementQName.getPrefix()); |
| OMElement bodyChild = RPCUtil.getResponseElement(resName, |
| objArray, |
| service.isElementFormDefault(), |
| service.getTypeTable()); |
| envelope.getBody().addChild(bodyChild); |
| } else { |
| if (SimpleTypeMapper.isCollection(resObject.getClass())) { |
| QName resName = new QName( |
| elementQName.getNamespaceURI(), |
| method.getName() + "Response", |
| elementQName.getPrefix()); |
| OMElement bodyChild = BeanUtil.getCollectionElement( |
| fac, method.getGenericReturnType(), |
| (Collection) resObject, Constants.RETURN_WRAPPER,null, |
| resName, service.getTypeTable(), |
| service.isElementFormDefault()); |
| envelope.getBody().addChild(bodyChild); |
| |
| } else if (SimpleTypeMapper.isMap(resObject.getClass())) { |
| OMElement resElemt = fac.createOMElement( |
| partName, ns); |
| List<OMElement> omList = BeanUtil.getMapElement(fac, |
| method.getGenericReturnType(), (Map) resObject, |
| service.getTypeTable(), |
| service.isElementFormDefault()); |
| Iterator<OMElement> omItr = omList.iterator(); |
| while (omItr.hasNext()) { |
| resElemt.addChild(omItr.next()); |
| } |
| envelope.getBody().addChild(resElemt); |
| |
| } else if (SimpleTypeMapper.isDataHandler(resObject |
| .getClass())) { |
| OMElement resElemt; |
| if (service.isElementFormDefault()) { |
| resElemt = fac.createOMElement(partName, ns); |
| } else { |
| resElemt = fac.createOMElement(partName, null); |
| } |
| OMText text = fac.createOMText((DataHandler)resObject, true); |
| resElemt.addChild(text); |
| envelope.getBody().addChild(resElemt); |
| } else { |
| if (service.isElementFormDefault()) { |
| RPCUtil.processObjectAsDocLitBare(fac, |
| resObject, |
| bodyContent, |
| ns, |
| method, |
| envelope, |
| service.isElementFormDefault(), |
| service.getTypeTable(), |
| partName); |
| } else { |
| RPCUtil.processObjectAsDocLitBare(fac, |
| resObject, |
| bodyContent, |
| ns, |
| method, |
| envelope, |
| service.isElementFormDefault(), |
| service.getTypeTable(), |
| partName); |
| } |
| } |
| } |
| } |
| } |
| outMessage.setEnvelope(envelope); |
| } |
| |
| public static void processResonseAsDocLitBare(Object resObject, |
| AxisService service, SOAPEnvelope envelope, SOAPFactory fac, |
| OMNamespace ns, OMElement bodyContent, MessageContext outMessage) |
| throws Exception { |
| processResonseAsDocLitBare(resObject, service, null, envelope, fac, ns, |
| bodyContent, outMessage); |
| |
| } |
| |
| /** |
| * This method is use to to crete the reposne when , the return value is null |
| * |
| * @param service Current AxisService |
| * @param envelope response envelope |
| * @param partName |
| */ |
| private static void processNullReturns(AxisService service, |
| SOAPEnvelope envelope, String partName) { |
| QName resName; |
| if (service.isElementFormDefault()) { |
| resName = new QName(service.getSchemaTargetNamespace(), |
| partName, |
| service.getSchemaTargetNamespacePrefix()); |
| } else { |
| resName = new QName(partName); |
| } |
| XMLStreamReader xr = new NullXMLStreamReader(resName); |
| StreamWrapper parser = new StreamWrapper(xr); |
| OMXMLParserWrapper stAXOMBuilder = |
| OMXMLBuilderFactory.createStAXOMBuilder( |
| OMAbstractFactory.getSOAP11Factory(), parser); |
| envelope.getBody().addChild(stAXOMBuilder.getDocumentElement()); |
| } |
| |
| |
| public static void processResponseAsDocLitWrapped(Object resObject, |
| AxisService service, |
| Method method, |
| SOAPEnvelope envelope, |
| SOAPFactory fac, |
| OMNamespace ns, |
| OMElement bodyContent, |
| MessageContext outMessage |
| ) throws Exception { |
| QName elementQName = outMessage.getAxisMessage().getElementQName(); |
| if (resObject == null) { |
| QName resName; |
| if (service.isElementFormDefault()) { |
| resName = new QName(service.getSchemaTargetNamespace(), |
| Constants.RETURN_WRAPPER, |
| service.getSchemaTargetNamespacePrefix()); |
| } else { |
| resName = new QName(Constants.RETURN_WRAPPER); |
| } |
| XMLStreamReader xr = new NullXMLStreamReader(resName); |
| StreamWrapper parser = new StreamWrapper(xr); |
| OMXMLParserWrapper stAXOMBuilder = |
| OMXMLBuilderFactory.createStAXOMBuilder( |
| OMAbstractFactory.getSOAP11Factory(), parser); |
| ns = fac.createOMNamespace(service.getSchemaTargetNamespace(), |
| service.getSchemaTargetNamespacePrefix()); |
| OMElement bodyChild = fac.createOMElement(method.getName() + "Response", ns); |
| bodyChild.addChild(stAXOMBuilder.getDocumentElement()); |
| envelope.getBody().addChild(bodyChild); |
| } else { |
| if (resObject instanceof Object[]) { |
| |
| QName resName = new QName(elementQName.getNamespaceURI(), |
| method.getName() + "Response", |
| elementQName.getPrefix()); |
| OMElement bodyChild = RPCUtil.getResponseElement(resName, |
| (Object[]) resObject, |
| service.isElementFormDefault(), |
| service.getTypeTable()); |
| envelope.getBody().addChild(bodyChild); |
| } else { |
| if (resObject.getClass().isArray()) { |
| int length = Array.getLength(resObject); |
| Object objArray[]; |
| if (resObject instanceof byte[]) { |
| objArray = new Object[1]; |
| objArray[0] = Base64Utils.encode((byte[]) resObject); |
| } else { |
| objArray = new Object[length]; |
| for (int i = 0; i < length; i++) { |
| objArray[i] = Array.get(resObject, i); |
| } |
| } |
| |
| QName resName = new QName(elementQName.getNamespaceURI(), |
| method.getName() + "Response", |
| elementQName.getPrefix()); |
| OMElement bodyChild = RPCUtil.getResponseElement(resName, |
| objArray, |
| service.isElementFormDefault(), |
| service.getTypeTable()); |
| envelope.getBody().addChild(bodyChild); |
| } else { |
| if (SimpleTypeMapper.isCollection(resObject.getClass())) { |
| QName resName = new QName( |
| elementQName.getNamespaceURI(), |
| method.getName() + "Response", |
| elementQName.getPrefix()); |
| OMElement bodyChild = BeanUtil.getCollectionElement( |
| fac, method.getGenericReturnType(), |
| (Collection) resObject, Constants.RETURN_WRAPPER,null, |
| resName, service.getTypeTable(), |
| service.isElementFormDefault()); |
| envelope.getBody().addChild(bodyChild); |
| } else if (SimpleTypeMapper.isMap(resObject.getClass())){ |
| OMElement resElemt = fac.createOMElement(method.getName() + "Response", ns); |
| List<OMElement> omList = BeanUtil.getMapElement(fac,method.getGenericReturnType(), (Map) resObject,service.getTypeTable(),service.isElementFormDefault()); |
| OMElement returnElement; |
| if (service.isElementFormDefault()) { |
| returnElement = fac.createOMElement(Constants.RETURN_WRAPPER, ns); |
| } else { |
| returnElement = fac.createOMElement(Constants.RETURN_WRAPPER, null); |
| } |
| Iterator<OMElement> omItr = omList.iterator(); |
| while(omItr.hasNext()){ |
| returnElement.addChild(omItr.next()); |
| } |
| resElemt.addChild(returnElement); |
| envelope.getBody().addChild(resElemt); |
| |
| } else if (SimpleTypeMapper.isDataHandler(resObject.getClass())) { |
| OMElement resElemt = fac.createOMElement(method.getName() + "Response", ns); |
| OMText text = fac.createOMText((DataHandler)resObject, true); |
| OMElement returnElement; |
| if (service.isElementFormDefault()) { |
| returnElement = fac.createOMElement(Constants.RETURN_WRAPPER, ns); |
| } else { |
| returnElement = fac.createOMElement(Constants.RETURN_WRAPPER, null); |
| } |
| returnElement.addChild(text); |
| resElemt.addChild(returnElement); |
| envelope.getBody().addChild(resElemt); |
| } |
| else { |
| if(SimpleTypeMapper.isEnum(resObject.getClass())){ |
| resObject = resObject.toString(); |
| } |
| if (service.isElementFormDefault()) { |
| RPCUtil.processResponse(fac, resObject, bodyContent, ns, |
| envelope, method, |
| service.isElementFormDefault(), |
| service.getTypeTable()); |
| } else { |
| RPCUtil.processResponse(fac, resObject, bodyContent, ns, |
| envelope, method, |
| service.isElementFormDefault(), |
| service.getTypeTable()); |
| } |
| } |
| } |
| } |
| } |
| outMessage.setEnvelope(envelope); |
| } |
| |
| private static void addInstanceTypeInfo(SOAPFactory fac, OMElement element, |
| Method method, Object resObject, TypeTable typeTable) { |
| Class returnType = method.getReturnType(); |
| // add instanceTypeInfo only if return type is java.lang.Object |
| if (SimpleTypeMapper.isObjectType(returnType)) { |
| BeanUtil.addInstanceTypeAttribute(fac, element, resObject, |
| typeTable); |
| } |
| } |
| } |