KickJava   Java API By Example, From Geeks To Geeks.

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


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: ServiceObjectFactory.java,v 1.28.2.3 2005/06/17 22:33:06 tdiesler Exp $
9
package org.jboss.webservice.client;
10
11 // $Id: ServiceObjectFactory.java,v 1.28.2.3 2005/06/17 22:33:06 tdiesler Exp $
12

13 import org.jboss.logging.Logger;
14 import org.jboss.mx.util.MBeanServerLocator;
15 import org.jboss.system.server.ServerConfig;
16 import org.jboss.webservice.AxisServiceMBean;
17 import org.jboss.webservice.PortComponentInfo;
18 import org.jboss.webservice.deployment.ServiceDescription;
19 import org.jboss.webservice.metadata.jaxrpcmapping.JavaWsdlMapping;
20 import org.jboss.webservice.metadata.serviceref.HandlerMetaData;
21 import org.jboss.webservice.metadata.serviceref.InitParamMetaData;
22 import org.jboss.webservice.metadata.serviceref.PortComponentRefMetaData;
23 import org.jboss.webservice.metadata.serviceref.ServiceRefMetaData;
24 import org.jboss.webservice.util.WSDLUtilities;
25
26 import javax.management.MBeanServer JavaDoc;
27 import javax.naming.Context JavaDoc;
28 import javax.naming.Name JavaDoc;
29 import javax.naming.NamingException JavaDoc;
30 import javax.naming.RefAddr JavaDoc;
31 import javax.naming.Reference JavaDoc;
32 import javax.naming.spi.NamingManager JavaDoc;
33 import javax.naming.spi.ObjectFactory JavaDoc;
34 import javax.wsdl.Definition;
35 import javax.wsdl.Port;
36 import javax.wsdl.Service;
37 import javax.xml.namespace.QName JavaDoc;
38 import javax.xml.rpc.JAXRPCException JavaDoc;
39 import javax.xml.rpc.handler.HandlerInfo JavaDoc;
40 import java.io.BufferedReader JavaDoc;
41 import java.io.ByteArrayInputStream JavaDoc;
42 import java.io.File JavaDoc;
43 import java.io.IOException JavaDoc;
44 import java.io.InputStream JavaDoc;
45 import java.io.InputStreamReader JavaDoc;
46 import java.io.ObjectInputStream JavaDoc;
47 import java.lang.reflect.InvocationHandler JavaDoc;
48 import java.lang.reflect.Proxy JavaDoc;
49 import java.net.MalformedURLException JavaDoc;
50 import java.net.URL JavaDoc;
51 import java.net.URLClassLoader JavaDoc;
52 import java.net.URLEncoder JavaDoc;
53 import java.util.ArrayList JavaDoc;
54 import java.util.Arrays JavaDoc;
55 import java.util.HashMap JavaDoc;
56 import java.util.HashSet JavaDoc;
57 import java.util.Hashtable JavaDoc;
58 import java.util.Iterator JavaDoc;
59 import java.util.List JavaDoc;
60 import java.util.Properties JavaDoc;
61
62 /**
63  * This ServiceObjectFactory reconstructs a javax.xml.rpc.Service
64  * for a given WSDL when the webservice client does a JNDI lookup
65  * <p/>
66  * It uses the information provided by the service-ref element in application-client.xml
67  *
68  * @author Thomas.Diesler@jboss.org
69  * @since 15-April-2004
70  */

