Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/mortbay/jetty/servlet/ServletHandler.java


1   // ===========================================================================
2   // Copyright (c) 1996-2003 Mort Bay Consulting Pty. Ltd. All rights reserved.
3   // $Id: ServletHandler.java,v 1.101 2003/11/19 11:35:55 gregwilkins Exp $
4   // ---------------------------------------------------------------------------
5   
6   package org.mortbay.jetty.servlet;
7   
8   
9   import java.io.File;
10  import java.io.IOException;
11  import java.io.InputStream;
12  import java.io.OutputStream;
13  import java.net.MalformedURLException;
14  import java.net.URL;
15  import java.util.Collections;
16  import java.util.Enumeration;
17  import java.util.HashMap;
18  import java.util.HashSet;
19  import java.util.Map;
20  import java.util.Set;
21  
22  import javax.servlet.RequestDispatcher;
23  import javax.servlet.Servlet;
24  import javax.servlet.ServletContext;
25  import javax.servlet.ServletException;
26  import javax.servlet.UnavailableException;
27  import javax.servlet.http.HttpServletRequest;
28  import javax.servlet.http.HttpServletResponse;
29  import javax.servlet.http.HttpSession;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.mortbay.http.EOFException;
34  import org.mortbay.http.HttpContext;
35  import org.mortbay.http.HttpException;
36  import org.mortbay.http.HttpFields;
37  import org.mortbay.http.HttpRequest;
38  import org.mortbay.http.HttpResponse;
39  import org.mortbay.http.PathMap;
40  import org.mortbay.http.Version;
41  import org.mortbay.http.handler.AbstractHttpHandler;
42  import org.mortbay.util.ByteArrayISO8859Writer;
43  import org.mortbay.util.LogSupport;
44  import org.mortbay.util.MultiException;
45  import org.mortbay.util.Resource;
46  import org.mortbay.util.URI;
47  
48  
49  /* --------------------------------------------------------------------- */
50  /** Servlet HttpHandler.
51   * This handler maps requests to servlets that implement the
52   * javax.servlet.http.HttpServlet API.
53   * <P>
54   * This handler does not implement the full J2EE features and is intended to
55   * be used when a full web application is not required.  Specifically filters
56   * and request wrapping are not supported.
57   * <P>
58   * If a SessionManager is not added to the handler before it is
59   * initialized, then a HashSessionManager with a standard
60   * java.util.Random generator is created.
61   * <P>
62   * @see org.mortbay.jetty.servlet.WebApplicationHandler
63   * @version $Id: ServletHandler.java,v 1.101 2003/11/19 11:35:55 gregwilkins Exp $
64   * @author Greg Wilkins
65   */
66  public class ServletHandler extends AbstractHttpHandler
67  {
68      private static Log log = LogFactory.getLog(ServletHandler.class);
69  
70      /* ------------------------------------------------------------ */
71      public static final String __DEFAULT_SERVLET="default";
72      public static final String __J_S_CONTEXT_TEMPDIR="javax.servlet.context.tempdir";
73      public static final String __J_S_ERROR_EXCEPTION="javax.servlet.error.exception";
74      public static final String __J_S_ERROR_EXCEPTION_TYPE="javax.servlet.error.exception_type";
75      public static final String __J_S_ERROR_MESSAGE="javax.servlet.error.message";
76      public static final String __J_S_ERROR_REQUEST_URI="javax.servlet.error.request_uri";
77      public static final String __J_S_ERROR_SERVLET_NAME="javax.servlet.error.servlet_name";
78      public static final String __J_S_ERROR_STATUS_CODE="javax.servlet.error.status_code";
79      
80      /* ------------------------------------------------------------ */
81      private static final boolean __Slosh2Slash=File.separatorChar=='\\';
82      private static String __AllowString="GET, HEAD, POST, OPTIONS, TRACE";
83  
84      
85      /* ------------------------------------------------------------ */
86      private boolean _usingCookies=true;
87      private boolean _autoInitializeServlets=true;
88      
89      /* ------------------------------------------------------------ */
90      protected PathMap _servletMap=new PathMap();
91      protected Map _nameMap=new HashMap();
92      protected String _formLoginPage;
93      protected String _formErrorPage;
94      protected SessionManager _sessionManager;
95  
96      protected transient Context _context;
97      protected transient ClassLoader _loader;
98  
99      /* ------------------------------------------------------------ */
100     /** Constructor. 
101      */
102     public ServletHandler()
103     {}
104     
105     /* ------------------------------------------------------------ */
106     public void initialize(HttpContext context)
107     {
108         SessionManager sessionManager=getSessionManager();
109         super.initialize(context);
110         _context=new Context();
111         sessionManager.initialize(this);
112     }
113 
114     /* ------------------------------------------------------------ */
115     public void formAuthInit(String formLoginPage,
116                              String formErrorPage)
117     {
118         _formLoginPage=formLoginPage;
119         _formErrorPage=formErrorPage;
120     }    
121     
122     /* ------------------------------------------------------------ */
123     public void setSessionManager(SessionManager sm)
124     {
125         if (isStarted())
126             throw new IllegalStateException("Started");
127 
128         _sessionManager=sm;
129     }
130     
131     /* ------------------------------------------------------------ */
132     public SessionManager getSessionManager()
133     {
134         if (_sessionManager==null)
135             _sessionManager = new HashSessionManager();
136         return _sessionManager;
137     }
138     
139     /* ------------------------------------------------------------ */
140     public ServletContext getServletContext() { return _context; }
141 
142     /* ------------------------------------------------------------ */
143     public PathMap getServletMap() { return _servletMap; }
144     
145     /* ------------------------------------------------------------ */
146     public boolean isUsingCookies() { return _usingCookies; }
147     
148     /* ------------------------------------------------------------ */
149     /** Set the dynamic servlet path.
150      * @deprecated Use org.mortbay.jetty.servlet.Invoker
151      */
152     public void setDynamicServletPathSpec(String dynamicServletPathSpec)
153     {
154         log.warn("setDynamicServletPathSpec is Deprecated.");
155     }
156     
157     /* ------------------------------------------------------------ */
158     /** Set dynamic servlet initial parameters.
159      * @deprecated Use org.mortbay.jetty.servlet.Invoker
160      */
161     public void setDynamicInitParams(Map initParams)
162     {
163         log.warn("setDynamicInitParams is Deprecated.");
164     }
165 
166     /* ------------------------------------------------------------ */
167     /** Set serving dynamic system servlets.
168      * @deprecated Use org.mortbay.jetty.servlet.Invoker
169      */
170     public void setServeDynamicSystemServlets(boolean b)
171     {
172         log.warn("setServeDynamicSystemServlets is Deprecated.");
173     }
174     
175     /* ------------------------------------------------------------ */
176     public ClassLoader getClassLoader()
177     {
178         return _loader;
179     }
180 
181     /* ------------------------------------------------------------ */
182     /** 
183      * @param uc If true, cookies are used for sessions
184      */
185     public void setUsingCookies(boolean uc)
186     {
187         _usingCookies=uc;
188     }
189 
190     /* ------------------------------------------------------------ */
191     public ServletHolder newServletHolder(String name,
192                                           String servletClass,
193                                           String forcedPath)
194     {
195         if (_nameMap.containsKey(name))
196             throw new IllegalArgumentException("Named servlet already exists: "+name);
197         
198         ServletHolder holder = new ServletHolder(this,name,servletClass,forcedPath);
199         _nameMap.put(holder.getName(),holder);
200         return holder;
201     }
202 
203     /* ------------------------------------------------------------ */
204     public ServletHolder newServletHolder(String name,
205                                           String servletClass)
206     {
207         return newServletHolder(name,servletClass,null);
208     }    
209     
210     /* ------------------------------------------------------------ */
211     public ServletHolder getServletHolder(String name)
212     {
213         return (ServletHolder)_nameMap.get(name);
214     }    
215 
216     /* ------------------------------------------------------------ */
217     public ServletHolder mapPathToServlet(String pathSpec,
218                                           String servletName)
219     {
220         ServletHolder holder =(ServletHolder)_nameMap.get(servletName);
221 
222         if (!pathSpec.startsWith("/") && !pathSpec.startsWith("*"))
223         {
224             log.warn("pathSpec should start with '/' or '*' : "+pathSpec);
225             pathSpec="/"+pathSpec;
226         }
227         
228         if (holder==null)
229             throw new IllegalArgumentException("Unknown servlet: "+servletName);
230         _servletMap.put(pathSpec,holder);
231         return holder;
232     }
233     
234     /* ------------------------------------------------------------ */
235     /** Add a servlet.
236      * @param name The servlet name.
237      * @param pathSpec A path specification to map this servlet to.
238      * @param servletClass The class name of the servlet.
239      * @param forcedPath If non null, the request attribute
240      * javax.servlet.include.servlet_path will be set to this path before
241      * service is called.
242      * @return The ServletHolder for the servlet.
243      */
244     public ServletHolder addServlet(String name,
245                                     String pathSpec,
246                                     String servletClass,
247                                     String forcedPath)
248     {
249         ServletHolder holder = getServletHolder(name);
250         if (holder==null)
251             holder = newServletHolder(name,servletClass,forcedPath);
252         mapPathToServlet(pathSpec,name);
253         if (isStarted() && !holder.isStarted())
254         {
255             try{holder.start();}
256             catch(Exception e){log.warn(LogSupport.EXCEPTION,e);}
257         }
258         return holder;
259     }
260     
261     /* ------------------------------------------------------------ */
262     /** Add a servlet.
263      * @param name The servlet name.
264      * @param pathSpec A path specification to map this servlet to.
265      * @param servletClass The class name of the servlet.
266      * @return The ServletHolder for the servlet.
267      */
268     public ServletHolder addServlet(String name,
269                                     String pathSpec,
270                                     String servletClass)
271     {
272         return addServlet(name,pathSpec,servletClass,null);
273     }
274 
275     
276     /* ------------------------------------------------------------ */
277     public ServletHolder addServlet(String pathSpec,
278                                     String servletClass)
279     {
280         return addServlet(servletClass,pathSpec,servletClass,null);
281     }
282 
283     /* ------------------------------------------------------------ */
284     void addServletHolder(String pathSpec, ServletHolder holder)
285     {
286         try
287         {
288             ServletHolder existing = (ServletHolder)
289                 _nameMap.get(holder.getName());
290             if (existing==null)
291                 _nameMap.put(holder.getName(),holder);
292             else if (existing!=holder)
293                 throw new IllegalArgumentException("Holder already exists for name: "+holder.getName());
294             
295             if (isStarted() && !holder.isStarted())
296                 holder.start();
297             _servletMap.put(pathSpec,holder);
298         }
299         catch(Exception e)
300         {
301             log.warn(LogSupport.EXCEPTION,e);
302         }
303     }
304     
305     /* ------------------------------------------------------------ */
306     public boolean isAutoInitializeServlets()
307     {
308         return _autoInitializeServlets;
309     }
310 
311     /* ------------------------------------------------------------ */
312     public void setAutoInitializeServlets(boolean b)
313     {
314         _autoInitializeServlets=b;
315     }
316     
317     /* ----------------------------------------------------------------- */
318     public synchronized void start()
319         throws Exception
320     {
321         if (isStarted())
322             return;
323         
324         if (_sessionManager!=null)
325             _sessionManager.start();
326         
327         // Initialize classloader
328         _loader=getHttpContext().getClassLoader();
329 
330         // start the handler - protected by synchronization until
331         // end of the call.
332         super.start();
333 
334         if (_autoInitializeServlets)
335             initializeServlets();
336     }   
337     
338     /* ------------------------------------------------------------ */
339     /** Get Servlets.
340      * @return Array of defined servlets
341      */
342     public ServletHolder[] getServlets()
343     {
344         // Sort and Initialize servlets
345         HashSet holder_set = new HashSet(_nameMap.size());
346         holder_set.addAll(_nameMap.values());
347         ServletHolder holders [] = (ServletHolder [])
348             holder_set.toArray(new ServletHolder [holder_set.size()]);
349         java.util.Arrays.sort (holders);
350         return holders;
351     }
352     
353     /* ------------------------------------------------------------ */
354     /** Initialize load-on-startup servlets.
355      * Called automatically from start if autoInitializeServlet is true.
356      */
357     public void initializeServlets()
358         throws Exception
359     {
360         MultiException mx = new MultiException();
361         
362         // Sort and Initialize servlets
363         ServletHolder[] holders = getServlets();
364         for (int i=0; i<holders.length; i++)
365         {
366             try{holders[i].start();}
367             catch(Exception e)
368             {
369                 log.debug(LogSupport.EXCEPTION,e);
370                 mx.add(e);
371             }
372         } 
373         mx.ifExceptionThrow();       
374     }
375     
376     /* ----------------------------------------------------------------- */
377     public synchronized void stop()
378         throws InterruptedException
379     {
380         // Sort and Initialize servlets
381         ServletHolder[] holders = getServlets();
382         
383         super.stop();
384         
385         // Stop servlets
386         for (int i=holders.length; i-->0;)
387         {
388             try
389             {
390                 if (holders[i].isStarted())
391                     holders[i].stop();
392             }
393             catch(Exception e){log.warn(LogSupport.EXCEPTION,e);}
394         }
395         
396         // Stop the session manager
397         _sessionManager.stop();
398         
399         _loader=null;
400     }
401 
402     /* ------------------------------------------------------------ */
403     HttpSession getHttpSession(String id)
404     {
405         return _sessionManager.getHttpSession(id);
406     }
407     
408     /* ------------------------------------------------------------ */
409     HttpSession newHttpSession(HttpServletRequest request)
410     {
411         return _sessionManager.newHttpSession(request);
412     }
413 
414     /* ------------------------------------------------------------ */
415     void setSessionInactiveInterval(int seconds)
416     {
417         _sessionManager.setMaxInactiveInterval(seconds);
418     }
419 
420     /* ----------------------------------------------------------------- */
421     /** Handle request.
422      * @param pathInContext
423      * @param pathParams
424      * @param httpRequest
425      * @param httpResponse 
426      * @exception IOException 
427      */
428     public void handle(String pathInContext,
429                        String pathParams,
430                        HttpRequest httpRequest,
431                        HttpResponse httpResponse)
432          throws IOException
433     {
434         if (!isStarted() && _context==null)
435             return;
436         
437         // Handle TRACE
438         if (HttpRequest.__TRACE.equals(httpRequest.getMethod()))
439         {
440             handleTrace(httpRequest,httpResponse);
441             return;
442         }
443 
444         // Look for existing request/response objects
445         ServletHttpRequest request = (ServletHttpRequest) httpRequest.getWrapper();
446         ServletHttpResponse response = (ServletHttpResponse) httpResponse.getWrapper();
447         if (request==null)
448         {
449             // Build the request and response.
450             request = new ServletHttpRequest(this,pathInContext,httpRequest);
451             response = new ServletHttpResponse(request,httpResponse);
452             httpRequest.setWrapper(request);
453             httpResponse.setWrapper(response);
454         }
455         else
456         {
457             // Recycled request
458             request.recycle(this,pathInContext);
459             response.recycle();
460         }
461         
462         
463         // Look for the servlet
464         Map.Entry servlet=getHolderEntry(pathInContext);
465         ServletHolder servletHolder=servlet==null?null:(ServletHolder)servlet.getValue();
466         if(log.isDebugEnabled())log.debug("servlet="+servlet);
467             
468         try
469         {
470             // Adjust request paths
471             if (servlet!=null)
472             {
473                 String servletPathSpec=(String)servlet.getKey(); 
474                 request.setServletPaths(PathMap.pathMatch(servletPathSpec,pathInContext),
475                                         PathMap.pathInfo(servletPathSpec,pathInContext),
476                                         servletHolder);
477             }
478             
479             // Handle the session ID
480             request.setSessionId(pathParams);
481             HttpSession session=request.getSession(false);
482             if (session!=null)
483                 ((SessionManager.Session)session).access();
484             if(log.isDebugEnabled())log.debug("session="+session);
485             
486             // Do that funky filter and servlet thang!
487             if (servletHolder!=null)
488                 dispatch(pathInContext,request,response,servletHolder);
489         }
490         catch(Exception e)
491         {
492             log.debug(LogSupport.EXCEPTION,e);
493             
494             Throwable th=e;
495             if (e instanceof ServletException)
496             {
497                 Throwable root=((ServletException)e).getRootCause();
498                 while (root instanceof ServletException)
499                     root=((ServletException)e).getRootCause();
500                 if (root instanceof HttpException ||
501                     root instanceof EOFException)
502                 {
503                     if(log.isDebugEnabled())log.debug("Extracting root cause from ",e);
504                     th=root;
505                 }
506             }
507             
508             if (th instanceof HttpException)
509                 throw (HttpException)th;
510             if (th instanceof EOFException)
511                 throw (IOException)th;
512             else if (!log.isDebugEnabled() && th instanceof java.io.IOException)
513                 log.warn("Exception for "+httpRequest.getURI()+": "+th);
514             else
515             {
516                 log.warn("Exception for "+httpRequest.getURI(),th);
517                 if(log.isDebugEnabled())log.debug(httpRequest);
518             }
519             
520             httpResponse.getHttpConnection().forceClose();
521             if (!httpResponse.isCommitted())
522             {
523                 request.setAttribute(ServletHandler.__J_S_ERROR_EXCEPTION_TYPE,th.getClass());
524                 request.setAttribute(ServletHandler.__J_S_ERROR_EXCEPTION,th);
525                 response.sendError(th instanceof UnavailableException
526                                    ?HttpResponse.__503_Service_Unavailable
527                                    :HttpResponse.__500_Internal_Server_Error,
528                                    e.getMessage());
529             }
530             else
531                 if(log.isDebugEnabled())log.debug("Response already committed for handling "+th);
532         }
533         catch(Error e)
534         {   
535             log.warn("Error for "+httpRequest.getURI(),e);
536             if(log.isDebugEnabled())log.debug(httpRequest);
537             
538             httpResponse.getHttpConnection().forceClose();
539             if (!httpResponse.isCommitted())
540             {
541                 request.setAttribute(ServletHandler.__J_S_ERROR_EXCEPTION_TYPE,e.getClass());
542                 request.setAttribute(ServletHandler.__J_S_ERROR_EXCEPTION,e);
543                 response.sendError(HttpResponse.__500_Internal_Server_Error,
544                                    e.getMessage());
545             }
546             else
547                 if(log.isDebugEnabled())log.debug("Response already committed for handling ",e);
548         }
549         finally
550         {
551             if (servletHolder!=null)
552             {
553                 response.flushBuffer();
554                 if (!httpRequest.isHandled())
555                     new Throwable().printStackTrace();
556             }
557         }
558     }
559 
560     /* ------------------------------------------------------------ */
561     /** Dispatch to a servletHolder.
562      * This method may be specialized to insert extra handling in the
563      * dispatch of a request to a specific servlet. This is used by
564      * WebApplicatonHandler to implement dispatched filters.
565      * The default implementation simply calls
566      * ServletHolder.handle(request,response)
567      * @param pathInContext The path used to select the servlet holder.
568      * @param request 
569      * @param response 
570      * @param servletHolder 
571      * @exception ServletException 
572      * @exception UnavailableException 
573      * @exception IOException 
574      */
575     protected void dispatch(String pathInContext,
576                             HttpServletRequest request,
577                             HttpServletResponse response,
578                             ServletHolder servletHolder)
579         throws ServletException,
580                UnavailableException,
581                IOException
582     {
583         servletHolder.handle(request,response);
584     }
585     
586     
587     /* ------------------------------------------------------------ */
588     /** ServletHolder matching path.
589      * @param pathInContext Path within context.
590      * @return PathMap Entries pathspec to ServletHolder
591      */
592     public Map.Entry getHolderEntry(String pathInContext)
593     {
594         return _servletMap.getMatch(pathInContext);
595     }
596     
597 
598     /* ------------------------------------------------------------ */
599     public Set getResourcePaths(String uriInContext)
600     {
601         try
602         {
603             uriInContext=URI.canonicalPath(uriInContext);
604             if (uriInContext==null)
605                 return Collections.EMPTY_SET;
606             Resource resource=getHttpContext().getResource(uriInContext);
607             if (resource==null || !resource.isDirectory())
608                 return Collections.EMPTY_SET;
609             String[] contents=resource.list();
610             if (contents==null || contents.length==0)
611                 return Collections.EMPTY_SET;
612             HashSet set = new HashSet(contents.length*2);
613             for (int i=0;i<contents.length;i++)
614                 set.add(URI.addPaths(uriInContext,contents[i]));
615             return set;
616         }
617         catch(Exception e)
618         {
619             LogSupport.ignore(log,e);
620         }
621         
622         return Collections.EMPTY_SET;
623     }
624     
625 
626     /* ------------------------------------------------------------ */
627     /** Get a Resource.
628      * If no resource is found, resource aliases are tried.
629      * @param uriInContext 
630      * @return URL of the resource.
631      * @exception MalformedURLException 
632      */
633     public URL getResource(String uriInContext)
634         throws MalformedURLException
635     {        
636         try{
637             Resource resource = getHttpContext().getResource(uriInContext);
638             if (resource!=null && resource.exists())
639                 return resource.getURL();
640         }
641         catch(IllegalArgumentException e)
642         {
643             LogSupport.ignore(log,e);
644         }
645         catch(MalformedURLException e)
646         {
647             throw e;
648         }
649         catch(IOException e)
650         {
651             log.warn(LogSupport.EXCEPTION,e);
652         }
653         return null;
654     }
655 
656     /* ------------------------------------------------------------ */
657     public InputStream getResourceAsStream(String uriInContext)
658     {
659         try
660         {
661             uriInContext=URI.canonicalPath(uriInContext);
662             URL url = getResource(uriInContext);
663             if (url!=null)
664                 return url.openStream();
665         }
666         catch(MalformedURLException e) {LogSupport.ignore(log,e);}
667         catch(IOException e) {LogSupport.ignore(log,e);}
668         return null;
669     }
670 
671     /* ------------------------------------------------------------ */
672     public String getRealPath(String path)
673     {
674         if(log.isDebugEnabled())log.debug("getRealPath of "+path+" in "+this);
675 
676         if (__Slosh2Slash)
677             path=path.replace('\\','/');
678         path=URI.canonicalPath(path);
679         if (path==null)
680             return null;
681 
682         Resource baseResource=getHttpContext().getBaseResource();
683         if (baseResource==null )
684             return null;
685 
686         try{
687             Resource resource = baseResource.addPath(path);
688             File file = resource.getFile();
689 
690             return (file==null)?null:(file.getAbsolutePath());
691         }
692         catch(IOException e)
693         {
694             log.warn(LogSupport.EXCEPTION,e);
695             return null;
696         }
697     }
698 
699     /* ------------------------------------------------------------ */
700     public RequestDispatcher getRequestDispatcher(String uriInContext)
701     {
702         if (uriInContext == null)
703             return null;
704 
705         if (!uriInContext.startsWith("/"))
706             uriInContext="/"+uriInContext;
707         
708         try
709         {
710             String query=null;
711             int q=0;
712             if ((q=uriInContext.indexOf('?'))>0)
713             {
714                 query=uriInContext.substring(q+1);
715                 uriInContext=uriInContext.substring(0,q);
716             }
717             if ((q=uriInContext.indexOf(';'))>0)
718                 uriInContext=uriInContext.substring(0,q);
719 
720             String pathInContext=URI.canonicalPath(URI.decodePath(uriInContext));
721             Map.Entry entry=getHolderEntry(pathInContext);
722             if (entry!=null)
723                 return new Dispatcher(ServletHandler.this,
724                                       uriInContext,
725                                       pathInContext,
726                                       query,
727                                       entry);
728         }
729         catch(Exception e)
730         {
731             LogSupport.ignore(log,e);
732         }
733         return null;
734     }
735 
736     /* ------------------------------------------------------------ */
737     /** Get Named dispatcher.
738      * @param name The name of the servlet. If null or empty string, the
739      * containers default servlet is returned.
740      * @return Request dispatcher for the named servlet.
741      */
742     public RequestDispatcher getNamedDispatcher(String name)
743     {
744         if (name == null || name.length()==0)
745             name=__DEFAULT_SERVLET;
746 
747         try { return new Dispatcher(ServletHandler.this,name); }
748         catch(Exception e) {LogSupport.ignore(log,e);}
749         
750         return null;
751     }
752 
753 
754     
755     /* ------------------------------------------------------------ */
756     void notFound(HttpServletRequest request,
757                   HttpServletResponse response)
758         throws IOException
759     {
760         if(log.isDebugEnabled())log.debug("Not Found "+request.getRequestURI());
761         String method=request.getMethod();
762             
763         // Not found special requests.
764         if (method.equals(HttpRequest.__GET)    ||
765             method.equals(HttpRequest.__HEAD)   ||
766             method.equals(HttpRequest.__POST))
767         {
768             response.sendError(HttpResponse.__404_Not_Found);
769         }
770         else if (method.equals(HttpRequest.__TRACE))
771             handleTrace(request,response);
772         else if (method.equals(HttpRequest.__OPTIONS))
773             handleOptions(request,response);
774         else
775         {
776             // Unknown METHOD
777             response.setHeader(HttpFields.__Allow,__AllowString);
778             response.sendError(HttpResponse.__405_Method_Not_Allowed);
779         }
780     }
781     
782     /* ------------------------------------------------------------ */
783     void handleTrace(HttpServletRequest request,
784                             HttpServletResponse response)
785         throws IOException
786     {
787         response.setHeader(HttpFields.__ContentType,
788                            HttpFields.__MessageHttp);
789         OutputStream out = response.getOutputStream();
790         ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer();
791         writer.write(request.toString());
792         writer.flush();
793         response.setIntHeader(HttpFields.__ContentLength,writer.size());
794         writer.writeTo(out);
795         out.flush();
796     }
797     
798     /* ------------------------------------------------------------ */
799     void handleOptions(HttpServletRequest request,
800                               HttpServletResponse response)
801         throws IOException
802     {
803         // Handle OPTIONS request for entire server
804         if ("*".equals(request.getRequestURI()))
805         {
806             // 9.2
807             response.setIntHeader(HttpFields.__ContentLength,0);
808             response.setHeader(HttpFields.__Allow,__AllowString);                
809             response.flushBuffer();
810         }
811         else
812             response.sendError(HttpResponse.__404_Not_Found);
813     }
814 
815     /* ------------------------------------------------------------ */
816     String getErrorPage(int status,ServletHttpRequest request)
817     {
818         return null;
819     }
820     
821     
822     
823     /* ------------------------------------------------------------ */
824     /* ------------------------------------------------------------ */
825     /* ------------------------------------------------------------ */
826     class Context implements ServletContext
827     {
828         /* -------------------------------------------------------- */
829         ServletHandler getServletHandler()
830         {
831             return ServletHandler.this;
832         }
833         
834         /* -------------------------------------------------------- */
835         public ServletContext getContext(String uri)
836         {        
837             ServletHandler handler= (ServletHandler)
838                 getHttpContext().getHttpServer()
839                 .findHandler(org.mortbay.jetty.servlet.ServletHandler.class,
840                              uri,
841                              getHttpContext().getVirtualHosts());
842             if (handler!=null)
843                 return handler.getServletContext();
844             return null;
845         }
846 
847         /* ------------------------------------------------------------ */
848         public int getMajorVersion()
849         {
850             return 2;
851         }
852 
853         /* ------------------------------------------------------------ */
854         public int getMinorVersion()
855         {
856             return 3;
857         }
858 
859         /* ------------------------------------------------------------ */
860         public String getMimeType(String file)
861         {
862             return getHttpContext().getMimeByExtension(file);
863         }
864 
865         /* ------------------------------------------------------------ */
866         public Set getResourcePaths(String uriInContext)
867         {
868             return ServletHandler.this.getResourcePaths(uriInContext);
869         }
870 
871         /* ------------------------------------------------------------ */
872         public URL getResource(String uriInContext)
873             throws MalformedURLException
874         {
875             return ServletHandler.this.getResource(uriInContext);
876         }
877 
878         /* ------------------------------------------------------------ */
879         public InputStream getResourceAsStream(String uriInContext)
880         {
881             return ServletHandler.this.getResourceAsStream(uriInContext);
882         }
883 
884         /* ------------------------------------------------------------ */
885         public String getRealPath(String path)
886         {
887             return ServletHandler.this.getRealPath(path);
888         }
889 
890         /* ------------------------------------------------------------ */
891         public RequestDispatcher getRequestDispatcher(String uriInContext)
892         {
893             return ServletHandler.this.getRequestDispatcher(uriInContext);
894         }
895 
896         /* ------------------------------------------------------------ */
897         public RequestDispatcher getNamedDispatcher(String name)
898         {
899             return ServletHandler.this.getNamedDispatcher(name);
900         }
901     
902         /* ------------------------------------------------------------ */
903         /**
904          * @deprecated 
905          */
906         public Servlet getServlet(String name)
907         {
908             return null;
909         }
910 
911         /* ------------------------------------------------------------ */
912         /**
913          * @deprecated 
914          */
915         public Enumeration getServlets()
916         {
917             return Collections.enumeration(Collections.EMPTY_LIST);
918         }
919 
920         /* ------------------------------------------------------------ */
921         /**
922          * @deprecated 
923          */
924         public Enumeration getServletNames()
925         {
926             return Collections.enumeration(Collections.EMPTY_LIST);
927         }
928     
929         /* ------------------------------------------------------------ */
930         /** Servlet Log.
931          * Log message to servlet log. Use either the system log or a
932          * LogSinkset via the context attribute
933          * org.mortbay.jetty.servlet.Context.LogSink
934          * @param msg 
935          */
936         public void log(String msg)
937         {
938             log.info(msg);
939         }
940 
941         /* ------------------------------------------------------------ */
942         /**
943          * @deprecated As of Java Servlet API 2.1, use
944          *       {@link #log(String message, Throwable throwable)} 
945          *      instead.
946          */
947         public void log(Exception e, String msg)
948         {
949             log.warn(msg,e);
950         }
951 
952         /* ------------------------------------------------------------ */
953         public void log(String msg, Throwable th)
954         {
955             log.warn(msg,th);
956         }
957 
958         /* ------------------------------------------------------------ */
959         public String getServerInfo()
960         {
961             return Version.__VersionImpl;
962         }
963 
964 
965         /* ------------------------------------------------------------ */
966         /** Get context init parameter.
967          * Delegated to HttpContext.
968          * @param param param name
969          * @return param value or null
970          */
971         public String getInitParameter(String param)
972         {
973             return getHttpContext().getInitParameter(param);
974         }
975 
976         /* ------------------------------------------------------------ */
977         /** Get context init parameter names.
978          * Delegated to HttpContext.
979          * @return Enumeration of names
980          */
981         public Enumeration getInitParameterNames()
982         {
983             return getHttpContext().getInitParameterNames();
984         }
985 
986     
987         /* ------------------------------------------------------------ */
988         /** Get context attribute.
989          * Delegated to HttpContext.
990          * @param name attribute name.
991          * @return attribute
992          */
993         public Object getAttribute(String name)
994         {
995             if (ServletHandler.__J_S_CONTEXT_TEMPDIR.equals(name))
996             {
997                 // Initialize temporary directory
998                 Object t = getHttpContext().getAttribute(ServletHandler.__J_S_CONTEXT_TEMPDIR);
999 
1000                if (t instanceof File)
1001                    return (File)t;
1002                
1003                return getHttpContext().getTempDirectory();
1004            }
1005
1006            return getHttpContext().getAttribute(name);
1007        }
1008
1009        /* ------------------------------------------------------------ */
1010        /** Get context attribute names.
1011         * Delegated to HttpContext.
1012         */
1013        public Enumeration getAttributeNames()
1014        {
1015            return getHttpContext().getAttributeNames();
1016        }
1017
1018        /* ------------------------------------------------------------ */
1019        /** Set context attribute names.
1020         * Delegated to HttpContext.
1021         * @param name attribute name.
1022         * @param value attribute value
1023         */
1024        public void setAttribute(String name, Object value)
1025        {
1026            getHttpContext().setAttribute(name,value);
1027        }
1028
1029        /* ------------------------------------------------------------ */
1030        /** Remove context attribute.
1031         * Delegated to HttpContext.
1032         * @param name attribute name.
1033         */
1034        public void removeAttribute(String name)
1035        {
1036            getHttpContext().removeAttribute(name);
1037        }
1038    
1039        /* ------------------------------------------------------------ */
1040        public String getServletContextName()
1041        {
1042            if (getHttpContext() instanceof WebApplicationContext)
1043                return ((WebApplicationContext)getHttpContext()).getDisplayName();
1044            return null;
1045        }
1046
1047        /* ------------------------------------------------------------ */
1048        public String toString()
1049        {
1050            return "ServletContext["+getHttpContext()+"]";
1051        }
1052    }    
1053}