View Javadoc

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