KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > webservice > AxisService


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

13 import org.jboss.axis.MessageContext;
14 import org.jboss.axis.server.AxisServer;
15 import org.jboss.axis.utils.Admin;
16 import org.jboss.deployment.DeploymentInfo;
17 import org.jboss.logging.Logger;
18 import org.jboss.metadata.WebMetaData;
19 import org.jboss.system.ServiceMBeanSupport;
20 import org.jboss.system.server.ServerConfig;
21 import org.jboss.webservice.deployment.MetaDataRegistry;
22 import org.jboss.webservice.deployment.ServiceDescription;
23 import org.jboss.webservice.deployment.TypeMappingDescription;
24 import org.jboss.webservice.deployment.WSDDGenerator;
25 import org.jboss.webservice.metadata.jaxrpcmapping.JavaWsdlMapping;
26 import org.jboss.webservice.metadata.PortComponentMetaData;
27 import org.jboss.webservice.metadata.WebserviceDescriptionMetaData;
28 import org.jboss.webservice.server.InvokerProviderJMX;
29 import org.jboss.webservice.server.JMXInvokerEndpoint;
30 import org.jboss.webservice.server.ServerEngine;
31 import org.w3c.dom.Document JavaDoc;
32
33 import javax.management.ObjectName JavaDoc;
34 import javax.wsdl.Definition;
35 import javax.xml.parsers.DocumentBuilder JavaDoc;
36 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
37 import javax.xml.parsers.ParserConfigurationException JavaDoc;
38 import java.io.ByteArrayInputStream JavaDoc;
39 import java.io.File JavaDoc;
40 import java.io.FileWriter JavaDoc;
41 import java.io.PrintWriter JavaDoc;
42 import java.io.StringWriter JavaDoc;
43 import java.net.InetAddress JavaDoc;
44 import java.net.MalformedURLException JavaDoc;
45 import java.net.URL JavaDoc;
46 import java.net.UnknownHostException JavaDoc;
47 import java.util.HashMap JavaDoc;
48 import java.util.Iterator JavaDoc;
49 import java.util.Map JavaDoc;
50
51 /**
52  * A service that keeps track of the Axis server and client engine
53  * and can deploy/undeploy services to/from Axis using the Axis wsdd format.
54  * <p/>
55  * Internally it keeps a registry of deployed {@link PortComponentInfo} objects.
56  * The key into that registry is [deploymentName]#[port-component-name]
57  *
58  * @author Thomas.Diesler@jboss.org
59  * @jmx.mbean name="jboss.ws4ee:service=AxisService"
60  * description="Axis Service"
61  * extends="org.jboss.system.ServiceMBean"
62  * @since 15-April-2004
63  */

