KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > axis > transport > http > AxisServlet


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2001-2003 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 "Axis" 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. For more
52  * information on the Apache Software Foundation, please see
53  * <http://www.apache.org/>.
54  */

55
56 package org.jboss.axis.transport.http;
57
58 import java.io.ByteArrayInputStream JavaDoc;
59 import java.io.File JavaDoc;
60 import java.io.IOException JavaDoc;
61 import java.io.InputStream JavaDoc;
62 import java.io.PrintWriter JavaDoc;
63 import java.net.HttpURLConnection JavaDoc;
64 import java.util.ArrayList JavaDoc;
65 import java.util.Enumeration JavaDoc;
66 import java.util.Iterator JavaDoc;
67 import java.util.StringTokenizer JavaDoc;
68
69 import javax.servlet.ServletContext JavaDoc;
70 import javax.servlet.ServletException JavaDoc;
71 import javax.servlet.http.HttpServletRequest JavaDoc;
72 import javax.servlet.http.HttpServletResponse JavaDoc;
73 import javax.xml.soap.MimeHeader JavaDoc;
74 import javax.xml.soap.MimeHeaders JavaDoc;
75 import javax.xml.soap.SOAPException JavaDoc;
76
77 import org.jboss.axis.AxisEngine;
78 import org.jboss.axis.AxisFault;
79 import org.jboss.axis.ConfigurationException;
80 import org.jboss.axis.Constants;
81 import org.jboss.axis.Message;
82 import org.jboss.axis.MessageContext;
83 import org.jboss.axis.MessagePart;
84 import org.jboss.axis.description.OperationDesc;
85 import org.jboss.axis.description.ServiceDesc;
86 import org.jboss.axis.handlers.soap.SOAPService;
87 import org.jboss.axis.security.servlet.ServletSecurityProvider;
88 import org.jboss.axis.utils.JavaUtils;
89 import org.jboss.axis.utils.Messages;
90 import org.jboss.axis.utils.XMLUtils;
91 import org.jboss.logging.Logger;
92 import org.w3c.dom.Document JavaDoc;
93 import org.w3c.dom.Element JavaDoc;
94
95 /**
96  * @author Doug Davis (dug@us.ibm.com)
97  * @author Steve Loughran
98  */

