KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > soap > server > http > MessageRouterServlet


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2000 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "SOAP" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 2000, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package org.apache.soap.server.http;
59
60 import java.io.*;
61 import java.util.*;
62 import java.lang.reflect.*;
63 import javax.servlet.*;
64 import javax.servlet.http.*;
65 import javax.xml.parsers.*;
66 import org.w3c.dom.*;
67 import org.apache.soap.*;
68 import org.apache.soap.rpc.*;
69 import org.apache.soap.server.*;
70 import org.apache.soap.encoding.*;
71 import org.apache.soap.util.*;
72 import org.apache.soap.util.xml.*;
73 import org.apache.soap.transport.*;
74
75 /**
76  * This servlet routes messages to the appropriate listener method.
77  *
78  * @author Sanjiva Weerawarana (sanjiva@watson.ibm.com)
79  * @author Matthew J. Duftler (duftler@us.ibm.com)
80  * @author Bill Nagy (nagy@watson.ibm.com)
81  */

82 public class MessageRouterServlet extends HttpServlet {
83   /*
84     EnvelopeEditorFactory, XMLParser, and ConfigFile are
85     all server-side parameters which can be set using Servlet
86     init-parameters or WebApp context-parameters.
87     For example, you may add the following
88     description to web.xml when using Tomcat:
89
90     <context-param>
91         <param-name>EnvelopeEditorFactory</param-name>
92         <param-value>MyEnvelopeEditorFactory</param-value>
93     </context-param>
94     <context-param>
95         <param-name>XMLParser</param-name>
96         <param-value>SampleXMLDocumentBuilderFactory</param-value>
97     </context-param>
98     <context-param>
99         <param-name>ConfigFile</param-name>
100         <param-value>myconfig.xml</param-value>
101     </context-param>
102     <servlet>
103       <servlet-name>MessageRouterServlet</servlet-name>
104       <servlet-class>org.apache.soap.server.http.MessageRouterServlet</servlet-class>
105       <init-param>
106         <param-name>EnvelopeEditorFactory</param-name>
107         <param-value>MyEnvelopeEditorFactory</param-value>
108       </init-param>
109       <init-param>
110         <param-name>XMLParser</param-name>
111         <param-value>SampleXMLDocumentBuilderFactory</param-value>
112       </init-param>
113       <init-param>
114         <param-name>ConfigFile</param-name>
115         <param-value>myconfig.xml</param-value>
116       </init-param>
117     </servlet>
118
119     The servlet init-parameter values will override those of the
120     context-parameters.
121   */

122   private EnvelopeEditor editor = null;
123   private String configFilename = null;
124
125   public void init() throws ServletException {
126     ClassLoader servletClassLoader =
127       Thread.currentThread().getContextClassLoader();
128     
129     try
130     {
131       /*Make sure that we got a useful classloader; if we can not
132     even load ourselves, then at least use the classloader that
133     loaded us.*/

134       servletClassLoader.loadClass(this.getClass().getName());
135     }
136     catch(ClassNotFoundException e)
137     {
138       servletClassLoader = getClass().getClassLoader();
139     }
140
141     if (servletClassLoader == null)
142     {
143       /*This is needed because some containers use hashtable to store
144     servlet attributes and therefore they can't be null.
145     If Class.forName is passed in null as the classloader, then it
146     seems to default to the system class loader, so this should be ok.*/

147       servletClassLoader = ClassLoader.getSystemClassLoader();
148     }
149     ServletConfig servletConfig = getServletConfig();
150     ServletContext servletContext = servletConfig.getServletContext();
151     String envelopeEditorFactoryClassName =
152       servletConfig.getInitParameter(Constants.ENVELOPE_EDITOR_FACTORY);
153
154     // Is there an envelope editory factory?
155
if (envelopeEditorFactoryClassName != null) {
156       EnvelopeEditorFactory factory =
157         (EnvelopeEditorFactory)createObject(envelopeEditorFactoryClassName,
158                                             servletClassLoader);
159
160       if (factory != null) {
161         try {
162           Properties props = new Properties();
163           Enumeration enum = servletConfig.getInitParameterNames();
164
165           while (enum.hasMoreElements()) {
166             String name = (String)enum.nextElement();
167
168             if (!Constants.ENVELOPE_EDITOR_FACTORY.equals(name)
169                 && !Constants.XML_PARSER.equals(name)) {
170               props.put(name, servletConfig.getInitParameter(name));
171             }
172           }
173
174           // Put the real path into the properties, if it can be found.
175
String servletContextPath = servletContext.getRealPath("");
176
177           if (servletContextPath != null) {
178             props.put("SOAPServerContextPath", servletContextPath);
179           }
180
181           // Create an editor by calling the factory.
182
editor = factory.create(props);
183         } catch (SOAPException e) {
184           throw new ServletException("Can't create editor", e);
185         }
186       }
187     }
188
189     String tempStr = servletConfig.getInitParameter(Constants.CONFIGFILENAME);
190
191     // Is there a user-specified config filename?
192
if (tempStr != null) {
193       configFilename = tempStr;
194     }
195
196     tempStr = servletConfig.getInitParameter(Constants.XML_PARSER);
197
198     // Is there a user-specified JAXP implementation?
199
if (tempStr != null) {
200       XMLParserUtils.refreshDocumentBuilderFactory(tempStr,
201                                                    true, // namespaceAware
202
false);// validating
203
}
204
205     ServerHTTPUtils.setServletClassLoaderIntoContext(servletContext,
206                                                      servletClassLoader);
207   }
208
209   private Object createObject(String className, ClassLoader classLoader)
210     throws ServletException
211   {
212     try {
213       return classLoader.loadClass(className).newInstance();
214     } catch (ClassNotFoundException e) {
215       throw new ServletException("Can't find class named '" + className +
216                                  "'.");
217     } catch (InstantiationException e) {
218       throw new ServletException("Can't instantiate class '" + className +
219                                  "'.");
220     } catch (IllegalAccessException e) {
221       throw new ServletException("WARNING: Can't access the constructor " +
222                                  "of the class '" + className + "'.");
223     }
224   }
225
226   public void doGet (HttpServletRequest req, HttpServletResponse res)
227        throws ServletException, IOException {
228     res.setContentType("text/html");
229
230     PrintWriter out = res.getWriter ();
231
232     out.println("<html><head><title>SOAP Message Router</title></head>");
233     out.println ("<body><h1>SOAP Message Router</h1>");
234     out.println ("<p>Sorry, I don't speak via HTTP GET- you have to use");
235     out.println ("HTTP POST to talk to me.</p></body></html>");
236   }
237
238   public void doPost (HttpServletRequest req, HttpServletResponse res)
239     throws ServletException, IOException
240   {
241     ServletConfig config = getServletConfig();
242     ServletContext context = config.getServletContext ();
243     HttpSession session = req.getSession ();
244     ServiceManager serviceManager =
245       ServerHTTPUtils.getServiceManagerFromContext (context, configFilename);
246     int status;
247     DeploymentDescriptor dd = null;
248     TransportMessage sres;
249
250     SOAPContext reqCtx = new SOAPContext() ;
251     SOAPContext resCtx = new SOAPContext() ;
252
253     reqCtx.setClassLoader( ServerHTTPUtils.
254                              getServletClassLoaderFromContext(context) );
255
256     try {
257       try {
258         reqCtx.setProperty( Constants.BAG_HTTPSERVLET, this );
259         reqCtx.setProperty( Constants.BAG_HTTPSESSION, session );
260         reqCtx.setProperty( Constants.BAG_HTTPSERVLETREQUEST, req );
261         reqCtx.setProperty( Constants.BAG_HTTPSERVLETRESPONSE, res );
262
263         // get the envelope and request SOAPContext
264

265         // Generate Envelope after the incoming message is translated by
266
// EnvelopeEditor
267
// Note: XMLParser that is specified by init-param isused in
268
// this process.
269
DocumentBuilder xdb = XMLParserUtils.getXMLDocBuilder();
270         Envelope msgEnv =
271           ServerHTTPUtils.readEnvelopeFromRequest(xdb,
272                                                   req.getContentType(),
273                                                   req.getContentLength(),
274                                                   req.getInputStream(),
275                                                   editor, res, reqCtx);
276         if (msgEnv == null)
277             return;
278   
279         // get the namespace URI and and localpart of the first child
280
// element of the body of the envelope
281
Body body = msgEnv.getBody ();
282         Element e = (Element) body.getBodyEntries().elementAt (0);
283         if (e == null) {
284           throw new SOAPException (Constants.FAULT_CODE_CLIENT,
285                                    "Message envelope's body is empty!");
286         }
287         String targetID = e.getNamespaceURI ();
288         String messageName = e.getLocalName ();
289   
290         // is this a valid message?
291
dd = serviceManager.query (targetID);
292         reqCtx.setProperty( Constants.BAG_DEPLOYMENTDESCRIPTOR, dd );
293   
294         Provider provider;
295         if ( dd.getProviderType() == DeploymentDescriptor.PROVIDER_JAVA ) {
296           // Handle Java based services
297
provider = new org.apache.soap.providers.MsgJavaProvider();
298         } else if (dd.getProviderType() ==
299                    DeploymentDescriptor.PROVIDER_USER_DEFINED) {
300           // Handle user-defined providers
301
provider = ServerUtils.loadProvider(dd, reqCtx);
302         } else {
303           // Handle scripts
304
provider = new org.apache.soap.providers.MsgJavaProvider();
305         }
306
307         provider.locate( dd, msgEnv, null, messageName, targetID, reqCtx );
308         provider.invoke( reqCtx, resCtx );
309   
310         sres = new TransportMessage(null, resCtx, null);
311   
312         // apply transport hook (if root part of response is text)
313
sres.editOutgoing(editor);
314   
315         // set the response status to 200 OK and put the contents of the
316
// out stream out
317
status = res.SC_OK;
318       } catch (Throwable t) {
319         // note that we catch runtime errors too with the above .. the
320
// idea is to do a SOAP fault for everything that goes out so
321
// that if the recepient is expecting to read some XML they'll
322
// get it. If not, it doesn't hurt.
323

324         SOAPException e = null;
325         if (t instanceof SOAPException)
326           e = (SOAPException)t;
327         else
328           e = new SOAPException(Constants.FAULT_CODE_SERVER +
329                                 ".Exception:", "", t);
330   
331         Fault fault = new Fault (e);
332         fault.setFaultActorURI (req.getRequestURI ());
333         if (dd != null)
334           dd.buildFaultRouter(reqCtx).notifyListeners(fault, e);
335   
336         // the status code for faults should always be the internal
337
// server error status code (per soap spec)
338
status = res.SC_INTERNAL_SERVER_ERROR;
339   
340         resCtx = new SOAPContext(); // get rid of old one
341
Response resp = new Response(null,
342                                      null,
343                                      fault,
344                                      null,
345                                      null,
346                                      Constants.NS_URI_SOAP_ENC,
347                                      resCtx);
348
349         Envelope env = resp.buildEnvelope();
350         StringWriter sw = new StringWriter();
351         env.marshall(sw, ServerHTTPUtils.getSMRFromContext (context),
352              resp.getSOAPContext());
353         String envelopeString = sw.toString();
354         sres = new TransportMessage(envelopeString, resCtx, null);
355       }
356
357       // Generate response byte array.
358
sres.save();
359
360       // Write.
361
res.setStatus(status);
362       res.setContentType(sres.getContentType());
363       for (Enumeration headers = sres.getHeaderNames();
364            headers.hasMoreElements(); ) {
365           String name = (String)headers.nextElement();
366           res.setHeader(name, sres.getHeader(name));
367       }
368
369       res.setContentLength(sres.getContentLength());
370       OutputStream outStream = res.getOutputStream();
371       sres.writeTo(outStream);
372     }
373     catch (Exception e)
374     {
375         throw new ServletException ("Error building response envelope: " + e);
376     }
377   }
378 }
379
Popular Tags