View Javadoc

1   /*
2    * $Id: UniversalSender.java 7963 2007-08-21 08:53:15Z dirk.olmes $
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.providers.soap.axis.extensions;
12  
13  import org.mule.MuleManager;
14  import org.mule.config.MuleProperties;
15  import org.mule.impl.MuleEvent;
16  import org.mule.impl.MuleMessage;
17  import org.mule.impl.RequestContext;
18  import org.mule.impl.endpoint.MuleEndpoint;
19  import org.mule.impl.endpoint.MuleEndpointURI;
20  import org.mule.impl.model.ModelHelper;
21  import org.mule.providers.http.HttpConstants;
22  import org.mule.providers.soap.axis.AxisConnector;
23  import org.mule.providers.soap.axis.extras.AxisCleanAndAddProperties;
24  import org.mule.umo.UMODescriptor;
25  import org.mule.umo.UMOEvent;
26  import org.mule.umo.UMOException;
27  import org.mule.umo.UMOMessage;
28  import org.mule.umo.UMOSession;
29  import org.mule.umo.endpoint.UMOEndpoint;
30  import org.mule.umo.endpoint.UMOEndpointURI;
31  import org.mule.umo.endpoint.UMOImmutableEndpoint;
32  import org.mule.umo.routing.UMOOutboundRouter;
33  import org.mule.umo.routing.UMOOutboundRouterCollection;
34  
35  import java.io.File;
36  import java.io.FileInputStream;
37  import java.io.FileOutputStream;
38  import java.util.HashMap;
39  import java.util.Iterator;
40  import java.util.Map;
41  
42  import org.apache.axis.AxisFault;
43  import org.apache.axis.Message;
44  import org.apache.axis.MessageContext;
45  import org.apache.axis.client.Call;
46  import org.apache.axis.handlers.BasicHandler;
47  import org.apache.commons.io.output.ByteArrayOutputStream;
48  import org.apache.commons.logging.Log;
49  import org.apache.commons.logging.LogFactory;
50  
51  /**
52   * An Axis handler that will dispatch the SOAP event via a Mule endpoint
53   */
54  public class UniversalSender extends BasicHandler
55  {
56      /**
57       * Serial version
58       */
59      private static final long serialVersionUID = 7943380365092172940L;
60  
61      /**
62       * logger used by this class
63       */
64      protected transient Log logger = LogFactory.getLog(getClass());
65  
66      protected Map endpointsCache = new HashMap();
67  
68      public void invoke(MessageContext msgContext) throws AxisFault
69      {
70          boolean sync = true;
71          Call call = (Call)msgContext.getProperty("call_object");
72          if (call == null)
73          {
74              throw new IllegalStateException(
75                  "The call_object property must be set on the message context to the client Call object");
76          }
77          if (Boolean.TRUE.equals(call.getProperty("axis.one.way")))
78          {
79              sync = false;
80          }
81          // Get the event stored in call
82          // If a receive call is made there will be no event
83          // UMOEvent event =
84          // (UMOEvent)call.getProperty(MuleProperties.MULE_EVENT_PROPERTY);
85          // Get the dispatch endpoint
86          String uri = msgContext.getStrProp(MessageContext.TRANS_URL);
87          UMOImmutableEndpoint requestEndpoint = (UMOImmutableEndpoint)call
88              .getProperty(MuleProperties.MULE_ENDPOINT_PROPERTY);
89          UMOImmutableEndpoint endpoint = null;
90  
91          // put username and password in URI if they are set on the current event
92          if (msgContext.getUsername() != null)
93          {
94              String[] tempEndpoint = uri.split("//");
95              String credentialString = msgContext.getUsername() + ":"
96                                        + msgContext.getPassword();
97              uri = tempEndpoint[0] + "//" + credentialString + "@" + tempEndpoint[1];
98              try
99              {
100                 endpoint = lookupEndpoint(uri);
101             }
102             catch (UMOException e)
103             {
104                 requestEndpoint.getConnector().handleException(e);
105                 return;
106             }
107         }
108         else
109         {
110             try
111             {
112                 endpoint = lookupEndpoint(uri);
113             }
114             catch (UMOException e)
115             {
116                 requestEndpoint.getConnector().handleException(e);
117                 return;
118             }
119         }
120 
121         try
122         {
123             if (requestEndpoint.getConnector() instanceof AxisConnector)
124             {
125                 msgContext.setTypeMappingRegistry(((AxisConnector)requestEndpoint.getConnector())
126                     .getAxisServer().getTypeMappingRegistry());
127             }
128             Object payload = null;
129             int contentLength = 0;
130             if (msgContext.getRequestMessage().countAttachments() > 0)
131             {
132                 File temp = File.createTempFile("soap", ".tmp");
133                 temp.deleteOnExit(); // TODO cleanup files earlier (IOUtils has a
134                 // file tracker)
135                 FileOutputStream fos = new FileOutputStream(temp);
136                 msgContext.getRequestMessage().writeTo(fos);
137                 fos.close();
138                 contentLength = (int)temp.length();
139                 payload = new FileInputStream(temp);
140             }
141             else
142             {
143                 ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
144                 msgContext.getRequestMessage().writeTo(baos);
145                 baos.close();
146                 payload = baos.toByteArray();
147             }
148 
149             Map props = new HashMap();
150             // props.putAll(event.getProperties());
151             for (Iterator iterator = msgContext.getPropertyNames(); iterator.hasNext();)
152             {
153                 String name = (String)iterator.next();
154                 if (!name.equals("call_object") && !name.equals("wsdl.service"))
155                 {
156                     props.put(name, msgContext.getProperty(name));
157                 }
158             }
159 
160             // add all custom headers, filter out all mule headers (such as
161             // MULE_SESSION) except
162             // for MULE_USER header. Filter out other headers like "soapMethods" and
163             // MuleProperties.MULE_METHOD_PROPERTY and "soapAction"
164             // and also filter out any http related header
165             if ((RequestContext.getEvent() != null)
166                 && (RequestContext.getEvent().getMessage() != null))
167             {
168                 props = AxisCleanAndAddProperties.cleanAndAdd(RequestContext.getEventContext());
169             }
170             
171             // with jms and vm the default SOAPAction will result in the name of the endpoint, which we may not necessarily want. This should be set manually on the endpoint
172             String scheme = requestEndpoint.getEndpointURI().getScheme(); 
173             if (!("vm".equalsIgnoreCase(scheme) || "jms".equalsIgnoreCase(scheme)))
174             {
175                 if (call.useSOAPAction())
176                 {
177                     uri = call.getSOAPActionURI();
178                 }
179                 props.put("SOAPAction", uri);
180             }
181             if (contentLength > 0)
182             {
183                 props.put(HttpConstants.HEADER_CONTENT_LENGTH, Integer.toString(contentLength)); // necessary
184                 // for
185                 // supporting
186                 // httpclient
187             }
188 
189             if (props.get(HttpConstants.HEADER_CONTENT_TYPE) == null)
190             {
191                 props.put(HttpConstants.HEADER_CONTENT_TYPE, "text/xml");
192             }
193             UMOMessage message = new MuleMessage(payload, props);
194             UMOSession session = RequestContext.getEventContext().getSession();
195 
196             UMOEvent dispatchEvent = new MuleEvent(message, endpoint, session, sync);
197             logger.info("Making Axis soap request on: " + uri);
198             if (logger.isDebugEnabled())
199             {
200                 logger.debug("Soap request is:\n" + payload.toString());
201             }
202             if (sync)
203             {
204                 // We need to rewrite the endpoint on the event to set the
205                 // reomoteSync property
206                 MuleEndpoint syncEndpoint = new MuleEndpoint(dispatchEvent.getEndpoint());
207                 syncEndpoint.setRemoteSync(true);
208                 dispatchEvent = new MuleEvent(dispatchEvent.getMessage(), syncEndpoint,
209                     dispatchEvent.getSession(), dispatchEvent.isSynchronous());
210                 
211                 //set username and password
212                 
213                 
214                 UMOMessage result = session.sendEvent(dispatchEvent);
215                 if (result != null)
216                 {
217                     byte[] response = result.getPayloadAsBytes();
218                     Message responseMessage = new Message(response);
219                     msgContext.setResponseMessage(responseMessage);
220 
221                 }
222                 else
223                 {
224                     logger
225                         .warn("No response message was returned from synchronous call to: " + uri);
226                 }
227                 // remove temp file created for streaming
228                 if (payload instanceof File)
229                 {
230                     ((File)payload).delete();
231                 }
232             }
233             else
234             {
235                 session.dispatchEvent(dispatchEvent);
236             }
237         }
238         catch (AxisFault axisFault)
239         {
240             throw axisFault;
241         }
242         catch (Exception e)
243         {
244             throw new AxisFault(e.getMessage(), new Throwable(e));
245         }
246 
247     }
248 
249     protected UMOEndpoint lookupEndpoint(String uri) throws UMOException
250     {
251         UMODescriptor axis = MuleManager.getInstance().lookupModel(ModelHelper.SYSTEM_MODEL)
252             .getDescriptor(AxisConnector.AXIS_SERVICE_COMPONENT_NAME);
253         UMOEndpointURI endpoint = new MuleEndpointURI(uri);
254         UMOEndpoint ep;
255         if (axis != null)
256         {
257             synchronized (endpointsCache)
258             {
259                 ep = (UMOEndpoint)endpointsCache.get(endpoint.getAddress());
260                 if (ep == null)
261                 {
262                     updateEndpointCache(axis.getOutboundRouter());
263                     ep = (UMOEndpoint)endpointsCache.get(endpoint.getAddress());
264                     if (ep == null)
265                     {
266                         logger.debug("Dispatch Endpoint uri: " + uri
267                                      + " not found on the cache. Creating the endpoint instead.");
268                         ep = new MuleEndpoint(uri, false);
269                     }
270                     else
271                     {
272                         logger.info("Found endpoint: " + uri + " on the Axis service component");
273                     }
274                 }
275                 else
276                 {
277                     logger.info("Found endpoint: " + uri + " on the Axis service component");
278                 }
279             }
280         }
281         else
282         {
283             ep = new MuleEndpoint(uri, false);
284         }
285         return ep;
286     }
287 
288     private void updateEndpointCache(UMOOutboundRouterCollection router)
289     {
290         endpointsCache.clear();
291         for (Iterator iterator = router.getRouters().iterator(); iterator.hasNext();)
292         {
293             UMOOutboundRouter r = (UMOOutboundRouter)iterator.next();
294             for (Iterator iterator1 = r.getEndpoints().iterator(); iterator1.hasNext();)
295             {
296                 UMOEndpoint endpoint = (UMOEndpoint)iterator1.next();
297                 endpointsCache.put(endpoint.getEndpointURI().getAddress(), endpoint);
298             }
299         }
300     }
301 }