KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > webservice > client > ServiceImpl


1 /*
2  * JBoss, the OpenSource J2EE webOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7
8 // $Id: ServiceImpl.java,v 1.17.4.11 2005/04/22 11:28:32 tdiesler Exp $
9
package org.jboss.webservice.client;
10
11 // $Id: ServiceImpl.java,v 1.17.4.11 2005/04/22 11:28:32 tdiesler Exp $
12

13 import org.jboss.axis.EngineConfiguration;
14 import org.jboss.axis.client.AxisClient;
15 import org.jboss.axis.wsdl.gen.Parser;
16 import org.jboss.logging.Logger;
17 import org.jboss.webservice.EngineConfigurationFinder;
18 import org.jboss.webservice.deployment.BeanXMLMetaData;
19 import org.jboss.webservice.deployment.ServiceDescription;
20 import org.jboss.webservice.deployment.TypeMappingDescription;
21 import org.jboss.webservice.deployment.WSDDGenerator;
22 import org.jboss.webservice.encoding.ser.MetaDataBeanDeserializerFactory;
23 import org.jboss.webservice.encoding.ser.MetaDataBeanSerializerFactory;
24 import org.jboss.webservice.metadata.jaxrpcmapping.JavaWsdlMapping;
25 import org.jboss.webservice.metadata.jaxrpcmapping.ServiceEndpointInterfaceMapping;
26
27 import javax.wsdl.Definition;
28 import javax.wsdl.Port;
29 import javax.xml.namespace.QName JavaDoc;
30 import javax.xml.rpc.Call JavaDoc;
31 import javax.xml.rpc.ServiceException JavaDoc;
32 import javax.xml.rpc.encoding.DeserializerFactory JavaDoc;
33 import javax.xml.rpc.encoding.SerializerFactory JavaDoc;
34 import javax.xml.rpc.encoding.TypeMapping JavaDoc;
35 import javax.xml.rpc.encoding.TypeMappingRegistry JavaDoc;
36 import javax.xml.rpc.handler.HandlerRegistry JavaDoc;
37 import java.io.PrintWriter JavaDoc;
38 import java.io.StringWriter JavaDoc;
39 import java.lang.reflect.Constructor JavaDoc;
40 import java.lang.reflect.InvocationHandler JavaDoc;
41 import java.lang.reflect.InvocationTargetException JavaDoc;
42 import java.lang.reflect.Proxy JavaDoc;
43 import java.net.URL JavaDoc;
44 import java.rmi.Remote JavaDoc;
45 import java.util.HashMap JavaDoc;
46 import java.util.Iterator JavaDoc;
47 import java.util.Map JavaDoc;
48 import java.util.Properties JavaDoc;
49
50 /**
51  * Lookup EngineConfiguration configure the the jaxrpc service with it.
52  *
53  * @author Thomas.Diesler@jboss.org
54  * @version $Revision: 1.17.4.11 $
55  * @since 27-April-2004
56  */