99 public class AxisServlet extends AxisServletBase
100 {
101
102    private static Logger log = Logger.getLogger(AxisServlet.class.getName());
103
104    /**
105     * this log is for timing
106     */

107    private static Logger tlog = Logger.getLogger(Constants.TIME_LOG_CATEGORY);
108
109    public static final String JavaDoc INIT_PROPERTY_TRANSPORT_NAME = "transport.name";
110
111    public static final String JavaDoc INIT_PROPERTY_USE_SECURITY = "use-servlet-security";
112    public static final String JavaDoc INIT_PROPERTY_ENABLE_LIST = "axis.enableListQuery";
113
114    public static final String JavaDoc INIT_PROPERTY_JWS_CLASS_DIR = "axis.jws.servletClassDir";
115
116    // These have default values.
117
private String JavaDoc transportName;
118
119    private ServletSecurityProvider securityProvider = null;
120
121    /**
122     * Cached path to JWS output directory
123     */

124    private String JavaDoc jwsClassDir = null;
125
126    protected String JavaDoc getJWSClassDir()
127    {
128       return jwsClassDir;
129    }
130
131
132    /**
133     * create a new servlet instance
134     */

135    public AxisServlet()
136    {
137    }
138
139    /**
140     * Initialization method.
141     */

142    public void init()
143    {
144       super.init();
145       ServletContext JavaDoc context = getServletConfig().getServletContext();
146
147
148       log.debug("In servlet init");
149
150       transportName = getOption(context,
151               INIT_PROPERTY_TRANSPORT_NAME,
152               HTTPTransport.DEFAULT_TRANSPORT_NAME);
153
154       if (JavaUtils.isTrueExplicitly(getOption(context, INIT_PROPERTY_USE_SECURITY, null)))
155       {
156          securityProvider = new ServletSecurityProvider();
157       }
158
159       jwsClassDir = getOption(context, INIT_PROPERTY_JWS_CLASS_DIR, null);
160
161       /**
162        * There are DEFINATE problems here if
163        * getHomeDir and/or getDefaultJWSClassDir return null
164        * (as they could with WebLogic).
165        * This needs to be reexamined in the future, but this
166        * should fix any NPE's in the mean time.
167        */

168       if (jwsClassDir != null)
169       {
170          if (getHomeDir() != null)
171          {
172             jwsClassDir = getHomeDir() + jwsClassDir;
173          }
174       }
175       else
176       {
177          jwsClassDir = getDefaultJWSClassDir();
178       }
179    }
180
181
182    /**
183     * Process GET requests. This includes handoff of pseudo-SOAP requests
184     *
185     * @param request request in
186     * @param response request out
187     * @throws ServletException
188     * @throws IOException
189     */

190    public void doGet(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response)
191            throws ServletException JavaDoc, IOException JavaDoc
192    {
193       log.debug("Enter: doGet()");
194
195       PrintWriter JavaDoc writer = response.getWriter();
196
197       try
198       {
199          AxisEngine engine = getEngine();
200          ServletContext JavaDoc servletContext =
201                  getServletConfig().getServletContext();
202
203          String JavaDoc pathInfo = request.getPathInfo();
204          String JavaDoc realpath = servletContext.getRealPath(request.getServletPath());
205          if (realpath == null)
206          {
207             realpath = request.getServletPath();
208          }
209
210          boolean wsdlRequested = false;
211          boolean hasParameters = request.getParameterNames().hasMoreElements();
212
213          //JWS pages are special; they are the servlet path and there
214
//is no pathinfo...we map the pathinfo to the servlet path to keep
215
//it happy
216
boolean isJWSPage = request.getRequestURI().endsWith(".jws");
217          if (isJWSPage)
218          {
219             pathInfo = request.getServletPath();
220          }
221
222          // check first if we are doing WSDL or a list operation
223
String JavaDoc queryString = request.getQueryString();
224          if (queryString != null)
225          {
226             if (queryString.equalsIgnoreCase("wsdl"))
227             {
228                wsdlRequested = true;
229             }
230          }
231
232          boolean hasNoPath = (pathInfo == null || pathInfo.equals(""));
233          if (!wsdlRequested && hasNoPath)
234          {
235             // If the user requested the servlet (i.e. /axis/servlet/AxisServlet)
236
// with no service name, present the user with a list of deployed
237
// services to be helpful
238
// Don't do this if we are doing WSDL or list.
239
reportAvailableServices(response, writer, request);
240          }
241          else if (realpath != null)
242          {
243             // We have a pathname, so now we perform WSDL or list operations
244

245             // get message context w/ various properties set
246
MessageContext msgContext = createMessageContext(engine, request, response);
247
248             String JavaDoc url = request.getRequestURL().toString();
249
250             msgContext.setProperty(MessageContext.TRANS_URL, url);
251
252             if (wsdlRequested)
253             {
254                // Do WSDL generation
255
processWsdlRequest(msgContext, response, writer);
256             }
257             else if (hasParameters)
258             {
259                // If we have ?method=x&param=y in the URL, make a stab
260
// at invoking the method with the parameters specified
261
// in the URL
262

263                processMethodRequest(msgContext, request, response, writer);
264
265             }
266             else
267             {
268
269                // See if we can locate the desired service. If we
270
// can't, return a 404 Not Found. Otherwise, just
271
// print the placeholder message.
272

273                String JavaDoc serviceName;
274                if (pathInfo.startsWith("/"))
275                {
276                   serviceName = pathInfo.substring(1);
277                }
278                else
279                {
280                   serviceName = pathInfo;
281                }
282
283                SOAPService s = engine.getService(serviceName);
284                if (s == null)
285                {
286                   //no service: report it
287
if (isJWSPage)
288                   {
289                      reportCantGetJWSService(request, response, writer);
290                   }
291                   else
292                   {
293                      reportCantGetAxisService(request, response, writer);
294                   }
295
296                }
297                else
298                {
299                   //print a snippet of service info.
300
reportServiceInfo(response, writer, s, serviceName);
301                }
302             }
303          }
304          else
305          {
306             // We didn't have a real path in the request, so just
307
// print a message informing the user that they reached
308
// the servlet.
309

310             response.setContentType("text/html");
311             writer.println("<html><h1>Axis HTTP Servlet</h1>");
312             writer.println(Messages.getMessage("reachedServlet00"));
313
314             writer.println("<p>" +
315                     Messages.getMessage("transportName00",
316                             "<b>" + transportName + "</b>"));
317             writer.println("</html>");
318          }
319       }
320       catch (AxisFault fault)
321       {
322          reportTrouble(fault, response, writer);
323       }
324       catch (Exception JavaDoc e)
325       {
326          reportTrouble(e, response, writer);
327       }
328       finally
329       {
330          // Make sure the MessageContext is removed from the calling ThreadLocal
331
AxisEngine.setCurrentMessageContext(null);
332
333          writer.close();
334          log.debug("Exit: doGet()");
335       }
336    }
337
338    /**
339     * when we get an exception or an axis fault in a GET, we handle
340     * it almost identically: we go 'something went wrong', set the response
341     * code to 500 and then dump info. But we dump different info for an axis fault
342     * or subclass thereof.
343     *
344     * @param exception what went wrong
345     * @param response current response
346     * @param writer open writer to response
347     */

348    protected void reportTrouble(Exception JavaDoc exception, HttpServletResponse JavaDoc response, PrintWriter JavaDoc writer)
349    {
350       response.setContentType("text/html");
351       response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
352
353       setupHTMLResponseHeader(response, writer);
354
355       writer.println("<h2>" + Messages.getMessage("error00") + "</h2>");
356       writer.println("<p>" + Messages.getMessage("somethingWrong00") + "</p>");
357
358       if (exception instanceof AxisFault)
359       {
360          AxisFault fault = (AxisFault)exception;
361          processAxisFault(fault);
362          writeFault(writer, fault);
363       }
364       else
365       {
366          logException(exception);
367          writer.println("<pre>" + exception + "<br>");
368          //dev systems only give fault dumps
369
if (isDevelopment())
370          {
371             writer.println(JavaUtils.stackToString(exception));
372          }
373          writer.println("</pre>");
374       }
375    }
376
377    protected void setupHTMLResponseHeader(HttpServletResponse JavaDoc response, PrintWriter JavaDoc writer)
378    {
379    }
380
381    /**
382     * routine called whenever an axis fault is caught; where they
383     * are logged and any other business. The method may modify the fault
384     * in the process
385     *
386     * @param fault what went wrong.
387     */

388    protected void processAxisFault(AxisFault fault)
389    {
390       //log the fault
391
Element JavaDoc runtimeException = fault.lookupFaultDetail(Constants.QNAME_FAULTDETAIL_RUNTIMEEXCEPTION);
392       if (runtimeException != null)
393       {
394          fault.removeFaultDetail(Constants.QNAME_FAULTDETAIL_RUNTIMEEXCEPTION);
395       }
396
397       //dev systems only give fault dumps
398
if (!isDevelopment())
399       {
400          //strip out the stack trace
401
fault.removeFaultDetail(Constants.QNAME_FAULTDETAIL_STACKTRACE);
402       }
403
404       log.info(fault.detail != null ? fault.detail : fault);
405    }
406
407    /**
408     * log any exception to our output log, at our chosen level
409     *
410     * @param e what went wrong
411     */

412    protected void logException(Exception JavaDoc e)
413    {
414       log.info(Messages.getMessage("exception00"), e);
415    }
416
417    /**
418     * this method writes a fault out to an HTML stream. This includes
419     * escaping the strings to defend against cross-site scripting attacks
420     *
421     * @param writer
422     * @param axisFault
423     */

424    private void writeFault(PrintWriter JavaDoc writer, AxisFault axisFault)
425    {
426       String JavaDoc localizedMessage = XMLUtils.xmlEncodeString(axisFault.getLocalizedMessage());
427       writer.println("<pre>Fault - " + localizedMessage + "<br>");
428       writer.println(axisFault.dumpToString());
429       writer.println("</pre>");
430    }
431
432    /**
433     * scan through the request for parameters, invoking the endpoint
434     * if we get a method param. If there was no method param then the
435     * response is set to a 400 Bad Request and some error text
436     *
437     * @param msgContext current message
438     * @param request incoming requests
439     * @param response response to generate
440     * @param writer output stream
441     * @throws AxisFault if anything goes wrong during method execution
442     */

443    protected void processMethodRequest(MessageContext msgContext,
444                                        HttpServletRequest JavaDoc request,
445                                        HttpServletResponse JavaDoc response,
446                                        PrintWriter JavaDoc writer) throws AxisFault
447    {
448       Enumeration JavaDoc en = request.getParameterNames();
449       String JavaDoc method = null;
450       String JavaDoc args = "";
451       while (en.hasMoreElements())
452       {
453          String JavaDoc param = (String JavaDoc)en.nextElement();
454          if (param.equalsIgnoreCase("method"))
455          {
456             method = request.getParameter(param);
457          }
458          else
459          {
460             args += "<" + param + ">" +
461                     request.getParameter(param) +
462                     "</" + param + ">";
463          }
464       }
465
466       if (method == null)
467       {
468          response.setContentType("text/html");
469          response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
470          writer.println("<h2>" +
471                  Messages.getMessage("error00") +
472                  ": " +
473                  Messages.getMessage("invokeGet00") +
474                  "</h2>");
475          writer.println("<p>" +
476                  Messages.getMessage("noMethod01") +
477                  "</p>");
478       }
479       else
480       {
481          invokeEndpointFromGet(msgContext, response, writer, method, args);
482
483       }
484    }
485
486    /**
487     * handle a ?wsdl request
488     *
489     * @param msgContext message context so far
490     * @param response response to write to
491     * @param writer output stream
492     * @throws AxisFault when anything other than a Server.NoService fault is reported
493     * during WSDL generation
494     */

495    protected void processWsdlRequest(MessageContext msgContext,
496                                      HttpServletResponse JavaDoc response,
497                                      PrintWriter JavaDoc writer) throws AxisFault
498    {
499       AxisEngine engine = getEngine();
500       try
501       {
502          engine.generateWSDL(msgContext);
503          Document JavaDoc doc = (Document JavaDoc)msgContext.getProperty("WSDL");
504          if (doc != null)
505          {
506             response.setContentType("text/xml");
507             XMLUtils.DocumentToWriter(doc, writer);
508          }
509          else
510          {
511             if (log.isDebugEnabled())
512             {
513                log.debug("processWsdlRequest: failed to create WSDL");
514             }
515             reportNoWSDL(response, writer, "noWSDL02", null);
516          }
517       }
518       catch (AxisFault axisFault)
519       {
520          //the no-service fault is mapped to a no-wsdl error
521
if (axisFault.getFaultCode().equals(Constants.QNAME_NO_SERVICE_FAULT_CODE))
522          {
523             //which we log
524
processAxisFault(axisFault);
525             //then report under a 404 error
526
response.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
527             reportNoWSDL(response, writer, "noWSDL01", axisFault);
528          }
529          else
530          {
531             //all other faults get thrown
532
throw axisFault;
533          }
534       }
535    }
536
537    /**
538     * invoke an endpoint from a get request by building an XML request and
539     * handing it down. If anything goes wrong, we generate an XML formatted
540     * axis fault
541     *
542     * @param msgContext current message
543     * @param response to return data
544     * @param writer output stream
545     * @param method method to invoke (may be null)
546     * @param args argument list in XML form
547     * @throws AxisFault iff something goes wrong when turning the response message
548     * into a SOAP string.
549     */

550    protected void invokeEndpointFromGet(MessageContext msgContext,
551                                         HttpServletResponse JavaDoc response,
552                                         PrintWriter JavaDoc writer,
553                                         String JavaDoc method,
554                                         String JavaDoc args) throws AxisFault
555    {
556       String JavaDoc body =
557               "<" + method + ">" + args + "</" + method + ">";
558
559       String JavaDoc msgtxt =
560               "<SOAP-ENV:Envelope" +
561               " xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
562               "<SOAP-ENV:Body>" + body + "</SOAP-ENV:Body>" +
563               "</SOAP-ENV:Envelope>";
564
565       Message responseMsg = null;
566       try
567       {
568          ByteArrayInputStream JavaDoc istream =
569                  new ByteArrayInputStream JavaDoc(msgtxt.getBytes(XMLUtils.httpAuthCharEncoding));
570
571          AxisEngine engine = getEngine();
572          Message msg = new Message(istream, false);
573          msgContext.setRequestMessage(msg);
574          engine.invoke(msgContext);
575          responseMsg = msgContext.getResponseMessage();
576          //turn off caching for GET requests
577
response.setHeader("Cache-Control", "no-cache");
578          response.setHeader("Pragma", "no-cache");
579          if (responseMsg == null)
580          {
581             //tell everyone that something is wrong
582
throw new Exception JavaDoc(Messages.getMessage("noResponse01"));
583          }
584       }
585       catch (AxisFault fault)
586       {
587          processAxisFault(fault);
588          configureResponseFromAxisFault(response, fault);
589          if (responseMsg == null)
590          {
591             responseMsg = new Message(fault);
592             msgContext.setResponseMessage(responseMsg);
593          }
594       }
595       catch (Exception JavaDoc e)
596       {
597          response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
598          responseMsg = convertExceptionToAxisFault(e, responseMsg);
599       }
600       //this call could throw an AxisFault. We delegate it up, because
601
//if we cant write the message there is not a lot we can do in pure SOAP terms.
602
response.setContentType("text/xml");
603       writer.println(responseMsg.getSOAPPartAsString());
604    }
605
606    /**
607     * print a snippet of service info.
608     *
609     * @param service service
610     * @param writer output channel
611     * @param serviceName where to put stuff
612     */

613
614    protected void reportServiceInfo(HttpServletResponse JavaDoc response, PrintWriter JavaDoc writer, SOAPService service, String JavaDoc serviceName)
615    {
616       response.setContentType("text/html");
617
618       writer.println("<h1>"
619               + service.getName()
620               + "</h1>");
621       writer.println("<p>" +
622               Messages.getMessage("axisService00") +
623               "</p>");
624       writer.println("<i>" +
625               Messages.getMessage("perhaps00") +
626               "</i>");
627    }
628
629    /**
630     * report that we have no WSDL
631     *
632     * @param res
633     * @param writer
634     * @param moreDetailCode optional name of a message to provide more detail
635     * @param axisFault optional fault string, for extra info at debug time only
636     */

637    protected void reportNoWSDL(HttpServletResponse JavaDoc res, PrintWriter JavaDoc writer,
638                                String JavaDoc moreDetailCode, AxisFault axisFault)
639    {
640       res.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
641       res.setContentType("text/html");
642       writer.println("<h2>" +
643               Messages.getMessage("error00") +
644               "</h2>");
645       writer.println("<p>" +
646               Messages.getMessage("noWSDL00") +
647               "</p>");
648       if (moreDetailCode != null)
649       {
650          writer.println("<p>"
651                  + Messages.getMessage(moreDetailCode)
652                  + "</p>");
653       }
654
655       if (axisFault != null && isDevelopment())
656       {
657          //dev systems only give fault dumps
658
writeFault(writer, axisFault);
659       }
660    }
661
662
663    /**
664     * This method lists the available services; it is called when there is
665     * nothing to execute on a GET
666     *
667     * @param response
668     * @param writer
669     * @param request
670     * @throws ConfigurationException
671     * @throws AxisFault
672     */

673    protected void reportAvailableServices(HttpServletResponse JavaDoc response,
674                                           PrintWriter JavaDoc writer,
675                                           HttpServletRequest JavaDoc request)
676            throws ConfigurationException, AxisFault
677    {
678       AxisEngine engine = getEngine();
679       response.setContentType("text/html");
680       writer.println("<h2>And now... Some Services</h2>");
681
682       Iterator JavaDoc i;
683       try
684       {
685          i = engine.getConfig().getDeployedServices();
686       }
687       catch (ConfigurationException configException)
688       {
689          //turn any internal configuration exceptions back into axis faults
690
//if that is what they are
691
if (configException.getContainedException() instanceof AxisFault)
692          {
693             throw (AxisFault)configException.getContainedException();
694          }
695          else
696          {
697             throw configException;
698          }
699       }
700       String JavaDoc baseURL = getWebappBase(request) + "/services/";
701       writer.println("<ul>");
702       while (i.hasNext())
703       {
704          ServiceDesc sd = (ServiceDesc)i.next();
705          StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
706          sb.append("<li>");
707          String JavaDoc name = sd.getName();
708          sb.append(name);
709          sb.append(" <a HREF=\"");
710          sb.append(baseURL);
711          sb.append(name);
712          sb.append("?wsdl\"><i>(wsdl)</i></a></li>");
713          writer.println(sb.toString());
714          ArrayList JavaDoc operations = sd.getOperations();
715          if (!operations.isEmpty())
716          {
717             writer.println("<ul>");
718             for (Iterator JavaDoc it = operations.iterator(); it.hasNext();)
719             {
720                OperationDesc desc = (OperationDesc)it.next();
721                writer.println("<li>" + desc.getName());
722             }
723             writer.println("</ul>");
724          }
725       }
726       writer.println("</ul>");
727    }
728
729    /**
730     * generate the error response to indicate that there is apparently no endpoint there
731     *
732     * @param request the request that didnt have an edpoint
733     * @param response response we are generating
734     * @param writer open writer for the request
735     */

736    protected void reportCantGetAxisService(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response, PrintWriter JavaDoc writer)
737    {
738       // no such service....
739
response.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
740       response.setContentType("text/html");
741       writer.println("<h2>" +
742               Messages.getMessage("error00") + "</h2>");
743       writer.println("<p>" +
744               Messages.getMessage("noService06") +
745               "</p>");
746    }
747
748    /**
749     * probe for a JWS page and report 'no service' if one is not found there
750     *
751     * @param request the request that didnt have an edpoint
752     * @param response response we are generating
753     * @param writer open writer for the request
754     */

755    protected void reportCantGetJWSService(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response, PrintWriter JavaDoc writer)
756    {
757       //first look to see if there is a service
758
String JavaDoc realpath =
759               getServletConfig().getServletContext()
760               .getRealPath(request.getServletPath());
761       boolean foundJWSFile = (new File JavaDoc(realpath).exists()) &&
762               (realpath.endsWith(Constants.JWS_DEFAULT_FILE_EXTENSION));
763       response.setContentType("text/html");
764       if (foundJWSFile)
765       {
766          response.setStatus(HttpURLConnection.HTTP_OK);
767          writer.println(Messages.getMessage("foundJWS00") + "<p>");
768          String JavaDoc url = request.getRequestURI();
769          String JavaDoc urltext = Messages.getMessage("foundJWS01");
770          writer.println("<a HREF='" + url + "?wsdl'>" + urltext + "</a>");
771       }
772       else
773       {
774          response.setStatus(HttpURLConnection.HTTP_NOT_FOUND);
775          writer.println(Messages.getMessage("noService06"));
776       }
777    }
778
779
780    /**
781     * Process a POST to the servlet by handing it off to the Axis Engine.
782     * Here is where SOAP messages are received
783     * <p/>
784     * 1. get the Axis server engine
785     * 2. create the MessageContext and populate it with the req/res objects
786     * 3. set security provider
787     * 4. create request SOAPMessage
788     * 5. set the SOAPAction in the message context
789     * 6. invoke the engine
790     * 7. get response SOAPMessage
791     * 8. get the response content type
792     * 9. send the response
793     *
794     * @param req posted request
795     * @param res respose
796     * @throws ServletException trouble
797     * @throws IOException different trouble
798     */

799    public void doPost(HttpServletRequest JavaDoc req, HttpServletResponse JavaDoc res)
800            throws ServletException JavaDoc, IOException JavaDoc
801    {
802       long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0;
803       String JavaDoc soapAction = null;
804       MessageContext msgContext = null;
805       log.debug("Enter: doPost()");
806
807       if (tlog.isDebugEnabled())
808       {
809          t0 = System.currentTimeMillis();
810       }
811
812       Message responseMsg = null;
813       String JavaDoc contentType = null;
814
815       try
816       {
817          AxisEngine engine = getEngine();
818
819          if (engine == null)
820          {
821             // !!! should return a SOAP fault...
822
ServletException JavaDoc se =
823                     new ServletException JavaDoc(Messages.getMessage("noEngine00"));
824             log.debug("No Engine!", se);
825             throw se;
826          }
827
828          res.setBufferSize(1024 * 8); // provide performance boost.
829

830          /** get message context w/ various properties set
831           */

832          msgContext = createMessageContext(engine, req, res);
833          String JavaDoc serviceName = getServiceName(req);
834          log.debug("serviceName: " + serviceName);
835
836          // Get the SOAP servie
837
SOAPService service = (serviceName != null ? engine.getService(serviceName) : null);
838          if (service != null)
839             msgContext.setTargetService(serviceName);
840
841          // ? OK to move this to 'getMessageContext',
842
// ? where it would also be picked up for 'doGet()' ?
843
if (securityProvider != null)
844          {
845             log.debug("securityProvider:" + securityProvider);
846             msgContext.setProperty(MessageContext.SECURITY_PROVIDER, securityProvider);
847          }
848
849          InputStream JavaDoc inputStream = req.getInputStream();
850
851          MimeHeaders JavaDoc headers = extractHttpHeaders(req);
852
853          /* Get request message
854           */

855          Message requestMsg =
856                  new Message(inputStream, false, headers);
857
858          //req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE),
859
//req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION), headers);
860

861          if (log.isDebugEnabled())
862          {
863             log.debug("XML request received");
864             log.debug("----------------------------------------------");
865             MessagePart msgPart = (MessagePart)requestMsg.getSOAPPart();
866             String JavaDoc xmlMessage = new String JavaDoc(msgPart.getAsBytes());
867             log.debug("----------------------------------------------");
868             log.debug(xmlMessage);
869             log.debug("----------------------------------------------");
870          }
871
872          /* Set the request(incoming) message field in the context */
873          /**********************************************************/
874          msgContext.setRequestMessage(requestMsg);
875          String JavaDoc url = req.getRequestURL().toString();
876          msgContext.setProperty(MessageContext.TRANS_URL, url);
877
878          try
879          {
880             /**
881              * Save the SOAPAction header in the MessageContext bag.
882              * This will be used to tell the Axis Engine which service
883              * is being invoked. This will save us the trouble of
884              * having to parse the Request message - although we will
885              * need to double-check later on that the SOAPAction header
886              * does in fact match the URI in the body.
887              */

888             // (is this last stmt true??? (I don't think so - Glen))
889
/********************************************************/
890             soapAction = getSoapAction(req);
891
892             if (soapAction != null)
893             {
894                msgContext.setUseSOAPAction(true);
895                msgContext.setSOAPActionURI(soapAction);
896             }
897
898             // Create a Session wrapper for the HTTP session.
899
// These can/should be pooled at some point.
900
// (Sam is Watching! :-)
901
msgContext.setSession(new AxisHttpSession(req));
902
903             if (tlog.isDebugEnabled())
904             {
905                t1 = System.currentTimeMillis();
906             }
907
908             /* Invoke the Axis engine... */
909             /*****************************/
910             log.debug("Invoking Axis Engine.");
911             engine.invoke(msgContext);
912
913
914             log.debug("Return from Axis Engine.");
915             if (tlog.isDebugEnabled())
916             {
917                t2 = System.currentTimeMillis();
918             }
919
920             OperationDesc opDesc = msgContext.getOperation();
921             boolean isOneWay = opDesc != null && opDesc.isOneWay();
922
923             responseMsg = msgContext.getResponseMessage();
924             if (responseMsg == null && isOneWay == false)
925             {
926                //tell everyone that something is wrong
927
throw new Exception JavaDoc(Messages.getMessage("noResponse01"));
928             }
929          }
930          catch (AxisFault fault)
931          {
932             //log and sanitize
933
processAxisFault(fault);
934             configureResponseFromAxisFault(res, fault);
935             responseMsg = msgContext.getResponseMessage();
936             if (responseMsg == null)
937             {
938                responseMsg = new Message(fault);
939                msgContext.setResponseMessage(responseMsg);
940             }
941          }
942          catch (Exception JavaDoc e)
943          {
944             //other exceptions are internal trouble
945
responseMsg = msgContext.getResponseMessage();
946             res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
947             responseMsg = convertExceptionToAxisFault(e, responseMsg);
948          }
949       }
950       catch (AxisFault fault)
951       {
952          processAxisFault(fault);
953          configureResponseFromAxisFault(res, fault);
954          responseMsg = msgContext.getResponseMessage();
955          if (responseMsg == null)
956          {
957             responseMsg = new Message(fault);
958             msgContext.setResponseMessage(responseMsg);
959          }
960       }
961       finally
962       {
963          // Make sure the MessageContext is removed from the calling ThreadLocal
964
AxisEngine.setCurrentMessageContext(null);
965       }
966
967       //determine content type from message response
968
if (tlog.isDebugEnabled())
969       {
970          t3 = System.currentTimeMillis();
971       }
972
973       /* Send response back along the wire... */
974       /***********************************/
975       if (responseMsg != null)
976       {
977          contentType = responseMsg.getContentType(msgContext.getSOAPConstants());
978          sendResponse(contentType,
979                  res, responseMsg);
980       }
981
982       log.debug("Response sent.");
983       log.debug("Exit: doPost()");
984
985       if (tlog.isDebugEnabled())
986       {
987          t4 = System.currentTimeMillis();
988          tlog.debug("axisServlet.doPost: " + soapAction +
989                  " pre=" + (t1 - t0) +
990                  " invoke=" + (t2 - t1) +
991                  " post=" + (t3 - t2) +
992                  " send=" + (t4 - t3) +
993                  " " + msgContext.getTargetService() + "." +
994                  ((msgContext.getOperation() == null) ?
995                  "" : msgContext.getOperation().getName()));
996       }
997
998    }
999
1000   /**
1001    * Assumes that the service name is the first token in the path info
1002    */

1003   protected String JavaDoc getServiceName(HttpServletRequest JavaDoc request)
1004   {
1005      String JavaDoc path = request.getPathInfo();
1006      if (path != null)
1007      {
1008         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(path, "/");
1009         if (st.hasMoreTokens())
1010         {
1011            return st.nextToken();
1012         }
1013      }
1014      return null;
1015   }
1016
1017   /**
1018    * Configure the servlet response status code and maybe other headers
1019    * from the fault info.
1020    *
1021    * @param response response to configure
1022    * @param fault what went wrong
1023    */

1024   private void configureResponseFromAxisFault(HttpServletResponse JavaDoc response,
1025                                               AxisFault fault)
1026   {
1027      // then get the status code
1028
// It's been suggested that a lack of SOAPAction
1029
// should produce some other error code (in the 400s)...
1030
int status = getHttpServletResponseStatus(fault);
1031      if (status == HttpServletResponse.SC_UNAUTHORIZED)
1032      {
1033         // unauth access results in authentication request
1034
// TODO: less generic realm choice?
1035
response.setHeader("WWW-Authenticate", "Basic realm=\"AXIS\"");
1036      }
1037      response.setStatus(status);
1038   }
1039
1040   /**
1041    * turn any Exception into an AxisFault, log it, set the response
1042    * status code according to what the specifications say and
1043    * return a response message for posting. This will be the response
1044    * message passed in if non-null; one generated from the fault otherwise.
1045    *
1046    * @param exception what went wrong
1047    * @param responseMsg what response we have (if any)
1048    * @return a response message to send to the user
1049    */

1050   private Message convertExceptionToAxisFault(Exception JavaDoc exception,
1051                                               Message responseMsg)
1052   {
1053      logException(exception);
1054      if (responseMsg == null)
1055      {
1056         AxisFault fault = AxisFault.makeFault(exception);
1057         processAxisFault(fault);
1058         responseMsg = new Message(fault);
1059      }
1060      return responseMsg;
1061   }
1062
1063   /**
1064    * Extract information from AxisFault and map it to a HTTP Status code.
1065    *
1066    * @param af Axis Fault
1067    * @return HTTP Status code.
1068    */

1069   protected int getHttpServletResponseStatus(AxisFault af)
1070   {
1071      // TODO: Should really be doing this with explicit AxisFault
1072
// subclasses... --Glen
1073
return af.getFaultCode().getLocalPart().startsWith("Server.Unauth")
1074              ? HttpServletResponse.SC_UNAUTHORIZED
1075              : HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
1076      // This will raise a 401 for both
1077
// "Unauthenticated" & "Unauthorized"...
1078
}
1079
1080   /**
1081    * write a message to the response, set appropriate headers for content
1082    * type..etc.
1083    *
1084    * @param res response
1085    * @param responseMsg message to write
1086    * @throws AxisFault
1087    * @throws IOException if the response stream can not be written to
1088    */

1089   private void sendResponse(String JavaDoc contentType, HttpServletResponse JavaDoc res, Message responseMsg)
1090           throws AxisFault, IOException JavaDoc
1091   {
1092
1093      if (responseMsg == null)
1094      {
1095         res.setStatus(HttpServletResponse.SC_NO_CONTENT);
1096         log.debug("NO AXIS MESSAGE TO RETURN!");
1097         //String resp = Messages.getMessage("noData00");
1098
//res.setContentLength((int) resp.getBytes().length);
1099
//res.getWriter().print(resp);
1100
}
1101      else
1102      {
1103         log.debug("Returned Content-Type:" + contentType);
1104         // log.debug("Returned Content-Length:" +
1105
// responseMsg.getContentLength());
1106

1107         try
1108         {
1109            res.setContentType(contentType);
1110
1111            /* My understand of Content-Length
1112             * HTTP 1.0
1113             * -Required for requests, but optional for responses.
1114             * HTTP 1.1
1115             * - Either Content-Length or HTTP Chunking is required.
1116             * Most servlet engines will do chunking if content-length is not specified.
1117             *
1118             *
1119             */

1120
1121            //if(clientVersion == HTTPConstants.HEADER_PROTOCOL_V10) //do chunking if necessary.
1122
// res.setContentLength(responseMsg.getContentLength());
1123

1124            //Add message headers
1125
MimeHeaders JavaDoc headers = responseMsg.getMimeHeaders();
1126            if (headers != null)
1127            {
1128               Iterator JavaDoc i = headers.getAllHeaders();
1129               while (i.hasNext())
1130               {
1131                  MimeHeader JavaDoc header = (MimeHeader JavaDoc)i.next();
1132                  res.addHeader(header.getName(), header.getValue());
1133               }
1134            }
1135
1136            responseMsg.writeTo(res.getOutputStream());
1137
1138            if (log.isDebugEnabled())
1139            {
1140               log.debug("XML response sent");
1141               log.debug("----------------------------------------------");
1142               MessagePart msgPart = (MessagePart)responseMsg.getSOAPPart();
1143               String JavaDoc xmlMessage = msgPart.getAsString();
1144               log.debug("----------------------------------------------");
1145               log.debug(xmlMessage);
1146               log.debug("----------------------------------------------");
1147            }
1148         }
1149         catch (SOAPException JavaDoc e)
1150         {
1151            logException(e);
1152         }
1153      }
1154
1155      if (!res.isCommitted())
1156      {
1157         res.flushBuffer(); // Force it right now.
1158
}
1159   }
1160
1161   /**
1162    * Place the Request message in the MessagContext object - notice
1163    * that we just leave it as a 'ServletRequest' object and let the
1164    * Message processing routine convert it - we don't do it since we
1165    * don't know how it's going to be used - perhaps it might not
1166    * even need to be parsed.
1167    *
1168    * @return a message context
1169    */

1170   protected MessageContext createMessageContext(AxisEngine engine,
1171                                                 HttpServletRequest JavaDoc req,
1172                                                 HttpServletResponse JavaDoc res)
1173   {
1174      MessageContext msgContext = new MessageContext(engine);
1175      AxisEngine.setCurrentMessageContext(msgContext);
1176
1177      if (log.isDebugEnabled())
1178      {
1179         log.debug("MessageContext:" + msgContext);
1180         log.debug("HEADER_CONTENT_TYPE:" +
1181                 req.getHeader(HTTPConstants.HEADER_CONTENT_TYPE));
1182         log.debug("HEADER_CONTENT_LOCATION:" +
1183                 req.getHeader(HTTPConstants.HEADER_CONTENT_LOCATION));
1184         log.debug("Constants.MC_HOME_DIR:" + String.valueOf(getHomeDir()));
1185         log.debug("Constants.MC_RELATIVE_PATH:" + req.getServletPath());
1186
1187         log.debug("HTTPConstants.MC_HTTP_SERVLETLOCATION:" + String.valueOf(getWebInfPath()));
1188         log.debug("HTTPConstants.MC_HTTP_SERVLETPATHINFO:" +
1189                 req.getPathInfo());
1190         log.debug("HTTPConstants.HEADER_AUTHORIZATION:" +
1191                 req.getHeader(HTTPConstants.HEADER_AUTHORIZATION));
1192         log.debug("Constants.MC_REMOTE_ADDR:" + req.getRemoteAddr());
1193         log.debug("configPath:" + String.valueOf(getWebInfPath()));
1194      }
1195
1196      /* Set the Transport */
1197      /*********************/
1198      msgContext.setTransportName(transportName);
1199
1200      /* Save some HTTP specific info in the bag in case someone needs it */
1201      /********************************************************************/
1202      msgContext.setProperty(Constants.MC_JWS_CLASSDIR, jwsClassDir);
1203      msgContext.setProperty(Constants.MC_HOME_DIR, getHomeDir());
1204      msgContext.setProperty(Constants.MC_RELATIVE_PATH,
1205              req.getServletPath());
1206      msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLET, this);
1207      msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST, req);
1208      msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETRESPONSE, res);
1209      msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETLOCATION,
1210              getWebInfPath());
1211      msgContext.setProperty(HTTPConstants.MC_HTTP_SERVLETPATHINFO,
1212              req.getPathInfo());
1213      msgContext.setProperty(HTTPConstants.HEADER_AUTHORIZATION,
1214              req.getHeader(HTTPConstants.HEADER_AUTHORIZATION));
1215      msgContext.setProperty(Constants.MC_REMOTE_ADDR, req.getRemoteAddr());
1216
1217      // Set up a javax.xml.rpc.server.ServletEndpointContext
1218
ServletEndpointContextImpl sec = new ServletEndpointContextImpl();
1219
1220      msgContext.setProperty(Constants.MC_SERVLET_ENDPOINT_CONTEXT, sec);
1221      /* Save the real path */
1222      /**********************/
1223      String JavaDoc realpath =
1224              getServletConfig().getServletContext()
1225              .getRealPath(req.getServletPath());
1226
1227      if (realpath != null)
1228      {
1229         msgContext.setProperty(Constants.MC_REALPATH, realpath);
1230      }
1231
1232      msgContext.setProperty(Constants.MC_CONFIGPATH, getWebInfPath());
1233
1234      return msgContext;
1235   }
1236
1237   /**
1238    * Extract the SOAPAction header.
1239    * if SOAPAction is null then we'll we be forced to scan the body for it.
1240    * if SOAPAction is "" then use the URL
1241    *
1242    * @param req incoming request
1243    * @return the action
1244    * @throws AxisFault
1245    */

