KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > rift > coad > lib > webservice > WebServiceWrapper


1 /*
2  * CoadunationLib: The coaduntion implementation library.
3  * Copyright (C) 2006 Rift IT Contracting
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *
19  * WebServiceWrapper.java
20  *
21  * The web service wrapper responsible for wrapping the SOAP web service
22  * information.
23  */

24
25 // package paths
26
package com.rift.coad.lib.webservice;
27
28 // java imports
29
import java.io.ByteArrayOutputStream JavaDoc;
30 import java.io.ByteArrayInputStream JavaDoc;
31 import java.io.File JavaDoc;
32 import java.io.FileInputStream JavaDoc;
33 import java.io.InputStream JavaDoc;
34 import java.lang.ClassLoader JavaDoc;
35 import java.net.InetAddress JavaDoc;
36 import java.util.Iterator JavaDoc;
37 import java.util.Map JavaDoc;
38 import java.util.Vector JavaDoc;
39 import java.util.Set JavaDoc;
40 import java.util.regex.Matcher JavaDoc;
41 import java.util.regex.Pattern JavaDoc;
42 import javax.xml.namespace.QName JavaDoc;
43 import java.lang.reflect.Method JavaDoc;
44 import javax.naming.InitialContext JavaDoc;
45 import javax.transaction.Status JavaDoc;
46 import javax.transaction.UserTransaction JavaDoc;
47
48
49 // w3c imports
50
import org.w3c.dom.Document JavaDoc;
51
52 // logging import
53
import org.apache.log4j.Logger;
54
55 // ibm imports
56
import com.ibm.wsdl.OperationImpl;
57
58 // jaxb imports
59
import javax.xml.soap.MimeHeaders JavaDoc;
60
61 // axis imports
62
import org.apache.axis.AxisFault;
63 import org.apache.axis.AxisEngine;
64 import org.apache.axis.Constants;
65 import org.apache.axis.Message;
66 import org.apache.axis.MessageContext;
67 import org.apache.axis.constants.Scope;
68 import org.apache.axis.description.ServiceDesc;
69 import org.apache.axis.handlers.soap.SOAPService;
70 import org.apache.axis.message.SOAPEnvelope;
71 import org.apache.axis.message.SOAPFault;
72 import org.apache.axis.providers.java.RPCProvider;
73 import org.apache.axis.transport.http.NonBlockingBufferedInputStream;
74 import org.apache.axis.server.AxisServer;
75 import org.apache.axis.utils.ClassUtils;
76 import org.apache.axis.utils.Messages;
77 import org.apache.axis.utils.XMLUtils;
78 import org.apache.axis.wsdl.gen.Parser;
79 import org.apache.axis.wsdl.symbolTable.SymbolTable;
80 import org.apache.axis.wsdl.symbolTable.BaseType;
81 import org.apache.axis.wsdl.symbolTable.BindingEntry;
82
83 // coadunation imports
84
import com.rift.coad.lib.configuration.Configuration;
85 import com.rift.coad.lib.configuration.ConfigurationFactory;
86 import com.rift.coad.lib.deployment.WebServiceInfo;
87 import com.rift.coad.lib.deployment.DeploymentLoader;
88 import com.rift.coad.lib.httpd.HttpDaemon;
89 import com.rift.coad.lib.httpd.MimeTypes;
90 import com.rift.coad.lib.thirdparty.axis.AxisManager;
91 import com.rift.coad.lib.thirdparty.axis.AxisException;
92
93 /**
94  * The web service wrapper responsible for wrapping the SOAP web service
95  * information.
96  *
97  * @author Brett Chaldecott
98  */