57 public class ServiceImpl extends org.jboss.axis.client.Service
58 {
59    /** @since 4.0.2 */
60    static final long serialVersionUID = -340351073471390974L;
61    // provide logging
62
private static final Logger log = Logger.getLogger(ServiceImpl.class);
63
64    // The key for the serviceDescMap if it only has one entry
65
private static final String JavaDoc DEFAULT_PORT = "DEFAULT_PORT";
66
67    // The target endpoitn address, used by port-component-links
68
private String JavaDoc targetEndpointAddress;
69    // Maps the port name to the service description generated from the wsdl and jaxrpc-mapping.xml
70
private Map JavaDoc serviceDescMap = new HashMap JavaDoc();
71    // The jaxrpc-mapping if we have one
72
private JavaWsdlMapping javaWsdlMapping;
73    // The wsdl definition if we have one
74
private Definition wsdlDefinition;
75    // The call properties from the client deployment descriptor
76
private Properties JavaDoc callProperties;
77
78    /**
79     * Constructs a new Service object - this assumes the caller will set
80     * the appropriate fields by hand rather than getting them from the
81     * WSDL.
82     */

83    public ServiceImpl()
84    {
85       super();
86    }
87
88    /**
89     * Constructs a new Service object - this assumes the caller will set
90     * the appropriate fields by hand rather than getting them from the
91     * WSDL.
92     */

93    public ServiceImpl(QName JavaDoc serviceName)
94    {
95       super(serviceName);
96       if (serviceName == null)
97          throw new IllegalStateException JavaDoc("service name cannot be null");
98    }
99
100    /**
101     * Constructs a new Service object for the service in the WSDL document
102     * pointed to by the wsdlDoc URL and serviceName parameters.
103     *
104     * @param wsdlDoc URL of the WSDL document
105     * @param serviceName Qualified name of the desired service
106     * @throws ServiceException If there's an error finding or parsing the WSDL
107     */

108    public ServiceImpl(URL JavaDoc wsdlDoc, QName JavaDoc serviceName) throws ServiceException JavaDoc
109    {
110       super(wsdlDoc, serviceName);
111       if (serviceName == null)
112          throw new IllegalStateException JavaDoc("service name cannot be null");
113    }
114
115    /**
116     * Add a service description for the client service
117     *
118     * @param serviceDesc The Service description to add
119     * @param portName The optional port name
120     */

121    public void initService(ServiceDescription serviceDesc, String JavaDoc portName) throws ServiceException JavaDoc
122    {
123       log.debug("initService: port=" + portName);
124
125       if (portName == null)
126          portName = DEFAULT_PORT;
127
128       if (wsdlDefinition != null && wsdlDefinition != serviceDesc.getWsdlDefinition())
129          throw new IllegalArgumentException JavaDoc("Cannot redefine the wsdl definition for this service");
130
131       if (javaWsdlMapping != null && javaWsdlMapping != serviceDesc.getJavaWsdlMapping())
132          throw new IllegalArgumentException JavaDoc("Cannot redefine the jaxrpc-mapping definition for this service");
133
134       if (serviceDescMap.get(portName) != null)
135          throw new IllegalArgumentException JavaDoc("A service decription for this tport is already registered");
136
137       wsdlDefinition = serviceDesc.getWsdlDefinition();
138       javaWsdlMapping = serviceDesc.getJavaWsdlMapping();
139
140       serviceDescMap.put(portName, serviceDesc);
141
142       if (log.isTraceEnabled())
143       {
144          WSDDGenerator wsddGenerator = new WSDDGenerator(serviceDesc);
145
146          StringWriter JavaDoc sw = new StringWriter JavaDoc();
147          PrintWriter JavaDoc pw = new PrintWriter JavaDoc(sw);
148          wsddGenerator.appendOperations(pw);
149          wsddGenerator.appendTypeMappings(pw);
150
151          log.trace("Service configuration:\n" + sw);
152       }
153
154       setupTypeMapping(serviceDesc);
155    }
156
157    /**
158     * J2EE components should not use the getHandlerRegistry() method.
159     * A container provider must throw a java.lang.UnsupportedOperationException from the getHandlerRegistry()
160     * method of the Service Interface. Handler support is documented in Chapter 6 Handlers.
161     */

162    public HandlerRegistry JavaDoc getHandlerRegistry()
163    {
164       throw new UnsupportedOperationException JavaDoc("Components should not use the getHandlerRegistry() method.");
165    }
166
167    /** J2EE components should not use the getTypeMappingRegistry() method.
168     * A container provider must throw a java.lang.UnsupportedOperationException from the getTypeMappingRegistry()
169     * method of the Service Interface.
170     */

171    public TypeMappingRegistry JavaDoc getTypeMappingRegistry()
172    {
173       throw new UnsupportedOperationException JavaDoc("Components should not use the getTypeMappingRegistry() method.");
174    }
175
176    /** Returns the dynamic proxy for the given SEI.
177     */

178    public Remote JavaDoc getPort(Class JavaDoc seiClass) throws ServiceException JavaDoc
179    {
180       Remote JavaDoc port = (Remote JavaDoc)super.getPort(seiClass);
181
182       // The proxy is required to support the SEI and Stub interfaces
183
InvocationHandler JavaDoc handler = new PortProxy(port, seiClass);
184       ClassLoader JavaDoc contextCL = Thread.currentThread().getContextClassLoader();
185       Class JavaDoc[] ifaces = {seiClass, org.jboss.webservice.client.Stub.class};
186       return (Remote JavaDoc)Proxy.newProxyInstance(contextCL, ifaces, handler);
187    }
188
189    /** Returns the dynamic proxy for the given SEI.
190     */

191    public Remote JavaDoc getPort(QName JavaDoc portName, Class JavaDoc seiClass) throws ServiceException JavaDoc
192    {
193       Remote JavaDoc port = (Remote JavaDoc)super.getPort(portName, seiClass);
194
195       // The proxy is required to support the SEI and Stub interfaces
196
InvocationHandler JavaDoc handler = new PortProxy(port, seiClass);
197       ClassLoader JavaDoc contextCL = Thread.currentThread().getContextClassLoader();
198       Class JavaDoc[] ifaces = {seiClass, org.jboss.webservice.client.Stub.class};
199       return (Remote JavaDoc)Proxy.newProxyInstance(contextCL, ifaces, handler);
200    }
201
202    protected Remote JavaDoc getGeneratedStub(QName JavaDoc portName, Class JavaDoc proxyInterface) throws ServiceException JavaDoc
203    {
204       // [TDI] 10-Feb-2005 Prevent use of Axis generated stubs
205
// http://jira.jboss.com/jira/browse/JBWS-105
206
Remote JavaDoc stub = super.getGeneratedStub(portName, proxyInterface);
207       if (stub != null)
208          throw new ServiceException JavaDoc("Axis generated stubs not supported in WS4EE clients: " + stub.getClass().getName());
209
210       return null;
211    }
212
213    /**
214     * Set the default call properties to use with every created call
215     *
216     * @param callProperties the properties to set
217     * @see #createCall()
218     */

219    public void setCallProperties(Properties JavaDoc callProperties)
220    {
221       this.callProperties = callProperties;
222    }
223
224
225    public ServiceDescription getServiceDescription(String JavaDoc portName)
226    {
227       ServiceDescription serviceDesc = null;
228
229       if (serviceDescMap.size() == 1 && DEFAULT_PORT.equals(serviceDescMap.keySet().iterator().next()))
230          serviceDesc = (ServiceDescription)serviceDescMap.values().iterator().next();
231
232       else if (portName != null)
233          serviceDesc = (ServiceDescription)serviceDescMap.get(portName);
234
235       if (serviceDesc == null)
236          log.warn("Cannot get ServiceDescription for: portName=" + portName + " we have " + serviceDescMap.keySet());
237
238       return serviceDesc;
239    }
240
241    public Definition getWsdlDefinition()
242    {
243       return wsdlDefinition;
244    }
245
246    public void setWsdlDefinition(Definition wsdlDefinition)
247    {
248       this.wsdlDefinition = wsdlDefinition;
249    }
250
251    public JavaWsdlMapping getJavaWsdlMapping()
252    {
253       return javaWsdlMapping;
254    }
255
256    public void setJavaWsdlMapping(JavaWsdlMapping javaWsdlMapping)
257    {
258       this.javaWsdlMapping = javaWsdlMapping;
259    }
260
261    /**
262     * Overwrite to provide a Call object that is ws4ee aware.
263     *
264     * @return Call Used for invoking the Web Service
265     * @throws javax.xml.rpc.ServiceException If there's an error
266     */

267    public Call JavaDoc createCall() throws ServiceException JavaDoc
268    {
269       CallImpl call = new CallImpl(this);
270       if (callProperties != null)
271       {
272          // Set the default call properties
273
Iterator JavaDoc keys = callProperties.keySet().iterator();
274          while (keys.hasNext())
275          {
276             String JavaDoc key = (String JavaDoc)keys.next();
277             String JavaDoc value = callProperties.getProperty(key);
278             call.setProperty(key, value);
279          }
280       }
281       return call;
282    }
283
284    /**
285     * Returns an <code>Iterator</code> for the list of
286     * <code>QName</code>s of service endpoints grouped by this
287     * service
288     * <p/>
289     * For a partial wsdl see ws-1.1 spec section
290     * 4.2.2.5 Service method use with partial WSDL
291     */

292    public Iterator JavaDoc getPorts() throws ServiceException JavaDoc
293    {
294       // This assumes that the client deploys a partial wsdl, but obtains
295
// a full wsdl using the <wsdl-override> element
296
if (wsdlService == null)
297          throw new UnsupportedOperationException JavaDoc("wsdl service is not available");
298
299       return wsdlService.getPorts().keySet().iterator();
300    }
301
302    /**
303     * Get the service name for this service.
304     */

305    public QName JavaDoc getServiceName()
306    {
307       if (serviceName != null)
308          return serviceName;
309
310       // This assumes that the client deploys a partial wsdl, but obtains
311
// a full wsdl using the <wsdl-override> element
312
if (wsdlService == null)
313          throw new UnsupportedOperationException JavaDoc("wsdl service is not available");
314
315       return wsdlService.getQName();
316    }
317
318    /**
319     * Get the AxisClient engine.
320     */

321    protected AxisClient getAxisClient()
322    {
323       if (engine == null)
324       {
325          engine = new ClientEngine(getEngineConfiguration());
326       }
327       return (AxisClient)engine;
328    }
329
330    /**
331     * Use the {@link org.jboss.webservice.EngineConfigurationFinder#getClientEngineConfiguration()}
332     * to discover the client engine configuration.
333     */

334    protected EngineConfiguration getEngineConfiguration()
335    {
336       if (config == null)
337       {
338          config = EngineConfigurationFinder.getClientEngineConfiguration();
339          if (config == null)
340             throw new IllegalStateException JavaDoc("Cannot obtain client config");
341       }
342
343       return config;
344    }
345
346    /**
347     * Turn off automatic wrapped style
348     */

349    protected Parser getParser()
350    {
351       Parser parser = super.getParser();
352       parser.setNowrap(true);
353       return parser;
354    }
355
356    /**
357     * The service may provide the target endpoint address, in case the client wsdl port
358     * does not contain a valid address. This maybe the case for ws4ee clients that use a
359     * port-component-link element.
360     */

361    protected String JavaDoc getTargetEnpointAddress()
362    {
363       return targetEndpointAddress;
364    }
365
366    public void setTargetEndpointAddress(String JavaDoc targetEndpointAddress)
367    {
368       this.targetEndpointAddress = targetEndpointAddress;
369    }
370
371    /**
372     * Get the WSDL Port for a given service portComponentLinkEndpoint interface
373     * <p/>
374     * This looks up the port from the jaxrpc-mapping
375     * before defaulting to the Axis functionality.
376     * <p/>
377     * Note, this method is not part of standard Axis.
378     *
379     * @param seiClass The service portComponentLinkEndpoint interface class
380     * @return A wsdl Port
381     * @throws javax.xml.rpc.ServiceException If there's an error
382     */

383    protected Port getWSDLPort(Class JavaDoc seiClass) throws ServiceException JavaDoc
384    {
385       // A partial wsdl may not have a service, nor a port
386
if (wsdlService == null)
387          return null;
388
389       Map JavaDoc wsdlPorts = wsdlService.getPorts();
390       if (wsdlPorts == null || wsdlPorts.size() == 0)
391          throw new ServiceException JavaDoc("Cannot obtain wsdl wsdlPorts for service: " + wsdlService.getQName());
392
393       Port wsdlPort = null;
394
395       // there is only one, so return it
396
if (wsdlPorts.values().size() == 1)
397       {
398          wsdlPort = (Port)wsdlPorts.values().iterator().next();
399          return wsdlPort;
400       }
401
402       if (javaWsdlMapping != null)
403       {
404          log.debug("Trying to get jaxrpc port mapping for: " + seiClass.getName());
405          ServiceEndpointInterfaceMapping[] seiMappings = javaWsdlMapping.getServiceEndpointInterfaceMappings();
406          for (int i = 0; wsdlPort == null && i < seiMappings.length; i++)
407          {
408             ServiceEndpointInterfaceMapping seiMapping = seiMappings[i];
409             if (seiClass.getName().equals(seiMapping.getServiceEndpointInterface()))
410             {
411                QName JavaDoc bindingName = seiMapping.getWsdlBinding();
412                Iterator JavaDoc it = wsdlPorts.values().iterator();
413                while (wsdlPort == null && it.hasNext())
414                {
415                   Port auxPort = (Port)it.next();
416                   if (auxPort.getBinding().getQName().equals(bindingName))
417                      wsdlPort = auxPort;
418                }
419             }
420          }
421       }
422
423       if (wsdlPort == null)
424       {
425          log.warn("Cannot obtain jaxrpc port mapping for: " + seiClass.getName());
426          wsdlPort = super.getWSDLPort(seiClass);
427       }
428
429       return wsdlPort;
430    }
431
432    /**
433     * Setup the type mapping for this service
434     */

435    private void setupTypeMapping(ServiceDescription serviceDesc) throws ServiceException JavaDoc
436    {
437       TypeMappingRegistry JavaDoc tmRegistry = super.getTypeMappingRegistry();
438       if (tmRegistry == null)
439          throw new IllegalStateException JavaDoc("Cannot obtain TypeMappingRegistry");
440
441       // Use the context classloader to load the user defined type
442
ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
443
444       Iterator JavaDoc it = serviceDesc.getTypMappings();
445       while (it.hasNext())
446       {
447          TypeMappingDescription typeMapping = (TypeMappingDescription)it.next();
448          QName JavaDoc typeQName = typeMapping.getTypeQName();
449          String JavaDoc javaType = typeMapping.getJavaType();
450          String JavaDoc encodingURI = typeMapping.getEncodingURI();
451          BeanXMLMetaData metaData = typeMapping.getMetaData();
452
453          TypeMapping JavaDoc tm = tmRegistry.getTypeMapping(encodingURI);
454
455          SerializerFactory serFactory = null;
456          DeserializerFactory desFactory = null;
457          try
458          {
459             // Note, the serializer/derserializer factory might not be known until we load the class
460
Class JavaDoc typeClass = typeMapping.loadJavaType(cl);
461
462             if (typeClass != null)
463             {
464                String JavaDoc serFactoryName = typeMapping.getSerializerFactoryName();
465                String JavaDoc desFactoryName = typeMapping.getDeserializerFactoryName();
466
467                if (tm.isRegistered(typeClass, typeQName) == false || typeMapping.isUserDefined())
468                {
469                   if (serFactoryName != null)
470                   {
471                      Class JavaDoc serFactoryClass = cl.loadClass(serFactoryName);
472                      if (hasQualifiedConstructor(serFactoryClass))
473                      {
474                         Constructor JavaDoc ctor = serFactoryClass.getConstructor(new Class JavaDoc[]{Class JavaDoc.class, QName JavaDoc.class});
475                         serFactory = (SerializerFactory)ctor.newInstance(new Object JavaDoc[]{typeClass, typeQName});
476
477                         // Set the TypeMappingDescription.metaData
478
if (serFactory instanceof MetaDataBeanSerializerFactory)
479                            ((MetaDataBeanSerializerFactory)serFactory).setMetaData(metaData);
480                      }
481                      else
482                      {
483                         serFactory = (SerializerFactory)serFactoryClass.newInstance();
484                      }
485                   }
486
487                   if (desFactoryName != null)
488                   {
489                      Class JavaDoc desFactoryClass = cl.loadClass(desFactoryName);
490                      if (hasQualifiedConstructor(desFactoryClass))
491                      {
492                         Constructor JavaDoc ctor = desFactoryClass.getConstructor(new Class JavaDoc[]{Class JavaDoc.class, QName JavaDoc.class});
493                         desFactory = (DeserializerFactory)ctor.newInstance(new Object JavaDoc[]{typeClass, typeQName});
494
495                         // Set the TypeMappingDescription.metaData
496
if (desFactory instanceof MetaDataBeanDeserializerFactory)
497                            ((MetaDataBeanDeserializerFactory)desFactory).setMetaData(metaData);
498                      }
499                      else
500                      {
501                         desFactory = (DeserializerFactory)desFactoryClass.newInstance();
502                      }
503                   }
504
505                   if (serFactory != null && desFactory != null)
506                   {
507                      log.debug("Register type mapping [qname=" + typeQName + ",class=" + javaType + "," + serFactoryName + "," + desFactoryName + "]");
508                      tm.register(typeClass, typeQName, serFactory, desFactory);
509                   }
510                }
511                else
512                {
513                   log.debug("Ignore type mapping [qname=" + typeQName + ",class=" + javaType + "," + serFactoryName + "," + desFactoryName + "]");
514                }
515             }
516          }
517          catch (InvocationTargetException JavaDoc e)
518          {
519             log.error("Cannot setup type mapping", e.getTargetException());
520             throw new ServiceException JavaDoc(e.getTargetException());
521          }
522          catch (Exception JavaDoc e)
523          {
524             log.error("Cannot setup type mapping", e);
525             throw new ServiceException JavaDoc(e);
526          }
527
528       }
529    }
530
531    private boolean hasQualifiedConstructor(Class JavaDoc factoryClass)
532    {
533       try
534       {
535          Constructor JavaDoc ctor = factoryClass.getConstructor(new Class JavaDoc[]{Class JavaDoc.class, QName JavaDoc.class});
536          return ctor != null;
537       }
538       catch (Exception JavaDoc ignore)
539       {
540       }
541
542       return false;
543    }
544 }
545
Popular Tags