71 public class ServiceObjectFactory implements ObjectFactory JavaDoc
72 {
73    // provide logging
74
private static final Logger log = Logger.getLogger(ServiceObjectFactory.class);
75
76    /**
77     * Creates an object using the location or reference information specified.
78     * <p/>
79     *
80     * @param obj The possibly null object containing location or reference
81     * information that can be used in creating an object.
82     * @param name The name of this object relative to <code>nameCtx</code>,
83     * or null if no name is specified.
84     * @param nameCtx The context relative to which the <code>name</code>
85     * parameter is specified, or null if <code>name</code> is
86     * relative to the default initial context.
87     * @param environment The possibly null environment that is used in
88     * creating the object.
89     * @return The object created; null if an object cannot be created.
90     * @throws Exception if this object factory encountered an exception
91     * while attempting to create an object, and no other object factories are
92     * to be tried.
93     * @see NamingManager#getObjectInstance
94     * @see NamingManager#getURLContext
95     */

96    public Object JavaDoc getObjectInstance(Object JavaDoc obj, Name JavaDoc name, Context JavaDoc nameCtx, Hashtable JavaDoc environment)
97            throws Exception JavaDoc
98    {
99       Reference JavaDoc ref = (Reference JavaDoc)obj;
100
101       ServiceRefMetaData serviceRef = null;
102
103       // unmarshall the ServiceRefMetaData
104
RefAddr JavaDoc metaRefAddr = ref.get(ServiceReferenceable.SERVICE_REF_META_DATA);
105       ByteArrayInputStream JavaDoc bais = new ByteArrayInputStream JavaDoc((byte[])metaRefAddr.getContent());
106       try
107       {
108          ObjectInputStream JavaDoc ois = new ObjectInputStream JavaDoc(bais);
109          serviceRef = (ServiceRefMetaData)ois.readObject();
110          ois.close();
111       }
112       catch (IOException JavaDoc e)
113       {
114          throw new NamingException JavaDoc("Cannot unmarshall service ref meta data, cause: " + e.toString());
115       }
116
117       // reconstruct the resourceCl
118
URL JavaDoc url = new URL JavaDoc((String JavaDoc)ref.get(ServiceReferenceable.DEPLOYMENT_URL).getContent());
119       ClassLoader JavaDoc contextCL = Thread.currentThread().getContextClassLoader();
120       URLClassLoader JavaDoc resourceCl = new URLClassLoader JavaDoc(new URL JavaDoc[]{url}, contextCL);
121       serviceRef.setResourceCl(resourceCl);
122
123       // get the wsdl URL if we have one
124
URL JavaDoc wsdlURL = serviceRef.getWsdlOverride();
125       if (wsdlURL == null && serviceRef.getWsdlFile() != null)
126       {
127          String JavaDoc wsdlFile = serviceRef.getWsdlFile();
128          wsdlURL = resourceCl.findResource(wsdlFile);
129          if (wsdlURL == null)
130             throw new NamingException JavaDoc("Cannot load wsdl file '" + wsdlFile + "' from: " + url);
131       }
132
133       JavaWsdlMapping javaWsdlMapping = serviceRef.getJavaWsdlMapping();
134
135       // Find the optional ws4ee-deployment.xml
136
URL JavaDoc ws4eeMetaData = findTypeMappingMetaData(resourceCl);
137
138       ServiceImpl jaxrpcService = null;
139       Definition wsdlDefinition = null;
140       Service wsdlService = null;
141
142       if (wsdlURL != null)
143       {
144          log.debug("Create jaxrpc service for wsdl: " + wsdlURL);
145          wsdlDefinition = serviceRef.getWsdlDefinition();
146
147          // A partial wsdl may have no service element
148
// We take the service name from ther service-ref
149
QName JavaDoc serviceName = serviceRef.getServiceQName();
150
151          if (serviceName == null && wsdlDefinition.getServices().values().size() == 1)
152             serviceName = (QName JavaDoc)wsdlDefinition.getServices().keySet().iterator().next();
153
154          if (serviceName == null)
155             throw new IllegalStateException JavaDoc("Cannot obtain service name, use <service-qname> in your <service-ref>");
156
157          // Create the actual service object
158
jaxrpcService = new ServiceImpl(wsdlURL, serviceName);
159          jaxrpcService.setWsdlDefinition(wsdlDefinition);
160          jaxrpcService.setJavaWsdlMapping(javaWsdlMapping);
161
162          wsdlService = getServiceForName(wsdlDefinition, serviceName);
163       }
164       else
165       {
166          log.debug("Create jaxrpc service with no wsdl");
167          jaxrpcService = new ServiceImpl();
168          jaxrpcService.setJavaWsdlMapping(javaWsdlMapping);
169       }
170
171       // If we have a wsdlService we can setup the ServiceDesc and handler chains
172
if (wsdlService != null)
173       {
174          // Create a service description for each port-component-ref
175
PortComponentRefMetaData[] pcRefs = serviceRef.getPortComponentRefs();
176          if (pcRefs.length > 0)
177          {
178             for (int i = 0; i < pcRefs.length; i++)
179             {
180                PortComponentRefMetaData pcRef = pcRefs[i];
181                String JavaDoc seiName = pcRef.getServiceEndpointInterface();
182
183                QName JavaDoc portTypeQName = null;
184                if (javaWsdlMapping != null)
185                   portTypeQName = javaWsdlMapping.getPortTypeQNameForServiceEndpointInterface(seiName);
186
187                List JavaDoc portNames = getPortNameForType(wsdlService, portTypeQName);
188                for (Iterator JavaDoc j = portNames.iterator(); j.hasNext();)
189                {
190                   String JavaDoc portName = (String JavaDoc)j.next();
191                   ServiceDescription serviceDesc = new ServiceDescription(wsdlDefinition, javaWsdlMapping, ws4eeMetaData, portName);
192                   serviceDesc.setCallProperties(pcRef.getCallProperties());
193                   jaxrpcService.initService(serviceDesc, portName);
194                }
195             }
196          }
197          else
198          {
199             // There are zero port-component-ref elements, use the single possible port binding
200
ServiceDescription serviceDesc = new ServiceDescription(wsdlDefinition, javaWsdlMapping, ws4eeMetaData, null);
201             jaxrpcService.initService(serviceDesc, null);
202          }
203
204          // Setup the client side handler chains
205
setupHandlerChain(jaxrpcService, serviceRef, wsdlService);
206       }
207
208       // Set any default call properties
209
Properties JavaDoc callProps = serviceRef.getCallProperties();
210       jaxrpcService.setCallProperties(callProps);
211
212       // The web service client using a port-component-link, the contet is the URL to
213
// the PortComponentLinkServlet that will return the actual endpoint address
214
RefAddr JavaDoc pclinkRef = ref.get(ServiceReferenceable.PORT_COMPONENT_LINK);
215       if (pclinkRef != null)
216       {
217          String JavaDoc serviceID = (String JavaDoc)pclinkRef.getContent();
218          log.debug("Resolving port-component-link: " + serviceID);
219
220          // First try to obtain the endpoint address loacally
221
String JavaDoc targetEndpointAddress = null;
222          try
223          {
224             MBeanServer JavaDoc server = MBeanServerLocator.locateJBoss();
225             PortComponentInfo pcInfo = (PortComponentInfo)server.invoke(AxisServiceMBean.OBJECT_NAME, "getPortComponentInfo",
226                     new Object JavaDoc[]{serviceID}, new String JavaDoc[]{String JavaDoc.class.getName()});
227
228             targetEndpointAddress = pcInfo.getServiceEndpointURL();
229          }
230          catch (Exception JavaDoc ignore)
231          {
232          }
233
234          // We may be remote in the esoteric case where an appclient uses the port-comonent-link feature
235
if (targetEndpointAddress == null)
236          {
237             String JavaDoc servletPath = (String JavaDoc)ref.get(ServiceReferenceable.PORT_COMPONENT_LINK_SERVLET).getContent();
238             servletPath += "?serviceID=" + URLEncoder.encode(serviceID, "UTF-8");
239             InputStream JavaDoc is = new URL JavaDoc(servletPath).openStream();
240             BufferedReader JavaDoc br = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(is));
241             targetEndpointAddress = br.readLine();
242             is.close();
243          }
244
245          log.debug("Resolved to: " + targetEndpointAddress);
246          jaxrpcService.setTargetEndpointAddress(targetEndpointAddress);
247       }
248
249       /********************************************************
250        * Setup the Proxy that implements the service-interface
251        ********************************************************/

252
253       // load the service interface class
254
Class JavaDoc siClass = serviceRef.getServiceInterfaceClass();
255       if (javax.xml.rpc.Service JavaDoc.class.isAssignableFrom(siClass) == false)
256          throw new JAXRPCException JavaDoc("The service interface does not implement javax.xml.rpc.Service: " + siClass.getName());
257
258       // load all service endpoint interface classes
259
PortComponentRefMetaData[] pcrArray = serviceRef.getPortComponentRefs();
260       for (int i = 0; i < pcrArray.length; i++)
261       {
262          PortComponentRefMetaData pcr = pcrArray[i];
263          Class JavaDoc seiClass = pcr.getServiceEndpointInterfaceClass();
264          if (java.rmi.Remote JavaDoc.class.isAssignableFrom(seiClass) == false)
265             throw new IllegalArgumentException JavaDoc("The SEI does not implement java.rmi.Remote: " + seiClass.getName());
266
267          if (wsdlDefinition != null)
268             WSDLUtilities.endorseServiceEndpointInterface(wsdlDefinition, seiClass, javaWsdlMapping);
269       }
270
271       InvocationHandler JavaDoc handler = new ServiceProxy(jaxrpcService, siClass);
272       return (javax.xml.rpc.Service JavaDoc)Proxy.newProxyInstance(contextCL, new Class JavaDoc[]{siClass}, handler);
273    }
274
275    /**
276     * @param wsdlService
277     * @param portType
278     * @return a List of Strings. The list is never empty and never null.
279     * @throws IllegalArgumentException when no port names could be obtained.
280     */

