KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > server > connection > AbstractHttpRequest


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.server.connection;
31
32 import com.caucho.i18n.CharacterEncoding;
33 import com.caucho.log.Log;
34 import com.caucho.security.SecurityContext;
35 import com.caucho.security.SecurityContextProvider;
36 import com.caucho.server.dispatch.DispatchServer;
37 import com.caucho.server.dispatch.Invocation;
38 import com.caucho.server.port.Port;
39 import com.caucho.server.port.TcpConnection;
40 import com.caucho.server.security.AbstractAuthenticator;
41 import com.caucho.server.security.AbstractLogin;
42 import com.caucho.server.session.SessionImpl;
43 import com.caucho.server.session.SessionManager;
44 import com.caucho.server.webapp.WebApp;
45 import com.caucho.util.*;
46 import com.caucho.vfs.BufferedReaderAdapter;
47 import com.caucho.vfs.Encoding;
48 import com.caucho.vfs.Path;
49 import com.caucho.vfs.ReadStream;
50
51 import javax.servlet.RequestDispatcher JavaDoc;
52 import javax.servlet.ServletContext JavaDoc;
53 import javax.servlet.ServletException JavaDoc;
54 import javax.servlet.ServletInputStream JavaDoc;
55 import javax.servlet.ServletRequestAttributeEvent JavaDoc;
56 import javax.servlet.ServletRequestAttributeListener JavaDoc;
57 import javax.servlet.http.Cookie JavaDoc;
58 import javax.servlet.http.HttpServletResponse JavaDoc;
59 import javax.servlet.http.HttpSession JavaDoc;
60 import java.io.BufferedReader JavaDoc;
61 import java.io.IOException JavaDoc;
62 import java.io.UnsupportedEncodingException JavaDoc;
63 import java.net.InetAddress JavaDoc;
64 import java.security.Principal JavaDoc;
65 import java.security.cert.X509Certificate JavaDoc;
66 import java.util.ArrayList JavaDoc;
67 import java.util.Collections JavaDoc;
68 import java.util.Enumeration JavaDoc;
69 import java.util.HashMap JavaDoc;
70 import java.util.Locale JavaDoc;
71 import java.util.Map JavaDoc;
72 import java.util.logging.Level JavaDoc;
73 import java.util.logging.Logger JavaDoc;
74
75 /**
76  * Abstract request implementing methods common to the different
77  * request implementations.
78  */