1246   private String JavaDoc getSoapAction(HttpServletRequest JavaDoc req)
1247           throws AxisFault
1248   {
1249      String JavaDoc soapAction = req.getHeader(HTTPConstants.HEADER_SOAP_ACTION);
1250
1251      log.debug("HEADER_SOAP_ACTION:" + soapAction);
1252
1253      /**
1254       * Technically, if we don't find this header, we should probably fault.
1255       * It's required in the SOAP HTTP binding.
1256       */

1257      if (soapAction == null)
1258      {
1259         AxisFault af = new AxisFault("Client.NoSOAPAction",
1260                 Messages.getMessage("noHeader00",
1261                         "SOAPAction"),
1262                 null, null);
1263
1264         log.error(Messages.getMessage("genFault00"), af);
1265
1266         throw af;
1267      }
1268
1269      if (soapAction.length() == 0)
1270         soapAction = req.getContextPath(); // Is this right?
1271

1272      return soapAction;
1273   }
1274
1275   /**
1276    * Provided to allow overload of default JWSClassDir
1277    * by derived class.
1278    *
1279    * @return directory for JWS files
1280    */

1281   protected String JavaDoc getDefaultJWSClassDir()
1282   {
1283      return (getWebInfPath() == null)
1284              ? null // ??? what is a good FINAL default for WebLogic?
1285
: getWebInfPath() + File.separator + "jwsClasses";
1286   }
1287
1288   /**
1289    * Return the HTTP protocol level 1.1 or 1.0
1290    * by derived class.
1291    *
1292    * @return one of the HTTPConstants values
1293    */