64 public class AxisService extends ServiceMBeanSupport
65         implements AxisServiceMBean
66 {
67    // provide logging
68
private static final Logger log = Logger.getLogger(AxisService.class);
69
70    // maps serviceID to PortComponentInfo
71
private Map JavaDoc wsRegistry = new HashMap JavaDoc();
72
73    // The axis server engine that serves all deployed web services
74
private ServerEngine axisServer;
75
76    // A registry for meta data needed by the MetaDataBean[Serializer|Deserializer]Factory
77
private MetaDataRegistry metaDataRegistry = new MetaDataRegistry();
78
79    // The webservice host name that will be used when updating the wsdl
80
private String JavaDoc webServiceHost;
81    // The webservice port that will be used when updating the wsdl
82
private int webServicePort;
83    // The webservice port that will be used when updating the wsdl
84
private int webServiceSecurePort;
85    // Whether we should always modify the soap address to the deployed endpoing location
86
private boolean alwaysModifySOAPAddress;
87    // The default invoker provider for EJB endpoints
88
private String JavaDoc invokerProviderEJB;
89    // The default invoker provider for JSE endpoints
90
private String JavaDoc invokerProviderJSE;
91
92    /**
93     * Sub-classes should override this method to provide
94     * custum 'start' logic.
95     * <p/>
96     * <p>This method is empty, and is provided for convenience
97     * when concrete service classes do not need to perform
98     * anything specific for this state change.
99     */

100    protected void startService() throws Exception JavaDoc
101    {
102       super.startService();
103    }
104
105    /**
106     * Sub-classes should override this method to provide
107     * custum 'stop' logic.
108     * <p/>
109     * <p>This method is empty, and is provided for convenience
110     * when concrete service classes do not need to perform
111     * anything specific for this state change.
112     */

113    protected void stopService() throws Exception JavaDoc
114    {
115       super.stopService();
116    }
117
118    /**
119     * @jmx.managed-attribute
120     */

121    public String JavaDoc getWebServiceHost()
122    {
123       return webServiceHost;
124    }
125
126    /**
127     * @jmx.managed-attribute
128     */

129    public int getWebServicePort()
130    {
131       return webServicePort;
132    }
133
134    /**
135     * @jmx.managed-attribute
136     */

137    public int getWebServiceSecurePort()
138    {
139       return webServiceSecurePort;
140    }
141
142    /**
143     * @jmx.managed-attribute
144     */

145    public boolean isAlwaysModifySOAPAddress()
146    {
147       return alwaysModifySOAPAddress;
148    }
149
150    /**
151     * @jmx.managed-attribute
152     */

153    public void setWebServiceHost(String JavaDoc host)
154    {
155       if ("0.0.0.0".equals(host))
156       {
157          try
158          {
159             InetAddress JavaDoc localHost = InetAddress.getLocalHost();
160             host = localHost.getHostName();
161          }
162          catch (UnknownHostException JavaDoc e)
163          {
164             log.error("Cannot map host: " + host, e);
165          }
166       }
167
168       this.webServiceHost = host;
169    }
170
171    /**
172     * @jmx.managed-attribute
173     */

174    public void setWebServicePort(int port)
175    {
176       this.webServicePort = port;
177    }
178
179    /**
180     * @jmx.managed-attribute
181     */

182    public void setWebServiceSecurePort(int port)
183    {
184       this.webServiceSecurePort = port;
185    }
186
187    /**
188     * @jmx.managed-attribute
189     */

190    public void setAlwaysModifySOAPAddress(boolean modify)
191    {
192       this.alwaysModifySOAPAddress = modify;
193    }
194
195    /**
196     * @jmx.managed-attribute
197     */

198    public String JavaDoc getInvokerProviderEJB()
199    {
200       return invokerProviderEJB;
201    }
202
203    /**
204     * @jmx.managed-attribute
205     */

206    public void setInvokerProviderEJB(String JavaDoc invokerProviderEJB)
207    {
208       this.invokerProviderEJB = invokerProviderEJB;
209    }
210
211    /**
212     * @jmx.managed-attribute
213     */

214    public String JavaDoc getInvokerProviderJSE()
215    {
216       return invokerProviderJSE;
217    }
218
219    /**
220     * @jmx.managed-attribute
221     */

222    public void setInvokerProviderJSE(String JavaDoc invokerProviderJSE)
223    {
224       this.invokerProviderJSE = invokerProviderJSE;
225    }
226
227    /**
228     * Get axis server singleton
229     *
230     * @jmx.managed-attribute
231     */

232    public AxisServer getAxisServer()
233    {
234       if (axisServer == null)
235          axisServer = new ServerEngine(EngineConfigurationFinder.getServerEngineConfiguration());
236
237       return axisServer;
238    }
239
240    /**
241     * Get MetaDataBeanSerializer/Deserializer metaData registry
242     *
243     * @jmx.managed-attribute
244     */

245    public MetaDataRegistry getMetaDataRegistry()
246    {
247       return metaDataRegistry;
248    }
249
250    /** Get port component info for a given web service id
251     *
252     * The keys into the registry are:
253     *
254     * [deploment.ear]/[deployment.?ar]#PortComponentName
255     *
256     * A client deployment may use a 'port-component-link' like:
257     *
258     * [deployment.?ar]#PortComponentName
259     *
260     * In case we don't find a direct match we try matching by
261     *
262     * key.endsWith(wsID)
263     *
264     * See CTS test: /com/sun/ts/tests/webservices/deploy/portcomplink
265     *
266     * @param wsID The web service identifier
267     * @return The port component info, or null
268     * @jmx.managed-operation
269     */

270    public PortComponentInfo getPortComponentInfo(String JavaDoc wsID)
271    {
272       PortComponentInfo pcInfo = (PortComponentInfo)wsRegistry.get(wsID);
273
274       if (pcInfo == null)
275       {
276          log.debug("No PortComponentInfo found for serviceID: " + wsID);
277          PortComponentInfo singleMatch = null;
278          Iterator JavaDoc it = wsRegistry.keySet().iterator();
279          while (it.hasNext())
280          {
281             String JavaDoc key = (String JavaDoc)it.next();
282             if (key.endsWith(wsID) && singleMatch != null)
283             {
284                log.warn("Too many possible serviceID matches: " + key);
285                return null;
286             }
287             if (key.endsWith(wsID) && singleMatch == null)
288             {
289                log.debug("Found possible match: " + key);
290                singleMatch = (PortComponentInfo)wsRegistry.get(key);
291             }
292          }
293          pcInfo = singleMatch;
294       }
295
296       return pcInfo;
297    }
298
299    /** Returns a the array of registered PortComponentInfo objects
300     *
301     * @jmx.managed-operation
302     */

303    public PortComponentInfo[] listServiceEndpointInfos()
304    {
305       PortComponentInfo[] arr = new PortComponentInfo[wsRegistry.size()];
306       wsRegistry.values().toArray(arr);
307       return arr;
308    }
309
310    /** List the registered webservices
311     *
312     * @jmx.managed-operation
313     */

314    public String JavaDoc listServiceEndpoints()
315    {
316       StringWriter JavaDoc sw = new StringWriter JavaDoc();
317       PrintWriter JavaDoc pw = new PrintWriter JavaDoc(sw);
318
319       pw.println("<table>");
320       pw.println("<tr><th>ID</th><th>Address</th></tr>");
321
322       PortComponentInfo[] pcInfoArr = listServiceEndpointInfos();
323       for (int i = 0; i < pcInfoArr.length; i++)
324       {
325          PortComponentInfo pcInfo = pcInfoArr[i];
326          String JavaDoc wsID = pcInfo.getServiceID();
327          PortComponentMetaData pcMetaData = pcInfo.getPortComponentMetaData();
328          pw.println("<tr><td>" + wsID + "</td><td>" + pcMetaData.getServiceEndpointURL() + "</td></tr>");
329       }
330       pw.println("</table>");
331       pw.close();
332
333       return sw.toString();
334    }
335
336    /**
337     * Deploy a webservice from a Axis WSDD URL
338     *
339     * @jmx.managed-operation
340     */

341    public void deployService(PortComponentInfo pcInfo) throws Exception JavaDoc
342    {
343       DeploymentInfo di = pcInfo.getDeploymentInfo();
344       PortComponentMetaData pcMetaData = pcInfo.getPortComponentMetaData();
345
346       ObjectName JavaDoc oname = pcInfo.getObjectName();
347       if (server.isRegistered(oname))
348          throw new IllegalStateException JavaDoc("Service already registerd, maybe the port-component-name is not unique: " + oname);
349
350       String JavaDoc serviceID = pcInfo.getServiceID();
351       log.debug("deployService: " + serviceID);
352
353       ServiceDescription serviceDesc = getServiceDescription(pcInfo);
354       pcInfo.setServiceDesc(serviceDesc);
355
356       String JavaDoc wsdd = generateDeploymentWSDD(pcInfo);
357       Document JavaDoc genDoc = getDocumentBuilder().parse(new ByteArrayInputStream JavaDoc(wsdd.getBytes()));
358
359       String JavaDoc deploymentName = di.getCanonicalName();
360       String JavaDoc dataDir = System.getProperty(ServerConfig.SERVER_DATA_DIR);
361       File JavaDoc wsddFile = new File JavaDoc(dataDir + "/wsdl/" + deploymentName + "/" + pcMetaData.getPortComponentName() + ".wsdd");
362       wsddFile.getParentFile().mkdirs();
363
364       FileWriter JavaDoc out = new FileWriter JavaDoc(wsddFile);
365       out.write(wsdd);
366       out.close();
367
368       log.info("WSDD published to: " + wsddFile.getCanonicalPath());
369
370       // Set the Context ClassLoader to the deployment ClassLoader, so that Axis
371
// can find the user defined types
372
ClassLoader JavaDoc ctxClassLoader = Thread.currentThread().getContextClassLoader();
373       try
374       {
375          ClassLoader JavaDoc deploymentCL = (di.metaData instanceof WebMetaData ? ((WebMetaData)di.metaData).getContextLoader() : di.ucl);
376          Thread.currentThread().setContextClassLoader(deploymentCL);
377
378          MessageContext msgContext = new MessageContext(getAxisServer());
379          new Admin().process(msgContext, genDoc.getDocumentElement());
380
381          registerBeanMetaData(serviceDesc);
382       }
383       finally
384       {
385          Thread.currentThread().setContextClassLoader(ctxClassLoader);
386       }
387
388       // Register the port component with the MBeanServer
389
PortComponent pc = new PortComponent(pcInfo);
390       server.registerMBean(pc, oname);
391
392       wsRegistry.put(serviceID, pcInfo);
393
394       String JavaDoc endpointURL = pcInfo.getServiceEndpointURL();
395       log.info("Web Service deployed: " + endpointURL);
396    }
397
398    /** Register the meta data for the MetaDataSerializer/Deserializer
399     */

400    private void registerBeanMetaData(ServiceDescription serviceDesc)
401    {
402       Iterator JavaDoc it = serviceDesc.getTypMappings();
403       while (it.hasNext())
404       {
405          TypeMappingDescription typeMapping = (TypeMappingDescription)it.next();
406          if (typeMapping.getMetaData() != null)
407             metaDataRegistry.registerTypeMappingMetaData(typeMapping);
408       }
409    }
410
411    /**
412     * Find optional type mapping meta data.
413     *
414     * @see {@link org.jboss.webservice.encoding.ser.MetaDataTypeDesc}
415     * <p/>
416     * It looks for "ws4ee-deployment.xml" in the WEB-INF/META-INF dir
417     */

418    private URL JavaDoc findTypeMappingMetaData(DeploymentInfo di)
419    {
420       URL JavaDoc resourceURL = null;
421
422       // check to see if wsdd file already exists for this deployment
423
String JavaDoc dataDir = System.getProperty(ServerConfig.SERVER_DATA_DIR);
424       File JavaDoc resourceFile = new File JavaDoc(dataDir + "/wsdl/ws4ee-deployment.xml");
425       if (resourceFile.exists())
426       {
427          try
428          {
429             resourceURL = resourceFile.toURL();
430          }
431          catch (MalformedURLException JavaDoc e)
432          {
433             log.warn("Could not get url to ws4ee-deployment.xml.", e);
434          }
435       }
436
437       if (resourceURL == null)
438       {
439          String JavaDoc infDir = (di.shortName.endsWith(".war") ? "WEB-INF" : "META-INF");
440          String JavaDoc resName = infDir + "/ws4ee-deployment.xml";
441          resourceURL = di.localCl.findResource(resName);
442       }
443
444       return resourceURL;
445    }
446
447    /**
448     * Undeploy a webservice for a given web service id
449     *
450     * @jmx.managed-operation
451     */

452    public void undeployService(String JavaDoc serviceID) throws Exception JavaDoc
453    {
454       PortComponentInfo pcInfo = getPortComponentInfo(serviceID);
455       if (pcInfo == null)
456          throw new IllegalStateException JavaDoc("Cannot find port component info for: " + serviceID);
457
458       StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
459       buffer.append("<undeployment");
460       buffer.append(" xmlns='http://xml.apache.org/axis/wsdd/'");
461       buffer.append(" xmlns:java='http://xml.apache.org/axis/wsdd/providers/java'");
462       buffer.append(" xmlns:xsi='http://www.w3.org/2000/10/XMLSchema-instance'>");
463       buffer.append(" <service name='" + serviceID + "'/>");
464       buffer.append("</undeployment>");
465
466       try
467       {
468          DocumentBuilder JavaDoc builder = getDocumentBuilder();
469          Document JavaDoc doc = builder.parse(new ByteArrayInputStream JavaDoc(buffer.toString().getBytes()));
470
471          MessageContext msgContext = new MessageContext(getAxisServer());
472          new Admin().process(msgContext, doc.getDocumentElement());
473       }
474       catch (Exception JavaDoc e)
475       {
476          log.error("Cannot unregister Axis service: " + serviceID);
477       }
478
479       // Unregister the port component from the MBeanServer
480
try
481       {
482          server.unregisterMBean(pcInfo.getObjectName());
483       }
484       catch (Exception JavaDoc e)
485       {
486          log.error("Cannot unregister port component MBean: " + serviceID);
487       }
488
489       unregisterBeanMetaData(pcInfo.getServiceDescription());
490
491       wsRegistry.remove(serviceID);
492
493       log.info("WebService undeployed: " + pcInfo.getServiceEndpointURL());
494    }
495
496    /** Unregister the meta data for the MetaDataSerializer/Deserializer
497     */

498    private void unregisterBeanMetaData(ServiceDescription serviceDesc)
499    {
500       Iterator JavaDoc it = serviceDesc.getTypMappings();
501       while (it.hasNext())
502       {
503          TypeMappingDescription typeMapping = (TypeMappingDescription)it.next();
504          if (typeMapping.getMetaData() != null)
505             metaDataRegistry.unregisterTypeMappingMetaData(typeMapping.getTypeQName());
506       }
507    }
508
509    /**
510     * Write the generated axis wsdd to the given print writer
511     */

512    private ServiceDescription getServiceDescription(PortComponentInfo pcInfo) throws Exception JavaDoc
513    {
514       DeploymentInfo di = pcInfo.getDeploymentInfo();
515       PortComponentMetaData pcMetaData = pcInfo.getPortComponentMetaData();
516       WebserviceDescriptionMetaData wsdMetaData = pcMetaData.getWebserviceDescription();
517       JavaWsdlMapping javaWsdlMapping = wsdMetaData.getJavaWsdlMapping();
518
519       String JavaDoc portName = pcMetaData.getWsdlPort().getLocalPart();
520
521       // build the ServiceDescr from wsdl + jaxrpc-mapping
522
Definition wsdlDefinition = wsdMetaData.getWsdlDefinition();
523
524       // Find the optional optional ws4ee-deployment.xml
525
URL JavaDoc ws4eeMetaData = findTypeMappingMetaData(di);
526
527       ServiceDescription serviceDesc = new ServiceDescription(wsdlDefinition, javaWsdlMapping, ws4eeMetaData, portName);
528       return serviceDesc;
529    }
530
531    /**
532     * Write the generated axis wsdd to the given print writer
533     */

534    private String JavaDoc generateDeploymentWSDD(PortComponentInfo pcInfo) throws Exception JavaDoc
535    {
536       StringWriter JavaDoc strWriter = new StringWriter JavaDoc(1024);
537       PrintWriter JavaDoc out = new PrintWriter JavaDoc(strWriter);
538
539       DeploymentInfo di = pcInfo.getDeploymentInfo();
540       PortComponentMetaData pcMetaData = pcInfo.getPortComponentMetaData();
541       ServiceDescription serviceDesc = pcInfo.getServiceDescription();
542       String JavaDoc serviceID = pcInfo.getServiceID();
543
544       WSDDGenerator wsddGenerator = new WSDDGenerator(serviceDesc);
545
546       wsddGenerator.appendHeader(out);
547       wsddGenerator.appendServiceElement(out, serviceID, "Handler");
548
549       String JavaDoc wsID = pcInfo.getServiceID();
550       out.println(" <parameter name='" + PortComponentMetaData.PARAMETER_WEBSERVICE_ID + "' value='" + wsID + "' />");
551
552       String JavaDoc ejbLink = pcMetaData.getEjbLink();
553       String JavaDoc servletLink = pcMetaData.getServletLink();
554       if (ejbLink != null)
555       {
556          out.println(" <parameter name='handlerClass' value='" + invokerProviderEJB + "' />");
557       }
558       else if (servletLink != null)
559       {
560          if (servletLink.equals(JMXInvokerEndpoint.class.getName()))
561             out.println(" <parameter name='handlerClass' value='" + InvokerProviderJMX.class.getName() + "' />");
562          else
563             out.println(" <parameter name='handlerClass' value='" + invokerProviderJSE + "' />");
564       }
565       else
566       {
567          throw new IllegalArgumentException JavaDoc("Cannot find <ejb-link> nor <servlet-link> in webservices.xml");
568       }
569
570       out.println();
571
572       // Append the operations
573
wsddGenerator.appendOperations(out);
574
575       ClassLoader JavaDoc ctxClassLoader = Thread.currentThread().getContextClassLoader();
576       try
577       {
578          ClassLoader JavaDoc deploymentCL = (di.metaData instanceof WebMetaData ? ((WebMetaData)di.metaData).getContextLoader() : di.ucl);
579          Thread.currentThread().setContextClassLoader(deploymentCL);
580
581          // Append the type mappings
582
wsddGenerator.appendTypeMappings(out);
583       }
584       finally
585       {
586          Thread.currentThread().setContextClassLoader(ctxClassLoader);
587       }
588
589       wsddGenerator.appendFooter(out);
590       out.close();
591
592       return strWriter.toString();
593    }
594
595    /**
596     * Get a namespace aware document builder
597     */

598    private DocumentBuilder JavaDoc getDocumentBuilder()
599            throws ParserConfigurationException JavaDoc
600    {
601       DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
602       factory.setNamespaceAware(true);
603       DocumentBuilder JavaDoc builder = factory.newDocumentBuilder();
604       return builder;
605    }
606 }
607
Popular Tags