99 public class WebServiceWrapper {
100     
101     // the class log variable
102
protected Logger log =
103             Logger.getLogger(WebServiceWrapper.class.getName());
104     
105     // class constants
106
private final static String JavaDoc PARSER_PATTERN =
107             "address[\\s]+location=\"[a-z0-9://_-]*\"";
108     private final static String JavaDoc SERVICE_END_POINT_FORMAT =
109             "address location=\"http://%s:%d%s\"";
110     private final static String JavaDoc URL_FORMAT =
111             "http://%s:%d%s";
112     private final static String JavaDoc HOST = "host";
113     private final static String JavaDoc PORT = "port";
114     private final static String JavaDoc TRANSPORT_NAME = "SimpleHTTP";
115     
116     
117     // the classes member variables
118
private String JavaDoc serviceEndPoint = null;
119     private String JavaDoc url = null;
120     private String JavaDoc path = null;
121     private String JavaDoc role = null;
122     private SOAPService service = null;
123     private ClassLoader JavaDoc classLoader = null;
124     private boolean transaction = false;
125     private InitialContext JavaDoc context = null;
126     private UserTransaction JavaDoc ut = null;
127     
128     /**
129      * Creates a new instance of WebServiceWrapper.
130      *
131      * @param webServiceInfo The reference to the web service information.
132      * @param deploymentLoader The object responsible for loading a deployment
133      * file.
134      * @exception WebServiceException
135      */

136     public WebServiceWrapper(WebServiceInfo webServiceInfo,
137             DeploymentLoader deploymentLoader)
138             throws WebServiceException {
139         
140         try {
141             Configuration config = ConfigurationFactory.getInstance().
142                     getConfig(WebServiceWrapper.class);
143             context = new InitialContext JavaDoc();
144             
145             String JavaDoc host = config.getString(HOST,
146                     InetAddress.getLocalHost().getCanonicalHostName());
147             int port = (int)config.getLong(PORT,HttpDaemon.DEFAULT_PORT);
148             
149             path = webServiceInfo.getPath();
150             role = webServiceInfo.getRole();
151             serviceEndPoint = String.format(
152                     SERVICE_END_POINT_FORMAT,host,port,path);
153             url = String.format(URL_FORMAT,host,port,path);
154             
155             // retrieve a reverence to the axis engine
156
AxisEngine engine = AxisManager.getInstance().getServer();
157             
158             // test the class
159
deploymentLoader.getClass(webServiceInfo.getClassName());
160             
161             // try different handlers
162
service = new SOAPService(new WebServiceInvoker(
163                     deploymentLoader.getClassLoader()));
164             
165             service.setName(webServiceInfo.getClassName());
166             service.setOption(RPCProvider.OPTION_CLASSNAME,
167                     webServiceInfo.getClassName());
168             service.setOption(RPCProvider.OPTION_ALLOWEDMETHODS, "*");
169             service.setOption(RPCProvider.OPTION_SCOPE,
170                     Scope.DEFAULT.getName());
171             
172             // validate
173
String JavaDoc wsdlPath = deploymentLoader.getTmpDir().getAbsolutePath() +
174                     File.separator +
175                     webServiceInfo.getWSDLPath();
176             validate(wsdlPath,deploymentLoader.getClassLoader().loadClass(
177                     webServiceInfo.getClassName()));
178             
179             // wsdl parameters
180
ServiceDesc serviceDesc = service.getServiceDescription();
181             serviceDesc.setWSDLFile(wsdlPath);
182             
183             service.setEngine(engine);
184             service.init();
185             
186             // set the class loader
187
classLoader = deploymentLoader.getClassLoader();
188             
189             // set the class loader
190
ClassUtils.setClassLoader(webServiceInfo.getClassName(),
191                     deploymentLoader.getClassLoader());
192             
193             transaction = webServiceInfo.getTransaction();
194             if (transaction) {
195                 ut = (UserTransaction JavaDoc)context.lookup(
196                         "java:comp/UserTransaction");
197             }
198             
199         } catch (Exception JavaDoc ex) {
200             throw new WebServiceException(
201                     "Failed to initialize the web service : " + ex.getMessage()
202                     ,ex);
203         }
204     }
205     
206     
207     /**
208      * This method returns the path to the web service.
209      *
210      * @return The string containing the path to the web service.
211      */

212     public String JavaDoc getPath() {
213         return path;
214     }
215     
216     
217     /**
218      * This method returns the role of the web service.
219      *
220      * @return The string containing the role information.
221      */

222     public String JavaDoc getRole() {
223         return role;
224     }
225     
226     
227     /**
228      * This method return the reference to the soap service.
229      *
230      * @return The reference to the soap service.
231      */

232     public SOAPService getService() {
233         return service;
234     }
235     
236     
237     /**
238      * This method returns the class loader that can be used to load the service.
239      *
240      * @return The reference to the class loader.
241      */

242     public ClassLoader JavaDoc getClassLoader() {
243         return classLoader;
244     }
245     
246     
247     /**
248      * This method returns a string containing the genreated WSDL
249      *
250      * @return String The string containing the wsdl.
251      * @exception WebServiceException
252      */

253     public String JavaDoc generateWSDL() throws
254             WebServiceException {
255         // setup the axis engine
256
MessageContext msgContext = null;
257         try {
258             msgContext = setupContext();
259             AxisServer engine = AxisManager.getInstance().getServer();
260             engine.generateWSDL(msgContext);
261             Document JavaDoc doc = (Document JavaDoc) msgContext.getProperty("WSDL");
262             XMLUtils.normalize(doc.getDocumentElement());
263             String JavaDoc wsdl = XMLUtils.PrettyDocumentToString(doc);
264             Pattern JavaDoc pattern = Pattern.compile(PARSER_PATTERN,
265                     Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
266             return pattern.matcher(wsdl).replaceFirst(serviceEndPoint);
267         } catch (WebServiceException ex) {
268             throw ex;
269         } catch (AxisException ex) {
270             throw new WebServiceException(
271                     "Failed to retrieve a valid axis reference : " +
272                     ex.getMessage(),ex);
273         } catch (Exception JavaDoc ex) {
274             processException(msgContext,ex);
275         }
276         // this statement will never get reached as the process exception will
277
// always throw, but to prevent the compiler from complaining it is
278
// put here.
279
return null;
280     }
281     
282     
283     /**
284      * This message takes a string message block and returns a string message
285      * block.
286      *
287      * @return The string result.
288      * @param message The message to process.
289      * @exception WebServiceException
290      */

291     public String JavaDoc processRequest(String JavaDoc message) throws WebServiceException {
292         return processRequest(new ByteArrayInputStream JavaDoc(message.getBytes()),
293                 new MimeHeaders JavaDoc());
294     }
295     
296     
297     /**
298      * This method process the input stream passed to it and returns a string
299      * message.
300      *
301      * @return An XML string result of the request.
302      * @param in The input stream containing the message to process.
303      * @param headers The headers to process.
304      * @exception WebServiceException
305      */

306     public String JavaDoc processRequest(InputStream JavaDoc in, MimeHeaders JavaDoc headers) throws
307             WebServiceException {
308         MessageContext msgContext = null;
309         boolean ownTransaction = false;
310         try {
311             if (transaction &&
312                     (ut.getStatus() == Status.STATUS_NO_TRANSACTION)) {
313                 ut.begin();
314                 ownTransaction = true;
315             }
316             msgContext = setupContext();
317             AxisServer engine = AxisManager.getInstance().getServer();
318             NonBlockingBufferedInputStream inputStream = new
319                 NonBlockingBufferedInputStream();
320             inputStream.setInputStream(in);
321             
322             // setup a message request
323
Message requestMsg = new Message(inputStream,false,headers);
324             msgContext.setRequestMessage(requestMsg);
325             
326             // invoke the request
327
engine.invoke(msgContext);
328             
329             // retrieve the result
330
Message responseMsg = msgContext.getResponseMessage();
331             ByteArrayOutputStream JavaDoc output = new ByteArrayOutputStream JavaDoc();
332             responseMsg.writeTo(output);
333             output.flush();
334             if (ownTransaction) {
335                 ut.commit();
336                 ownTransaction = false;
337             }
338             return output.toString();
339         } catch (WebServiceException ex) {
340             throw ex;
341         } catch (Exception JavaDoc ex) {
342             processException(msgContext,ex);
343         } finally {
344             if (ownTransaction) {
345                 try {
346                     if (ut.getStatus() == Status.STATUS_ACTIVE) {
347                         ut.rollback();
348                     }
349                 } catch (Exception JavaDoc ex2) {
350                     log.error("Failed to rollback the changes : " +
351                             ex2.getMessage(),ex2);
352                 }
353             }
354         }
355         
356         // this statement will never get reached as the process exception will
357
// always throw, but to prevent the compiler from complaining it is
358
// put here.
359
return null;
360     }
361     
362     /**
363      * This method validates the WSDL file
364      *
365      * @param wsdlPath The path to the wsdl file to perform the validation for.
366      * @param ref The reference to the class to validate.
367      * @exception WebServiceException
368      */

369     private void validate(String JavaDoc wsdlPath,Class JavaDoc ref) throws WebServiceException {
370         try {
371             // TODO: Improve WSDL validation to check more than just the operation names
372
// This will be done at a later date when it becomes a problem
373

374             Parser parser = new Parser();
375             parser.run(wsdlPath);
376             Set JavaDoc operations = getOpertations(parser);
377             Method JavaDoc[] methods = ref.getDeclaredMethods();
378             for (Iterator JavaDoc iter = operations.iterator(); iter.hasNext();) {
379                 OperationImpl operation = (OperationImpl)iter.next();
380                 boolean found = false;
381                 for (int index = 0; index < methods.length; index++) {
382                     if (methods[index].getName().equals(operation.getName())) {
383                         found = true;
384                     }
385                 }
386                 if (!found) {
387                     throw new WebServiceException("The operation [" +
388                             operation.getName() + "] not found on [" +
389                             ref.getName() + "]");
390                 }
391             }
392         } catch (WebServiceException ex) {
393             throw ex;
394         } catch (Exception JavaDoc ex) {
395             log.error("Validation on [" + wsdlPath + "] failed : " +
396                     ex.getMessage(),ex);
397             throw new WebServiceException("Validation on [" + wsdlPath
398                     + "] failed : " + ex.getMessage(),ex);
399         }
400     }
401     
402     
403     /**
404      * This method returns the list of operations on a wsdl interface.
405      *
406      * @return The set containing the list of operations.
407      * @param parser The reference to the parser
408      */

409     private Set JavaDoc getOpertations(Parser parser) throws WebServiceException {
410         SymbolTable symbolTable = parser.getSymbolTable();
411         Map JavaDoc index = symbolTable.getHashMap();
412         for (Iterator JavaDoc iter = index.keySet().iterator(); iter.hasNext();) {
413             QName JavaDoc key = (QName JavaDoc)iter.next();
414             Object JavaDoc value = index.get(key);
415             if (value instanceof Vector JavaDoc) {
416                 Vector JavaDoc list = (Vector JavaDoc)value;
417                 for (int count = 0; count < list.size(); count++) {
418                     Object JavaDoc listValue = list.get(count);
419                     if (listValue instanceof BindingEntry) {
420                         BindingEntry entry = (BindingEntry)listValue;
421                         return entry.getOperations();
422                     }
423                 }
424             }
425         }
426         throw new WebServiceException(
427                 "There are no operations defined for this wsdl file");
428     }
429     
430     
431     /**
432      * This method setups the message context
433      *
434      * @returns A message context.
435      * @exception WebServiceException
436      */

437     private MessageContext setupContext() throws WebServiceException {
438         try {
439             // setup the axis engine
440
AxisServer engine = AxisManager.getInstance().getServer();
441             MessageContext msgContext = new MessageContext(engine);
442             msgContext.setTransportName(TRANSPORT_NAME);
443             msgContext.setProperty(MessageContext.TRANS_URL, url);
444             msgContext.setProperty(Constants.MC_REALPATH,path);
445             msgContext.setProperty(Constants.MC_RELATIVE_PATH,path);
446             msgContext.setService(service);
447             return msgContext;
448         } catch (Exception JavaDoc ex) {
449             log.error("Failed to setup the message context : " +
450                     ex.getMessage(),ex);
451             throw new WebServiceException(
452                     "Failed to setup the message context : " + ex.getMessage(),
453                     ex);
454         }
455     }
456     
457     
458     /**
459      * This method handles the exceptions generated by axis generically.
460      *
461      * @param msgContext The message context.
462      * @param ex The exception to throw
463      */

464     private void processException(MessageContext msgContext,Exception JavaDoc ex) throws
465             WebServiceException {
466         try {
467             // check that the message context has been set
468
if (msgContext == null) {
469                 throw new WebServiceException("Failed to process request : " +
470                         ex.getMessage(),ex);
471             }
472             
473             // handle the axis fault
474
AxisFault af;
475             if (ex instanceof AxisFault) {
476                 af = (AxisFault) ex;
477                 log.debug(Messages.getMessage("serverFault00"), af);
478             } else {
479                 af = AxisFault.makeFault(ex);
480             }
481             
482             // There may be headers we want to preserve in the
483
// response message - so if it's there, just add the
484
// FaultElement to it. Otherwise, make a new one.
485
Message responseMsg = msgContext.getResponseMessage();
486             if (responseMsg == null) {
487                 responseMsg = new Message(af);
488                 responseMsg.setMessageContext(msgContext);
489             } else {
490                 SOAPEnvelope env = responseMsg.getSOAPEnvelope();
491                 env.clearBody();
492                 env.addBodyElement(new SOAPFault((AxisFault) ex));
493             }
494             ByteArrayOutputStream JavaDoc output = new ByteArrayOutputStream JavaDoc();
495             responseMsg.writeTo(output);
496             output.flush();
497             
498             // throw an exception with the xml content wrapped properly
499
throw new WebServiceException(output.toString(),MimeTypes.XML);
500         } catch (WebServiceException ex2) {
501             throw ex2;
502         } catch (Exception JavaDoc ex2) {
503             log.error("Failed to process the exception : " +
504                     ex2.getMessage(),ex2);
505             throw new WebServiceException(
506                     "Failed to process the exception : " + ex2.getMessage(),
507                     ex2);
508         }
509     }
510 }
511
Popular Tags