View Javadoc

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