View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.transport.soap.axis.extensions;
8   
9   import org.mule.RequestContext;
10  import org.mule.api.service.Service;
11  import org.mule.transport.soap.axis.AxisConnector;
12  import org.mule.transport.soap.axis.AxisMessageReceiver;
13  import org.mule.transport.soap.axis.AxisServiceProxy;
14  
15  import java.lang.reflect.Proxy;
16  import java.util.ArrayList;
17  import java.util.Iterator;
18  
19  import javax.xml.namespace.QName;
20  import javax.xml.rpc.holders.Holder;
21  
22  import org.apache.axis.AxisFault;
23  import org.apache.axis.Constants;
24  import org.apache.axis.MessageContext;
25  import org.apache.axis.constants.Style;
26  import org.apache.axis.description.OperationDesc;
27  import org.apache.axis.description.ParameterDesc;
28  import org.apache.axis.description.ServiceDesc;
29  import org.apache.axis.handlers.soap.SOAPService;
30  import org.apache.axis.message.RPCElement;
31  import org.apache.axis.message.RPCHeaderParam;
32  import org.apache.axis.message.RPCParam;
33  import org.apache.axis.message.SOAPEnvelope;
34  import org.apache.axis.providers.java.RPCProvider;
35  import org.apache.axis.soap.SOAPConstants;
36  import org.apache.axis.utils.JavaUtils;
37  
38  /**
39   * <code>MuleProvider</code> is an Axis service endpoint that builds services from
40   * Mule managed components.
41   */
42  public class MuleRPCProvider extends RPCProvider
43  {
44      /**
45       * Serial version
46       */
47      private static final long serialVersionUID = -4987111047650933518L;
48  
49      private AxisConnector connector;
50  
51      public MuleRPCProvider(AxisConnector connector)
52      {
53          this.connector = connector;
54      }
55  
56      protected Object makeNewServiceObject(MessageContext messageContext, String s) throws Exception
57      {
58          String transUrl = (String)messageContext.getProperty("transport.url");
59          int i = transUrl.indexOf("?");
60          if (i > -1)
61          {
62              transUrl = transUrl.substring(0, i);
63          }
64          AxisMessageReceiver receiver = (AxisMessageReceiver)connector.lookupReceiver(transUrl);
65          if (receiver == null)
66          {
67              receiver = (AxisMessageReceiver)connector.lookupReceiver(messageContext.getTargetService());
68          }
69          if (receiver == null)
70          {
71              throw new AxisFault("Could not find Mule registered service: " + s);
72          }
73          
74          if (!(receiver.getFlowConstruct() instanceof Service))
75          {
76              throw new IllegalArgumentException(
77                  "Only the Service flow constuct is supported by the axis transport");
78          }
79          Service service = (Service) receiver.getFlowConstruct();
80          Class[] classes = AxisServiceProxy.getInterfacesForComponent(service);
81          return AxisServiceProxy.createProxy(receiver, true, classes);
82      }
83  
84      protected Class getServiceClass(String s, SOAPService soapService, MessageContext messageContext)
85          throws AxisFault
86      {
87          Service component = connector.getMuleContext().getRegistry().lookupService(soapService.getName());
88          try
89          {
90              Class[] classes = AxisServiceProxy.getInterfacesForComponent(component);
91              return Proxy.getProxyClass(Thread.currentThread().getContextClassLoader(), classes);
92          }
93          catch (Exception e)
94          {
95              throw new AxisFault("Failed to implementation class for component: " + e.getMessage(), e);
96          }
97      }
98  
99      public void invoke(MessageContext msgContext) throws AxisFault
100     {
101         super.invoke(msgContext);
102         if (RequestContext.getExceptionPayload() != null)
103         {
104             Throwable t = RequestContext.getExceptionPayload().getException();
105             if (t instanceof Exception)
106             {
107                 AxisFault fault = AxisFault.makeFault((Exception)t);
108                 if (t instanceof RuntimeException)
109                 {
110                     fault.addFaultDetail(Constants.QNAME_FAULTDETAIL_RUNTIMEEXCEPTION, "true");
111                 }
112                 throw fault;
113             }
114             else
115             {
116                 throw (Error)t;
117             }
118         }
119     }
120 
121     protected RPCElement createResponseBody(RPCElement body,
122                                             MessageContext msgContext,
123                                             OperationDesc operation,
124                                             ServiceDesc serviceDesc,
125                                             Object objRes,
126                                             SOAPEnvelope resEnv,
127                                             ArrayList outs) throws Exception
128     {
129         String methodName = operation.getName();
130 
131         /* Now put the result in the result SOAPEnvelope */
132         RPCElement resBody = new RPCElement(methodName + "Response");
133         resBody.setPrefix(body.getPrefix());
134         resBody.setNamespaceURI(body.getNamespaceURI());
135         resBody.setEncodingStyle(msgContext.getEncodingStyle());
136         try
137         {
138             // Return first
139             if (operation.getMethod().getReturnType() != Void.TYPE)
140             {
141                 QName returnQName = operation.getReturnQName();
142                 if (returnQName == null)
143                 {
144                     String nsp = body.getNamespaceURI();
145                     if (nsp == null || nsp.length() == 0)
146                     {
147                         nsp = serviceDesc.getDefaultNamespace();
148                     }
149                     returnQName = new QName(msgContext.isEncoded() ? "" : nsp, methodName + "Return");
150                 }
151 
152                 RPCParam param = new RPCParam(returnQName, objRes);
153                 param.setParamDesc(operation.getReturnParamDesc());
154 
155                 if (!operation.isReturnHeader())
156                 {
157                     // For SOAP 1.2 rpc style, add a result
158                     if (msgContext.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS
159                         && (serviceDesc.getStyle().equals(Style.RPC)))
160                     {
161                         RPCParam resultParam = new RPCParam(Constants.QNAME_RPC_RESULT, returnQName);
162                         resultParam.setXSITypeGeneration(Boolean.FALSE);
163                         resBody.addParam(resultParam);
164                     }
165                     resBody.addParam(param);
166                 }
167                 else
168                 {
169                     resEnv.addHeader(new RPCHeaderParam(param));
170                 }
171 
172             }
173 
174             // Then any other out params
175             if (!outs.isEmpty())
176             {
177                 for (Iterator i = outs.iterator(); i.hasNext();)
178                 {
179                     // We know this has a holder, so just unwrap the value
180                     RPCParam param = (RPCParam)i.next();
181                     Holder holder = (Holder)param.getObjectValue();
182                     Object value = JavaUtils.getHolderValue(holder);
183                     ParameterDesc paramDesc = param.getParamDesc();
184 
185                     param.setObjectValue(value);
186                     if (paramDesc != null && paramDesc.isOutHeader())
187                     {
188                         resEnv.addHeader(new RPCHeaderParam(param));
189                     }
190                     else
191                     {
192                         resBody.addParam(param);
193                     }
194                 }
195             }
196         }
197         catch (Exception e)
198         {
199             throw e;
200         }
201         return resBody;
202     }
203 }