Coverage Report - org.mule.module.cxf.CxfInboundMessageProcessor
 
Classes in this File Line Coverage Branch Coverage Complexity
CxfInboundMessageProcessor
0%
0/140
0%
0/64
0
CxfInboundMessageProcessor$1
0%
0/16
0%
0/8
0
 
 1  
 /*
 2  
  * $Id: CxfInboundMessageProcessor.java 19191 2010-08-25 21:05:23Z tcarlson $
 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.local.LocalConduit;
 57  
 import org.apache.cxf.transports.http.QueryHandler;
 58  
 import org.apache.cxf.transports.http.QueryHandlerRegistry;
 59  
 import org.apache.cxf.wsdl.http.AddressType;
 60  
 import org.w3c.dom.Document;
 61  
 import org.w3c.dom.Node;
 62  
 
 63  
 /**
 64  
  * The CxfInboundMessageProcessor performs inbound CXF processing, sending an event
 65  
  * through the CXF service, then on to the next MessageProcessor. This processor gets
 66  
  * built by a MessageProcessorBuilder which is responsible for configuring it and the
 67  
  * {@link Server} that it dispatches to.
 68  
  */
 69  0
 public class CxfInboundMessageProcessor extends AbstractInterceptingMessageProcessor implements Lifecycle
 70  
 {
 71  
     /**
 72  
      * logger used by this class
 73  
      */
 74  0
     protected transient Log logger = LogFactory.getLog(getClass());
 75  
 
 76  
     protected Bus bus;
 77  
 
 78  
     // manager to the component
 79  
     protected String transportClass;
 80  
 
 81  
     protected Server server;
 82  
 
 83  
     private boolean proxy;
 84  
 
 85  
     public void initialise() throws InitialisationException
 86  
     {
 87  0
         if (bus == null)
 88  
         {
 89  0
             throw new InitialisationException(
 90  
                 MessageFactory.createStaticMessage("No CXF bus instance, this component has not been initialized properly."),
 91  
                 this);
 92  
         }
 93  
 
 94  0
         if (server == null)
 95  
         {
 96  0
             throw new InitialisationException(
 97  
                 MessageFactory.createStaticMessage("No CXF Server instance, this component has not been initialized properly."),
 98  
                 this);
 99  
         }
 100  0
     }
 101  
 
 102  
     public void stop() throws MuleException
 103  
     {
 104  0
         if (server != null)
 105  
         {
 106  0
             server.stop();
 107  
         }
 108  0
     }
 109  
 
 110  
     public void start() throws MuleException
 111  
     {
 112  
         // Start the CXF Server
 113  0
         server.start();
 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 = getWsdlUri(event, req);
 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().setProperty(HttpConstants.HEADER_CONTENT_TYPE, ct);
 208  0
         return event;
 209  
     }
 210  
 
 211  
     private String getWsdlUri(MuleEvent event, String reqPath)
 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  0
         return epUri.getScheme() + "://" + host + ctx;
 217  
     }
 218  
 
 219  
     protected MuleEvent sendToDestination(MuleEvent event) throws MuleException, IOException
 220  
     {
 221  
         try
 222  
         {
 223  0
             final MessageImpl m = new MessageImpl();
 224  0
             final MuleMessage muleReqMsg = event.getMessage();
 225  0
             String method = muleReqMsg.getInboundProperty(HttpConnector.HTTP_METHOD_PROPERTY);
 226  
 
 227  0
             String ct = muleReqMsg.getInboundProperty(HttpConstants.HEADER_CONTENT_TYPE);
 228  0
             if (ct != null)
 229  
             {
 230  0
                 m.put(Message.CONTENT_TYPE, ct);
 231  
             }
 232  
 
 233  0
             String path = muleReqMsg.getInboundProperty(HttpConnector.HTTP_REQUEST_PATH_PROPERTY);
 234  0
             if (path == null)
 235  
             {
 236  0
                 path = "";
 237  
             }
 238  
 
 239  0
             if (method != null)
 240  
             {
 241  0
                 m.put(Message.HTTP_REQUEST_METHOD, method);
 242  0
                 m.put(Message.PATH_INFO, path);
 243  0
                 Object basePath = muleReqMsg.getInboundProperty(HttpConnector.HTTP_CONTEXT_PATH_PROPERTY);
 244  0
                 m.put(Message.BASE_PATH, basePath);
 245  
 
 246  0
                 method = method.toUpperCase();
 247  
             }
 248  
 
 249  0
             if (!"GET".equals(method))
 250  
             {
 251  0
                 Object payload = event.getMessage().getPayload();
 252  
 
 253  0
                 setPayload(event, m, payload);
 254  
             }
 255  
 
 256  
             // TODO: Not sure if this is 100% correct - DBD
 257  0
             String soapAction = getSoapAction(event.getMessage());
 258  0
             m.put(org.mule.module.cxf.SoapConstants.SOAP_ACTION_PROPERTY_CAPS, soapAction);
 259  
 
 260  0
             org.apache.cxf.transport.Destination d = server.getDestination();
 261  
 
 262  
             // Set up a listener for the response
 263  0
             m.put(LocalConduit.DIRECT_DISPATCH, Boolean.TRUE);
 264  0
             m.put(MuleProperties.MULE_EVENT_PROPERTY, RequestContext.getEvent());
 265  0
             m.setDestination(d);
 266  
 
 267  0
             ExchangeImpl exchange = new ExchangeImpl();
 268  0
             exchange.setInMessage(m);
 269  0
             m.put(CxfConstants.MULE_EVENT, event);
 270  
 
 271  
             // if there is a fault, then we need an event in here because we won't
 272  
             // have a responseEvent from the MuleInvoker
 273  0
             exchange.put(CxfConstants.MULE_EVENT, event);
 274  
 
 275  
             // invoke the actual web service up until right before we serialize the
 276  
             // response
 277  0
             d.getMessageObserver().onMessage(m);
 278  
 
 279  
             // get the response event
 280  0
             MuleEvent responseEvent = (MuleEvent) exchange.get(CxfConstants.MULE_EVENT);
 281  
 
 282  
             // If there isn't one, there was probably a fault, so use the original
 283  
             // event
 284  0
             if (responseEvent == null || !event.getEndpoint().getExchangePattern().hasResponse())
 285  
             {
 286  0
                 return null;
 287  
             }
 288  
             
 289  0
             MuleMessage muleResMsg = responseEvent.getMessage();
 290  0
             muleResMsg.setPayload(getRessponseOutputHandler(m));
 291  
 
 292  
             // Handle a fault if there is one.
 293  0
             Message faultMsg = m.getExchange().getOutFaultMessage();
 294  0
             if (faultMsg != null)
 295  
             {
 296  0
                 Exception ex = faultMsg.getContent(Exception.class);
 297  0
                 if (ex != null)
 298  
                 {
 299  0
                     ExceptionPayload exceptionPayload = new DefaultExceptionPayload(new Exception(""));
 300  0
                     event.getMessage().setExceptionPayload(exceptionPayload);
 301  0
                     muleResMsg.setOutboundProperty(HttpConnector.HTTP_STATUS_PROPERTY, 500);
 302  
                 }
 303  
             }
 304  
 
 305  0
             return responseEvent;
 306  
         }
 307  0
         catch (MuleException e)
 308  
         {
 309  0
             logger.warn("Could not dispatch message to CXF!", e);
 310  0
             throw e;
 311  
         }
 312  
     }
 313  
 
 314  
     @Override
 315  
     public MuleEvent processNext(MuleEvent event) throws MuleException
 316  
     {
 317  0
         return next.process(event);
 318  
     }
 319  
 
 320  
     protected OutputHandler getRessponseOutputHandler(final MessageImpl m)
 321  
     {
 322  0
         OutputHandler outputHandler = new OutputHandler()
 323  0
         {
 324  
             public void write(MuleEvent event, OutputStream out) throws IOException
 325  
             {
 326  0
                 Message outFaultMessage = m.getExchange().getOutFaultMessage();
 327  0
                 Message outMessage = m.getExchange().getOutMessage();
 328  
 
 329  0
                 Message contentMsg = null;
 330  0
                 if (outFaultMessage != null && outFaultMessage.getContent(OutputStream.class) != null)
 331  
                 {
 332  0
                     contentMsg = outFaultMessage;
 333  
                 }
 334  0
                 else if (outMessage != null)
 335  
                 {
 336  0
                     contentMsg = outMessage;
 337  
                 }
 338  
 
 339  0
                 if (contentMsg == null)
 340  
                 {
 341  0
                     return;
 342  
                 }
 343  
 
 344  0
                 DelegatingOutputStream delegate = contentMsg.getContent(DelegatingOutputStream.class);
 345  0
                 out.write(((ByteArrayOutputStream) delegate.getOutputStream()).toByteArray());
 346  0
                 delegate.setOutputStream(out);
 347  
 
 348  0
                 out.flush();
 349  
 
 350  0
                 contentMsg.getInterceptorChain().resume();
 351  0
             }
 352  
 
 353  
         };
 354  0
         return outputHandler;
 355  
     }
 356  
 
 357  
     private void setPayload(MuleEvent ctx, final MessageImpl m, Object payload) throws TransformerException
 358  
     {
 359  0
         if (payload instanceof InputStream)
 360  
         {
 361  0
             m.put(Message.ENCODING, ctx.getEncoding());
 362  0
             m.setContent(InputStream.class, payload);
 363  
         }
 364  0
         else if (payload instanceof Reader)
 365  
         {
 366  0
             m.setContent(XMLStreamReader.class, StaxUtils.createXMLStreamReader((Reader) payload));
 367  
         }
 368  0
         else if (payload instanceof byte[])
 369  
         {
 370  0
             m.setContent(InputStream.class, new ByteArrayInputStream((byte[]) payload));
 371  
         }
 372  0
         else if (payload instanceof StaxSource)
 373  
         {
 374  0
             m.setContent(XMLStreamReader.class, ((StaxSource) payload).getXMLStreamReader());
 375  
         }
 376  0
         else if (payload instanceof Source)
 377  
         {
 378  0
             m.setContent(XMLStreamReader.class, StaxUtils.createXMLStreamReader((Source) payload));
 379  
         }
 380  0
         else if (payload instanceof XMLStreamReader)
 381  
         {
 382  0
             m.setContent(XMLStreamReader.class, payload);
 383  
         }
 384  0
         else if (payload instanceof Document)
 385  
         {
 386  0
             DOMSource source = new DOMSource((Node) payload);
 387  0
             m.setContent(XMLStreamReader.class, StaxUtils.createXMLStreamReader(source));
 388  0
         }
 389  
         else
 390  
         {
 391  0
             InputStream is = (InputStream) ctx.transformMessage(DataTypeFactory.create(InputStream.class));
 392  0
             m.put(Message.ENCODING, ctx.getEncoding());
 393  0
             m.setContent(InputStream.class, is);
 394  
         }
 395  0
     }
 396  
 
 397  
     /**
 398  
      * Gets the stream representation of the current message.
 399  
      * 
 400  
      * @param context the event context
 401  
      * @return The inputstream for the current message
 402  
      * @throws MuleException
 403  
      */
 404  
     protected InputStream getMessageStream(MuleEvent context) throws MuleException
 405  
     {
 406  
         InputStream is;
 407  0
         Object eventMsgPayload = context.getMessage().getPayload();
 408  
 
 409  0
         if (eventMsgPayload instanceof InputStream)
 410  
         {
 411  0
             is = (InputStream) eventMsgPayload;
 412  
         }
 413  
         else
 414  
         {
 415  0
             is = (InputStream) context.transformMessage(DataTypeFactory.create(InputStream.class));
 416  
         }
 417  0
         return is;
 418  
     }
 419  
 
 420  
     protected String getSoapAction(MuleMessage message)
 421  
     {
 422  0
         String action = message.getInboundProperty(SoapConstants.SOAP_ACTION_PROPERTY);
 423  
 
 424  0
         if (action != null && action.startsWith("\"") && action.endsWith("\"") && action.length() >= 2)
 425  
         {
 426  0
             action = action.substring(1, action.length() - 1);
 427  
         }
 428  
 
 429  0
         return action;
 430  
     }
 431  
 
 432  
     public Bus getBus()
 433  
     {
 434  0
         return bus;
 435  
     }
 436  
 
 437  
     public void setBus(Bus bus)
 438  
     {
 439  0
         this.bus = bus;
 440  0
     }
 441  
 
 442  
     public Server getServer()
 443  
     {
 444  0
         return server;
 445  
     }
 446  
 
 447  
     public void setServer(Server server)
 448  
     {
 449  0
         this.server = server;
 450  0
     }
 451  
 
 452  
     public void setProxy(boolean proxy)
 453  
     {
 454  0
         this.proxy = proxy;
 455  0
     }
 456  
 
 457  
     public boolean isProxy()
 458  
     {
 459  0
         return proxy;
 460  
     }
 461  
 }