Coverage Report - org.mule.transport.cxf.ClientWrapper
 
Classes in this File Line Coverage Branch Coverage Complexity
ClientWrapper
82%
143/175
53%
48/90
0
 
 1  
 /*
 2  
  * $Id: ClientWrapper.java 12248 2008-07-07 22:08:28Z 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.api.MuleEvent;
 14  
 import org.mule.api.config.MuleProperties;
 15  
 import org.mule.api.endpoint.EndpointURI;
 16  
 import org.mule.api.endpoint.ImmutableEndpoint;
 17  
 import org.mule.api.lifecycle.CreateException;
 18  
 import org.mule.api.transport.DispatchException;
 19  
 import org.mule.transport.cxf.i18n.CxfMessages;
 20  
 import org.mule.transport.cxf.support.MuleHeadersInInterceptor;
 21  
 import org.mule.transport.cxf.support.MuleHeadersOutInterceptor;
 22  
 import org.mule.transport.cxf.support.MuleProtocolHeadersOutInterceptor;
 23  
 import org.mule.transport.cxf.support.OutputPayloadInterceptor;
 24  
 import org.mule.transport.cxf.support.ProxyService;
 25  
 import org.mule.transport.soap.i18n.SoapMessages;
 26  
 
 27  
 import java.lang.reflect.Constructor;
 28  
 import java.lang.reflect.Method;
 29  
 import java.net.URL;
 30  
 import java.util.HashMap;
 31  
 import java.util.List;
 32  
 
 33  
 import javax.xml.namespace.QName;
 34  
 import javax.xml.ws.BindingProvider;
 35  
 import javax.xml.ws.Service;
 36  
 import javax.xml.ws.WebEndpoint;
 37  
 import javax.xml.ws.WebServiceClient;
 38  
 
 39  
 import org.apache.commons.lang.BooleanUtils;
 40  
 import org.apache.cxf.Bus;
 41  
 import org.apache.cxf.binding.Binding;
 42  
 import org.apache.cxf.common.classloader.ClassLoaderUtils;
 43  
 import org.apache.cxf.databinding.stax.StaxDataBinding;
 44  
 import org.apache.cxf.databinding.stax.StaxDataBindingFeature;
 45  
 import org.apache.cxf.endpoint.Client;
 46  
 import org.apache.cxf.endpoint.ClientImpl;
 47  
 import org.apache.cxf.endpoint.Endpoint;
 48  
 import org.apache.cxf.endpoint.EndpointImpl;
 49  
 import org.apache.cxf.feature.AbstractFeature;
 50  
 import org.apache.cxf.frontend.ClientProxy;
 51  
 import org.apache.cxf.frontend.ClientProxyFactoryBean;
 52  
 import org.apache.cxf.frontend.MethodDispatcher;
 53  
 import org.apache.cxf.interceptor.Interceptor;
 54  
 import org.apache.cxf.interceptor.WrappedOutInterceptor;
 55  
 import org.apache.cxf.message.Message;
 56  
 import org.apache.cxf.phase.PhaseInterceptor;
 57  
 import org.apache.cxf.resource.ResourceManager;
 58  
 import org.apache.cxf.resource.URIResolver;
 59  
 import org.apache.cxf.service.model.BindingOperationInfo;
 60  
 import org.apache.cxf.service.model.EndpointInfo;
 61  
 import org.apache.cxf.transport.ChainInitiationObserver;
 62  
 import org.apache.cxf.transport.Destination;
 63  
 import org.apache.cxf.transport.DestinationFactory;
 64  
 import org.apache.cxf.transport.DestinationFactoryManager;
 65  
 import org.apache.cxf.transport.MessageObserver;
 66  
 
 67  76
 public class ClientWrapper
 68  
 {
 69  
 
 70  
     protected ImmutableEndpoint endpoint;
 71  
     protected Bus bus;
 72  
     protected Client client;
 73  
     protected String defaultMethodName;
 74  
 
 75  
     // If we have a proxy we're going to invoke it directly
 76  
     // Since the JAX-WS proxy does extra special things for us.
 77  
     protected BindingProvider clientProxy;
 78  
     protected Method defaultMethod;
 79  
 
 80  
     protected boolean proxy;
 81  
     
 82  
     public Client getClient()
 83  
     {
 84  154
         return client;
 85  
     }
 86  
 
 87  
     public BindingProvider getClientProxy()
 88  
     {
 89  12
         return clientProxy;
 90  
     }
 91  
 
 92  
     @SuppressWarnings("unchecked")
 93  
     public void initialize() throws Exception
 94  
     {
 95  76
         String clientClass = (String) endpoint.getProperty(CxfConstants.CLIENT_CLASS);
 96  76
         proxy = BooleanUtils.toBoolean((String) endpoint.getProperty(CxfConstants.PROXY));
 97  
         
 98  76
         if (clientClass != null)
 99  
         {
 100  6
             createClientFromClass(bus, clientClass);
 101  
         }
 102  70
         else if (proxy)
 103  
         {
 104  6
             createClientProxy(bus);
 105  
         }
 106  
         else
 107  
         {
 108  64
             createClientFromLocalServer(bus);
 109  
         }
 110  
         
 111  76
         addInterceptors(client.getInInterceptors(), (List<Interceptor>) endpoint.getProperty(CxfConstants.IN_INTERCEPTORS));
 112  76
         addInterceptors(client.getInFaultInterceptors(), (List<Interceptor>) endpoint.getProperty(CxfConstants.IN_FAULT_INTERCEPTORS));
 113  76
         addInterceptors(client.getOutInterceptors(), (List<Interceptor>) endpoint.getProperty(CxfConstants.OUT_INTERCEPTORS));
 114  76
         addInterceptors(client.getOutFaultInterceptors(), (List<Interceptor>) endpoint.getProperty(CxfConstants.OUT_FAULT_INTERCEPTORS));
 115  
 
 116  76
         if (proxy)
 117  
         {
 118  6
             client.getOutInterceptors().add(new OutputPayloadInterceptor());
 119  
         }
 120  
         
 121  76
         List<AbstractFeature> features = (List<AbstractFeature>) endpoint.getProperty(CxfConstants.OUT_FAULT_INTERCEPTORS);
 122  
         
 123  76
         if (features != null)
 124  
         {
 125  0
             for (AbstractFeature f : features)
 126  
             {
 127  0
                 f.initialize(client, bus);
 128  
             }
 129  
         }
 130  
 
 131  76
         EndpointImpl ep = (EndpointImpl) client.getEndpoint();
 132  
         
 133  76
         Object mtomEnabled = endpoint.getProperty(CxfConstants.MTOM_ENABLED);
 134  76
         if (mtomEnabled != null) 
 135  
         {
 136  2
             HashMap<String, Object> props = new HashMap<String, Object>();
 137  2
             props.put(Message.MTOM_ENABLED, mtomEnabled);
 138  2
             ep.setProperties(props);
 139  
         }
 140  
         
 141  76
         addMuleInterceptors();
 142  76
     }
 143  
 
 144  
     @SuppressWarnings("unchecked")
 145  
     private void addInterceptors(List<Interceptor> col, List<Interceptor> supplied)
 146  
     {
 147  304
         if (supplied != null) 
 148  
         {
 149  4
             col.addAll(supplied);
 150  
         }
 151  304
     }
 152  
 
 153  
     protected Method findMethod(Class<?> clientCls) throws Exception
 154  
     {
 155  6
         if (defaultMethod == null)
 156  
         {
 157  6
             String op = (String) endpoint.getProperties().get(CxfConstants.OPERATION);
 158  6
             if (op == null)
 159  
             {
 160  0
                 op = (String) endpoint.getProperties().get(CxfConstants.OPERATION);
 161  
             }
 162  
 
 163  6
             if (op != null)
 164  
             {
 165  6
                 return getMethodFromOperation(op);
 166  
             }
 167  
         }
 168  
 
 169  0
         return null;
 170  
     }
 171  
 
 172  
     protected BindingOperationInfo getOperation(String opName) throws Exception
 173  
     {
 174  
         // Normally its not this hard to invoke the CXF Client, but we're
 175  
         // sending along some exchange properties, so we need to use a more advanced
 176  
         // method
 177  58
         Endpoint ep = client.getEndpoint();
 178  58
         QName q = new QName(ep.getService().getName().getNamespaceURI(), opName);
 179  58
         BindingOperationInfo bop = ep.getBinding().getBindingInfo().getOperation(q);
 180  58
         if (bop == null)
 181  
         {
 182  0
             throw new Exception("No such operation: " + defaultMethod);
 183  
         }
 184  
 
 185  58
         if (bop.isUnwrappedCapable())
 186  
         {
 187  58
             bop = bop.getUnwrappedOperation();
 188  
         }
 189  58
         return bop;
 190  
     }
 191  
 
 192  
     private Method getMethodFromOperation(String op) throws Exception
 193  
     {
 194  6
         BindingOperationInfo bop = getOperation(op);
 195  6
         MethodDispatcher md = (MethodDispatcher) client.getEndpoint().getService().get(
 196  
             MethodDispatcher.class.getName());
 197  6
         return md.getMethod(bop);
 198  
     }
 199  
 
 200  
     protected void createClientProxy(Bus bus) throws Exception
 201  
     {
 202  
         // TODO: Specify WSDL
 203  6
         String wsdlLocation = (String) endpoint.getProperty(CxfConstants.WSDL_LOCATION);
 204  
         
 205  6
         ClientProxyFactoryBean cpf = new ClientProxyFactoryBean();
 206  6
         cpf.setServiceClass(ProxyService.class);
 207  6
         cpf.setDataBinding(new StaxDataBinding());
 208  6
         cpf.getFeatures().add(new StaxDataBindingFeature());
 209  6
         cpf.setAddress(endpoint.getEndpointURI().getAddress());
 210  
 
 211  6
         if (wsdlLocation != null) 
 212  
         {
 213  0
             cpf.setWsdlLocation(wsdlLocation);
 214  
         }
 215  
         
 216  6
         this.client = ClientProxy.getClient(cpf.create());
 217  
         
 218  6
         Binding binding = this.client.getEndpoint().getBinding();
 219  
         
 220  6
         removeInterceptor(binding.getOutInterceptors(), WrappedOutInterceptor.class.getName());
 221  
         
 222  6
         proxy = true;
 223  6
     }
 224  
 
 225  
     @SuppressWarnings("unchecked")
 226  
     private void removeInterceptor(List<Interceptor> inInterceptors, String name) {
 227  
 
 228  6
         for (Interceptor<?> i : inInterceptors) {
 229  30
             if (i instanceof PhaseInterceptor) {
 230  30
                 PhaseInterceptor<Message> p = (PhaseInterceptor<Message>)i;
 231  
 
 232  30
                 if (p.getId().equals(name)) {
 233  6
                     inInterceptors.remove(p);
 234  6
                     return;
 235  
                 }
 236  24
             }
 237  
         }
 238  0
     }
 239  
 
 240  
     protected void createClientFromClass(Bus bus, String clientClassName) throws Exception
 241  
     {
 242  
         // TODO: Specify WSDL
 243  6
         String wsdlLocation = (String) endpoint.getProperty(CxfConstants.WSDL_LOCATION);
 244  6
         Class<?> clientCls = ClassLoaderUtils.loadClass(clientClassName, getClass());
 245  
 
 246  6
         Service s = null;
 247  6
         if (wsdlLocation != null)
 248  
         {
 249  6
             Constructor<?> cons = clientCls.getConstructor(URL.class, QName.class);
 250  6
             ResourceManager rr = bus.getExtension(ResourceManager.class);
 251  6
             URL url = rr.resolveResource(wsdlLocation, URL.class);
 252  
 
 253  6
             if (url == null)
 254  
             {
 255  0
                 URIResolver res = new URIResolver(wsdlLocation);
 256  
 
 257  0
                 if (!res.isResolved())
 258  
                 {
 259  0
                     throw new CreateException(CxfMessages.wsdlNotFound(wsdlLocation), this);
 260  
                 }
 261  0
                 url = res.getURL();
 262  
             }
 263  
 
 264  6
             WebServiceClient clientAnn = clientCls.getAnnotation(WebServiceClient.class);
 265  6
             QName svcName = new QName(clientAnn.targetNamespace(), clientAnn.name());
 266  
 
 267  6
             s = (Service) cons.newInstance(url, svcName);
 268  6
         }
 269  
         else
 270  
         {
 271  0
             s = (Service) clientCls.newInstance();
 272  
         }
 273  6
         String port = (String) endpoint.getProperty(CxfConstants.CLIENT_PORT);
 274  
 
 275  6
         if (port == null)
 276  
         {
 277  0
             throw new CreateException(CxfMessages.mustSpecifyPort(), this);
 278  
         }
 279  
 
 280  6
         clientProxy = null;
 281  6
         if (port != null)
 282  
         {
 283  6
             for (Method m : clientCls.getMethods())
 284  
             {
 285  6
                 WebEndpoint we = m.getAnnotation(WebEndpoint.class);
 286  
 
 287  6
                 if (we != null && we.name().equals(port))
 288  
                 {
 289  6
                     clientProxy = (BindingProvider) m.invoke(s, new Object[0]);
 290  6
                     break;
 291  
                 }
 292  
             }
 293  
         }
 294  
 
 295  6
         if (clientProxy == null)
 296  
         {
 297  0
             throw new CreateException(CxfMessages.portNotFound(port), this);
 298  
         }
 299  
 
 300  6
         EndpointURI uri = endpoint.getEndpointURI();
 301  6
         if (uri.getUser() != null)
 302  
         {
 303  0
             clientProxy.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, uri.getUser());
 304  
         }
 305  
 
 306  6
         if (uri.getPassword() != null)
 307  
         {
 308  0
             clientProxy.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, uri.getPassword());
 309  
         }
 310  
 
 311  6
         clientProxy.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, uri.getAddress());
 312  
 
 313  6
         client = ClientProxy.getClient(clientProxy);
 314  
 
 315  6
         defaultMethod = findMethod(clientCls);
 316  6
         defaultMethodName = getDefaultMethodName();
 317  6
     }
 318  
 
 319  
     private String getDefaultMethodName()
 320  
     {
 321  6
         EndpointURI endpointUri = endpoint.getEndpointURI();
 322  6
         String m = (String) endpointUri.getParams().get(MuleProperties.MULE_METHOD_PROPERTY);
 323  
 
 324  6
         if (m == null)
 325  
         {
 326  6
             m = (String) endpoint.getProperties().get(MuleProperties.MULE_METHOD_PROPERTY);
 327  
         }
 328  
 
 329  6
         return m;
 330  
     }
 331  
 
 332  
     protected void createClientFromLocalServer(final Bus bus) throws Exception
 333  
     {
 334  64
         String uri = endpoint.getEndpointURI().toString();
 335  64
         int idx = uri.indexOf('?');
 336  64
         if (idx != -1)
 337  
         {
 338  64
             uri = uri.substring(0, idx);
 339  
         }
 340  
 
 341  64
         EndpointInfo ei = new EndpointInfo();
 342  64
         ei.setAddress(uri);
 343  
 
 344  64
         DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class);
 345  64
         DestinationFactory df = dfm.getDestinationFactoryForUri(uri);
 346  64
         if (df == null)
 347  
         {
 348  0
             throw new Exception("Could not find a destination factory for uri " + uri);
 349  
         }
 350  
 
 351  64
         Destination dest = df.getDestination(ei);
 352  64
         MessageObserver mo = dest.getMessageObserver();
 353  64
         if (mo instanceof ChainInitiationObserver)
 354  
         {
 355  64
             ChainInitiationObserver cMo = (ChainInitiationObserver) mo;
 356  64
             Endpoint cxfEP = cMo.getEndpoint();
 357  
 
 358  64
             client = new ClientImpl(bus, cxfEP);
 359  64
         }
 360  
         else
 361  
         {
 362  0
             throw new Exception("Could not create client! No Server was found directly on the endpoint: "
 363  
                                 + uri);
 364  
         }
 365  64
     }
 366  
 
 367  
     protected void addMuleInterceptors()
 368  
     {
 369  76
         client.getInInterceptors().add(new MuleHeadersInInterceptor());
 370  76
         client.getInFaultInterceptors().add(new MuleHeadersInInterceptor());
 371  76
         client.getOutInterceptors().add(new MuleHeadersOutInterceptor());
 372  76
         client.getOutFaultInterceptors().add(new MuleHeadersOutInterceptor());
 373  76
         client.getOutInterceptors().add(new MuleProtocolHeadersOutInterceptor());
 374  76
         client.getOutFaultInterceptors().add(new MuleProtocolHeadersOutInterceptor());
 375  76
     }
 376  
 
 377  
     protected String getMethodOrOperationName(MuleEvent event) throws DispatchException
 378  
     {
 379  
         // @TODO: Which of these *really* matter?
 380  52
         String method = (String) event.getMessage().getProperty(MuleProperties.MULE_METHOD_PROPERTY);
 381  
 
 382  52
         if (method == null)
 383  
         {
 384  6
             method = (String) event.getMessage().getProperty(CxfConstants.OPERATION);
 385  
         }
 386  
 
 387  52
         if (method == null)
 388  
         {
 389  6
             method = defaultMethodName;
 390  
         }
 391  
         
 392  52
         if (method == null && proxy)
 393  
         {
 394  6
             return "invoke";
 395  
         }
 396  
 
 397  46
         if (method == null)
 398  
         {
 399  0
             throw new DispatchException(SoapMessages.cannotInvokeCallWithoutOperation(), event.getMessage(),
 400  
                 event.getEndpoint());
 401  
         }
 402  
 
 403  46
         return method;
 404  
     }
 405  
 
 406  
     public void setEndpoint(ImmutableEndpoint endpoint)
 407  
     {
 408  76
         this.endpoint = endpoint;
 409  76
     }
 410  
 
 411  
     public void setBus(Bus bus)
 412  
     {
 413  76
         this.bus = bus;
 414  76
     }
 415  
 
 416  
     public boolean isClientProxyAvailable()
 417  
     {
 418  58
         return clientProxy != null;
 419  
     }
 420  
 
 421  
     public BindingOperationInfo getOperation(MuleEvent event) throws Exception
 422  
     {
 423  52
         String opName = getMethodOrOperationName(event);
 424  
 
 425  52
         if (opName == null)
 426  
         {
 427  0
             opName = defaultMethodName;
 428  
         }
 429  
 
 430  52
         return getOperation(opName);
 431  
     }
 432  
 
 433  
     public Method getMethod(MuleEvent event) throws Exception
 434  
     {
 435  6
         Method method = defaultMethod;
 436  6
         if (method == null)
 437  
         {
 438  0
             String opName = (String) event.getMessage().getProperty(CxfConstants.OPERATION);
 439  0
             if (opName != null) 
 440  
             {
 441  0
                 method = getMethodFromOperation(opName);
 442  
             }
 443  
 
 444  0
             if (method == null)
 445  
             {
 446  0
                 opName = (String) endpoint.getProperty(CxfConstants.OPERATION);
 447  0
                 if (opName != null) 
 448  
                 {
 449  0
                     method = getMethodFromOperation(opName);
 450  
                 }
 451  
             }
 452  
             
 453  0
             if (method == null)
 454  
             {
 455  0
                 opName = defaultMethodName;
 456  0
                 if (opName != null) 
 457  
                 {
 458  0
                     method = getMethodFromOperation(opName);
 459  
                 }
 460  
             }
 461  
         }
 462  
 
 463  6
         if (method == null)
 464  
         {
 465  0
             throw new DispatchException(CxfMessages.noOperationWasFoundOrSpecified(), event.getMessage(),
 466  
                 endpoint);
 467  
         }
 468  6
         return method;
 469  
     }
 470  
 }