281    private List JavaDoc getPortNameForType(javax.wsdl.Service wsdlService, QName JavaDoc portType)
282    {
283       List JavaDoc portNames = new ArrayList JavaDoc();
284
285       if (portType != null)
286       {
287          for (Iterator JavaDoc i = wsdlService.getPorts().values().iterator(); i.hasNext();)
288          {
289             Port wsdlPort = (Port)i.next();
290             if (wsdlPort.getBinding().getPortType().getQName().equals(portType))
291                portNames.add(wsdlPort.getName());
292          }
293       }
294
295       // Fallback strategy when no portType is given
296
else if (wsdlService.getPorts().values().size() == 1)
297       {
298          for (Iterator JavaDoc i = wsdlService.getPorts().values().iterator(); i.hasNext();)
299          {
300             Port wsdlPort = (Port)i.next();
301             portNames.add(wsdlPort.getName());
302          }
303       }
304
305       if (portNames.isEmpty())
306          throw new IllegalArgumentException JavaDoc("Cannot obtatin portName for binding: " + portType);
307
308       return portNames;
309    }
310
311    private javax.wsdl.Service getServiceForName(Definition wsdlDefinition, QName JavaDoc serviceName)
312    {
313       javax.wsdl.Service wsdlService = null;
314
315       if (serviceName != null)
316       {
317          wsdlService = wsdlDefinition.getService(serviceName);
318       }
319       else if (wsdlDefinition.getServices().values().size() == 1)
320       {
321          wsdlService = (javax.wsdl.Service)wsdlDefinition.getServices().values().iterator().next();
322       }
323
324       if (wsdlService == null)
325          throw new IllegalArgumentException JavaDoc("Cannot obtain WSDL service for name: " + serviceName);
326
327       return wsdlService;
328    }
329
330    /**
331     * Find optional type mapping meta data.
332     *
333     * @see {@link org.jboss.webservice.encoding.ser.MetaDataTypeDesc}
334     * <p/>
335     * It looks for "ws4ee-deployment.xml" in the WEB-INF/META-INF dir
336     */

