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