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