337    private URL JavaDoc findTypeMappingMetaData(URLClassLoader JavaDoc resourceCL)
338    {
339       URL JavaDoc resourceURL = null;
340
341       // check to see if wsdd file already exists for this deployment
342
String JavaDoc dataDir = System.getProperty(ServerConfig.SERVER_DATA_DIR);
343       File JavaDoc resourceFile = new File JavaDoc(dataDir + "/wsdl/ws4ee-deployment.xml");
344       if (resourceFile.exists())
345       {
346          try
347          {
348             resourceURL = resourceFile.toURL();
349          }
350          catch (MalformedURLException JavaDoc e)
351          {
352             log.warn("Could not get url to ws4ee-deployment.xml.", e);
353          }
354       }
355
356       if (resourceURL == null)
357       {
358          String JavaDoc[] infDirs = new String JavaDoc[]{"META-INF", "WEB-INF"};
359          for (int i = 0; resourceURL == null && i < infDirs.length; i++)
360          {
361             String JavaDoc resName = infDirs[i] + "/ws4ee-deployment.xml";
362             resourceURL = resourceCL.findResource(resName);
363          }
364       }
365
366       return resourceURL;
367    }
368
369    /**
370     * Setup the handler chain(s) for this service
371     * <p/>
372     * This registers a handler chain with the client engine for every port
373     * that hat handlers configured in the <service-ref> element
374     */

