View Javadoc

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