1294   protected String JavaDoc getProtocolVersion(HttpServletRequest JavaDoc req)
1295   {
1296      String JavaDoc ret = HTTPConstants.HEADER_PROTOCOL_V10;
1297      String JavaDoc prot = req.getProtocol();
1298      if (prot != null)
1299      {
1300         int sindex = prot.indexOf('/');
1301         if (-1 != sindex)
1302         {
1303            String JavaDoc ver = prot.substring(sindex + 1);
1304            if (HTTPConstants.HEADER_PROTOCOL_V11.equals(ver.trim()))
1305            {
1306               ret = HTTPConstants.HEADER_PROTOCOL_V11;
1307            }
1308         }
1309      }
1310      return ret;
1311   }
1312
1313   private MimeHeaders JavaDoc extractHttpHeaders(HttpServletRequest JavaDoc req)
1314   {
1315      Enumeration JavaDoc headers = req.getHeaderNames();
1316      MimeHeaders JavaDoc mimeHeaders = new MimeHeaders JavaDoc();
1317      while (headers.hasMoreElements())
1318      {
1319         String JavaDoc name = (String JavaDoc)headers.nextElement();
1320         Enumeration JavaDoc values = req.getHeaders(name);
1321         while (values.hasMoreElements())
1322            mimeHeaders.addHeader(name, (String JavaDoc)values.nextElement());
1323      }
1324
1325      return mimeHeaders;
1326   }
1327}
1328
Popular Tags