Coverage Report - org.mule.transport.cxf.CxfServiceComponent
 
Classes in this File Line Coverage Branch Coverage Complexity
CxfServiceComponent
86%
114/132
65%
44/68
0
CxfServiceComponent$1
100%
16/16
100%
6/6
0
CxfServiceComponent$ResponseListener
0%
0/5
N/A
0
 
 1  
 /*
 2  
  * $Id: CxfServiceComponent.java 12283 2008-07-10 18:16:53Z dandiep $
 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.cxf;
 12  
 
 13  
 import org.mule.DefaultMuleMessage;
 14  
 import org.mule.RequestContext;
 15  
 import org.mule.api.ExceptionPayload;
 16  
 import org.mule.api.MuleEvent;
 17  
 import org.mule.api.MuleEventContext;
 18  
 import org.mule.api.MuleException;
 19  
 import org.mule.api.MuleMessage;
 20  
 import org.mule.api.config.ConfigurationException;
 21  
 import org.mule.api.config.MuleProperties;
 22  
 import org.mule.api.endpoint.EndpointNotFoundException;
 23  
 import org.mule.api.endpoint.EndpointURI;
 24  
 import org.mule.api.lifecycle.Callable;
 25  
 import org.mule.api.lifecycle.InitialisationException;
 26  
 import org.mule.api.lifecycle.Lifecycle;
 27  
 import org.mule.api.transformer.TransformerException;
 28  
 import org.mule.api.transport.OutputHandler;
 29  
 import org.mule.config.i18n.MessageFactory;
 30  
 import org.mule.message.DefaultExceptionPayload;
 31  
 import org.mule.module.xml.stax.StaxSource;
 32  
 import org.mule.transport.cxf.support.DelegatingOutputStream;
 33  
 import org.mule.transport.http.HttpConnector;
 34  
 import org.mule.transport.http.HttpConstants;
 35  
 import org.mule.transport.soap.SoapConstants;
 36  
 import org.mule.util.StringUtils;
 37  
 
 38  
 import java.io.ByteArrayInputStream;
 39  
 import java.io.ByteArrayOutputStream;
 40  
 import java.io.IOException;
 41  
 import java.io.InputStream;
 42  
 import java.io.OutputStream;
 43  
 import java.io.Reader;
 44  
 
 45  
 import javax.xml.stream.XMLStreamReader;
 46  
 import javax.xml.transform.Source;
 47  
 import javax.xml.transform.dom.DOMSource;
 48  
 
 49  
 import org.apache.commons.logging.Log;
 50  
 import org.apache.commons.logging.LogFactory;
 51  
 import org.apache.cxf.Bus;
 52  
 import org.apache.cxf.endpoint.Server;
 53  
 import org.apache.cxf.io.CachedOutputStream;
 54  
 import org.apache.cxf.message.ExchangeImpl;
 55  
 import org.apache.cxf.message.Message;
 56  
 import org.apache.cxf.message.MessageImpl;
 57  
 import org.apache.cxf.service.model.EndpointInfo;
 58  
 import org.apache.cxf.staxutils.StaxUtils;
 59  
 import org.apache.cxf.transport.MessageObserver;
 60  
 import org.apache.cxf.transport.local.LocalConduit;
 61  
 import org.apache.cxf.transports.http.QueryHandler;
 62  
 import org.apache.cxf.transports.http.QueryHandlerRegistry;
 63  
 import org.w3c.dom.Document;
 64  
 import org.w3c.dom.Node;
 65  
 import org.xmlsoap.schemas.wsdl.http.AddressType;
 66  
 
 67  
 /**
 68  
  * The CXF receives messages from Mule, converts them into CXF messages and dispatches
 69  
  * them into the receiving CXF destination.
 70  
  */
 71  
 public class CxfServiceComponent implements Callable, Lifecycle
 72  
 {
 73  
     /**
 74  
      * logger used by this class
 75  
      */
 76  288
     protected transient Log logger = LogFactory.getLog(getClass());
 77  
 
 78  
     protected Bus bus;
 79  
 
 80  
     // manager to the component
 81  
     protected String transportClass;
 82  
 
 83  
     private CxfMessageReceiver receiver;
 84  
 
 85  
     private final CxfConnector connector;
 86  
 
 87  
     public CxfServiceComponent(CxfConnector connector,
 88  
                                CxfMessageReceiver receiver) throws ConfigurationException
 89  
     {
 90  288
         super();
 91  288
         this.connector = connector;
 92  288
         this.receiver = receiver;
 93  288
         this.bus = receiver.connector.getCxfBus();
 94  288
     }
 95  
 
 96  
 
 97  
     public Object onCall(MuleEventContext eventContext) throws Exception
 98  
     {
 99  120
         if (logger.isDebugEnabled())
 100  
         {
 101  0
             logger.debug(eventContext);
 102  
         }
 103  
 
 104  
         // if http request
 105  120
         String request = eventContext.getMessage().getStringProperty(HttpConnector.HTTP_REQUEST_PROPERTY,
 106  
             StringUtils.EMPTY);
 107  120
         String uri = eventContext.getEndpointURI().toString();
 108  
 
 109  120
         if (request.indexOf('?') > -1 || uri.indexOf('?') > -1)
 110  
         {
 111  12
             return generateWSDLOrXSD(eventContext, request, uri);
 112  
         }
 113  
         else
 114  
         {
 115  108
             return sendToDestination(eventContext, uri);
 116  
         }
 117  
     }
 118  
 
 119  
     protected Object generateWSDLOrXSD(MuleEventContext eventContext, String req, String uri)
 120  
         throws EndpointNotFoundException, IOException
 121  
     {
 122  
         
 123  
         // TODO: Is there a way to make this not so ugly?
 124  
         String ctxUri;
 125  12
         String uriBase = (String) eventContext.getMessage().getProperty(MuleProperties.MULE_ENDPOINT_PROPERTY);
 126  
         
 127  12
         if (uriBase == null) {
 128  4
             EndpointURI epUri = eventContext.getEndpointURI();
 129  4
             String host = (String) eventContext.getMessage().getProperty("Host", epUri.getHost());
 130  
             
 131  4
             uriBase = epUri.getScheme() + "://" + host + epUri.getPath();
 132  
         }
 133  
         
 134  
         // This is the case of the HTTP message receiver. The servlet one sends different info
 135  12
         if (req != null && req.length() > 0) {
 136  12
             int qIdx = uriBase.indexOf('?');
 137  12
             if (qIdx > -1) {
 138  8
                 uriBase = uriBase.substring(0, qIdx);
 139  
             }
 140  
             
 141  12
             qIdx = req.indexOf('?');
 142  12
             if (qIdx > -1) {
 143  12
                 req = req.substring(qIdx);
 144  
             }
 145  
             
 146  12
             qIdx = req.indexOf('&');
 147  12
             if (qIdx > -1) {
 148  2
                 req = req.substring(0, qIdx);
 149  
             }
 150  
             
 151  12
             uri = uriBase + req;
 152  
         }
 153  
        
 154  12
         ctxUri = eventContext.getEndpointURI().getPath();
 155  
         
 156  12
         EndpointInfo ei = receiver.getServer().getEndpoint().getEndpointInfo();
 157  
 
 158  12
         if (uriBase != null) {
 159  12
             ei.setAddress(uriBase);
 160  
             
 161  12
             if (ei.getExtensor(AddressType.class) != null) {
 162  12
                 ei.getExtensor(AddressType.class).setLocation(uriBase);
 163  
             }
 164  
         }
 165  
 
 166  12
         ByteArrayOutputStream out = new ByteArrayOutputStream();
 167  12
         String ct = null;
 168  
 
 169  12
         for (QueryHandler qh : bus.getExtension(QueryHandlerRegistry.class).getHandlers())
 170  
         {
 171  12
             if (qh.isRecognizedQuery(uri, ctxUri, ei))
 172  
             {
 173  12
                 ct = qh.getResponseContentType(uri, ctxUri);
 174  12
                 qh.writeResponse(uri, ctxUri, ei, out);
 175  12
                 out.flush();
 176  
             }
 177  
         }
 178  
 
 179  
         String msg;
 180  12
         if (ct == null)
 181  
         {
 182  0
             ct = "text/plain";
 183  0
             msg = "No query handler found for URL.";
 184  
         }
 185  
         else
 186  
         {
 187  12
             msg = out.toString();
 188  
         }
 189  
 
 190  12
         MuleMessage result = new DefaultMuleMessage(msg);
 191  12
         result.setProperty(HttpConstants.HEADER_CONTENT_TYPE, ct);
 192  
 
 193  12
         return result;
 194  
     }
 195  
 
 196  
     protected Object sendToDestination(MuleEventContext ctx, String uri) throws MuleException, IOException
 197  
     {
 198  
         try
 199  
         {
 200  108
             final MessageImpl m = new MessageImpl();
 201  108
             final MuleMessage muleReqMsg = ctx.getMessage();
 202  108
             String method = (String) muleReqMsg.getProperty(HttpConnector.HTTP_METHOD_PROPERTY);
 203  
             
 204  108
             String ct = (String) muleReqMsg.getProperty(HttpConstants.HEADER_CONTENT_TYPE);
 205  108
             if (ct != null) {
 206  94
                 m.put(Message.CONTENT_TYPE, ct);
 207  
             }
 208  
             
 209  108
             String path = (String) muleReqMsg.getProperty(HttpConnector.HTTP_REQUEST_PROPERTY);
 210  108
             if (path == null) 
 211  
             {
 212  34
                 path = "";
 213  
             }
 214  
             
 215  108
             if (method != null) 
 216  
             {
 217  94
                 m.put(Message.HTTP_REQUEST_METHOD, method);
 218  94
                 m.put(Message.PATH_INFO, path);
 219  94
                 m.put(Message.BASE_PATH, ctx.getEndpointURI().getPath());
 220  
                 
 221  94
                 method = method.toUpperCase();
 222  
             }
 223  
             
 224  108
             if (!"GET".equals(method)) 
 225  
             {
 226  108
                 Object payload = ctx.transformMessage();
 227  
 
 228  108
                 setPayload(ctx, m, payload);
 229  
             }
 230  
             
 231  
             // TODO: Not sure if this is 100% correct - DBD
 232  108
             String soapAction = getSoapAction(ctx.getMessage());
 233  108
             m.put(org.mule.transport.soap.SoapConstants.SOAP_ACTION_PROPERTY_CAPS, soapAction);
 234  
 
 235  108
             EndpointURI epUri = ctx.getEndpointURI();
 236  108
             Server server = connector.getServer(epUri.toString());
 237  108
             if (server == null)
 238  
             {
 239  
                 // TODO is this the right Mule exception?
 240  0
                 throw new EndpointNotFoundException(uri);
 241  
             }
 242  
 
 243  108
             org.apache.cxf.transport.Destination d = server.getDestination();
 244  
             // Set up a listener for the response
 245  108
             m.put(LocalConduit.DIRECT_DISPATCH, Boolean.TRUE);
 246  108
             m.put(MuleProperties.MULE_EVENT_PROPERTY, RequestContext.getEvent());
 247  108
             m.setDestination(d);
 248  
             
 249  108
             OutputHandler outputHandler = new OutputHandler() 
 250  
             {
 251  108
                 public void write(MuleEvent event, OutputStream out) throws IOException
 252  
                 {
 253  108
                     Message outFaultMessage = m.getExchange().getOutFaultMessage();
 254  108
                     Message outMessage = m.getExchange().getOutMessage();
 255  
                     
 256  108
                     Message contentMsg = null;
 257  108
                     if (outFaultMessage != null) 
 258  
                     {
 259  10
                         contentMsg = outFaultMessage;
 260  
                     } 
 261  98
                     else if (outMessage != null) 
 262  
                     {
 263  96
                         contentMsg = outMessage;
 264  
                     }
 265  
                     
 266  108
                     if (contentMsg == null)
 267  
                     {
 268  2
                         return;
 269  
                     }
 270  
                     
 271  106
                     DelegatingOutputStream delegate = (DelegatingOutputStream) contentMsg.getContent(OutputStream.class);
 272  106
                     out.write(((ByteArrayOutputStream) delegate.getOutputStream()).toByteArray());
 273  106
                     delegate.setOutputStream(out);
 274  
                     
 275  106
                     contentMsg.getInterceptorChain().resume();
 276  
                     
 277  106
                     out.flush();
 278  106
                 }
 279  
                 
 280  
             };
 281  108
             DefaultMuleMessage muleResMsg = new DefaultMuleMessage(outputHandler);
 282  
             
 283  108
             ExchangeImpl exchange = new ExchangeImpl();
 284  108
             exchange.setInMessage(m);
 285  108
             m.put(CxfConstants.MULE_MESSAGE, muleReqMsg);
 286  
             
 287  108
             exchange.put(CxfConstants.MULE_MESSAGE, muleResMsg);
 288  
             
 289  
             // invoke the actual web service up until right before we serialize the response
 290  108
             d.getMessageObserver().onMessage(m);
 291  
             
 292  
             // Handle a fault if there is one.
 293  108
             Message faultMsg = m.getExchange().getOutFaultMessage();
 294  108
             if (faultMsg != null)
 295  
             {
 296  10
                 Exception ex = faultMsg.getContent(Exception.class);
 297  10
                 if (ex != null)
 298  
                 {
 299  10
                     ExceptionPayload exceptionPayload = new DefaultExceptionPayload(new Exception(""));
 300  10
                     ctx.getMessage().setExceptionPayload(exceptionPayload);
 301  
                 }
 302  
             }
 303  
             
 304  108
             return muleResMsg;
 305  
         }
 306  0
         catch (MuleException e)
 307  
         {
 308  0
             logger.warn("Could not dispatch message to XFire!", e);
 309  0
             throw e;
 310  
         }
 311  
     }
 312  
 
 313  
 
 314  
     private void setPayload(MuleEventContext ctx, final MessageImpl m, Object payload)
 315  
         throws TransformerException
 316  
     {
 317  108
         if (payload instanceof InputStream)
 318  
         {
 319  76
             m.put(Message.ENCODING, ctx.getEncoding());
 320  76
             m.setContent(InputStream.class, payload);
 321  
         }
 322  32
         else if (payload instanceof Reader)
 323  
         {
 324  0
             m.setContent(XMLStreamReader.class, StaxUtils.createXMLStreamReader((Reader) payload));
 325  
         }
 326  32
         else if (payload instanceof byte[])
 327  
         {
 328  0
             m.setContent(InputStream.class, new ByteArrayInputStream((byte[]) payload));
 329  
         }
 330  32
         else if (payload instanceof StaxSource)
 331  
         {
 332  2
             m.setContent(XMLStreamReader.class, ((StaxSource) payload).getXMLStreamReader());
 333  
         }
 334  30
         else if (payload instanceof Source)
 335  
         {
 336  4
             m.setContent(XMLStreamReader.class, StaxUtils.createXMLStreamReader((Source) payload));
 337  
         }
 338  26
         else if (payload instanceof XMLStreamReader)
 339  
         {
 340  2
             m.setContent(XMLStreamReader.class, (XMLStreamReader) payload);
 341  
         }
 342  24
         else if (payload instanceof Document)
 343  
         {
 344  4
             DOMSource source = new DOMSource((Node) payload);
 345  4
             m.setContent(XMLStreamReader.class, StaxUtils.createXMLStreamReader(source));
 346  4
         }
 347  
         else
 348  
         {
 349  20
             InputStream is = (InputStream) ctx.transformMessage(InputStream.class);
 350  20
             m.put(Message.ENCODING, ctx.getEncoding());
 351  20
             m.setContent(InputStream.class, is);
 352  
         }
 353  108
     }
 354  
 
 355  
     /**
 356  
      * Gets the stream representation of the current message. If the message is set
 357  
      * for streaming the input stream on the UMOStreamMEssageAdapter will be used,
 358  
      * otherwise a byteArrayInputStream will be used to hold the byte[]
 359  
      * representation of the current message.
 360  
      * 
 361  
      * @param context the event context
 362  
      * @return The inputstream for the current message
 363  
      * @throws MuleException
 364  
      */
 365  
 
 366  
     protected InputStream getMessageStream(MuleEventContext context) throws MuleException
 367  
     {
 368  
         InputStream is;
 369  0
         Object eventMsgPayload = context.transformMessage();
 370  
 
 371  0
         if (eventMsgPayload instanceof InputStream)
 372  
         {
 373  0
             is = (InputStream) eventMsgPayload;
 374  
         }
 375  
         else
 376  
         {
 377  0
             is = (InputStream) context.transformMessage(InputStream.class);
 378  
         }
 379  0
         return is;
 380  
     }
 381  
 
 382  
     protected String getSoapAction(MuleMessage message)
 383  
     {
 384  108
         String action = (String) message.getProperty(SoapConstants.SOAP_ACTION_PROPERTY);
 385  
 
 386  108
         if (action != null && action.startsWith("\"") && action.endsWith("\"") && action.length() >= 2)
 387  
         {
 388  0
             action = action.substring(1, action.length() - 1);
 389  
         }
 390  
 
 391  108
         return action;
 392  
     }
 393  
 
 394  
     public Bus getBus()
 395  
     {
 396  0
         return bus;
 397  
     }
 398  
 
 399  
     public void setBus(Bus bus)
 400  
     {
 401  288
         this.bus = bus;
 402  288
     }
 403  
 
 404  0
     class ResponseListener implements MessageObserver
 405  
     {
 406  
         private Message message;
 407  
 
 408  
         public CachedOutputStream getCachedStream()
 409  
         {
 410  0
             return message.getContent(CachedOutputStream.class);
 411  
         }
 412  
 
 413  
         public Message getMessage()
 414  
         {
 415  0
             return message;
 416  
         }
 417  
 
 418  
         public synchronized void onMessage(Message message)
 419  
         {
 420  0
             this.message = message;
 421  0
         }
 422  
     }
 423  
 
 424  
     public void initialise() throws InitialisationException
 425  
     {
 426  288
         if (bus == null)
 427  
         {
 428  0
             throw new InitialisationException(MessageFactory.createStaticMessage("No Cxf bus instance, this component has not been initialized properly."), this);
 429  
         }
 430  288
     }
 431  
 
 432  
     public void start() throws MuleException
 433  
     {
 434  
         // nothing to do
 435  288
     }
 436  
     
 437  
     public void stop() throws MuleException
 438  
     {
 439  
         // nothing to do
 440  288
     }
 441  
 
 442  
     public void dispose()
 443  
     {
 444  
         // template method
 445  0
     }
 446  
 }