Coverage Report - org.mule.providers.soap.xfire.transport.MuleUniversalChannel
 
Classes in this File Line Coverage Branch Coverage Complexity
MuleUniversalChannel
0%
0/93
0%
0/13
3.308
MuleUniversalChannel$1
0%
0/26
0%
0/3
3.308
 
 1  
 /*
 2  
  * $Id: MuleUniversalChannel.java 7976 2007-08-21 14:26:13Z 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.xfire.transport;
 12  
 
 13  
 import org.mule.config.MuleProperties;
 14  
 import org.mule.impl.MuleEvent;
 15  
 import org.mule.impl.MuleMessage;
 16  
 import org.mule.impl.RequestContext;
 17  
 import org.mule.impl.endpoint.MuleEndpoint;
 18  
 import org.mule.providers.http.HttpConnector;
 19  
 import org.mule.providers.http.HttpConstants;
 20  
 import org.mule.providers.streaming.StreamMessageAdapter;
 21  
 import org.mule.umo.UMOEvent;
 22  
 import org.mule.umo.UMOException;
 23  
 import org.mule.umo.UMOMessage;
 24  
 import org.mule.umo.endpoint.UMOEndpoint;
 25  
 import org.mule.umo.provider.OutputHandler;
 26  
 import org.mule.umo.provider.UMOStreamMessageAdapter;
 27  
 
 28  
 import java.io.IOException;
 29  
 import java.io.InputStream;
 30  
 import java.io.OutputStream;
 31  
 import java.util.HashMap;
 32  
 import java.util.Iterator;
 33  
 import java.util.Map;
 34  
 
 35  
 import javax.activation.DataHandler;
 36  
 import javax.mail.MessagingException;
 37  
 import javax.xml.stream.XMLStreamException;
 38  
 import javax.xml.stream.XMLStreamWriter;
 39  
 
 40  
 import org.apache.commons.io.output.ByteArrayOutputStream;
 41  
 import org.apache.commons.logging.Log;
 42  
 import org.apache.commons.logging.LogFactory;
 43  
 import org.codehaus.xfire.MessageContext;
 44  
 import org.codehaus.xfire.XFireException;
 45  
 import org.codehaus.xfire.XFireRuntimeException;
 46  
 import org.codehaus.xfire.attachments.Attachments;
 47  
 import org.codehaus.xfire.attachments.ByteDataSource;
 48  
 import org.codehaus.xfire.attachments.JavaMailAttachments;
 49  
 import org.codehaus.xfire.attachments.SimpleAttachment;
 50  
 import org.codehaus.xfire.exchange.AbstractMessage;
 51  
 import org.codehaus.xfire.exchange.InMessage;
 52  
 import org.codehaus.xfire.exchange.OutMessage;
 53  
 import org.codehaus.xfire.soap.Soap12;
 54  
 import org.codehaus.xfire.soap.SoapConstants;
 55  
 import org.codehaus.xfire.soap.SoapVersion;
 56  
 import org.codehaus.xfire.transport.AbstractChannel;
 57  
 import org.codehaus.xfire.transport.Channel;
 58  
 import org.codehaus.xfire.transport.Transport;
 59  
 import org.codehaus.xfire.util.STAXUtils;
 60  
 
 61  
 /**
 62  
  * The MuleUniversalChannel is an XFire Channel implementation that uses
 63  
  * a Mule Transport under the covers. It theoretically can use any Mule transport
 64  
  * but only transports that support streaming can be used with XFire.
 65  
  *
 66  
  * This channel is used for making Soap requests using XFire, not receiving them.
 67  
  *
 68  
  */
 69  
 public class MuleUniversalChannel extends AbstractChannel
 70  
 {
 71  
     /**
 72  
      * logger used by this class
 73  
      */
 74  0
     protected final transient Log logger = LogFactory.getLog(getClass());
 75  
 
 76  
     public MuleUniversalChannel(String uri, Transport transport)
 77  0
     {
 78  0
         setTransport(transport);
 79  0
         setUri(uri);
 80  0
     }
 81  
 
 82  
     public void open()
 83  
     {
 84  
         // nothing to do here
 85  0
     }
 86  
 
 87  
     public void send(MessageContext context, OutMessage message) throws XFireException
 88  
     {
 89  0
         if (message.getUri().equals(Channel.BACKCHANNEL_URI))
 90  
         {
 91  0
             final OutputStream out = (OutputStream)context.getProperty(Channel.BACKCHANNEL_URI);
 92  0
             if (out != null)
 93  
             {
 94  0
                 final XMLStreamWriter writer = STAXUtils.createXMLStreamWriter(out, message.getEncoding(),
 95  
                     context);
 96  
 
 97  0
                 message.getSerializer().writeMessage(message, writer, context);
 98  
             }
 99  
             else
 100  
             {
 101  0
                 throw new XFireRuntimeException("No backchannel exists for message");
 102  
             }
 103  
 
 104  
             try
 105  
             {
 106  0
                 Attachments atts = message.getAttachments();
 107  0
                 if (atts != null && atts.size() > 0)
 108  
                 {
 109  0
                     writeAttachmentBody(context, message);
 110  
                     // TODO response.setContentType(atts.getContentType());
 111  0
                     atts.write(out);
 112  
                 }
 113  
                 else
 114  
                 {
 115  
                     // TODO response.setContentType(getSoapMimeType(message));
 116  0
                     writeWithoutAttachments(context, message, out);
 117  
                 }
 118  
             }
 119  0
             catch (IOException e)
 120  
             {
 121  0
                 throw new XFireException("Couldn't send message.", e);
 122  0
             }
 123  
         }
 124  
         else
 125  
         {
 126  
             try
 127  
             {
 128  0
                 sendViaClient(context, message);
 129  
             }
 130  0
             catch (Exception e)
 131  
             {
 132  0
                 throw new XFireException("Failed to Send via MuleUniversalChannel: " + e.getMessage(), e);
 133  0
             }
 134  
         }
 135  0
     }
 136  
 
 137  
     void writeWithoutAttachments(MessageContext context, OutMessage message, OutputStream out)
 138  
         throws XFireException
 139  
     {
 140  0
         XMLStreamWriter writer = STAXUtils.createXMLStreamWriter(out, message.getEncoding(), context);
 141  
 
 142  0
         message.getSerializer().writeMessage(message, writer, context);
 143  
 
 144  
         try
 145  
         {
 146  0
             writer.flush();
 147  
         }
 148  0
         catch (XMLStreamException e)
 149  
         {
 150  0
             logger.error(e);
 151  0
             throw new XFireException("Couldn't send message.", e);
 152  0
         }
 153  0
     }
 154  
 
 155  
     void writeAttachmentBody(MessageContext context, OutMessage message) throws XFireException
 156  
     {
 157  0
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
 158  0
         writeWithoutAttachments(context, message, bos);
 159  
 
 160  0
         Attachments atts = message.getAttachments();
 161  
 
 162  0
         ByteDataSource ds = new ByteDataSource(bos.toByteArray());
 163  0
         ds.setContentType(getSoapMimeType(message));
 164  0
         DataHandler dh = new DataHandler(ds);
 165  
 
 166  0
         SimpleAttachment att = new SimpleAttachment("soap-message.xml", dh);
 167  
 
 168  0
         atts.setSoapMessage(att);
 169  0
     }
 170  
 
 171  
     String getMimeType(AbstractMessage msg)
 172  
     {
 173  0
         Attachments atts = msg.getAttachments();
 174  
 
 175  0
         if (atts != null && atts.size() > 0)
 176  
         {
 177  0
             return atts.getContentType();
 178  
         }
 179  
         else
 180  
         {
 181  0
             return getSoapMimeType(msg);
 182  
         }
 183  
     }
 184  
 
 185  
     static String getSoapMimeType(AbstractMessage msg)
 186  
     {
 187  0
         SoapVersion soap = msg.getSoapVersion();
 188  0
         String encoding = msg.getEncoding();
 189  0
         StringBuffer soapMimeType = new StringBuffer(40);
 190  
 
 191  0
         if (soap instanceof Soap12)
 192  
         {
 193  0
             soapMimeType.append("application/soap+xml; charset=");
 194  
         }
 195  
         else
 196  
         {
 197  
             // SOAP 1.1 & default
 198  0
             soapMimeType.append("text/xml; charset=");
 199  
         }
 200  
 
 201  0
         return soapMimeType.append(encoding).toString();
 202  
     }
 203  
 
 204  
     private void sendViaClient(final MessageContext context, final OutMessage message) throws Exception
 205  
     {
 206  0
         OutputHandler handler = new OutputHandler()
 207  
         {
 208  
             public void write(UMOEvent event, OutputStream out) throws IOException
 209  
             {
 210  
                 try
 211  
                 {
 212  0
                     Attachments atts = message.getAttachments();
 213  0
                     if (atts != null && atts.size() > 0)
 214  
                     {
 215  0
                         atts.write(out);
 216  
                     }
 217  
                     else
 218  
                     {
 219  0
                         XMLStreamWriter writer = STAXUtils.createXMLStreamWriter(out, message.getEncoding(),
 220  
                             context);
 221  0
                         message.getSerializer().writeMessage(message, writer, context);
 222  
                         try
 223  
                         {
 224  0
                             writer.flush();
 225  
                         }
 226  0
                         catch (XMLStreamException e)
 227  
                         {
 228  0
                             logger.error(e);
 229  0
                             throw new XFireException("Couldn't send message.", e);
 230  0
                         }
 231  
                     }
 232  
                 }
 233  0
                 catch (XFireException e)
 234  
                 {
 235  0
                     logger.error("Couldn't send message.", e);
 236  0
                     throw new IOException(e.getMessage());
 237  0
                 }
 238  0
             }
 239  
 
 240  0
             public Map getHeaders(UMOEvent event)
 241  
             {
 242  0
                 Map headers = new HashMap();
 243  0
                 headers.put(HttpConstants.HEADER_CONTENT_TYPE, getSoapMimeType(message));
 244  0
                 headers.put(SoapConstants.SOAP_ACTION, message.getProperty(SoapConstants.SOAP_ACTION));
 245  0
                 UMOMessage msg = event.getMessage();
 246  0
                 for (Iterator iterator = msg.getPropertyNames().iterator(); iterator.hasNext();)
 247  
                 {
 248  0
                     String headerName = (String)iterator.next();
 249  0
                     Object headerValue = msg.getStringProperty(headerName, null);
 250  
 
 251  
                     // let us filter only MULE properties except MULE_USER,
 252  
                     // Content-Type and Content-Lenght; all other properties are
 253  
                     // allowed through including custom headers
 254  0
                     if ((!headerName.startsWith(MuleProperties.PROPERTY_PREFIX) || (MuleProperties.MULE_USER_PROPERTY.compareTo(headerName) == 0))
 255  
                         && (!HttpConstants.HEADER_CONTENT_TYPE.equalsIgnoreCase(headerName))
 256  
                         && (!HttpConstants.HEADER_CONTENT_LENGTH.equalsIgnoreCase(headerName)))
 257  
                     {
 258  0
                         headers.put(headerName, headerValue);
 259  
                     }
 260  
                 }
 261  
 
 262  0
                 return headers;
 263  
             }
 264  
         };
 265  
 
 266  
         // We can create a generic StreamMessageAdapter here as the underlying
 267  
         // transport will create one specific to the transport
 268  0
         UMOStreamMessageAdapter sp = new StreamMessageAdapter(handler);
 269  0
         sp.setProperty(HttpConnector.HTTP_METHOD_PROPERTY, HttpConstants.METHOD_POST);
 270  
 
 271  
         // set all properties on the message adapter
 272  0
         UMOMessage msg = RequestContext.getEvent().getMessage();
 273  0
         for (Iterator i = msg.getPropertyNames().iterator(); i.hasNext();)
 274  
         {
 275  0
             String propertyName = (String)i.next();
 276  0
             sp.setProperty(propertyName, msg.getProperty(propertyName));
 277  
         }
 278  
 
 279  0
         UMOStreamMessageAdapter result = null;
 280  
 
 281  
         try
 282  
         {
 283  0
             result = sendStream(getUri(), sp);
 284  0
             if (result != null)
 285  
             {
 286  
                 InMessage inMessage;
 287  0
                 String contentType = sp.getStringProperty(HttpConstants.HEADER_CONTENT_TYPE, "text/xml");
 288  0
                 InputStream in = result.getInputStream();
 289  0
                 if (contentType.toLowerCase().indexOf("multipart/related") != -1)
 290  
                 {
 291  
                     try
 292  
                     {
 293  0
                         Attachments atts = new JavaMailAttachments(in, contentType);
 294  0
                         InputStream msgIs = atts.getSoapMessage().getDataHandler().getInputStream();
 295  0
                         inMessage = new InMessage(STAXUtils.createXMLStreamReader(msgIs,
 296  
                             message.getEncoding(), context), getUri());
 297  0
                         inMessage.setAttachments(atts);
 298  
                     }
 299  0
                     catch (MessagingException e)
 300  
                     {
 301  0
                         throw new IOException(e.getMessage());
 302  0
                     }
 303  
                 }
 304  
                 else
 305  
                 {
 306  0
                     inMessage = new InMessage(STAXUtils.createXMLStreamReader(in, message.getEncoding(),
 307  
                         context), getUri());
 308  
                 }
 309  0
                 getEndpoint().onReceive(context, inMessage);
 310  
             }
 311  0
         }
 312  
         finally
 313  
         {
 314  0
             sp.release();
 315  0
             if (result != null)
 316  
             {
 317  0
                 result.release();
 318  
             }
 319  0
         }
 320  0
     }
 321  
 
 322  
     public void close()
 323  
     {
 324  
         // nothing to do here
 325  0
     }
 326  
 
 327  
     public boolean isAsync()
 328  
     {
 329  0
         return false;
 330  
     }
 331  
 
 332  
     protected UMOStreamMessageAdapter sendStream(String uri, UMOStreamMessageAdapter sa) throws UMOException
 333  
     {
 334  
 
 335  0
         UMOEndpoint ep = MuleEndpoint.getOrCreateEndpointForUri(uri, UMOEndpoint.ENDPOINT_TYPE_SENDER);
 336  0
         ep.setStreaming(true);
 337  0
         UMOMessage message = new MuleMessage(sa);
 338  0
         UMOEvent event = new MuleEvent(message, ep, RequestContext.getEventContext().getSession(), true);
 339  0
         UMOMessage result = ep.send(event);
 340  0
         if (result != null)
 341  
         {
 342  0
             if (result.getAdapter() instanceof UMOStreamMessageAdapter)
 343  
             {
 344  0
                 return (UMOStreamMessageAdapter) result.getAdapter();
 345  
             }
 346  
             else
 347  
             {
 348  
                 // TODO i18n (though this case should never happen...)
 349  0
                 throw new IllegalStateException(
 350  
                         "Mismatch of stream states. A stream was used for outbound channel, but a stream was not used for the response");
 351  
             }
 352  
         }
 353  0
         return null;
 354  
     }
 355  
 
 356  
 }