View Javadoc
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.builder;
8   
9   import org.mule.api.lifecycle.CreateException;
10  import org.mule.module.cxf.CxfOutboundMessageProcessor;
11  import org.mule.module.cxf.i18n.CxfMessages;
12  import org.mule.module.cxf.support.CxfUtils;
13  
14  import java.io.IOException;
15  import java.lang.reflect.Constructor;
16  import java.lang.reflect.InvocationTargetException;
17  import java.lang.reflect.Method;
18  import java.net.URL;
19  
20  import javax.xml.namespace.QName;
21  import javax.xml.ws.BindingProvider;
22  import javax.xml.ws.Service;
23  import javax.xml.ws.WebEndpoint;
24  import javax.xml.ws.WebServiceClient;
25  
26  import org.apache.cxf.common.classloader.ClassLoaderUtils;
27  import org.apache.cxf.endpoint.Client;
28  import org.apache.cxf.frontend.ClientProxy;
29  import org.apache.cxf.jaxws.JaxWsClientFactoryBean;
30  import org.apache.cxf.resource.ResourceManager;
31  import org.apache.cxf.resource.URIResolver;
32  
33  /**
34   * Builds a JAX-WS client based {@link CxfOutboundMessageProcessor}. There 
35   * are two ways to configure the client:
36   * <ol>
37   * <li>WSDL generated client: using the CXF wsdl2java tool, you can configure
38   * this biulder using the clientClass, port and wsdlLocation property. The
39   * MessageProcessor will then use the generated client proxy to make service invocations.
40   * <li>JAX-WS service class: if the serviceClass attribute is specified, this builder
41   * will use the {@link JaxWsClientFactoryBean} from CXF to biuld a CXF Client.
42   * The MessageProcessor will then use this client instnace to make invocations.
43   * </ol>
44   * The serviceClass and clientClass attributes are mutually exclusive.
45   * @author Dan
46   *
47   */
48  public class JaxWsClientMessageProcessorBuilder extends AbstractClientMessageProcessorBuilder
49  {
50  
51      // If we have a proxy we're going to invoke it directly
52      // Since the JAX-WS proxy does extra special things for us.
53      protected BindingProvider clientProxy;
54  
55      protected String clientClass;
56  
57      protected String port;
58  
59      @Override
60      protected Client createClient() throws CreateException, Exception
61      {
62          if (clientClass != null && serviceClass != null) 
63          {
64              throw new CreateException(CxfMessages.onlyServiceOrClientClassIsValid(), this);
65          }
66          
67          if (clientClass != null)
68          {
69              return createClientFromJaxWsProxy();
70          }
71          else
72          {
73              return createClientFromFactoryBean();
74          }
75      }
76  
77      private Client createClientFromFactoryBean()
78      {
79          JaxWsClientFactoryBean cpf = new JaxWsClientFactoryBean();
80          cpf.setServiceClass(serviceClass);
81          if (databinding == null) 
82          {
83              cpf.setDataBinding(databinding);
84          }
85          cpf.setAddress(getAddress());
86          cpf.setBus(getBus());
87          cpf.setProperties(properties);
88  
89          // If there's a soapVersion defined then the corresponding bindingId will be set
90          if(soapVersion != null)
91          {
92              cpf.setBindingId(CxfUtils.getBindingIdForSoapVersion(soapVersion));
93          }
94  
95          if (wsdlLocation != null)
96          {
97              cpf.setWsdlURL(wsdlLocation);
98          }
99  
100         return cpf.create();
101     }
102 
103     private Client createClientFromJaxWsProxy()
104         throws ClassNotFoundException, NoSuchMethodException, IOException, CreateException,
105         InstantiationException, IllegalAccessException, InvocationTargetException
106     {
107         Class<?> clientCls = ClassLoaderUtils.loadClass(clientClass, getClass());
108 
109         Service s = null;
110         if (wsdlLocation != null)
111         {
112             Constructor<?> cons = clientCls.getConstructor(URL.class, QName.class);
113             ResourceManager rr = getBus().getExtension(ResourceManager.class);
114             URL url = rr.resolveResource(wsdlLocation, URL.class);
115 
116             if (url == null)
117             {
118                 URIResolver res = new URIResolver(wsdlLocation);
119 
120                 if (!res.isResolved())
121                 {
122                     throw new CreateException(CxfMessages.wsdlNotFound(wsdlLocation), this);
123                 }
124                 url = res.getURL();
125             }
126 
127             WebServiceClient clientAnn = clientCls.getAnnotation(WebServiceClient.class);
128             QName svcName = new QName(clientAnn.targetNamespace(), clientAnn.name());
129 
130             s = (Service) cons.newInstance(url, svcName);
131         }
132         else
133         {
134             s = (Service) clientCls.newInstance();
135         }
136 
137         if (port == null)
138         {
139             throw new CreateException(CxfMessages.mustSpecifyPort(), this);
140         }
141 
142         clientProxy = null;
143         if (port != null)
144         {
145             for (Method m : clientCls.getMethods())
146             {
147                 WebEndpoint we = m.getAnnotation(WebEndpoint.class);
148 
149                 if (we != null && we.name().equals(port) && m.getParameterTypes().length == 0)
150                 {
151                     clientProxy = (BindingProvider) m.invoke(s, new Object[0]);
152                     break;
153                 }
154             }
155         }
156 
157         if (clientProxy == null)
158         {
159             throw new CreateException(CxfMessages.portNotFound(port), this);
160         }
161 
162         return ClientProxy.getClient(clientProxy);
163     }
164 
165     @Override
166     protected void configureMessageProcessor(CxfOutboundMessageProcessor processor)
167     {
168         super.configureMessageProcessor(processor);
169         processor.setClientProxy(clientProxy);
170     }
171 
172     public String getClientClass()
173     {
174         return clientClass;
175     }
176 
177     public void setClientClass(String clientClass)
178     {
179         this.clientClass = clientClass;
180     }
181 
182     public String getPort()
183     {
184         return port;
185     }
186 
187     public void setPort(String port)
188     {
189         this.port = port;
190     }
191 }