375    private void setupHandlerChain(ServiceImpl jaxrpcService, ServiceRefMetaData serviceRef, javax.wsdl.Service wsdlService) throws Exception JavaDoc
376    {
377       HandlerMetaData[] handlers = serviceRef.getHandlers();
378
379       ClientEngine engine = (ClientEngine)jaxrpcService.getAxisClient();
380
381       // for every port in the wsdl for a given service
382
Iterator JavaDoc itPorts = wsdlService.getPorts().values().iterator();
383       while (itPorts.hasNext())
384       {
385          Port wsdlPort = (Port)itPorts.next();
386          String JavaDoc portName = wsdlPort.getName();
387
388          ServiceDescription serviceDesc = jaxrpcService.getServiceDescription(portName);
389
390          // no service, no handlers ;-)
391
if (serviceDesc != null)
392          {
393             HashSet JavaDoc handlerRoles = new HashSet JavaDoc();
394             ArrayList JavaDoc handlerInfos = new ArrayList JavaDoc();
395             for (int i = 0; i < handlers.length; i++)
396             {
397                HandlerMetaData hMetaData = handlers[i];
398                handlerRoles.addAll(Arrays.asList(hMetaData.getSoapRoles()));
399
400                List JavaDoc hPortNames = Arrays.asList(hMetaData.getPortNames());
401                if (hPortNames.size() == 0 || hPortNames.contains(portName))
402                {
403                   ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
404                   Class JavaDoc hClass = cl.loadClass(hMetaData.getHandlerClass());
405
406                   HashMap JavaDoc hConfig = new HashMap JavaDoc();
407                   InitParamMetaData[] params = hMetaData.getInitParams();
408                   for (int j = 0; j < params.length; j++)
409                   {
410                      InitParamMetaData param = params[j];
411                      hConfig.put(param.getParamName(), param.getParamValue());
412                   }
413
414                   QName JavaDoc[] hHeaders = hMetaData.getSoapHeaders();
415                   HandlerInfo JavaDoc info = new HandlerInfo JavaDoc(hClass, hConfig, hHeaders);
416
417                   log.debug("Adding client side handler to port '" + portName + "': " + info);
418                   handlerInfos.add(info);
419                }
420             }
421
422             // register the handlers with the client engine
423
if (handlerInfos.size() > 0)
424                engine.registerHandlerChain(portName, handlerInfos, handlerRoles);
425          }
426       }
427    }
428 }
429
Popular Tags