79 public abstract class AbstractHttpRequest
80   implements CauchoRequest, SecurityContextProvider {
81   protected static final Logger JavaDoc log = Log.open(AbstractHttpRequest.class);
82
83   static final L10N L = new L10N(AbstractHttpRequest.class);
84
85   protected static final CaseInsensitiveIntMap _headerCodes;
86   
87   public static final String JavaDoc REQUEST_URI = "javax.servlet.include.request_uri";
88   public static final String JavaDoc CONTEXT_PATH = "javax.servlet.include.context_path";
89   public static final String JavaDoc SERVLET_PATH = "javax.servlet.include.servlet_path";
90   public static final String JavaDoc PATH_INFO = "javax.servlet.include.path_info";
91   public static final String JavaDoc QUERY_STRING = "javax.servlet.include.query_string";
92   
93   public static final String JavaDoc STATUS_CODE = "javax.servlet.error.status_code";
94   public static final String JavaDoc EXCEPTION_TYPE = "javax.servlet.error.exception_type";
95   public static final String JavaDoc MESSAGE = "javax.servlet.error.message";
96   public static final String JavaDoc EXCEPTION = "javax.servlet.error.exception";
97   public static final String JavaDoc ERROR_URI = "javax.servlet.error.request_uri";
98   public static final String JavaDoc SERVLET_NAME = "javax.servlet.error.servlet_name";
99   
100   public static final String JavaDoc JSP_EXCEPTION = "javax.servlet.jsp.jspException";
101   
102   public static final String JavaDoc SHUTDOWN = "com.caucho.shutdown";
103   
104   private static final String JavaDoc CHAR_ENCODING = "resin.form.character.encoding";
105   private static final String JavaDoc FORM_LOCALE = "resin.form.local";
106   private static final String JavaDoc CAUCHO_CHAR_ENCODING = "caucho.form.character.encoding";
107
108   private static final char []CONNECTION = "connection".toCharArray();
109   private static final char []COOKIE = "cookie".toCharArray();
110   private static final char []EXPECT = "expect".toCharArray();
111   private static final char []HOST = "host".toCharArray();
112   
113   private static final char []CONTINUE_100 = "100-continue".toCharArray();
114   private static final char []CLOSE = "close".toCharArray();
115
116   private static final ServletRequestAttributeListener JavaDoc []NULL_LISTENERS =
117     new ServletRequestAttributeListener JavaDoc[0];
118   
119   protected final DispatchServer _server;
120   
121   protected final Connection _conn;
122   protected final TcpConnection _tcpConn;
123
124   private SecurityContextProvider _oldProvider;
125   protected AbstractHttpResponse _response;
126
127   protected Invocation _invocation;
128
129   private boolean _keepalive;
130
131   protected CharSegment _hostHeader;
132   protected boolean _expect100Continue;
133     
134   private Cookie JavaDoc []_cookiesIn;
135   private ArrayList JavaDoc<Cookie JavaDoc> _cookies = new ArrayList JavaDoc<Cookie JavaDoc>();
136   
137   // True if the page depends on cookies
138
private boolean _varyCookies;
139   // The cookie the page depends on
140
private String JavaDoc _varyCookie;
141   private boolean _hasCookie;
142   private boolean _isSessionIdFromCookie;
143   
144   protected int _sessionGroup;
145
146   private boolean _sessionIsLoaded;
147   private SessionImpl _session;
148
149   // Connection stream
150
protected final ReadStream _rawRead;
151   // Stream for reading post contents
152
protected final ReadStream _readStream;
153
154   // True if the post stream has been initialized
155
protected boolean _hasReadStream;
156
157   // Servlet input stream for post contents
158
private final ServletInputStreamImpl _is = new ServletInputStreamImpl();
159
160   // character incoding for a Post
161
private String JavaDoc _readEncoding;
162   // Reader for post contents
163
private final BufferedReaderAdapter _bufferedReader;
164
165   private boolean _hasReader;
166   private boolean _hasInputStream;
167
168   // HttpServletRequest stuff
169
private final Form _formParser = new Form();
170   private final HashMapImpl<String JavaDoc,String JavaDoc[]> _form = new HashMapImpl<String JavaDoc,String JavaDoc[]>();
171   private HashMapImpl<String JavaDoc,String JavaDoc[]> _filledForm;
172   
173   private final HashMapImpl<String JavaDoc,Object JavaDoc> _attributes = new HashMapImpl<String JavaDoc,Object JavaDoc>();
174
175   private ArrayList JavaDoc<Locale JavaDoc> _locales = new ArrayList JavaDoc<Locale JavaDoc>();
176
177   private long _startTime;
178   private ArrayList JavaDoc<Path> _closeOnExit = new ArrayList JavaDoc<Path>();
179
180   // Efficient date class for printing date headers
181
protected final QDate _calendar = new QDate();
182   private final CharBuffer _cbName = new CharBuffer();
183   private final CharBuffer _cbValue = new CharBuffer();
184   protected final CharBuffer _cb = new CharBuffer();
185   // private final ArrayList<CharSegment> _arrayList = new ArrayList<CharSegment>();
186

187   private final byte []_address = new byte[256];
188
189   private final byte []_logBuffer = new byte[8 * 1024];
190
191   private ServletRequestAttributeListener JavaDoc []_attributeListeners;
192   
193   /**
194    * Create a new Request. Because the actual initialization occurs with
195    * the start() method, this just allocates statics.
196    *
197    * @param server the parent server
198    */

199   protected AbstractHttpRequest(DispatchServer server, Connection conn)
200   {
201     _server = server;
202
203     _conn = conn;
204     if (conn != null)
205       _rawRead = conn.getReadStream();
206     else
207       _rawRead = null;
208
209     if (conn instanceof TcpConnection)
210       _tcpConn = (TcpConnection) conn;
211     else
212       _tcpConn = null;
213
214     _readStream = new ReadStream();
215     _readStream.setReuseBuffer(true);
216
217     _bufferedReader = new BufferedReaderAdapter(_readStream);
218   }
219
220   /**
221    * Initialization.
222    */

223   public void init()
224   {
225   }
226
227   /**
228    * Returns the connection.
229    */

230   public final Connection getConnection()
231   {
232     return _conn;
233   }
234
235   /**
236    * returns the dispatch server.
237    */

238   public final DispatchServer getDispatchServer()
239   {
240     return _server;
241   }
242
243   /**
244    * Prepare the Request object for a new request.
245    *
246    * @param s the raw connection stream
247    */

248   protected void start()
249     throws IOException JavaDoc
250   {
251     _oldProvider = SecurityContext.setProvider(this);
252     
253     _invocation = null;
254
255     _varyCookies = false;
256     _varyCookie = null;
257     _hasCookie = false;
258     
259     _startTime = Alarm.getCurrentTime();
260
261     _hostHeader = null;
262     _expect100Continue = false;
263     
264     _cookiesIn = null;
265     _cookies.clear();
266
267     _sessionGroup = -1;
268     _session = null;
269     _sessionIsLoaded = false;
270     
271     _hasReadStream = false;
272     _hasReader = false;
273     _hasInputStream = false;
274
275     _filledForm = null;
276     _locales.clear();
277
278     _readEncoding = null;
279
280     _keepalive = true;
281     _isSessionIdFromCookie = false;
282
283     _oldProvider = null;
284
285     _attributeListeners = NULL_LISTENERS;
286
287     if (_tcpConn != null)
288       _tcpConn.beginActive();
289   }
290
291   /**
292    * Returns true if client disconnects should be ignored.
293    */

294   public boolean isIgnoreClientDisconnect()
295   {
296     // server/183c
297

298     if (_invocation == null)
299       return true;
300     else
301       return _invocation.getWebApp().isIgnoreClientDisconnect();
302   }
303
304   /**
305    * Returns the response for this request.
306    */

307   public CauchoResponse getResponse()
308   {
309     return _response;
310   }
311
312   /**
313    * Returns the local server name.
314    */

315   public String JavaDoc getServerName()
316   {
317     String JavaDoc host = _conn.getVirtualHost();
318
319     /*
320     if (host == null && _invocation != null)
321       host = _invocation.getHostName();
322     */

323     
324     CharSequence JavaDoc rawHost;
325     if (host == null && (rawHost = getHost()) != null) {
326       if (rawHost instanceof CharSegment) {
327     CharSegment cb = (CharSegment) rawHost;
328     
329     char []buffer = cb.getBuffer();
330     int offset = cb.getOffset();
331     int length = cb.getLength();
332
333     for (int i = length - 1; i >= 0; i--) {
334       char ch = buffer[i + offset];
335
336       if ('A' <= ch && ch <= 'Z')
337         buffer[i + offset] = (char) (ch + 'a' - 'A');
338     }
339     
340     host = new String JavaDoc(buffer, offset, length);
341       }
342       else
343     return rawHost.toString().toLowerCase();
344     }
345
346     if (host == null) {
347       InetAddress JavaDoc addr = _conn.getLocalAddress();
348       return addr.getHostName();
349     }
350
351     int p1 = host.lastIndexOf('/');
352     if (p1 < 0)
353       p1 = 0;
354     
355     int p = host.lastIndexOf(':');
356     if (p >= 0 && p1 < p)
357       return host.substring(p1, p);
358     else
359       return host;
360   }
361
362   protected CharSequence JavaDoc getHost()
363   {
364     return null;
365   }
366
367   /**
368    * Returns the server's port.
369    */

370   public int getServerPort()
371   {
372     String JavaDoc host = _conn.getVirtualHost();
373     
374     CharSequence JavaDoc rawHost;
375     if (host == null && (rawHost = getHost()) != null) {
376       int length = rawHost.length();
377       int i;
378
379       for (i = length - 1; i >= 0; i--) {
380     if (rawHost.charAt(i) == ':') {
381       int port = 0;
382
383       for (i++; i < length; i++) {
384         char ch = rawHost.charAt(i);
385
386         if ('0' <= ch && ch <= '9')
387           port = 10 * port + ch - '0';
388       }
389
390       return port;
391     }
392       }
393       
394       return isSecure() ? 443 : 80;
395     }
396
397     if (host == null)
398       return _conn.getLocalPort();
399
400     int p1 = host.lastIndexOf(':');
401     if (p1 < 0)
402       return isSecure() ? 443 : 80;
403     else {
404       int length = host.length();
405       int port = 0;
406
407       for (int i = p1 + 1; i < length; i++) {
408     char ch = host.charAt(i);
409
410     if ('0' <= ch && ch <= '9')
411       port = 10 * port + ch;
412       }
413
414       return port;
415     }
416   }
417
418   /**
419    * Returns the local port.
420    */

421   public int getLocalPort()
422   {
423     return _conn.getLocalPort();
424   }
425
426   /**
427    * Returns the server's address.
428    */

429   public String JavaDoc getLocalAddr()
430   {
431     return _conn.getLocalAddress().getHostAddress();
432   }
433
434   /**
435    * Returns the server's address.
436    */

437   public String JavaDoc getLocalName()
438   {
439     return _conn.getLocalAddress().getHostAddress();
440   }
441
442   public String JavaDoc getRemoteAddr()
443   {
444     return _conn.getRemoteHost();
445   }
446
447   public int printRemoteAddr(byte []buffer, int offset)
448     throws IOException JavaDoc
449   {
450     int len = _conn.getRemoteAddress(buffer, offset, buffer.length - offset);
451
452     return offset + len;
453   }
454
455   public String JavaDoc getRemoteHost()
456   {
457     return _conn.getRemoteHost();
458   }
459
460   /**
461    * Returns the local port.
462    */

463   public int getRemotePort()
464   {
465     return _conn.getRemotePort();
466   }
467
468   /**
469    * Returns the request's scheme.
470    */

471   public String JavaDoc getScheme()
472   {
473     return isSecure() ? "https" : "http";
474   }
475
476   abstract public String JavaDoc getProtocol();
477
478   abstract public String JavaDoc getMethod();
479
480   /**
481    * Returns the URI for the request
482    */

483   public String JavaDoc getRequestURI()
484   {
485     return _invocation.getRawURI();
486   }
487
488   /**
489    * Returns the URI for the page. getPageURI and getRequestURI differ
490    * for included files. getPageURI gets the URI for the included page.
491    * getRequestURI returns the original URI.
492    */

493   public String JavaDoc getPageURI()
494   {
495     return _invocation.getRawURI();
496   }
497
498   public abstract byte []getUriBuffer();
499
500   public abstract int getUriLength();
501
502   /**
503    * Returns the context part of the uri. The context part is the part
504    * that maps to an webApp.
505    */

506   public String JavaDoc getContextPath()
507   {
508     return _invocation.getContextPath();
509   }
510
511   /**
512    * Returns the context part of the uri. For included files, this will
513    * return the included context-path.
514    */

515   public String JavaDoc getPageContextPath()
516   {
517     return getContextPath();
518   }
519
520   /**
521    * Returns the portion of the uri mapped to the servlet for the original
522    * request.
523    */

524   public String JavaDoc getServletPath()
525   {
526     return _invocation.getServletPath();
527   }
528
529   /**
530    * Returns the portion of the uri mapped to the servlet for the current
531    * page.
532    */

533   public String JavaDoc getPageServletPath()
534   {
535     return _invocation.getServletPath();
536   }
537
538   /**
539    * Returns the portion of the uri after the servlet path for the original
540    * request.
541    */

542   public String JavaDoc getPathInfo()
543   {
544     return _invocation.getPathInfo();
545   }
546
547   /**
548    * Returns the portion of the uri after the servlet path for the current
549    * page.
550    */

551   public String JavaDoc getPagePathInfo()
552   {
553     return _invocation.getPathInfo();
554   }
555
556   /**
557    * Returns the URL for the request
558    */

559   public StringBuffer JavaDoc getRequestURL()
560   {
561     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
562
563     sb.append(getScheme());
564     sb.append("://");
565
566     sb.append(getServerName());
567     int port = getServerPort();
568     
569     if (port > 0 &&
570     port != 80 &&
571     port != 443) {
572       sb.append(":");
573       sb.append(port);
574     }
575
576     sb.append(getRequestURI());
577
578     return sb;
579   }
580
581   /**
582    * @deprecated As of JSDK 2.1
583    */

584   public String JavaDoc getRealPath(String JavaDoc path)
585   {
586     if (path == null)
587       return null;
588     if (path.length() > 0 && path.charAt(0) == '/')
589       return _invocation.getWebApp().getRealPath(path);
590
591     String JavaDoc uri = getPageURI();
592     String JavaDoc context = getPageContextPath();
593     if (context != null)
594       uri = uri.substring(context.length());
595     
596     int p = uri.lastIndexOf('/');
597     if (p >= 0)
598       path = uri.substring(0, p + 1) + path;
599
600     return _invocation.getWebApp().getRealPath(path);
601   }
602
603   /**
604    * Returns the real path of pathInfo.
605    */

606   public String JavaDoc getPathTranslated()
607   {
608     String JavaDoc pathInfo = getPathInfo();
609
610     if (pathInfo == null)
611       return null;
612     else
613       return getRealPath(pathInfo);
614   }
615
616   /**
617    * Returns the current page's query string.
618    */

619   public String JavaDoc getQueryString()
620   {
621     if (_invocation != null)
622       return _invocation.getQueryString();
623     else
624       return null;
625   }
626
627   /**
628    * Returns the current page's query string.
629    */

630   public String JavaDoc getPageQueryString()
631   {
632     return getQueryString();
633   }
634
635   /**
636    * Returns the named header.
637    *
638    * @param key the header key
639    */

640   abstract public String JavaDoc getHeader(String JavaDoc key);
641
642   /**
643    * Returns the number of headers.
644    */

645   public int getHeaderSize()
646   {
647     return -1;
648   }
649
650   /**
651    * Returns the header key
652    */

653   public CharSegment getHeaderKey(int index)
654   {
655     throw new UnsupportedOperationException JavaDoc();
656   }
657
658   /**
659    * Returns the header value
660    */

661   public CharSegment getHeaderValue(int index)
662   {
663     throw new UnsupportedOperationException JavaDoc();
664   }
665
666   /**
667    * Fills the result with the header values as
668    * CharSegment values. Most implementations will
669    * implement this directly.
670    *
671    * @param name the header name
672    */

673   public CharSegment getHeaderBuffer(String JavaDoc name)
674   {
675     String JavaDoc value = getHeader(name);
676     
677     if (value != null)
678       return new CharBuffer(value);
679     else
680       return null;
681   }
682
683   /**
684    * Enumerates the header keys
685    */

686   abstract public Enumeration JavaDoc getHeaderNames();
687
688   /**
689    * Sets the header. setHeader is used for
690    * Resin's caching to simulate If-None-Match.
691    */

692   public void setHeader(String JavaDoc key, String JavaDoc value)
693   {
694   }
695
696   /**
697    * Adds the header, checking for known values.
698    */

699   protected void addHeaderInt(char []keyBuf, int keyOff, int keyLen,
700                   CharSegment value)
701   {
702     if (keyLen < 4)
703       return;
704
705     int key1 = keyBuf[keyOff];
706     switch (key1) {
707     case 'c':
708     case 'C':
709       if (keyLen == CONNECTION.length &&
710       match(keyBuf, keyOff, keyLen, CONNECTION)) {
711     if (match(value.getBuffer(), value.getOffset(), value.length(),
712           CLOSE)) {
713       connectionClose();
714     }
715       }
716       else if (keyLen == COOKIE.length &&
717            match(keyBuf, keyOff, keyLen, COOKIE)) {
718     fillCookie(_cookies, value);
719       }
720       break;
721       
722     case 'e':
723     case 'E':
724       if (match(keyBuf, keyOff, keyLen, EXPECT)) {
725     if (match(value.getBuffer(), value.getOffset(), value.length(),
726           CONTINUE_100)) {
727       _expect100Continue = true;
728     }
729       }
730       break;
731       
732     case 'h':
733     case 'H':
734       if (match(keyBuf, keyOff, keyLen, HOST)) {
735     _hostHeader = value;
736       }
737       break;
738       
739     default:
740       return;
741     }
742   }
743
744   /**
745    * Called for a connection: close
746    */

747   protected void connectionClose()
748   {
749     killKeepalive();
750   }
751
752   /**
753    * Matches case insensitively, with the second normalized to lower case.
754    */

755   private boolean match(char []a, int aOff, int aLength, char []b)
756   {
757     int bLength = b.length;
758     
759     if (aLength != bLength)
760       return false;
761
762     for (int i = aLength - 1; i >= 0; i--) {
763       char chA = a[aOff + i];
764       char chB = b[i];
765
766       if (chA != chB && chA + 'a' - 'A' != chB) {
767     return false;
768       }
769     }
770
771     return true;
772   }
773
774   /**
775    * Returns an enumeration of the headers for the named attribute.
776    *
777    * @param name the header name
778    */

779   public Enumeration JavaDoc getHeaders(String JavaDoc name)
780   {
781     String JavaDoc value = getHeader(name);
782     if (value == null)
783       return NullEnumeration.create();
784
785     ArrayList JavaDoc<String JavaDoc> list = new ArrayList JavaDoc<String JavaDoc>();
786     list.add(value);
787
788     return Collections.enumeration(list);
789   }
790
791   /**
792    * Fills the result with a list of the header values as
793    * CharSegment values. Most implementations will
794    * implement this directly.
795    *
796    * @param name the header name
797    * @param resultList the resulting buffer
798    */

799   public void getHeaderBuffers(String JavaDoc name, ArrayList JavaDoc<CharSegment> resultList)
800   {
801     String JavaDoc value = getHeader(name);
802
803     if (value != null)
804       resultList.add(new CharBuffer(value));
805   }
806
807   /**
808    * Returns the named header, converted to an integer.
809    *
810    * @param key the header key.
811    *
812    * @return the value of the header as an integer.
813    */

814   public int getIntHeader(String JavaDoc key)
815   {
816     CharSegment value = getHeaderBuffer(key);
817
818     if (value == null)
819       return -1;
820
821     int len = value.length();
822     if (len == 0)
823       throw new NumberFormatException JavaDoc(value.toString());
824
825     int iValue = 0;
826     int i = 0;
827     int ch = value.charAt(i);
828     int sign = 1;
829     if (ch == '+') {
830       if (i + 1 < len)
831     ch = value.charAt(++i);
832       else
833     throw new NumberFormatException JavaDoc(value.toString());
834     } else if (ch == '-') {
835       sign = -1;
836       if (i + 1 < len)
837     ch = value.charAt(++i);
838       else
839     throw new NumberFormatException JavaDoc(value.toString());
840     }
841
842     for (; i < len && (ch = value.charAt(i)) >= '0' && ch <= '9'; i++)
843       iValue = 10 * iValue + ch - '0';
844
845     if (i < len)
846       throw new NumberFormatException JavaDoc(value.toString());
847
848     return sign * iValue;
849   }
850
851   /**
852    * Returns a header interpreted as a date.
853    *
854    * @param key the header key.
855    *
856    * @return the value of the header as an integer.
857    */

858   public long getDateHeader(String JavaDoc key)
859   {
860     String JavaDoc value = getHeader(key);
861     if (value == null)
862       return -1;
863
864     long date = -1;
865     try {
866       date = _calendar.parseDate(value);
867     } catch (Exception JavaDoc e) {
868     }
869
870     if (date == Long.MAX_VALUE)
871       throw new IllegalArgumentException JavaDoc(value);
872     else
873       return date;
874   }
875
876   /**
877    * Returns the content length of a post.
878    */

879   public int getContentLength()
880   {
881     CharSegment cl = getHeaderBuffer("Content-Length");
882
883     if (cl == null)
884       return -1;
885
886     int value = 0;
887     int i = 0;
888     int ch;
889
890     int length = cl.length();
891     for (; i < length && (ch = cl.charAt(i)) >= '0' && ch <= '9'; i++)
892       value = 10 * value + ch - '0';
893  
894     return i == 0 ? -1 : value;
895   }
896
897   /**
898    * Returns the content-length of a post.
899    */

900   public String JavaDoc getContentType()
901   {
902     return getHeader("Content-Type");
903   }
904
905   /**
906    * Returns the content-length of a post.
907    */

908   public CharSegment getContentTypeBuffer()
909   {
910     return getHeaderBuffer("Content-Type");
911   }
912
913   /**
914    * Returns the character encoding of a post.
915    */

916   public String JavaDoc getCharacterEncoding()
917   {
918     if (_readEncoding != null)
919       return _readEncoding;
920     
921     CharSegment value = getHeaderBuffer("Content-Type");
922
923     if (value == null)
924       return null;
925
926     int i = value.indexOf("charset");
927     if (i < 0)
928       return null;
929
930     int len = value.length();
931     for (i += 7; i < len && Character.isWhitespace(value.charAt(i)); i++) {
932     }
933
934     if (i >= len || value.charAt(i) != '=')
935       return null;
936
937     for (i++; i < len && Character.isWhitespace(value.charAt(i)); i++) {
938     }
939
940     if (i >= len)
941       return null;
942
943     char end = value.charAt(i);
944     if (end == '"') {
945       int tail;
946       for (tail = ++i; tail < len; tail++) {
947         if (value.charAt(tail) == end)
948           break;
949       }
950
951       _readEncoding = Encoding.getMimeName(value.substring(i, tail));
952       
953       return _readEncoding;
954     }
955
956     int tail;
957     for (tail = i; tail < len; tail++) {
958       if (Character.isWhitespace(value.charAt(tail)) ||
959       value.charAt(tail) == ';')
960     break;
961     }
962
963     _readEncoding = Encoding.getMimeName(value.substring(i, tail));
964     
965     return _readEncoding;
966   }
967
968   /**
969    * Sets the character encoding of a post.
970    */

971   public void setCharacterEncoding(String JavaDoc encoding)
972     throws UnsupportedEncodingException JavaDoc
973   {
974     _readEncoding = encoding;
975     
976     try {
977       getStream().setEncoding(_readEncoding);
978     } catch (UnsupportedEncodingException JavaDoc e) {
979       throw e;
980     } catch (java.nio.charset.UnsupportedCharsetException JavaDoc e) {
981       throw new UnsupportedEncodingException JavaDoc(e.getMessage());
982     } catch (IOException JavaDoc e) {
983       log.log(Level.FINE, e.toString(), e);
984     }
985   }
986
987   /**
988    * Returns the cookies from the browser
989    */

990   public Cookie JavaDoc []getCookies()
991   {
992     // The page varies depending on the presense of any cookies
993
setVaryCookie(null);
994     
995     if (_cookiesIn == null)
996       fillCookies();
997
998     // If any cookies actually exist, the page is not anonymous
999
if (_cookiesIn != null && _cookiesIn.length > 0)
1000      setHasCookie();
1001
1002    if (_cookiesIn == null || _cookiesIn.length == 0)
1003      return null;
1004    else
1005      return _cookiesIn;
1006  }
1007
1008  /**
1009   * Returns the named cookie from the browser
1010   */

1011  public Cookie JavaDoc getCookie(String JavaDoc name)
1012  {
1013    // The page varies depending on the presense of any cookies
1014
setVaryCookie(name);
1015
1016    return findCookie(name);
1017  }
1018
1019  private Cookie JavaDoc findCookie(String JavaDoc name)
1020  {
1021    if (_cookiesIn == null)
1022      fillCookies();
1023
1024    if (_cookiesIn == null)
1025      return null;
1026
1027    int length = _cookiesIn.length;
1028    for (int i = 0; i < length; i++) {
1029      Cookie JavaDoc cookie = _cookiesIn[i];
1030      
1031      if (cookie.getName().equals(name)) {
1032        setHasCookie();
1033        return cookie;
1034      }
1035    }
1036
1037    return null;
1038  }
1039
1040  /**
1041   * Parses cookie information from the cookie headers.
1042   */

1043  private void fillCookies()
1044  {
1045    /*
1046    ArrayList<CharSegment> cookieHeaders = _arrayList;
1047    cookieHeaders.clear();
1048    getHeaderBuffers("Cookie", cookieHeaders);
1049
1050    int length = cookieHeaders.size();
1051    for (int i = 0; i < length; i++) {
1052      CharSegment rawCookie = cookieHeaders.get(i);
1053
1054      fillCookie(_cookies, rawCookie);
1055    }
1056    */

1057    
1058    _cookiesIn = new Cookie JavaDoc[_cookies.size()];
1059    _cookies.toArray(_cookiesIn);
1060  }
1061
1062  /**
1063   * Parses a single cookie
1064   *
1065   * @param cookies the array of cookies read
1066   * @param rawCook the input for the cookie
1067   */

1068  private void fillCookie(ArrayList JavaDoc cookies, CharSegment rawCookie)
1069  {
1070    int j = 0;
1071    int len = rawCookie.length();
1072    int version = 0;
1073    Cookie JavaDoc cookie = null;
1074
1075    while (j < len) {
1076      char ch = 0;
1077
1078      CharBuffer cbName = _cbName;
1079      CharBuffer cbValue = _cbValue;
1080      
1081      cbName.clear();
1082      cbValue.clear();
1083
1084      for (; j < len && ((ch = rawCookie.charAt(j)) == ' ' ||
1085                         ch == ';' || ch ==','); j++) {
1086      }
1087
1088      if (j >= len)
1089        break;
1090
1091      boolean isSpecial = false;
1092      if (rawCookie.charAt(j) == '$') {
1093        isSpecial = true;
1094        j++;
1095      }
1096
1097      for (; j < len; j++) {
1098    ch = rawCookie.charAt(j);
1099    if (ch == ' ' || ch == '=' || ch == ';' || ch == ',')
1100      break;
1101    cbName.append(ch);
1102      }
1103
1104      for (; j < len && (ch = rawCookie.charAt(j)) == ' '; j++) {
1105      }
1106
1107      if (j >= len)
1108    break;
1109      else if (ch == ';' || ch == ',') {
1110        try {
1111          cookie = new Cookie JavaDoc(cbName.toString(), "");
1112          cookie.setVersion(version);
1113          _cookies.add(cookie);
1114          // some clients can send bogus cookies
1115
} catch (Exception JavaDoc e) {
1116          log.log(Level.FINE, e.toString(), e);
1117        }
1118        continue;
1119      }
1120      else if (ch != '=') {
1121        for (; j < len && (ch = rawCookie.charAt(j)) != ';'; j++) {
1122        }
1123        continue;
1124      }
1125
1126      j++;
1127
1128      for (; j < len && (ch = rawCookie.charAt(j)) == ' '; j++) {
1129      }
1130
1131      if (ch == '"') {
1132        for (j++; j < len; j++) {
1133          ch = rawCookie.charAt(j);
1134          if (ch == '"')
1135            break;
1136          cbValue.append(ch);
1137        }
1138        j++;
1139      }
1140      else {
1141        for (; j < len; j++) {
1142          ch = rawCookie.charAt(j);
1143          if (ch == ' ' || ch == ';' || ch == ',')
1144            break;
1145          cbValue.append(ch);
1146        }
1147      }
1148
1149      if (! isSpecial) {
1150        if (cbName.length() == 0)
1151          getWebApp().log("bad cookie: " + rawCookie);
1152        else {
1153          cookie = new Cookie JavaDoc(cbName.toString(), cbValue.toString());
1154          cookie.setVersion(version);
1155          _cookies.add(cookie);
1156        }
1157      }
1158      else if (cookie == null) {
1159        if (cbName.matchesIgnoreCase("Version"))
1160          version = cbValue.charAt(0) - '0';
1161      }
1162      else if (cbName.matchesIgnoreCase("Version"))
1163        cookie.setVersion(cbValue.charAt(0) - '0');
1164      else if (cbName.matchesIgnoreCase("Domain"))
1165        cookie.setDomain(cbValue.toString());
1166      else if (cbName.matchesIgnoreCase("Path"))
1167        cookie.setPath(cbValue.toString());
1168    }
1169  }
1170
1171  /**
1172   * Called if the page depends on a cookie. If the cookie is null, then
1173   * the page depends on all cookies.
1174   *
1175   * @param cookie the cookie the page depends on.
1176   */

1177  public void setVaryCookie(String JavaDoc cookie)
1178  {
1179    if (_varyCookies == false)
1180      _varyCookie = cookie;
1181    else if (_varyCookie != null && ! _varyCookie.equals(cookie))
1182      _varyCookie = null;
1183    
1184    _varyCookies = true;
1185
1186    // XXX: server/1315 vs 2671
1187
// _response.setPrivateOrResinCache(true);
1188
}
1189  
1190  /**
1191   * Returns true if the page depends on cookies.
1192   */

1193  public boolean getVaryCookies()
1194  {
1195    return _varyCookies;
1196  }
1197  
1198  /**
1199   * Returns the cookie the page depends on, or null if the page
1200   * depends on several cookies.
1201   */

1202  public String JavaDoc getVaryCookie()
1203  {
1204    return _varyCookie;
1205  }
1206
1207  /**
1208   * Set when the page actually has a cookie.
1209   */

1210  public void setHasCookie()
1211  {
1212    _hasCookie = true;
1213    
1214    // XXX: 1171 vs 1240
1215
// _response.setPrivateOrResinCache(true);
1216
}
1217
1218  /**
1219   * True if this page uses cookies.
1220   */

1221  public boolean getHasCookie()
1222  {
1223    if (_hasCookie)
1224      return true;
1225    else if (_invocation != null)
1226      return _invocation.getSessionId() != null;
1227    else
1228      return false;
1229  }
1230
1231  /**
1232   * Returns the current session, creating one if necessary.
1233   */

1234  public HttpSession JavaDoc getSession()
1235  {
1236    return getSession(true);
1237  }
1238
1239  /**
1240   * Returns the current session.
1241   *
1242   * @param create true if a new session should be created
1243   *
1244   * @return the current session
1245   */

1246  public HttpSession JavaDoc getSession(boolean create)
1247  {
1248    if (_session != null) {
1249      if (_session.isValid())
1250    return _session;
1251    }
1252    else if (! create && _sessionIsLoaded)
1253      return null;
1254
1255    _sessionIsLoaded = true;
1256
1257    boolean hasOldSession = _session != null;
1258    _session = createSession(create, hasOldSession);
1259    
1260    return _session;
1261  }
1262
1263  /**
1264   * Returns the current session.
1265   *
1266   * @param create true if a new session should be created
1267   *
1268   * @return the current session
1269   */

1270  public HttpSession JavaDoc getLoadedSession()
1271  {
1272    if (_session != null && _session.isValid())
1273      return _session;
1274    else
1275      return null;
1276  }
1277
1278  /**
1279   * Returns true if the HTTP request's session id refers to a valid
1280   * session.
1281   */

1282  public boolean isRequestedSessionIdValid()
1283  {
1284    String JavaDoc id = getRequestedSessionId();
1285
1286    if (id == null)
1287      return false;
1288    
1289    SessionImpl session = (SessionImpl) getSession(false);
1290
1291    return session != null && session.isValid() && session.getId().equals(id);
1292  }
1293
1294  /**
1295   * Returns true if the current sessionId came from a cookie.
1296   */

1297  public boolean isRequestedSessionIdFromCookie()
1298  {
1299    return findSessionIdFromCookie() != null;
1300  }
1301
1302  /**
1303   * Returns true if the current sessionId came from the url.
1304   */

1305  public boolean isRequestedSessionIdFromURL()
1306  {
1307    return findSessionIdFromUrl() != null;
1308  }
1309
1310  /**
1311   * @deprecated
1312   */

1313  public boolean isRequestedSessionIdFromUrl()
1314  {
1315    return isRequestedSessionIdFromURL();
1316  }
1317
1318  /**
1319   * Returns the session id in the HTTP request. The cookie has
1320   * priority over the URL. Because the webApp might be using
1321   * the cookie to change the page contents, the caching sets
1322   * vary: JSESSIONID.
1323   */

1324  public String JavaDoc getRequestedSessionIdNoVary()
1325  {
1326    boolean varyCookies = _varyCookies;
1327    String JavaDoc varyCookie = _varyCookie;
1328    boolean hasCookie = _hasCookie;
1329    boolean privateCache = _response.getPrivateCache();
1330    
1331    String JavaDoc id = getRequestedSessionId();
1332
1333    _varyCookies = varyCookies;
1334    _varyCookie = varyCookie;
1335    _hasCookie = hasCookie;
1336    _response.setPrivateOrResinCache(privateCache);
1337
1338    return id;
1339  }
1340
1341  /**
1342   * Returns the session id in the HTTP request. The cookie has
1343   * priority over the URL. Because the webApp might be using
1344   * the cookie to change the page contents, the caching sets
1345   * vary: JSESSIONID.
1346   */

1347  public String JavaDoc getRequestedSessionId()
1348  {
1349    SessionManager manager = getSessionManager();
1350    
1351    if (manager != null && manager.enableSessionCookies()) {
1352      setVaryCookie(getSessionCookie(manager));
1353
1354      String JavaDoc id = findSessionIdFromCookie();
1355      if (id != null) {
1356    _isSessionIdFromCookie = true;
1357        setHasCookie();
1358        return id;
1359      }
1360    }
1361
1362    String JavaDoc id = findSessionIdFromUrl();
1363    if (id != null) {
1364      return id;
1365    }
1366
1367    if (manager != null && manager.enableSessionCookies())
1368      return null;
1369    else
1370      return findSessionIdFromConnection();
1371  }
1372
1373  /**
1374   * For SSL connections, use the SSL identifier.
1375   */

1376  public String JavaDoc findSessionIdFromConnection()
1377  {
1378    return null;
1379  }
1380
1381  /**
1382   * Returns the session id in the HTTP request cookies.
1383   * Because the webApp might use the cookie to change
1384   * the page contents, the caching sets vary: JSESSIONID.
1385   */

1386  private String JavaDoc findSessionIdFromCookie()
1387  {
1388    SessionManager manager = getSessionManager();
1389    
1390    if (manager == null || ! manager.enableSessionCookies())
1391      return null;
1392
1393    Cookie JavaDoc cookie = findCookie(getSessionCookie(manager));
1394
1395    if (cookie != null) {
1396      _isSessionIdFromCookie = true;
1397      return cookie.getValue();
1398    }
1399    else
1400      return null;
1401  }
1402
1403  /**
1404   * Returns the session id in the HTTP request from the url.
1405   */

1406  private String JavaDoc findSessionIdFromUrl()
1407  {
1408    // server/1319
1409
// setVaryCookie(getSessionCookie(manager));
1410

1411    String JavaDoc id = _invocation != null ? _invocation.getSessionId() : null;
1412    if (id != null)
1413      setHasCookie();
1414
1415    return id;
1416  }
1417
1418  public int getSessionGroup()
1419  {
1420    return _sessionGroup;
1421  }
1422
1423  /**
1424   * Returns the current session.
1425   *
1426   * XXX: duplicated in RequestAdapter
1427   *
1428   * @param create true if a new session should be created
1429   *
1430   * @return the current session
1431   */

1432  private SessionImpl createSession(boolean create, boolean hasOldSession)
1433  {
1434    SessionManager manager = getSessionManager();
1435
1436    String JavaDoc id = getRequestedSessionId();
1437
1438    long now = Alarm.getCurrentTime();
1439
1440    SessionImpl session;
1441    
1442    if (id != null && id.length() > 6) {
1443      session = manager.getSession(id, now, create, _isSessionIdFromCookie);
1444
1445      if (session == null) {
1446      }
1447      else if (session.isValid()) {
1448        if (session != null) {
1449      setVaryCookie(getSessionCookie(manager));
1450          setHasCookie();
1451    }
1452    
1453        if (! session.getId().equals(id) && manager.enableSessionCookies())
1454          getResponse().setSessionId(session.getId());
1455        
1456        return session;
1457      }
1458    }
1459    else
1460      id = null;
1461
1462    if (! create)
1463      return null;
1464
1465    // Must accept old ids because different webApps in the same
1466
// server must share the same cookie
1467
//
1468
// But, if the session group doesn't match, then create a new
1469
// session.
1470

1471    session = manager.createSession(id, now, this, _isSessionIdFromCookie);
1472
1473    if (session != null)
1474      setHasCookie();
1475      
1476    if (session.getId().equals(id))
1477      return session;
1478
1479    if (manager.enableSessionCookies())
1480      getResponse().setSessionId(session.getId());
1481
1482    return session;
1483  }
1484
1485  /**
1486   * Returns the session manager.
1487   */

1488  protected final SessionManager getSessionManager()
1489  {
1490    WebApp app = getWebApp();
1491
1492    if (app != null)
1493      return app.getSessionManager();
1494    else
1495      return null;
1496  }
1497  
1498  /**
1499   * Returns the session cookie.
1500   */

1501  protected final String JavaDoc getSessionCookie(SessionManager manager)
1502  {
1503    if (isSecure())
1504      return manager.getSSLCookieName();
1505    else
1506      return manager.getCookieName();
1507  }
1508
1509  /**
1510   * Gets the authorization type
1511   */

1512  public String JavaDoc getAuthType()
1513  {
1514    Object JavaDoc login = getAttribute(com.caucho.server.security.AbstractAuthenticator.LOGIN_NAME);
1515
1516    if (login instanceof X509Certificate JavaDoc)
1517      return CLIENT_CERT_AUTH;
1518    
1519    WebApp app = getWebApp();
1520
1521    if (app != null && app.getLogin() != null && getUserPrincipal() != null)
1522      return app.getLogin().getAuthType();
1523    else
1524      return null;
1525  }
1526
1527  /**
1528   * Internal logging return to get the remote user. If the request already
1529   * knows the user, get it, otherwise just return null.
1530   */

1531  public String JavaDoc getRemoteUser(boolean create)
1532  {
1533    if (_session == null)
1534      return null;
1535
1536    Principal JavaDoc user = _session.getUser();
1537
1538    if (user == null) {
1539      if (! create)
1540        return null;
1541
1542      user = getUserPrincipal();
1543    }
1544
1545    if (user != null)
1546      return user.getName();
1547    else
1548      return null;
1549  }
1550
1551  /**
1552   * Authenticate the user.
1553   */

1554  public boolean authenticate()
1555    throws ServletException JavaDoc, IOException JavaDoc
1556  {
1557    Principal JavaDoc user = null;
1558        
1559    if (_session == null)
1560      getSession(false);
1561
1562      // If the user object is already an attribute, return it.
1563
if (_session != null) {
1564      user = _session.getUser();
1565      if (user != null)
1566        return true;
1567    }
1568
1569    WebApp app = getWebApp();
1570    if (app == null) {
1571      _response.sendError(HttpServletResponse.SC_FORBIDDEN);
1572      return false;
1573    }
1574
1575    // If the authenticator can find the user, return it.
1576
AbstractLogin login = app.getLogin();
1577
1578    if (login != null) {
1579      user = login.authenticate(this, getResponse(), app);
1580      if (user == null)
1581        return false;
1582        
1583      if (_session == null)
1584        getSession(true);
1585        
1586      _session.setUser(user);
1587    }
1588
1589    if (user != null)
1590      return true;
1591    else {
1592      _response.sendError(HttpServletResponse.SC_FORBIDDEN);
1593      return false;
1594    }
1595  }
1596  
1597  /**
1598   * Gets the remote user from the authorization type
1599   */

1600  public String JavaDoc getRemoteUser()
1601  {
1602    Principal JavaDoc principal = getUserPrincipal();
1603
1604    if (principal != null)
1605      return principal.getName();
1606    else
1607      return null;
1608  }
1609  
1610  /**
1611   * Returns the Principal representing the logged in user.
1612   */

1613  public Principal JavaDoc getUserPrincipal()
1614  {
1615    try {
1616      Principal JavaDoc user;
1617      user = (Principal JavaDoc) getAttribute(AbstractAuthenticator.LOGIN_NAME);
1618
1619      if (user != null)
1620    return user;
1621
1622      if (_session == null)
1623        getSession(false);
1624      
1625      // If the user object is already an attribute, return it.
1626
if (_session != null) {
1627        user = _session.getUser();
1628        if (user != null)
1629          return user;
1630      }
1631
1632      WebApp app = getWebApp();
1633      if (app == null)
1634        return null;
1635    
1636      // If the authenticator can find the user, return it.
1637
AbstractLogin login = app.getLogin();
1638
1639      if (login != null) {
1640        user = login.getUserPrincipal(this, getResponse(), app);
1641
1642        if (user != null) {
1643          getSession(true);
1644          
1645          _session.setUser(user);
1646
1647      _response.setPrivateCache(true);
1648        }
1649    else {
1650      // server/123h, server/1920
1651
// distinguishes between setPrivateCache and setPrivateOrResinCache
1652
// _response.setPrivateOrResinCache(true);
1653
}
1654      }
1655
1656      return user;
1657    } catch (ServletException JavaDoc e) {
1658      log.log(Level.WARNING, e.toString(), e);
1659
1660      return null;
1661    }
1662  }
1663
1664  /**
1665   * Logs out the principal.
1666   */

1667  public void logout()
1668  {
1669    if (_session != null)
1670      _session.logout();
1671  }
1672
1673  /**
1674   * Clear the principal from the request object.
1675   */

1676  public void logoutUserPrincipal()
1677  {
1678    if (_session != null)
1679      _session.logout();
1680  }
1681  
1682  /**
1683   * Returns true if the user represented by the current request
1684   * plays the named role.
1685   *
1686   * @param role the named role to test.
1687   * @return true if the user plays the role.
1688   */

1689  public boolean isUserInRole(String JavaDoc role)
1690  {
1691    HashMap JavaDoc<String JavaDoc,String JavaDoc> roleMap = _invocation.getSecurityRoleMap();
1692    
1693    if (roleMap != null) {
1694      String JavaDoc linkRole = roleMap.get(role);
1695      
1696      if (linkRole != null)
1697    role = linkRole;
1698    }
1699    
1700    WebApp app = getWebApp();
1701    AbstractLogin login = app == null ? null : app.getLogin();
1702
1703    if (login == null)
1704      return false;
1705    
1706    boolean inRole = false;
1707      
1708    Principal JavaDoc user = getUserPrincipal();
1709
1710    try {
1711      inRole = login.isUserInRole(this, getResponse(), app, user, role);
1712    } catch (ServletException JavaDoc e) {
1713      if (app != null)
1714        app.log(String.valueOf(e), e);
1715      
1716      log.log(Level.FINE, e.toString(), e);
1717    }
1718      
1719    if (log.isLoggable(Level.FINE)) {
1720      if (user == null)
1721        log.fine("no user for isUserInRole");
1722      else if (inRole)
1723        log.fine(user + " is in role: " + role);
1724      else
1725        log.fine("failed " + user + " in role: " + role);
1726    }
1727
1728    return inRole;
1729  }
1730
1731  /**
1732   * Returns true if the transport is secure.
1733   */

1734  public boolean isTransportSecure()
1735  {
1736    return _conn.isSecure();
1737  }
1738
1739  /**
1740   * Returns the requests underlying read stream, e.g. the post stream.
1741   */

1742  public ReadStream getStream()
1743    throws IOException JavaDoc
1744  {
1745    if (! _hasReadStream) {
1746      _hasReadStream = true;
1747      
1748      initStream(_readStream, _rawRead);
1749      
1750      // Encoding is based on getCharacterEncoding.
1751
// getReader needs the encoding.
1752
String JavaDoc charEncoding = getCharacterEncoding();
1753      String JavaDoc javaEncoding = Encoding.getJavaName(charEncoding);
1754      _readStream.setEncoding(javaEncoding);
1755
1756      if (_expect100Continue) {
1757    _expect100Continue = false;
1758    _response.writeContinue();
1759      }
1760    }
1761
1762    return _readStream;
1763  }
1764
1765  /**
1766   * Returns the raw read buffer.
1767   */

1768  public byte []getRawReadBuffer()
1769  {
1770    return _rawRead.getBuffer();
1771  }
1772
1773  protected void skip()
1774    throws IOException JavaDoc
1775  {
1776    if (! _hasReadStream) {
1777      if (! initStream(_readStream, _rawRead))
1778        return;
1779      
1780      _hasReadStream = true;
1781    }
1782
1783    while ((_readStream.skip(8192) > 0)) {
1784    }
1785  }
1786
1787  /**
1788   * Initialize the read stream from the raw stream.
1789   */

1790  abstract protected boolean initStream(ReadStream readStream,
1791                                        ReadStream rawStream)
1792    throws IOException JavaDoc;
1793
1794  /**
1795   * Returns the raw input stream.
1796   */

1797  public ReadStream getRawInput()
1798  {
1799    throw new UnsupportedOperationException JavaDoc(L.l("raw mode is not supported in this configuration"));
1800  }
1801
1802  /**
1803   * Returns a stream for reading POST data.
1804   */

1805  public ServletInputStream JavaDoc getInputStream()
1806    throws IOException JavaDoc
1807  {
1808    if (_hasReader)
1809      throw new IllegalStateException JavaDoc(L.l("getInputStream() can't be called after getReader()"));
1810
1811    _hasInputStream = true;
1812    
1813    ReadStream stream = getStream();
1814
1815    _is.init(stream);
1816
1817    return _is;
1818  }
1819  
1820  /**
1821   * Returns a Reader for the POST contents
1822   */

1823  public BufferedReader JavaDoc getReader()
1824    throws IOException JavaDoc
1825  {
1826    if (_hasInputStream)
1827      throw new IllegalStateException JavaDoc(L.l("getReader() can't be called after getInputStream()"));
1828
1829    _hasReader = true;
1830
1831    try {
1832      // bufferedReader is just an adapter to get the signature right.
1833
_bufferedReader.init(getStream());
1834
1835      return _bufferedReader;
1836    } catch (java.nio.charset.UnsupportedCharsetException JavaDoc e) {
1837      throw new UnsupportedEncodingException JavaDoc(e.getMessage());
1838    }
1839  }
1840
1841  /**
1842   * Returns an enumeration of the form names.
1843   */

1844  public Enumeration JavaDoc<String JavaDoc> getParameterNames()
1845  {
1846    if (_filledForm == null)
1847      _filledForm = parseQuery();
1848
1849    return Collections.enumeration(_filledForm.keySet());
1850  }
1851
1852  /**
1853   * Returns a map of the form.
1854   */

1855  public Map JavaDoc<String JavaDoc,String JavaDoc[]> getParameterMap()
1856  {
1857    if (_filledForm == null)
1858      _filledForm = parseQuery();
1859
1860    return Collections.unmodifiableMap(_filledForm);
1861  }
1862
1863  /**
1864   * Returns the form's values for the given name.
1865   *
1866   * @param name key in the form
1867   * @return value matching the key
1868   */

1869  public String JavaDoc []getParameterValues(String JavaDoc name)
1870  {
1871    if (_filledForm == null)
1872      _filledForm = parseQuery();
1873
1874    return (String JavaDoc []) _filledForm.get(name);
1875  }
1876
1877  /**
1878   * Returns the form primary value for the given name.
1879   */

1880  public String JavaDoc getParameter(String JavaDoc name)
1881  {
1882    String JavaDoc []values = getParameterValues(name);
1883    if (values == null || values.length == 0)
1884      return null;
1885
1886    return values[0];
1887  }
1888
1889  /**
1890   * Parses the query, either from the GET or the post.
1891   *
1892   * <p/>The character encoding is somewhat tricky. If it's a post, then
1893   * assume the encoded form uses the same encoding as
1894   * getCharacterEncoding().
1895   *
1896   * <p/>If the request doesn't provide the encoding, use the
1897   * character-encoding parameter from the webApp.
1898   *
1899   * <p/>Otherwise use the default system encoding.
1900   */

1901  private HashMapImpl<String JavaDoc,String JavaDoc[]> parseQuery()
1902  {
1903    try {
1904      _form.clear();
1905      
1906      String JavaDoc query = getQueryString();
1907      CharSegment contentType = getContentTypeBuffer();
1908
1909      if (query == null && contentType == null)
1910        return _form;
1911      
1912      String JavaDoc charEncoding = getCharacterEncoding();
1913      if (charEncoding == null)
1914    charEncoding = (String JavaDoc) getAttribute(CAUCHO_CHAR_ENCODING);
1915      if (charEncoding == null)
1916    charEncoding = (String JavaDoc) getAttribute(CHAR_ENCODING);
1917      if (charEncoding == null) {
1918        Locale JavaDoc locale = (Locale JavaDoc) getAttribute(FORM_LOCALE);
1919        if (locale != null)
1920          charEncoding = Encoding.getMimeName(locale);
1921      }
1922      if (charEncoding == null)
1923    charEncoding = CharacterEncoding.getLocalEncoding();
1924
1925      String JavaDoc javaEncoding = Encoding.getJavaName(charEncoding);
1926
1927      if (query != null)
1928    _formParser.parseQueryString(_form, query, javaEncoding, true);
1929
1930      if (contentType == null || ! "POST".equalsIgnoreCase(getMethod())) {
1931      }
1932      
1933      else if (contentType.startsWith("application/x-www-form-urlencoded")) {
1934    _formParser.parsePostData(_form, getInputStream(), javaEncoding);
1935      }
1936
1937      else if (getWebApp().doMultipartForm() &&
1938               contentType.startsWith("multipart/form-data")) {
1939        int length = contentType.length();
1940        int i = contentType.indexOf("boundary=");
1941
1942        if (i < 0)
1943          return _form;
1944
1945        long formUploadMax = getWebApp().getFormUploadMax();
1946
1947    Object JavaDoc uploadMax = getAttribute("caucho.multipart.form.upload-max");
1948    if (uploadMax instanceof Number JavaDoc)
1949      formUploadMax = ((Number JavaDoc) uploadMax).longValue();
1950
1951        // XXX: should this be an error?
1952
if (formUploadMax >= 0 && formUploadMax < getContentLength()) {
1953          setAttribute("caucho.multipart.form.error",
1954                       L.l("Multipart form upload of `{0}' bytes was too large.",
1955                           String.valueOf(getContentLength())));
1956          setAttribute("caucho.multipart.form.error.size",
1957               new Integer JavaDoc(getContentLength()));
1958
1959          return _form;
1960        }
1961
1962        i += "boundary=".length();
1963        char ch = contentType.charAt(i);
1964        CharBuffer boundary = new CharBuffer();
1965        if (ch == '\'') {
1966          for (i++; i < length && contentType.charAt(i) != '\''; i++)
1967            boundary.append(contentType.charAt(i));
1968        }
1969        else if (ch == '\"') {
1970          for (i++; i < length && contentType.charAt(i) != '\"'; i++)
1971            boundary.append(contentType.charAt(i));
1972        }
1973        else {
1974          for (;
1975               i < length && (ch = contentType.charAt(i)) != ' ' &&
1976                 ch != ';';
1977               i++) {
1978            boundary.append(ch);
1979          }
1980        }
1981
1982        try {
1983          MultipartForm.parsePostData(_form,
1984                                      getStream(), boundary.toString(),
1985                                      this,
1986                                      javaEncoding,
1987                                      formUploadMax);
1988        } catch (IOException JavaDoc e) {
1989          log.log(Level.FINE, e.toString(), e);
1990          setAttribute("caucho.multipart.form.error", e.getMessage());
1991        }
1992      }
1993    } catch (IOException JavaDoc e) {
1994      log.log(Level.FINE, e.toString(), e);
1995    }
1996
1997    return _form;
1998  }
1999
2000  // request attributes
2001

2002  /**
2003   * Returns an enumeration of the request attribute names.
2004   */

2005  public Enumeration JavaDoc<String JavaDoc> getAttributeNames()
2006  {
2007    return Collections.enumeration(_attributes.keySet());
2008  }
2009
2010  /**
2011   * Returns the value of the named request attribute.
2012   *
2013   * @param name the attribute name.
2014   *
2015   * @return the attribute value.
2016   */

2017  public Object JavaDoc getAttribute(String JavaDoc name)
2018  {
2019    return _attributes.get(name);
2020  }
2021
2022  /**
2023   * Sets the value of the named request attribute.
2024   *
2025   * @param name the attribute name.
2026   * @param value the new attribute value.
2027   */

2028  public void setAttribute(String JavaDoc name, Object JavaDoc value)
2029  {
2030    if (value != null) {
2031      Object JavaDoc oldValue = _attributes.put(name, value);
2032
2033      for (int i = 0; i < _attributeListeners.length; i++) {
2034    ServletRequestAttributeEvent JavaDoc event;
2035
2036    if (oldValue != null) {
2037      event = new ServletRequestAttributeEvent JavaDoc(getWebApp(), this,
2038                           name, oldValue);
2039
2040      _attributeListeners[i].attributeReplaced(event);
2041    }
2042    else {
2043      event = new ServletRequestAttributeEvent JavaDoc(getWebApp(), this,
2044                           name, value);
2045
2046      _attributeListeners[i].attributeAdded(event);
2047    }
2048      }
2049    }
2050    else
2051      removeAttribute(name);
2052  }
2053
2054  /**
2055   * Removes the value of the named request attribute.
2056   *
2057   * @param name the attribute name.
2058   */

2059  public void removeAttribute(String JavaDoc name)
2060  {
2061    Object JavaDoc oldValue = _attributes.remove(name);
2062    
2063    for (int i = 0; i < _attributeListeners.length; i++) {
2064      ServletRequestAttributeEvent JavaDoc event;
2065
2066      event = new ServletRequestAttributeEvent JavaDoc(getWebApp(), this,
2067                           name, oldValue);
2068
2069      _attributeListeners[i].attributeRemoved(event);
2070    }
2071  }
2072
2073  /**
2074   * Returns a request dispatcher relative to the current request.
2075   *
2076   * @param path the relative uri to the new servlet.
2077   */

2078  public RequestDispatcher JavaDoc getRequestDispatcher(String JavaDoc path)
2079  {
2080    if (path == null || path.length() == 0)
2081      return null;
2082    else if (path.charAt(0) == '/')
2083      return getWebApp().getRequestDispatcher(path);
2084    else {
2085      CharBuffer cb = new CharBuffer();
2086      
2087      ServletContext JavaDoc app = getWebApp();
2088
2089      String JavaDoc servletPath = getPageServletPath();
2090      if (servletPath != null)
2091        cb.append(servletPath);
2092      String JavaDoc pathInfo = getPagePathInfo();
2093      if (pathInfo != null)
2094        cb.append(pathInfo);
2095      
2096      int p = cb.lastIndexOf('/');
2097      if (p >= 0)
2098    cb.setLength(p);
2099      cb.append('/');
2100      cb.append(path);
2101
2102      if (app != null)
2103    return app.getRequestDispatcher(cb.toString());
2104
2105      return app.getRequestDispatcher(cb.toString());
2106    }
2107  }
2108  
2109  /*
2110   * jsdk 2.2
2111   */

2112
2113  public Locale JavaDoc getLocale()
2114  {
2115    fillLocales();
2116
2117    return _locales.get(0);
2118  }
2119
2120  public Enumeration JavaDoc<Locale JavaDoc> getLocales()
2121  {
2122    fillLocales();
2123
2124    return Collections.enumeration(_locales);
2125  }
2126
2127  /**
2128   * Fill the locale array from the request's headers.
2129   */

2130  private void fillLocales()
2131  {
2132    if (_locales.size() > 0)
2133      return;
2134    
2135    Enumeration JavaDoc headers = getHeaders("Accept-Language");
2136    if (headers == null) {
2137      _locales.add(Locale.getDefault());
2138      return;
2139    }
2140
2141    CharBuffer cb = _cb;
2142    while (headers.hasMoreElements()) {
2143      String JavaDoc header = (String JavaDoc) headers.nextElement();
2144      StringCharCursor cursor = new StringCharCursor(header);
2145
2146      while (cursor.current() != cursor.DONE) {
2147    char ch;
2148    for (; Character.isWhitespace(cursor.current()); cursor.next()) {
2149    }
2150
2151    cb.clear();
2152    for (; (ch = cursor.current()) >= 'a' && ch <= 'z' ||
2153           ch >= 'A' && ch <= 'Z' ||
2154           ch >= '0' && ch <= '0';
2155         cursor.next()) {
2156      cb.append(cursor.current());
2157    }
2158
2159    String JavaDoc language = cb.toString();
2160    String JavaDoc country = "";
2161
2162    if (cursor.current() == '-' || cursor.current() == '_') {
2163      cb.clear();
2164      for (cursor.next();
2165           (ch = cursor.current()) >= 'a' && ch <= 'z' ||
2166           ch >= 'A' && ch <= 'Z' ||
2167           ch >= '0' && ch <= '0';
2168           cursor.next()) {
2169        cb.append(cursor.current());
2170      }
2171      country = cb.toString();
2172    }
2173
2174    if (language.length() > 0) {
2175      Locale JavaDoc locale = new Locale JavaDoc(language, country);
2176      _locales.add(locale);
2177    }
2178
2179    for (;
2180         cursor.current() != cursor.DONE && cursor.current() != ',';
2181         cursor.next()) {
2182    }
2183    cursor.next();
2184      }
2185    }
2186
2187    if (_locales.size() == 0)
2188      _locales.add(Locale.getDefault());
2189  }
2190
2191  /**
2192   * Returns true if the request is secure.
2193   */

2194  public boolean isSecure()
2195  {
2196    return _conn.isSecure();
2197  }
2198
2199  // internal goodies
2200

2201  /**
2202   * Returns the request's invocation.
2203   */

2204  public final Invocation getInvocation()
2205  {
2206    return _invocation;
2207  }
2208
2209  /**
2210   * Sets the request's invocation.
2211   */

2212  public final void setInvocation(Invocation invocation)
2213  {
2214    _invocation = invocation;
2215
2216    WebApp app = invocation.getWebApp();
2217    if (app != null)
2218      _attributeListeners = app.getRequestAttributeListeners();
2219  }
2220
2221  /**
2222   * Sets the start time to the current time.
2223   */

2224  protected final void setStartTime()
2225  {
2226    _startTime = Alarm.getExactTime();
2227  }
2228  
2229  /**
2230   * Returns the date for the current request.
2231   */

2232  public final long getStartTime()
2233  {
2234    return _startTime;
2235  }
2236
2237  /**
2238   * Returns the servlet name.
2239   */

2240  public String JavaDoc getServletName()
2241  {
2242    return _invocation.getServletName();
2243  }
2244
2245  /**
2246   * Returns the invocation's webApp.
2247   */

2248  public final WebApp getWebApp()
2249  {
2250    if (_invocation != null)
2251      return _invocation.getWebApp();
2252    else
2253      return null;
2254  }
2255
2256  /**
2257   * Returns the log buffer.
2258   */

2259  public final byte []getLogBuffer()
2260  {
2261    return _logBuffer;
2262  }
2263
2264  /**
2265   * Returns true for the top-level request, but false for any include()
2266   * or forward()
2267   */

2268  public boolean isTop()
2269  {
2270    return false;
2271  }
2272
2273  /**
2274   * Adds a file to be removed at the end.
2275   */

2276  public void addCloseOnExit(Path path)
2277  {
2278    _closeOnExit.add(path);
2279  }
2280
2281  /**
2282   * Returns the depth of the request calls.
2283   */

2284  public int getRequestDepth(int depth)
2285  {
2286    return depth + 1;
2287  }
2288
2289  public int getRequestDepth()
2290  {
2291    return 0;
2292  }
2293
2294  /**
2295   * Kills the keepalive.
2296   */

2297  public void killKeepalive()
2298  {
2299    _keepalive = false;
2300  }
2301
2302  /**
2303   * Returns true if the keepalive is active.
2304   */

2305  protected boolean isKeepalive()
2306  {
2307    return _keepalive;
2308  }
2309
2310  /**
2311   * Returns true if keepalives are allowed.
2312   *
2313   * This method should only be called once, when the response is
2314   * deciding whether to send the Connection: close (or 'Q' vs 'X'),
2315   * after that, the calling routines should call isKeepalive() to
2316   * see what the decision was.
2317   *
2318   * Otherwise, the browser might see a keepalive when the final decision
2319   * is to close the connection.
2320   */

2321  public boolean allowKeepalive()
2322  {
2323    if (! _keepalive)
2324      return false;
2325
2326    TcpConnection tcpConn = _tcpConn;
2327    
2328    if (tcpConn == null)
2329      return true;
2330
2331    Port port = tcpConn.getPort();
2332
2333    // the 16 is spare space for threading, since the keepalive connection
2334
// isn't actually allocated here
2335
if (port.getFreeKeepalive() < 16)
2336      _keepalive = false;
2337
2338    return _keepalive;
2339  }
2340
2341  /**
2342   * Restarts the server.
2343   */

2344  protected void restartServer()
2345    throws IOException JavaDoc, ServletException JavaDoc
2346  {
2347    HttpServletResponse JavaDoc res = (HttpServletResponse JavaDoc) getResponse();
2348
2349    res.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
2350
2351    _server.update();
2352  }
2353
2354  void saveSession()
2355  {
2356    SessionImpl session = _session;
2357    if (session != null)
2358      session.save();
2359  }
2360  
2361  /**
2362   * Cleans up at the end of the request
2363   */

2364  public void finish()
2365    throws IOException JavaDoc
2366  {
2367    try {
2368      SecurityContextProvider oldProvider = _oldProvider;
2369      _oldProvider = null;
2370
2371      SessionImpl session = _session;
2372      _session = null;
2373
2374      _invocation = null;
2375      
2376      SecurityContext.setProvider(oldProvider);
2377      
2378      if (session != null)
2379        session.finish();
2380      
2381      if (_attributes.size() > 0)
2382    _attributes.clear();
2383    } finally {
2384      for (int i = _closeOnExit.size() - 1; i >= 0; i--) {
2385        Path path = _closeOnExit.get(i);
2386
2387        try {
2388          path.remove();
2389        } catch (Throwable JavaDoc e) {
2390          log.log(Level.FINE, e.toString(), e);
2391        }
2392      }
2393      _closeOnExit.clear();
2394      
2395      if (_tcpConn != null)
2396    _tcpConn.beginActive();
2397    }
2398  }
2399
2400  static {
2401    _headerCodes = new CaseInsensitiveIntMap();
2402  }
2403}
2404
Popular Tags