View Javadoc

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