Coverage Report - org.mule.module.cxf.WSProxyService
 
Classes in this File Line Coverage Branch Coverage Complexity
WSProxyService
0%
0/68
0%
0/32
0
 
 1  
 /*
 2  
  * $Id: WSProxyService.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.DefaultMuleMessage;
 14  
 import org.mule.api.MuleContext;
 15  
 import org.mule.api.MuleEventContext;
 16  
 import org.mule.api.MuleMessage;
 17  
 import org.mule.api.endpoint.ImmutableEndpoint;
 18  
 import org.mule.api.endpoint.InboundEndpoint;
 19  
 import org.mule.api.lifecycle.Callable;
 20  
 import org.mule.api.lifecycle.Initialisable;
 21  
 import org.mule.api.lifecycle.InitialisationException;
 22  
 import org.mule.api.routing.OutboundRouter;
 23  
 import org.mule.api.routing.OutboundRouterCollection;
 24  
 import org.mule.api.service.Service;
 25  
 import org.mule.api.service.ServiceAware;
 26  
 import org.mule.config.i18n.CoreMessages;
 27  
 import org.mule.config.i18n.MessageFactory;
 28  
 import org.mule.util.IOUtils;
 29  
 import org.mule.util.StringUtils;
 30  
 
 31  
 import java.io.IOException;
 32  
 import java.net.InetAddress;
 33  
 
 34  
 import org.apache.commons.logging.Log;
 35  
 import org.apache.commons.logging.LogFactory;
 36  
 
 37  
 /**
 38  
  * This class is implemented to act as a Proxy for a Web Service. It listens for
 39  
  * requests on the inbound endpoint and if it encounters the "WSDL" property in the
 40  
  * address, it will fetch the WSDL from the original web service and return it back.
 41  
  * In case the wsdlFile property is set, when the WSProxyService encounters a request
 42  
  * for the wsdl, instead of fetching the WSDL from the original web service, it will
 43  
  * return back the file expressed in the property. When a normal SOAP request is
 44  
  * encountered, it will forward the call to the web service with no modifications to
 45  
  * the SOAP message. The outbound router of this class must include the address of
 46  
  * the webservice to be proxied. No need to include the method name as a parameter in
 47  
  * the address, since it will be in the SOAP message as well. Furthermore a property
 48  
  * named uriWsdl can optionally be set which as the name suggests, indicate the URL
 49  
  * of the WSDL for the service. If this property is not set, the address of the WSDL
 50  
  * will be assumed to be the value of uriWebservice followed by "?WSDL". It is
 51  
  * important to note that both urls' of the webservice to be proxied and the WSDL
 52  
  * address must contain no cxf or axis endpoints, just plain http endpoints. Even
 53  
  * the inbound endpoint of the WSProxyService must be residing on an http protocol
 54  
  * (with no cxf or axis).
 55  
  */
 56  0
 public class WSProxyService implements Callable, ServiceAware, Initialisable
 57  
 {
 58  
 
 59  
     private String urlWebservice;
 60  
     private String wsdlEndpoint;
 61  
     private String wsdlFile;
 62  
     private String wsdlFileContents;
 63  0
     private boolean useFile = false;
 64  
 
 65  
     private Service service;
 66  
 
 67  
     private static final String HTTP_REQUEST = "http.request";
 68  
     private static final String WSDL_PARAM_1 = "?wsdl";
 69  
     private static final String WSDL_PARAM_2 = "&wsdl";
 70  
 
 71  
     /** This is an internal semaphore, not a property */
 72  0
     private boolean lazyInit = true;
 73  
     
 74  0
     protected static transient Log logger = LogFactory.getLog(WSProxyService.class);
 75  
 
 76  
     /**
 77  
      * @return returns the url of the WSDL
 78  
      */
 79  
     public String getWsdlEndpoint()
 80  
     {
 81  0
         return wsdlEndpoint;
 82  
     }
 83  
 
 84  
     /**
 85  
      * @param urlWsdl Sets the property urlWsdl (the url of the WSDL of the web
 86  
      *            service)
 87  
      */
 88  
     public void setWsdlEndpoint(String urlWsdl)
 89  
     {
 90  0
         this.wsdlEndpoint = urlWsdl;
 91  0
     }
 92  
 
 93  
     /**
 94  
      * @return returns the location of the local wsdl
 95  
      */
 96  
     public String getWsdlFile()
 97  
     {
 98  0
         return wsdlFile;
 99  
     }
 100  
 
 101  
     /**
 102  
      * @param wsdlFile sets the location of the local wsdl file
 103  
      */
 104  
     public void setWsdlFile(String wsdlFile)
 105  
     {
 106  0
         this.wsdlFile = wsdlFile;
 107  0
     }
 108  
 
 109  
     public Object onCall(MuleEventContext eventContext) throws Exception
 110  
     {
 111  0
         if (wsdlEndpoint == null && lazyInit)
 112  
         {
 113  0
             initialise();
 114  
         }
 115  
         
 116  
         // retrieve the message
 117  0
         MuleMessage message = eventContext.getMessage();
 118  
 
 119  
         // retrieve the original http request. This will be used to check if the user
 120  
         // asked for the WSDL or just for the service
 121  0
         String httpRequest = message.<String>getInboundProperty(HTTP_REQUEST).toLowerCase();
 122  
 
 123  
         // check if the inbound endpoint contains the WSDL parameter
 124  0
         if ((httpRequest.indexOf(WSDL_PARAM_1) != -1) || (httpRequest.indexOf(WSDL_PARAM_2) != -1))
 125  
         {
 126  0
             logger.debug("Retrieving WSDL from web service");
 127  
 
 128  
             String wsdlString;
 129  
 
 130  0
             if (this.useFile)
 131  
             {
 132  
                 // the processing is stopped so that the result is not passed through the
 133  
                 // outbound router but will be passed back as a result
 134  0
                 eventContext.setStopFurtherProcessing(true);
 135  0
                 return wsdlFileContents;
 136  
             }
 137  0
             MuleContext muleContext = eventContext.getMuleContext();
 138  0
             InboundEndpoint webServiceEndpoint = muleContext.getRegistry()
 139  
                 .lookupEndpointFactory()
 140  
                 .getInboundEndpoint(this.wsdlEndpoint);
 141  
 
 142  0
             MuleMessage replyWSDL = eventContext.requestEvent(webServiceEndpoint, eventContext.getTimeout());
 143  
 
 144  0
             wsdlString = replyWSDL.getPayloadAsString();
 145  
 
 146  
             // create a new mule message with the new WSDL
 147  0
             String realWSDLURI = wsdlEndpoint.split("\\?")[0];
 148  0
             String proxyWSDLURI = eventContext.getEndpointURI().toString();
 149  
             
 150  0
             wsdlString = wsdlString.replaceAll(realWSDLURI, proxyWSDLURI);
 151  0
             if (wsdlString.indexOf("localhost") > -1)
 152  
             {
 153  0
                 wsdlString = wsdlString.replaceAll("localhost", InetAddress.getLocalHost().getHostName());
 154  
             }
 155  
             
 156  0
             DefaultMuleMessage modifiedWsdl = new DefaultMuleMessage(wsdlString, muleContext);
 157  0
             logger.debug("WSDL retrieved successfully");
 158  
 
 159  
             // the processing is stopped so that the result is not passed through the
 160  
             // outbound router but will be passed back as a result
 161  0
             eventContext.setStopFurtherProcessing(true);
 162  
 
 163  0
             return modifiedWsdl;
 164  
         }
 165  
         else
 166  
         // forward the normal call on the outbound router without any modification
 167  
         {
 168  0
             logger.debug("Forwarding SOAP message");
 169  0
             return eventContext.getMessage().getPayload();
 170  
         }
 171  
     }
 172  
 
 173  
     // called once upon initialisation
 174  
     public void setService(Service service)
 175  
     {
 176  0
         this.service = service;
 177  0
     }
 178  
 
 179  
     public void initialise() throws InitialisationException
 180  
     {
 181  0
         if (service != null)
 182  
         {
 183  0
             OutboundRouter router = null;
 184  0
             if (service.getOutboundMessageProcessor() instanceof OutboundRouterCollection)
 185  
             {
 186  0
                 router = (OutboundRouter) ((OutboundRouterCollection) service.getOutboundMessageProcessor()).getRoutes()
 187  
                     .get(0);
 188  
             }
 189  0
             else if (service.getOutboundMessageProcessor() instanceof OutboundRouter)
 190  
             {
 191  0
                 router = (OutboundRouter) service.getOutboundMessageProcessor();
 192  
             }
 193  
             else
 194  
             {
 195  0
                 throw new IllegalStateException(
 196  
                     "WSProxyService is only supported when using an OutboundRouter");
 197  
             }
 198  0
             ImmutableEndpoint endpoint = (ImmutableEndpoint) router.getRoutes().get(0);
 199  0
             this.urlWebservice = endpoint.getEndpointURI().getAddress();
 200  
     
 201  
             // remove any params from the url
 202  
             int paramIndex;
 203  0
             if ((paramIndex = this.urlWebservice.indexOf("?")) != -1)
 204  
             {
 205  0
                 this.urlWebservice = this.urlWebservice.substring(0, paramIndex);
 206  
             }
 207  
     
 208  
             // if the wsdlFile property is not empty, the onCall() will use this file for WSDL requests
 209  0
             if (StringUtils.isNotBlank(this.wsdlFile))
 210  
             {
 211  
                 try
 212  
                 {
 213  0
                     this.wsdlFileContents = IOUtils.getResourceAsString(this.wsdlFile, getClass());
 214  
     
 215  0
                     if (StringUtils.isNotBlank(this.wsdlFileContents))
 216  
                     {
 217  0
                         this.useFile = true;
 218  0
                         logger.info("Using file " + this.wsdlFile + " as WSDL file");
 219  
                     }
 220  
                 }
 221  0
                 catch (IOException fileError)
 222  
                 {
 223  0
                     throw new InitialisationException(CoreMessages.failedToLoad(this.wsdlFile), this);
 224  0
                 }
 225  
             }
 226  
     
 227  0
             if (!this.useFile)
 228  
             {
 229  
                 // if no wsdl property is set, create one which will include the original
 230  
                 // url of the webservice followed by ?WSDL
 231  0
                 if (StringUtils.isBlank(this.wsdlEndpoint))
 232  
                 {
 233  0
                     if (urlWebservice == null)
 234  
                     {
 235  0
                         throw new InitialisationException(MessageFactory.createStaticMessage("urlWebservice has not been set, service has not been initialized properly"), this);
 236  
                     }
 237  0
                     this.wsdlEndpoint = this.urlWebservice.concat("?wsdl");
 238  0
                     logger.info("Defaulting to: " + this.wsdlEndpoint);
 239  
                 }
 240  
                 else
 241  
                 {
 242  0
                     logger.info("Using url " + this.wsdlEndpoint + " as WSDL");
 243  
                 }
 244  
             }
 245  0
         }
 246  0
         else if (!lazyInit)
 247  
         {
 248  
             // Service not injected yet, try lazy init (i.e., upon onCall()).
 249  0
             logger.debug("Service has not yet been injected, lazy initialization will be used.");
 250  0
             lazyInit = true;
 251  
         }
 252  
         else
 253  
         {
 254  
             // We're already in lazy init and the service is still not set, so throw an exception.
 255  0
             throw new InitialisationException(MessageFactory.createStaticMessage("Service not set, this service has not been initialized properly."), this);                        
 256  
         }
 257  0
     }
 258  
 }