View Javadoc

1   /*
2    * $Id: JaxWsClientMessageProcessorBuilder.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.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.aegis.databinding.AegisDatabinding;
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 (wsdlLocation != null)
94          {
95              cpf.setWsdlURL(wsdlLocation);
96          }
97          
98          return cpf.create();
99      }
100 
101     private Client createClientFromJaxWsProxy()
102         throws ClassNotFoundException, NoSuchMethodException, IOException, CreateException,
103         InstantiationException, IllegalAccessException, InvocationTargetException
104     {
105         Class<?> clientCls = ClassLoaderUtils.loadClass(clientClass, getClass());
106 
107         Service s = null;
108         if (wsdlLocation != null)
109         {
110             Constructor<?> cons = clientCls.getConstructor(URL.class, QName.class);
111             ResourceManager rr = getBus().getExtension(ResourceManager.class);
112             URL url = rr.resolveResource(wsdlLocation, URL.class);
113 
114             if (url == null)
115             {
116                 URIResolver res = new URIResolver(wsdlLocation);
117 
118                 if (!res.isResolved())
119                 {
120                     throw new CreateException(CxfMessages.wsdlNotFound(wsdlLocation), this);
121                 }
122                 url = res.getURL();
123             }
124 
125             WebServiceClient clientAnn = clientCls.getAnnotation(WebServiceClient.class);
126             QName svcName = new QName(clientAnn.targetNamespace(), clientAnn.name());
127 
128             s = (Service) cons.newInstance(url, svcName);
129         }
130         else
131         {
132             s = (Service) clientCls.newInstance();
133         }
134         
135         if (port == null)
136         {
137             throw new CreateException(CxfMessages.mustSpecifyPort(), this);
138         }
139 
140         clientProxy = null;
141         if (port != null)
142         {
143             for (Method m : clientCls.getMethods())
144             {
145                 WebEndpoint we = m.getAnnotation(WebEndpoint.class);
146 
147                 if (we != null && we.name().equals(port) && m.getParameterTypes().length == 0)
148                 {
149                     clientProxy = (BindingProvider) m.invoke(s, new Object[0]);
150                     break;
151                 }
152             }
153         }
154 
155         if (clientProxy == null)
156         {
157             throw new CreateException(CxfMessages.portNotFound(port), this);
158         }
159 
160         return ClientProxy.getClient(clientProxy);
161     }
162 
163     @Override
164     protected void configureMessageProcessor(CxfOutboundMessageProcessor processor)
165     {
166         super.configureMessageProcessor(processor);
167         processor.setClientProxy(clientProxy);
168     }
169 
170     public String getClientClass()
171     {
172         return clientClass;
173     }
174 
175     public void setClientClass(String clientClass)
176     {
177         this.clientClass = clientClass;
178     }
179 
180     public String getPort()
181     {
182         return port;
183     }
184 
185     public void setPort(String port)
186     {
187         this.port = port;
188     }
189 }