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

Quick Search    Search Deep

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


1   // ===========================================================================
2   // Copyright (c) 1996-2003 Mort Bay Consulting Pty. Ltd. All rights reserved.
3   // $Id: Dispatcher.java,v 1.65 2003/10/16 23:48:36 gregwilkins Exp $
4   // ---------------------------------------------------------------------------
5   
6   package org.mortbay.jetty.servlet;
7   
8   import java.io.IOException;
9   import java.io.PrintWriter;
10  import java.util.Collections;
11  import java.util.Enumeration;
12  import java.util.HashMap;
13  import java.util.HashSet;
14  import java.util.List;
15  import java.util.Locale;
16  import java.util.Map;
17  
18  import javax.servlet.RequestDispatcher;
19  import javax.servlet.ServletException;
20  import javax.servlet.ServletOutputStream;
21  import javax.servlet.ServletRequest;
22  import javax.servlet.ServletResponse;
23  import javax.servlet.http.HttpServletRequest;
24  import javax.servlet.http.HttpServletRequestWrapper;
25  import javax.servlet.http.HttpServletResponse;
26  import javax.servlet.http.HttpServletResponseWrapper;
27  import javax.servlet.http.HttpSession;
28  
29  import org.apache.commons.logging.Log;
30  import org.apache.commons.logging.LogFactory;
31  import org.mortbay.http.HttpConnection;
32  import org.mortbay.http.PathMap;
33  import org.mortbay.util.LogSupport;
34  import org.mortbay.util.MultiMap;
35  import org.mortbay.util.StringMap;
36  import org.mortbay.util.URI;
37  import org.mortbay.util.UrlEncoded;
38  import org.mortbay.util.WriterOutputStream;
39  
40  
41  /* ------------------------------------------------------------ */
42  /** Servlet RequestDispatcher.
43   * 
44   * @version $Id: Dispatcher.java,v 1.65 2003/10/16 23:48:36 gregwilkins Exp $
45   * @author Greg Wilkins (gregw)
46   */
47  public class Dispatcher implements RequestDispatcher
48  {
49      static Log log = LogFactory.getLog(Dispatcher.class);
50  
51      public final static String __INCLUDE_REQUEST_URI= "javax.servlet.include.request_uri";
52      public final static String __INCLUDE_CONTEXT_PATH= "javax.servlet.include.context_path";
53      public final static String __INCLUDE_SERVLET_PATH= "javax.servlet.include.servlet_path";
54      public final static String __INCLUDE_PATH_INFO= "javax.servlet.include.path_info";
55      public final static String __INCLUDE_QUERY_STRING= "javax.servlet.include.query_string";
56  
57      public final static String __FORWARD_REQUEST_URI= "javax.servlet.forward.request_uri";
58      public final static String __FORWARD_CONTEXT_PATH= "javax.servlet.forward.context_path";
59      public final static String __FORWARD_SERVLET_PATH= "javax.servlet.forward.servlet_path";
60      public final static String __FORWARD_PATH_INFO= "javax.servlet.forward.path_info";
61      public final static String __FORWARD_QUERY_STRING= "javax.servlet.forward.query_string";
62  
63      
64      
65      public final static StringMap __managedAttributes = new StringMap();
66      static
67      {
68          __managedAttributes.put(__INCLUDE_REQUEST_URI,__INCLUDE_REQUEST_URI);
69          __managedAttributes.put(__INCLUDE_CONTEXT_PATH,__INCLUDE_CONTEXT_PATH);
70          __managedAttributes.put(__INCLUDE_SERVLET_PATH,__INCLUDE_SERVLET_PATH);
71          __managedAttributes.put(__INCLUDE_PATH_INFO,__INCLUDE_PATH_INFO);
72          __managedAttributes.put(__INCLUDE_QUERY_STRING,__INCLUDE_QUERY_STRING);
73          
74          __managedAttributes.put(__FORWARD_REQUEST_URI,__FORWARD_REQUEST_URI);
75          __managedAttributes.put(__FORWARD_CONTEXT_PATH,__FORWARD_CONTEXT_PATH);
76          __managedAttributes.put(__FORWARD_SERVLET_PATH,__FORWARD_SERVLET_PATH);
77          __managedAttributes.put(__FORWARD_PATH_INFO,__FORWARD_PATH_INFO);
78          __managedAttributes.put(__FORWARD_QUERY_STRING,__FORWARD_QUERY_STRING);
79      }
80      
81      ServletHandler _servletHandler;
82      ServletHolder _holder=null;
83      String _pathSpec;
84      String _uriInContext;
85      String _pathInContext;
86      String _query;
87      
88      /* ------------------------------------------------------------ */
89      /** Constructor. 
90      /** Constructor. 
91       * @param servletHandler 
92       * @param uriInContext Encoded uriInContext
93       * @param pathInContext Encoded pathInContext
94       * @param query
95       * @exception IllegalStateException 
96       */
97      Dispatcher(ServletHandler servletHandler,
98                 String uriInContext,
99                 String pathInContext,
100                String query,
101                Map.Entry entry)
102         throws IllegalStateException
103     {
104         if(log.isDebugEnabled())log.debug("Dispatcher for "+servletHandler+","+uriInContext+","+query);
105         
106         _servletHandler=servletHandler;
107         _uriInContext=uriInContext;
108         _pathInContext=pathInContext;        
109         _query=query;
110         _pathSpec=(String)entry.getKey();
111         _holder = (ServletHolder)entry.getValue();
112     }
113     
114     /* ------------------------------------------------------------ */
115     /** Constructor. 
116      * @param servletHandler
117      * @param name
118      */
119     Dispatcher(ServletHandler servletHandler,String name)
120         throws IllegalStateException
121     {
122         _servletHandler=servletHandler;
123         _holder=_servletHandler.getServletHolder(name);
124         if (_holder==null)
125             throw new IllegalStateException("No named servlet handler in context");
126     }
127 
128     /* ------------------------------------------------------------ */
129     public boolean isNamed()
130     {
131         return _pathInContext==null;
132     }
133     
134     /* ------------------------------------------------------------ */
135     public void include(ServletRequest servletRequest,
136                         ServletResponse servletResponse)
137         throws ServletException, IOException     
138     {
139         dispatch(servletRequest,servletResponse,FilterHolder.__INCLUDE);
140     }
141     
142     /* ------------------------------------------------------------ */
143     public void forward(ServletRequest servletRequest,
144                         ServletResponse servletResponse)
145         throws ServletException,IOException
146     {
147         dispatch(servletRequest,servletResponse,FilterHolder.__FORWARD);
148     }
149     
150     /* ------------------------------------------------------------ */
151     void error(ServletRequest servletRequest,
152                         ServletResponse servletResponse)
153         throws ServletException,IOException
154     {
155         dispatch(servletRequest,servletResponse,FilterHolder.__ERROR);
156     }
157     
158     /* ------------------------------------------------------------ */
159     void dispatch(ServletRequest servletRequest,
160                   ServletResponse servletResponse,
161                   int filterType)
162         throws ServletException,IOException
163     {
164         HttpServletRequest httpServletRequest=(HttpServletRequest)servletRequest;
165         HttpServletResponse httpServletResponse=(HttpServletResponse)servletResponse;
166 
167         HttpConnection httpConnection=
168             _servletHandler.getHttpContext().getHttpConnection();
169         ServletHttpRequest servletHttpRequest=
170             (ServletHttpRequest)httpConnection.getRequest().getWrapper();
171         
172         // wrap the request and response
173         DispatcherRequest request = new DispatcherRequest(httpServletRequest,
174                                                           servletHttpRequest,
175                                                           filterType);
176         DispatcherResponse response = new DispatcherResponse(request,
177                                                              httpServletResponse);        
178         
179         if (filterType!=FilterHolder.__INCLUDE)
180             servletResponse.resetBuffer();
181         
182         // Merge parameters
183         String query=_query;
184         MultiMap parameters=null;
185         if (query!=null)
186         {
187             // Add the parameters
188             parameters=new MultiMap();
189             UrlEncoded.decodeTo(query,parameters);
190             request.addParameters(parameters);
191         }
192         
193         Object old_scope = null;
194         try
195         {
196             if (request.crossContext())
197             {
198                 // Setup new context
199                 old_scope=
200                     _servletHandler.getHttpContext()
201                     .enterContextScope(httpConnection.getRequest(),httpConnection.getResponse());
202             }
203         
204             if (isNamed())
205             {
206                 // No further modifications required.
207                 _servletHandler.dispatch(null,request,response,_holder);
208             }
209             else
210             {
211                 // merge query string
212                 String oldQ=httpServletRequest.getQueryString();
213                 if (oldQ!=null && oldQ.length()>0)
214                 {
215                     if (query==null)
216                         query=oldQ;
217                     else
218                         query=query+"&"+oldQ;
219                 }
220                 
221                 
222                 // Adjust servlet paths
223                 request.setPaths(_servletHandler.getHttpContext().getContextPath(),
224                                  PathMap.pathMatch(_pathSpec,_pathInContext),
225                                  PathMap.pathInfo(_pathSpec,_pathInContext),
226                                  query);
227                 _servletHandler.dispatch(_pathInContext,request,response,_holder);
228                 
229                 if (filterType!=FilterHolder.__INCLUDE)
230                     response.close();
231                 else if (response.isFlushNeeded())
232                     response.flushBuffer();
233             }
234         }
235         finally
236         {
237             // restore context
238             if (request.crossContext())
239                 _servletHandler.getHttpContext()
240                     .leaveContextScope(httpConnection.getRequest(),
241                                        httpConnection.getResponse(),
242                                        old_scope);
243         }   
244     }
245 
246     /* ------------------------------------------------------------ */
247     public String toString()
248     {
249         return "Dispatcher["+_pathSpec+","+_holder+"]";
250     }
251         
252 
253     /* ------------------------------------------------------------ */
254     /* ------------------------------------------------------------ */
255     /* ------------------------------------------------------------ */
256     class DispatcherRequest extends HttpServletRequestWrapper
257     {   
258         int _filterType;
259         String _contextPath;
260         String _servletPath;
261         String _pathInfo;
262         String _query;
263         MultiMap _parameters;
264         HashMap _attributes;
265         boolean _xContext;
266         HttpSession _xSession;
267         String _requestedSessionId;
268         ServletHttpRequest _servletHttpRequest;
269         
270         /* ------------------------------------------------------------ */
271         DispatcherRequest(HttpServletRequest httpServletRequest,
272                           ServletHttpRequest servletHttpRequest,
273                           int filterType)
274         {
275             super(httpServletRequest);
276             _servletHttpRequest=servletHttpRequest;
277             _filterType=filterType;
278             
279             // Is this being dispatched to a different context?
280             _xContext=
281                 servletHttpRequest.getServletHandler()!=_servletHandler;
282             if (_xContext)
283             {
284                 // Look for an existing or requested session ID.
285                 HttpSession session=httpServletRequest.getSession(false);
286                 String session_id=(session==null)
287                     ?httpServletRequest.getRequestedSessionId()
288                     :session.getId();
289 
290                 // Look for that session in new context to access it.
291                 if (session_id!=null)
292                 {
293                     _xSession=_servletHandler.getHttpSession(session_id);
294                     if (_xSession!=null)
295                         ((SessionManager.Session)_xSession).access(); 
296                 }
297             }
298         }
299 
300         /* ------------------------------------------------------------ */
301         boolean crossContext()
302         {
303             return _xContext;
304         }
305         
306         /* ------------------------------------------------------------ */
307         void setPaths(String cp,String sp, String pi, String qs)
308         {
309             _contextPath = (cp.length()==1 && cp.charAt(0)=='/')?"":cp;
310             _servletPath=sp;
311             _pathInfo=pi;
312             _query=qs;
313         }
314         
315         /* ------------------------------------------------------------ */
316         int getFilterType()
317         {
318             return _filterType;
319         }
320 
321         /* ------------------------------------------------------------ */
322         String getPathInContext()
323         {
324             if (_pathInContext!=null)
325                 return _pathInContext;
326             else
327                 return URI.addPaths(getServletPath(),getPathInfo());
328         }
329         
330         /* ------------------------------------------------------------ */
331         public String getRequestURI()
332         {
333             if (_filterType==FilterHolder.__INCLUDE || isNamed())
334                 return super.getRequestURI();
335             return URI.addPaths(_contextPath,_uriInContext);
336         }
337         
338         /* ------------------------------------------------------------ */
339         public StringBuffer getRequestURL()
340         {
341             if (_filterType==FilterHolder.__INCLUDE || isNamed())
342                 return super.getRequestURL();
343             StringBuffer buf = getRootURL();
344             if (_contextPath.length()>0)
345                 buf.append(_contextPath);
346             buf.append(_uriInContext);
347             return buf;
348         }
349 
350         
351         /* ------------------------------------------------------------ */
352         public String getPathTranslated()
353         {
354             String info=getPathInfo();
355             if (info==null)
356                 return null;
357             return getRealPath(info);
358         }
359         
360         /* ------------------------------------------------------------ */
361         StringBuffer getRootURL()
362         {
363             StringBuffer buf = super.getRequestURL();
364             int d=3;
365             for (int i=0;i<buf.length();i++)
366             {
367                 if (buf.charAt(i)=='/' && --d==0)
368                 {
369                     buf.setLength(i);
370                     break;
371                 }
372             }
373             return buf;
374         }
375         
376         /* ------------------------------------------------------------ */
377         public String getContextPath()
378         {
379             return(_filterType==FilterHolder.__INCLUDE||isNamed())?super.getContextPath():_contextPath;
380         }
381         
382         /* ------------------------------------------------------------ */
383         public String getServletPath()
384         {
385             return(_filterType==FilterHolder.__INCLUDE||isNamed())?super.getServletPath():_servletPath;
386         }
387         
388         /* ------------------------------------------------------------ */
389         public String getPathInfo()
390         {
391             return(_filterType==FilterHolder.__INCLUDE||isNamed())?super.getPathInfo():_pathInfo;
392         }
393         
394         /* ------------------------------------------------------------ */
395         public String getQueryString()
396         {
397             return(_filterType==FilterHolder.__INCLUDE||isNamed())?super.getQueryString():_query;
398         }
399         
400 
401         /* ------------------------------------------------------------ */
402         void addParameters(MultiMap parameters)
403         {
404             _parameters=parameters;
405         }
406         
407         /* -------------------------------------------------------------- */
408         public Enumeration getParameterNames()
409         {
410             if (_parameters==null)
411                 return super.getParameterNames();
412             
413             HashSet set = new HashSet(_parameters.keySet());
414             Enumeration e = super.getParameterNames();
415             while (e.hasMoreElements())
416                 set.add(e.nextElement());
417 
418             return Collections.enumeration(set);
419         }
420         
421         /* -------------------------------------------------------------- */
422         public String getParameter(String name)
423         {
424             if (_parameters==null)
425                 return super.getParameter(name);
426             String value=_parameters.getString(name);
427             if (value!=null)
428                 return value;
429             return super.getParameter(name);
430         }
431         
432         /* -------------------------------------------------------------- */
433         public String[] getParameterValues(String name)
434         {
435             List v0=_parameters==null?null:_parameters.getValues(name);
436             String[] v1=super.getParameterValues(name);
437 
438             if (v0==null && v1==null)
439                 return null;
440             
441             String[] a=new String[(v0==null?0:v0.size())+(v1==null?0:v1.length)];
442             if (v0==null || v0.size()==0)
443                 return v1;
444             if (v1==null || v1.length==0)
445                 return (String[])v0.toArray(a);
446             
447             for (int i=0;i<v0.size();i++)
448                 a[i]=(String)v0.get(i);
449             for (int i=0;i<v1.length;i++)
450                 a[v0.size()+i]=v1[i];
451             return a;
452         }
453         
454         /* -------------------------------------------------------------- */
455         public Map getParameterMap()
456         {       
457             if (_parameters==null)
458                 return super.getParameterMap();
459             
460             Map m0 = super.getParameterMap();
461             if (m0==null || m0.size()==0)
462                 return _parameters.toStringArrayMap();
463 
464             Enumeration p = getParameterNames();
465             Map m = new HashMap();
466             while(p.hasMoreElements())
467             {
468                 String name=(String)p.nextElement();
469                 m.put(name,getParameterValues(name));
470             }
471             
472             return m;
473         }
474 
475         /* ------------------------------------------------------------ */
476         public void setAttribute(String name, Object value)
477         {
478             if (__managedAttributes.containsKey(name))
479             {
480                 if (_attributes==null)
481                     _attributes=new HashMap(3);
482                 _attributes.put(name,value);
483             }
484             else
485                 super.setAttribute(name,value);
486         }
487         
488         /* ------------------------------------------------------------ */
489         public Object getAttribute(String name)
490         {
491             if (_attributes!=null && _attributes.containsKey(name))
492                 return _attributes.get(name);
493                 
494             if (_filterType==FilterHolder.__INCLUDE && !isNamed())
495             {
496                 if (name.equals(__INCLUDE_PATH_INFO))    return _pathInfo;
497                 if (name.equals(__INCLUDE_REQUEST_URI))  return URI.addPaths(_contextPath,_uriInContext);
498                 if (name.equals(__INCLUDE_SERVLET_PATH)) return _servletPath;
499                 if (name.equals(__INCLUDE_CONTEXT_PATH)) return _contextPath;
500                 if (name.equals(__INCLUDE_QUERY_STRING)) return _query;
501             }
502             else
503             {
504                 if (name.equals(__INCLUDE_PATH_INFO))    return null;
505                 if (name.equals(__INCLUDE_REQUEST_URI))  return null;
506                 if (name.equals(__INCLUDE_SERVLET_PATH)) return null;
507                 if (name.equals(__INCLUDE_CONTEXT_PATH)) return null;
508                 if (name.equals(__INCLUDE_QUERY_STRING)) return null;
509             }
510 
511             if (_filterType!=FilterHolder.__INCLUDE)
512             {
513                 if (name.equals(__FORWARD_PATH_INFO))
514                     return _servletHttpRequest.getPathInfo();
515                 if (name.equals(__FORWARD_REQUEST_URI))
516                     return _servletHttpRequest.getRequestURI();
517                 if (name.equals(__FORWARD_SERVLET_PATH))
518                     return _servletHttpRequest.getServletPath();
519                 if (name.equals(__FORWARD_CONTEXT_PATH))
520                     return _servletHttpRequest.getContextPath();
521                 if (name.equals(__FORWARD_QUERY_STRING))
522                     return _servletHttpRequest.getQueryString();
523             }
524             
525             
526             return super.getAttribute(name);
527         }
528         
529         /* ------------------------------------------------------------ */
530         public Enumeration getAttributeNames()
531         {
532             HashSet set=new HashSet();
533             Enumeration e=super.getAttributeNames();
534             while (e.hasMoreElements())
535                 set.add(e.nextElement());
536             
537             if (_filterType==FilterHolder.__INCLUDE && !isNamed())
538             {
539                 set.add(__INCLUDE_PATH_INFO);
540                 set.add(__INCLUDE_REQUEST_URI);
541                 set.add(__INCLUDE_SERVLET_PATH);
542                 set.add(__INCLUDE_CONTEXT_PATH);
543                 set.add(__INCLUDE_QUERY_STRING);
544             }
545             else
546             {
547                 set.remove(__INCLUDE_PATH_INFO);
548                 set.remove(__INCLUDE_REQUEST_URI);
549                 set.remove(__INCLUDE_SERVLET_PATH);
550                 set.remove(__INCLUDE_CONTEXT_PATH);
551                 set.remove(__INCLUDE_QUERY_STRING);
552             }
553 
554             if (_filterType!=FilterHolder.__INCLUDE)
555             {
556                 set.add(__FORWARD_PATH_INFO);
557                 set.add(__FORWARD_REQUEST_URI);
558                 set.add(__FORWARD_SERVLET_PATH);
559                 set.add(__FORWARD_CONTEXT_PATH);
560                 set.add(__FORWARD_QUERY_STRING);
561             }
562             
563             if (_attributes!=null)
564                 set.addAll(_attributes.keySet());
565             
566             return Collections.enumeration(set);
567         }
568         
569         /* ------------------------------------------------------------ */
570         public HttpSession getSession(boolean create)
571         {
572             if (_xContext)
573             {
574                 if (_xSession==null)
575                 {
576                     log.debug("Ctx dispatch session");
577                     if (_requestedSessionId==null)
578                         _requestedSessionId=super.getSession(true).getId();
579                     _xSession=_servletHandler.getHttpSession(_requestedSessionId);
580                     if (create && _xSession==null)
581                         _xSession=_servletHandler.newHttpSession(this);
582                 }
583                 return _xSession;
584             }
585             else
586                 return super.getSession(create);
587         }
588     
589         /* ------------------------------------------------------------ */
590         public HttpSession getSession()
591         {
592             return getSession(true);
593         }
594 
595         /* ------------------------------------------------------------ */
596         public String getRequestedSessionId()
597         {
598             if (_requestedSessionId!=null)
599                 return _requestedSessionId;
600             return super.getRequestedSessionId();
601         }
602         
603         /* ------------------------------------------------------------ */
604         public String getRealPath(String path)
605         {
606             return _servletHandler.getServletContext().getRealPath(path);
607         }
608         
609         /* ------------------------------------------------------------ */
610         public RequestDispatcher getRequestDispatcher(String url)
611         {
612             if (url == null)
613                 return null;
614             
615             if (!url.startsWith("/"))
616             {
617                 String relTo=URI.addPaths(getServletPath(),getPathInfo());
618                 int slash=relTo.lastIndexOf("/");
619                 if (slash>1)
620                     relTo=relTo.substring(0,slash+1);
621                 else
622                     relTo="/";
623                 url=URI.addPaths(relTo,url);
624             }
625             
626             return _servletHandler.getServletContext().getRequestDispatcher(url);
627         }
628         
629     }
630     
631     /* ------------------------------------------------------------ */
632     /* ------------------------------------------------------------ */
633     /* ------------------------------------------------------------ */
634     class DispatcherResponse extends HttpServletResponseWrapper
635     {
636         DispatcherRequest _request;
637         private ServletOutputStream _out=null;
638         private PrintWriter _writer=null;
639         private boolean _flushNeeded=false;
640         private boolean _include;
641         
642         /* ------------------------------------------------------------ */
643         DispatcherResponse(DispatcherRequest request, HttpServletResponse response)
644         {
645             super(response);
646             _request=request;
647             _include=_request._filterType==FilterHolder.__INCLUDE;
648         }
649 
650         /* ------------------------------------------------------------ */
651         public ServletOutputStream getOutputStream()
652             throws IOException
653         {
654             if (_writer!=null)
655                 throw new IllegalStateException("getWriter called");
656 
657             if (_out==null)
658             {
659                 try {_out=super.getOutputStream();}
660                 catch(IllegalStateException e)
661                 {
662                     LogSupport.ignore(log,e);
663                     _flushNeeded=true;
664                     _out=new ServletOut(new WriterOutputStream(super.getWriter()));
665                 }
666             }
667 
668             if (_include)
669                 _out=new DontCloseServletOut(_out);
670             
671             return _out;
672         }  
673       
674         /* ------------------------------------------------------------ */
675         public PrintWriter getWriter()
676             throws IOException
677         {
678             if (_out!=null)
679                 throw new IllegalStateException("getOutputStream called");
680 
681             if (_writer==null)
682             {                
683                 try{_writer=super.getWriter();}
684                 catch(IllegalStateException e)
685                 {
686                     if (log.isDebugEnabled()) log.warn(LogSupport.EXCEPTION,e);
687                     _flushNeeded=true;
688                     _writer = new ServletWriter(super.getOutputStream(),
689                                                 getCharacterEncoding());
690                 }
691             }
692 
693             if (_include)
694                 _writer=new DontCloseWriter(_writer);
695             return _writer;
696         }
697 
698         /* ------------------------------------------------------------ */
699         boolean isFlushNeeded()
700         {
701             return _flushNeeded;
702         }
703         
704         /* ------------------------------------------------------------ */
705         public void flushBuffer()
706             throws IOException
707         {
708             if (_writer!=null)
709                 _writer.flush();
710             if (_out!=null)
711                 _out.flush();
712             super.flushBuffer();
713         }
714         
715         /* ------------------------------------------------------------ */
716         public void close()
717             throws IOException
718         {
719             if (_writer!=null)
720                 _writer.close();
721             if (_out!=null)
722                 _out.close();
723         }
724         
725         /* ------------------------------------------------------------ */
726         public void setLocale(Locale locale)
727         {
728             if (!_include) super.setLocale(locale);
729         }
730         
731         /* ------------------------------------------------------------ */
732         public void sendError(int status, String message)
733             throws IOException
734         {
735             if (!_include) super.sendError(status,message);
736         }
737         
738         /* ------------------------------------------------------------ */
739         public void sendError(int status)
740             throws IOException
741         {
742             if (!_include) super.sendError(status);
743         }
744         
745         /* ------------------------------------------------------------ */
746         public void sendRedirect(String url)
747             throws IOException
748         {
749             if (!_include)
750             {
751                 if (!url.startsWith("http:/")&&!url.startsWith("https:/"))
752                 {
753                     StringBuffer buf = _request.getRootURL();
754                     
755                     if (url.startsWith("/"))
756                         buf.append(URI.canonicalPath(url));
757                     else
758                         buf.append(URI.canonicalPath(URI.addPaths(URI.parentPath(_request.getRequestURI()),url)));
759                     url=buf.toString();
760                 }
761                 
762                 super.sendRedirect(url);
763             }
764         }
765         
766         /* ------------------------------------------------------------ */
767         public void setDateHeader(String name, long value)
768         {
769             if (!_include) super.setDateHeader(name,value);
770         }
771         
772         /* ------------------------------------------------------------ */
773         public void setHeader(String name, String value)
774         {
775             if (!_include) super.setHeader(name,value);
776         }
777         
778         /* ------------------------------------------------------------ */
779         public void setIntHeader(String name, int value)
780         {
781             if (!_include) super.setIntHeader(name,value);
782         }
783         
784         /* ------------------------------------------------------------ */
785         public void addHeader(String name, String value)
786         {
787             if (!_include) super.addHeader(name,value);
788         }
789         
790         /* ------------------------------------------------------------ */
791         public void addDateHeader(String name, long value)
792         {
793             if (!_include) super.addDateHeader(name,value);
794         }
795         
796         /* ------------------------------------------------------------ */
797         public void addIntHeader(String name, int value)
798         {
799             if (!_include) super.addIntHeader(name,value);
800         }
801         
802         /* ------------------------------------------------------------ */
803         public void setStatus(int status)
804         {
805             if (!_include) super.setStatus(status);
806         }
807         
808         /* ------------------------------------------------------------ */
809         /**
810         * The default behavior of this method is to call setStatus(int sc, String sm)
811         * on the wrapped response object.
812         * 
813         * @deprecated As of version 2.1 of the Servlet spec.
814         * To set a status code 
815         * use <code>setStatus(int)</code>, to send an error with a description
816         * use <code>sendError(int, String)</code>.
817         * 
818         * @param status the status code
819         * @param message the status message
820         */
821         public void setStatus(int status, String message)
822         {
823             if (!_include) super.setStatus(status,message);
824         }
825         
826         /* ------------------------------------------------------------ */
827         public void setContentLength(int len)
828         {
829             if (!_include) super.setContentLength(len);
830         }
831         
832         /* ------------------------------------------------------------ */
833         public void setContentType(String contentType)
834         {
835             if (!_include) super.setContentType(contentType);
836         }
837     }
838 
839 
840     /* ------------------------------------------------------------ */
841     /* ------------------------------------------------------------ */
842     /* ------------------------------------------------------------ */
843     private class DontCloseWriter extends PrintWriter
844     {
845         DontCloseWriter(PrintWriter writer)
846         {
847             super(writer);
848         }
849 
850         public void close()
851         {}
852     }
853 
854     /* ------------------------------------------------------------ */
855     /* ------------------------------------------------------------ */
856     /* ------------------------------------------------------------ */
857     private class DontCloseServletOut extends ServletOut
858     {
859         DontCloseServletOut(ServletOutputStream output)
860         {
861             super(output);
862         }
863 
864         public void close()
865             throws IOException
866         {}
867     }
868 };