KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > http > HttpRequest


1 // ========================================================================
2
// $Id: HttpRequest.java,v 1.90 2005/12/21 23:14:38 gregwilkins Exp $
3
// Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
4
// ------------------------------------------------------------------------
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
// ========================================================================
15

16 package org.mortbay.http;
17
18 import java.io.IOException JavaDoc;
19 import java.io.InputStream JavaDoc;
20 import java.io.Writer JavaDoc;
21 import java.net.InetAddress JavaDoc;
22 import java.security.Principal JavaDoc;
23 import java.util.Collections JavaDoc;
24 import java.util.Enumeration JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.ListIterator JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.util.Set JavaDoc;
29
30 import javax.print.URIException JavaDoc;
31 import javax.servlet.http.Cookie JavaDoc;
32
33 import org.apache.commons.logging.Log;
34 import org.mortbay.log.LogFactory;
35 import org.mortbay.util.ByteArrayOutputStream2;
36 import org.mortbay.util.IO;
37 import org.mortbay.util.InetAddrPort;
38 import org.mortbay.util.LazyList;
39 import org.mortbay.util.LineInput;
40 import org.mortbay.util.LogSupport;
41 import org.mortbay.util.MultiMap;
42 import org.mortbay.util.QuotedStringTokenizer;
43 import org.mortbay.util.StringMap;
44 import org.mortbay.util.StringUtil;
45 import org.mortbay.util.TypeUtil;
46 import org.mortbay.util.URI;
47 import org.mortbay.util.UrlEncoded;
48
49 /* ------------------------------------------------------------ */
50 /**
51  * HTTP Request. This class manages the headers, trailers and content streams of a HTTP request. It
52  * can be used for receiving or generating requests.
53  * <P>
54  * This class is not synchronized. It should be explicitly synchronized if it is used by multiple
55  * threads.
56  *
57  * @see HttpResponse
58  * @version $Id: HttpRequest.java,v 1.90 2005/12/21 23:14:38 gregwilkins Exp $
59  * @author Greg Wilkins (gregw)
60  */

61 public class HttpRequest extends HttpMessage
62 {
63     private static Log log = LogFactory.getLog(HttpRequest.class);
64
65     /* ------------------------------------------------------------ */
66     /**
67      * Request METHODS.
68      */

69     public static final String JavaDoc __GET = "GET", __POST = "POST", __HEAD = "HEAD", __PUT = "PUT",
70             __OPTIONS = "OPTIONS", __DELETE = "DELETE", __TRACE = "TRACE", __CONNECT = "CONNECT",
71             __MOVE = "MOVE";
72
73     /* ------------------------------------------------------------ */
74     /**
75      * Max size of the form content. Limits the size of the data a client can push at the server.
76      * Set via the org.mortbay.http.HttpRequest.maxContentSize system property.
77      */

78     public static int __maxFormContentSize = Integer.getInteger(
79             "org.mortbay.http.HttpRequest.maxFormContentSize", 200000).intValue();
80
81     /* ------------------------------------------------------------ */
82     /**
83      * Maximum header line length.
84      */

85     public static int __maxLineLength = 4096;
86
87     public static final StringMap __methodCache = new StringMap(true);
88     public static final StringMap __versionCache = new StringMap(true);
89     static
90     {
91         __methodCache.put(__GET, null);
92         __methodCache.put(__POST, null);
93         __methodCache.put(__HEAD, null);
94         __methodCache.put(__PUT, null);
95         __methodCache.put(__OPTIONS, null);
96         __methodCache.put(__DELETE, null);
97         __methodCache.put(__TRACE, null);
98         __methodCache.put(__CONNECT, null);
99         __methodCache.put(__MOVE, null);
100
101         __versionCache.put(__HTTP_1_1, null);
102         __versionCache.put(__HTTP_1_0, null);
103         __versionCache.put(__HTTP_0_9, null);
104     }
105
106     private static Cookie JavaDoc[] __noCookies = new Cookie JavaDoc[0];
107
108     /* ------------------------------------------------------------ */
109     private String JavaDoc _method = null;
110     private URI _uri = null;
111     private String JavaDoc _host;
112     private String JavaDoc _hostPort;
113     private int _port;
114     private List JavaDoc _te;
115     private MultiMap _parameters;
116     private boolean _paramsExtracted;
117     private boolean _handled;
118     private Cookie JavaDoc[] _cookies;
119     private String JavaDoc[] _lastCookies;
120     private boolean _cookiesExtracted;
121     private long _timeStamp;
122     private String JavaDoc _timeStampStr;
123     private Principal JavaDoc _userPrincipal;
124     private String JavaDoc _authUser;
125     private String JavaDoc _authType;
126     private char[] _uriExpanded;
127
128     /* ------------------------------------------------------------ */
129     /**
130      * Constructor.
131      */

132     public HttpRequest()
133     {
134     }
135
136     /* ------------------------------------------------------------ */
137     /**
138      * Constructor.
139      *
140      * @param connection
141      */

142     public HttpRequest(HttpConnection connection)
143     {
144         super(connection);
145     }
146
147     /* ------------------------------------------------------------ */
148     /**
149      * Get Request TimeStamp
150      *
151      * @return The time that the request was received.
152      */

153     public String JavaDoc getTimeStampStr()
154     {
155         if (_timeStampStr == null && _timeStamp > 0)
156                 _timeStampStr = HttpFields.__dateCache.format(_timeStamp);
157         return _timeStampStr;
158     }
159
160     /* ------------------------------------------------------------ */
161     /**
162      * Get Request TimeStamp
163      *
164      * @return The time that the request was received.
165      */

166     public long getTimeStamp()
167     {
168         return _timeStamp;
169     }
170
171     /* ------------------------------------------------------------ */
172     public void setTimeStamp(long ts)
173     {
174         _timeStamp = ts;
175     }
176
177     /* ------------------------------------------------------------ */
178     /**
179      * @deprecated use getHttpResponse()
180      */

181     public HttpResponse getResponse()
182     {
183         return getHttpResponse();
184     }
185
186     /* ------------------------------------------------------------ */
187     /**
188      * Get the HTTP Response. Get the HTTP Response associated with this request.
189      *
190      * @return associated response
191      */

192     public HttpResponse getHttpResponse()
193     {
194         if (_connection == null) return null;
195         return _connection.getResponse();
196     }
197
198     /* ------------------------------------------------------------ */
199     /**
200      * Is the request handled.
201      *
202      * @return True if the request has been set to handled or the associated response is not
203      * editable.
204      */

205     public boolean isHandled()
206     {
207         if (_handled) return true;
208
209         HttpResponse response = getHttpResponse();
210         return (response != null && response.getState() != HttpMessage.__MSG_EDITABLE);
211     }
212
213     /* ------------------------------------------------------------ */
214     /**
215      * Set the handled status.
216      *
217      * @param handled true or false
218      */

219     public void setHandled(boolean handled)
220     {
221         _handled = handled;
222     }
223
224     /* ------------------------------------------------------------ */
225     /**
226      * Read the request line and header.
227      *
228      * @param in
229      * @exception IOException
230      */

231     public void readHeader(LineInput in) throws IOException JavaDoc
232     {
233         _state = __MSG_BAD;
234
235         // Get start line
236
org.mortbay.util.LineInput.LineBuffer line_buffer;
237
238         do
239         {
240             line_buffer = in.readLineBuffer();
241             if (line_buffer == null) throw new EOFException();
242         }
243         while (line_buffer.size == 0);
244
245         if (line_buffer.size >= __maxLineLength)
246                 throw new HttpException(HttpResponse.__414_Request_URI_Too_Large);
247         decodeRequestLine(line_buffer.buffer, line_buffer.size);
248         _timeStamp = System.currentTimeMillis();
249
250         // Handle version - replace with fast compare
251
if (__HTTP_1_1.equals(_version))
252         {
253             _dotVersion = 1;
254             _version = __HTTP_1_1;
255             _header.read(in);
256             updateMimeType();
257         }
258         else if (__HTTP_0_9.equals(_version))
259         {
260             _dotVersion = -1;
261             _version = __HTTP_0_9;
262         }
263         else
264         {
265             _dotVersion = 0;
266             _version = __HTTP_1_0;
267             _header.read(in);
268             updateMimeType();
269         }
270
271         _handled = false;
272         _state = __MSG_RECEIVED;
273     }
274
275     /* -------------------------------------------------------------- */
276     /**
277      * Write the HTTP request line as it was received.
278      */

279     public void writeRequestLine(Writer JavaDoc writer) throws IOException JavaDoc
280     {
281         writer.write(_method);
282         writer.write(' ');
283         writer.write(_uri != null ? _uri.toString() : "null");
284         writer.write(' ');
285         writer.write(_version);
286     }
287
288     /* -------------------------------------------------------------- */
289     /**
290      * Write the request header. Places the message in __MSG_SENDING state.
291      *
292      * @param writer Http output stream
293      * @exception IOException IO problem
294      */

295     public void writeHeader(Writer JavaDoc writer) throws IOException JavaDoc
296     {
297         if (_state != __MSG_EDITABLE) throw new IllegalStateException JavaDoc("Not MSG_EDITABLE");
298
299         _state = __MSG_BAD;
300         writeRequestLine(writer);
301         writer.write(HttpFields.__CRLF);
302         _header.write(writer);
303         _state = __MSG_SENDING;
304     }
305
306     /* -------------------------------------------------------------- */
307     /**
308      * Return the HTTP request line as it was received.
309      */

310     public String JavaDoc getRequestLine()
311     {
312         return _method + " " + _uri + " " + _version;
313     }
314
315     /* -------------------------------------------------------------- */
316     /**
317      * Get the HTTP method for this request. Returns the method with which the request was made. The
318      * returned value can be "GET", "HEAD", "POST", or an extension method. Same as the CGI variable
319      * REQUEST_METHOD.
320      *
321      * @return The method
322      */

323     public String JavaDoc getMethod()
324     {
325         return _method;
326     }
327
328     /* ------------------------------------------------------------ */
329     public void setMethod(String JavaDoc method)
330     {
331         if (getState() != __MSG_EDITABLE) throw new IllegalStateException JavaDoc("Not EDITABLE");
332         _method = method;
333     }
334
335     /* ------------------------------------------------------------ */
336     public String JavaDoc getVersion()
337     {
338         return _version;
339     }
340
341     /* ------------------------------------------------------------ */
342     /**
343      * Reconstructs the URL the client used to make the request. The returned URL contains a
344      * protocol, server name, port number, and, but it does not include a path.
345      * <p>
346      * Because this method returns a <code>StringBuffer</code>, not a string, you can modify the
347      * URL easily, for example, to append path and query parameters.
348      *
349      * This method is useful for creating redirect messages and for reporting errors.
350      *
351      * @return "scheme://host:port"
352      */

353     public StringBuffer JavaDoc getRootURL()
354     {
355         StringBuffer JavaDoc url = new StringBuffer JavaDoc(48);
356         synchronized (url)
357         {
358             String JavaDoc scheme = getScheme();
359             int port = getPort();
360
361             url.append(scheme);
362             url.append("://");
363             if (_hostPort != null)
364                 url.append(_hostPort);
365             else
366             {
367                 url.append(getHost());
368                 if (port > 0
369                         && ((scheme.equalsIgnoreCase("http") && port != 80) || (scheme
370                                 .equalsIgnoreCase("https") && port != 443)))
371                 {
372                     url.append(':');
373                     url.append(port);
374                 }
375             }
376             return url;
377         }
378     }
379
380     /* ------------------------------------------------------------ */
381     /**
382      * Reconstructs the URL the client used to make the request. The returned URL contains a
383      * protocol, server name, port number, and server path, but it does not include query string
384      * parameters.
385      *
386      * <p>
387      * Because this method returns a <code>StringBuffer</code>, not a string, you can modify the
388      * URL easily, for example, to append query parameters.
389      *
390      * <p>
391      * This method is useful for creating redirect messages and for reporting errors.
392      *
393      * @return a <code>StringBuffer</code> object containing the reconstructed URL
394      *
395      */

396     public StringBuffer JavaDoc getRequestURL()
397     {
398         StringBuffer JavaDoc buf = getRootURL();
399         buf.append(getPath());
400         return buf;
401     }
402
403     /* -------------------------------------------------------------- */
404     /**
405      * Get the full URI.
406      *
407      * @return the request URI (not a clone).
408      */

409     public URI getURI()
410     {
411         return _uri;
412     }
413
414     /* ------------------------------------------------------------ */
415     /**
416      * Get the request Scheme. The scheme is obtained from an absolute URI. If the URI in the
417      * request is not absolute, then the connections default scheme is returned. If there is no
418      * connection "http" is returned.
419      *
420      * @return The request scheme (eg. "http", "https", etc.)
421      */

422     public String JavaDoc getScheme()
423     {
424         String JavaDoc scheme = _uri.getScheme();
425         if (scheme == null && _connection != null) scheme = _connection.getDefaultScheme();
426         return scheme == null ? "http" : scheme;
427     }
428
429     /* ------------------------------------------------------------ */
430     /**
431      * @return True if this request came over an integral channel such as SSL
432      */

433     public boolean isIntegral()
434     {
435         return _connection.getListener().isIntegral(_connection);
436     }
437
438     /* ------------------------------------------------------------ */
439     /**
440      * @return True if this request came over an confidential channel such as SSL.
441      */

442     public boolean isConfidential()
443     {
444         return _connection.getListener().isConfidential(_connection);
445     }
446
447     /* ------------------------------------------------------------ */
448     /**
449      * Get the request host.
450      *
451      * @return The host name obtained from an absolute URI, the HTTP header field, the requests
452      * connection or the local host name.
453      */

454     public String JavaDoc getHost()
455     {
456         // Return already determined host
457
if (_host != null) return _host;
458
459         // Return host from absolute URI
460
_host = _uri.getHost();
461         _port = _uri.getPort();
462         if (_host != null) return _host;
463
464         // Return host from header field
465
_hostPort = _header.get(HttpFields.__Host);
466         _host = _hostPort;
467         _port = 0;
468         if (_host != null && _host.length() > 0)
469         {
470             int colon = _host.lastIndexOf(':');
471             if (colon >= 0)
472             {
473                 if (colon < _host.length())
474                 {
475                     try
476                     {
477                         _port = TypeUtil.parseInt(_host, colon + 1, -1, 10);
478                     }
479                     catch (Exception JavaDoc e)
480                     {
481                         LogSupport.ignore(log, e);
482                     }
483                 }
484                 _host = _host.substring(0, colon);
485             }
486
487             return _host;
488         }
489
490         // Return host from connection
491
if (_connection != null)
492         {
493             _host = _connection.getServerName();
494             _port = _connection.getServerPort();
495             if (_host != null && !InetAddrPort.__0_0_0_0.equals(_host)) return _host;
496         }
497
498         // Return the local host
499
try
500         {
501             _host = InetAddress.getLocalHost().getHostAddress();
502         }
503         catch (java.net.UnknownHostException JavaDoc e)
504         {
505             LogSupport.ignore(log, e);
506         }
507         return _host;
508     }
509
510     /* ------------------------------------------------------------ */
511     /**
512      * Get the request port. The port is obtained either from an absolute URI, the HTTP Host header
513      * field, the connection or the default.
514      *
515      * @return The port. 0 should be interpreted as the default port.
516      */

517     public int getPort()
518     {
519         if (_port > 0) return _port;
520         if (_host != null) return 0;
521         if (_uri.isAbsolute())
522             _port = _uri.getPort();
523         else if (_connection != null) _port = _connection.getServerPort();
524         return _port;
525     }
526
527     /* ------------------------------------------------------------ */
528     /**
529      * Get the request path.
530      *
531      * @return The URI path of the request.
532      */

533     public String JavaDoc getPath()
534     {
535         return _uri.getPath();
536     }
537
538     /* ------------------------------------------------------------ */
539     public void setPath(String JavaDoc path)
540     {
541         if (getState() != __MSG_EDITABLE) throw new IllegalStateException JavaDoc("Not EDITABLE");
542         if (_uri == null)
543             _uri = new URI(path);
544         else
545             _uri.setURI(path);
546     }
547
548     /* ------------------------------------------------------------ */
549     /**
550      * Get the encoded request path.
551      *
552      * @return The path with % encoding.
553      */

554     public String JavaDoc getEncodedPath()
555     {
556         return _uri.getEncodedPath();
557     }
558
559     /* ------------------------------------------------------------ */
560     /**
561      * Get the request query.
562      *
563      * @return the request query excluding the '?'
564      */

565     public String JavaDoc getQuery()
566     {
567         return _uri.getQuery();
568     }
569
570     /* ------------------------------------------------------------ */
571     public void setQuery(String JavaDoc q)
572     {
573         if (getState() != __MSG_EDITABLE) throw new IllegalStateException JavaDoc("Not EDITABLE");
574         _uri.setQuery(q);
575     }
576
577     /* ------------------------------------------------------------ */
578     public String JavaDoc getRemoteAddr()
579     {
580         String JavaDoc addr = "127.0.0.1";
581         HttpConnection connection = getHttpConnection();
582         if (connection != null)
583         {
584             addr = connection.getRemoteAddr();
585             if (addr == null) addr = connection.getRemoteHost();
586         }
587         return addr;
588     }
589
590     /* ------------------------------------------------------------ */
591     public String JavaDoc getRemoteHost()
592     {
593         String JavaDoc host = "127.0.0.1";
594         HttpConnection connection = getHttpConnection();
595         if (connection != null)
596         {
597             host = connection.getRemoteHost();
598             if (host == null) host = connection.getRemoteAddr();
599         }
600         return host;
601     }
602
603     /* ------------------------------------------------------------ */
604     /**
605      * Decode HTTP request line.
606      *
607      * @param buf Character buffer
608      * @param len Length of line in buffer.
609      * @exception IOException
610      */

611     void decodeRequestLine(char[] buf, int len) throws IOException JavaDoc
612     {
613         // Search for first space separated chunk
614
int s1 = -1, s2 = -1, s3 = -1;
615         int state = 0;
616         startloop: for (int i = 0; i < len; i++)
617         {
618             char c = buf[i];
619             switch (state)
620             {
621                 case 0: // leading white
622
if (c == ' ') continue;
623                     state = 1;
624                     s1 = i;
625
626                 case 1: // reading method
627
if (c == ' ')
628                         state = 2;
629                     else
630                     {
631                         s2 = i;
632                         if (c >= 'a' && c <= 'z') buf[i] = (char) (c - 'a' + 'A');
633                     }
634                     continue;
635
636                 case 2: // skip whitespace after method
637
s3 = i;
638                     if (c != ' ') break startloop;
639             }
640         }
641
642         // Search for last space separated chunk
643
int e1 = -1, e2 = -1, e3 = -1;
644         state = 0;
645         endloop: for (int i = len; i-- > 0;)
646         {
647             char c = buf[i];
648             switch (state)
649             {
650                 case 0: // trailing white
651
if (c == ' ') continue;
652                     state = 1;
653                     e1 = i;
654
655                 case 1: // reading Version
656
if (c == ' ')
657                         state = 2;
658                     else
659                         e2 = i;
660                     continue;
661
662                 case 2: // skip whitespace before version
663
e3 = i;
664                     if (c != ' ') break endloop;
665             }
666         }
667
668         // Check sufficient params
669
if (s3 < 0 || e1 < 0 || e3 < s2)
670                 throw new IOException JavaDoc("Bad Request: " + new String JavaDoc(buf, 0, len));
671
672         // get method
673
Map.Entry JavaDoc method = __methodCache.getEntry(buf, s1, s2 - s1 + 1);
674         if (method != null)
675             _method = (String JavaDoc) method.getKey();
676         else
677             _method = new String JavaDoc(buf, s1, s2 - s1 + 1).toUpperCase();
678
679         // get version as uppercase
680
if (s2 != e3 || s3 != e2)
681         {
682             Map.Entry JavaDoc version = __versionCache.getEntry(buf, e2, e1 - e2 + 1);
683             if (version != null)
684                 _version = (String JavaDoc) version.getKey();
685             else
686             {
687                 for (int i = e2; i <= e1; i++)
688                     if (buf[i] >= 'a' && buf[i] <= 'z') buf[i] = (char) (buf[i] - 'a' + 'A');
689                 _version = new String JavaDoc(buf, e2, e1 - e2 + 1);
690             }
691         }
692         else
693         {
694             // missing version
695
_version = __HTTP_0_9;
696             e3 = e1;
697         }
698
699         // handle URI
700
try
701         {
702             String JavaDoc raw_uri =null;
703             if (URI.__CHARSET_IS_DEFAULT)
704                 raw_uri = new String JavaDoc(buf, s3, e3 - s3 + 1);
705             else
706             {
707                 int l=e3-s3+1;
708                 for (int i=0;i<l;i++)
709                 {
710                     char c=buf[s3+i];
711                     
712                     if (c>=0 && c<0x80)
713                         continue;
714                 
715                     if (_uriExpanded==null || _uriExpanded.length<3*l)
716                         _uriExpanded=new char[3*l];
717                     
718                     if (i>0)
719                         System.arraycopy(buf, s3, _uriExpanded, 0, i);
720                     int j=i;
721                     for (;i<l;i++)
722                     {
723                         c=buf[s3+i];
724                         if (c>=0 && c<0x80)
725                             _uriExpanded[j++]=c;
726                         else
727                         {
728                             _uriExpanded[j++]='%';
729                             _uriExpanded[j++]=TypeUtil.toHexChar(0xf&(c>>4));
730                             _uriExpanded[j++]=TypeUtil.toHexChar(0xf&c);
731                         }
732                     }
733                     raw_uri=new String JavaDoc(_uriExpanded, 0, j);
734                 }
735
736                 if (raw_uri==null)
737                     raw_uri = new String JavaDoc(buf, s3, e3 - s3 + 1);
738             }
739            
740             if (_uri == null)
741                 _uri = new URI(raw_uri);
742             else
743                 _uri.setURI(raw_uri);
744         }
745         catch (IllegalArgumentException JavaDoc e)
746         {
747             LogSupport.ignore(log, e);
748             throw new HttpException(HttpResponse.__400_Bad_Request,
749                     new String JavaDoc(buf, s3, e3 - s3 + 1));
750         }
751     }
752
753     /* ------------------------------------------------------------ */
754     /**
755      * Force a removeField. This call ignores the message state and forces a field to be removed
756      * from the request. It is required for the handling of the Connection field.
757      *
758      * @param name The field name
759      * @return The old value or null.
760      */

761     Object JavaDoc forceRemoveField(String JavaDoc name)
762     {
763         int saved_state = _state;
764         try
765         {
766             _state = __MSG_EDITABLE;
767             return removeField(name);
768         }
769         finally
770         {
771             _state = saved_state;
772         }
773     }
774
775     /* ------------------------------------------------------------ */
776     /**
777      * Get the acceptable transfer encodings. The TE field is used to construct a list of acceptable
778      * extension transfer codings in quality order. An empty list implies that only "chunked" is
779      * acceptable. A null list implies that no transfer coding can be applied.
780      *
781      * If the "trailer" coding is found in the TE field, then message trailers are enabled in any
782      * linked response.
783      *
784      * @return List of codings.
785      */

786     public List JavaDoc getAcceptableTransferCodings()
787     {
788         if (_dotVersion < 1) return null;
789         if (_te != null) return _te;
790
791         // Decode any TE field
792
Enumeration JavaDoc tenum = getFieldValues(HttpFields.__TE, HttpFields.__separators);
793
794         if (tenum != null)
795         {
796             // Sort the list
797
List JavaDoc te = HttpFields.qualityList(tenum);
798             int size = te.size();
799             // Process if something there
800
if (size > 0)
801             {
802                 Object JavaDoc acceptable = null;
803
804                 // remove trailer and chunked items.
805
ListIterator JavaDoc iter = te.listIterator();
806                 while (iter.hasNext())
807                 {
808                     String JavaDoc coding = StringUtil.asciiToLowerCase(HttpFields.valueParameters(iter
809                             .next().toString(), null));
810
811                     if (!HttpFields.__Chunked.equalsIgnoreCase(coding))
812                     {
813                         acceptable = LazyList.ensureSize(acceptable, size);
814                         acceptable = LazyList.add(acceptable, coding);
815                     }
816                 }
817                 _te = LazyList.getList(acceptable);
818             }
819             else
820                 _te = Collections.EMPTY_LIST;
821         }
822         else
823             _te = Collections.EMPTY_LIST;
824
825         return _te;
826     }
827
828     /* ------------------------------------------------------------ */
829     /*
830      * Extract Paramters from query string and/or form content.
831      */

832     private void extractParameters()
833     {
834         if (_paramsExtracted) return;
835         _paramsExtracted = true;
836
837         if (_parameters == null) _parameters = new MultiMap(16);
838
839         // Handle query string
840
String JavaDoc encoding = getCharacterEncoding();
841         if (encoding == null)
842         {
843             _uri.putParametersTo(_parameters);
844         }
845         else
846         {
847             // An encoding has been set, so reencode query string.
848
String JavaDoc query = _uri.getQuery();
849             if (query != null) UrlEncoded.decodeTo(query, _parameters, encoding);
850         }
851
852         // handle any content.
853
if (_state == __MSG_RECEIVED)
854         {
855             String JavaDoc content_type = getField(HttpFields.__ContentType);
856             if (content_type != null && content_type.length() > 0)
857             {
858                 content_type = StringUtil.asciiToLowerCase(content_type);
859                 content_type = HttpFields.valueParameters(content_type, null);
860
861                 if (HttpFields.__WwwFormUrlEncode.equalsIgnoreCase(content_type)
862                         && HttpRequest.__POST.equals(getMethod()))
863                 {
864                     int content_length = getIntField(HttpFields.__ContentLength);
865                     if (content_length == 0)
866                         log.debug("No form content");
867                     else
868                     {
869                         try
870                         {
871                             int max = content_length;
872                             if (__maxFormContentSize > 0)
873                             {
874                                 if (max < 0)
875                                     max = __maxFormContentSize;
876                                 else if (max > __maxFormContentSize)
877                                     throw new IllegalStateException JavaDoc("Form too large");
878                             }
879
880                             // Read the content
881
ByteArrayOutputStream2 bout = new ByteArrayOutputStream2(max > 0 ? max
882                                     : 4096);
883                             InputStream JavaDoc in = getInputStream();
884
885                             // Copy to a byte array.
886
// TODO - this is very inefficient and we could
887
// save lots of memory by streaming this!!!!
888
IO.copy(in, bout, max);
889                             
890                             if (bout.size()==__maxFormContentSize && in.available()>0)
891                                 throw new IllegalStateException JavaDoc("Form too large");
892                             
893                             // Add form params to query params
894
UrlEncoded.decodeTo(bout.getBuf(), 0, bout.getCount(), _parameters,encoding);
895                         }
896                         catch (EOFException e)
897                         {
898                             LogSupport.ignore(log, e);
899                         }
900                         catch (IOException JavaDoc e)
901                         {
902                             if (log.isDebugEnabled())
903                                 log.warn(LogSupport.EXCEPTION, e);
904                             else
905                                 log.warn(e.toString());
906                         }
907                     }
908                 }
909             }
910         }
911     }
912
913     /* ------------------------------------------------------------ */
914     /**
915      * @return Map of parameters
916      */

917     public MultiMap getParameters()
918     {
919         if (!_paramsExtracted) extractParameters();
920         return _parameters;
921     }
922
923     /* ------------------------------------------------------------ */
924     /**
925      * Get the set of parameter names.
926      *
927      * @return Set of parameter names.
928      */

929     public Set JavaDoc getParameterNames()
930     {
931         if (!_paramsExtracted) extractParameters();
932         return _parameters.keySet();
933     }
934
935     /* ------------------------------------------------------------ */
936     /**
937      * Get a parameter value.
938      *
939      * @param name Parameter name
940      * @return Parameter value
941      */

942     public String JavaDoc getParameter(String JavaDoc name)
943     {
944         if (!_paramsExtracted) extractParameters();
945         return (String JavaDoc) _parameters.getValue(name, 0);
946     }
947
948     /* ------------------------------------------------------------ */
949     /**
950      * Get multi valued paramater.
951      *
952      * @param name Parameter name
953      * @return Parameter values
954      */

955     public List JavaDoc getParameterValues(String JavaDoc name)
956     {
957         if (!_paramsExtracted) extractParameters();
958         return _parameters.getValues(name);
959     }
960
961     /* ------------------------------------------------------------ */
962     /**
963      * @return Parameters as a map of String arrays
964      */

965     public Map JavaDoc getParameterStringArrayMap()
966     {
967         if (!_paramsExtracted) extractParameters();
968         return _parameters.toStringArrayMap();
969     }
970
971     /* -------------------------------------------------------------- */
972     /**
973      * Extract received cookies from a header.
974      *
975      * @return Array of Cookies.
976      */

977     public Cookie JavaDoc[] getCookies()
978     {
979         if (_cookies != null && _cookiesExtracted) return _cookies;
980
981         try
982         {
983             // Handle no cookies
984
if (!_header.containsKey(HttpFields.__Cookie))
985             {
986                 _cookies = __noCookies;
987                 _cookiesExtracted = true;
988                 _lastCookies = null;
989                 return _cookies;
990             }
991
992             // Check if cookie headers match last cookies
993
if (_lastCookies != null)
994             {
995                 int last = 0;
996                 Enumeration JavaDoc enm = _header.getValues(HttpFields.__Cookie);
997                 while (enm.hasMoreElements())
998                 {
999                     String JavaDoc c = (String JavaDoc) enm.nextElement();
1000                    if (last >= _lastCookies.length || !c.equals(_lastCookies[last]))
1001                    {
1002                        _lastCookies = null;
1003                        break;
1004                    }
1005                    last++;
1006                }
1007                if (_lastCookies != null)
1008                {
1009                    _cookiesExtracted = true;
1010                    return _cookies;
1011                }
1012            }
1013
1014            // Get ready to parse cookies (Expensive!!!)
1015
Object JavaDoc cookies = null;
1016            Object JavaDoc lastCookies = null;
1017
1018            int version = 0;
1019            Cookie JavaDoc cookie = null;
1020
1021            // For each cookie header
1022
Enumeration JavaDoc enm = _header.getValues(HttpFields.__Cookie);
1023            while (enm.hasMoreElements())
1024            {
1025                // Save a copy of the unparsed header as cache.
1026
String JavaDoc hdr = enm.nextElement().toString();
1027                lastCookies = LazyList.add(lastCookies, hdr);
1028
1029                // Parse the header
1030
QuotedStringTokenizer tok = new QuotedStringTokenizer(hdr, ",;", false, false);
1031                while (tok.hasMoreElements())
1032                {
1033                    String JavaDoc c = (String JavaDoc) tok.nextElement();
1034                    if (c == null) continue;
1035                    c = c.trim();
1036
1037                    try
1038                    {
1039                        String JavaDoc n;
1040                        String JavaDoc v;
1041                        int e = c.indexOf('=');
1042                        if (e > 0)
1043                        {
1044                            n = c.substring(0, e);
1045                            v = c.substring(e + 1);
1046                        }
1047                        else
1048                        {
1049                            n = c;
1050                            v = "";
1051                        }
1052
1053                        // Handle quoted values
1054
if (version > 0) v = StringUtil.unquote(v);
1055
1056                        // Ignore $ names
1057
if (n.startsWith("$"))
1058                        {
1059                            if ("$version".equalsIgnoreCase(n))
1060                                version = Integer.parseInt(StringUtil.unquote(v));
1061                            else if ("$path".equalsIgnoreCase(n) && cookie != null)
1062                                cookie.setPath(v);
1063                            else if ("$domain".equalsIgnoreCase(n) && cookie != null)
1064                                    cookie.setDomain(v);
1065                            continue;
1066                        }
1067
1068                        v = URI.decodePath(v);
1069                        cookie = new Cookie JavaDoc(n, v);
1070                        if (version > 0) cookie.setVersion(version);
1071                        cookies = LazyList.add(cookies, cookie);
1072                    }
1073                    catch (Exception JavaDoc ex)
1074                    {
1075                        LogSupport.ignore(log, ex);
1076                    }
1077                }
1078            }
1079
1080            int l = LazyList.size(cookies);
1081            if (_cookies == null || _cookies.length != l) _cookies = new Cookie JavaDoc[l];
1082            for (int i = 0; i < l; i++)
1083                _cookies[i] = (Cookie JavaDoc) LazyList.get(cookies, i);
1084            _cookiesExtracted = true;
1085
1086            l = LazyList.size(lastCookies);
1087            _lastCookies = new String JavaDoc[l];
1088            for (int i = 0; i < l; i++)
1089                _lastCookies[i] = (String JavaDoc) LazyList.get(lastCookies, i);
1090
1091        }
1092        catch (Exception JavaDoc e)
1093        {
1094            log.warn(LogSupport.EXCEPTION, e);
1095        }
1096
1097        return _cookies;
1098    }
1099
1100    /* ------------------------------------------------------------ */
1101    public boolean isUserInRole(String JavaDoc role)
1102    {
1103        Principal JavaDoc principal = getUserPrincipal();
1104        if (principal != null)
1105        {
1106            UserRealm realm = getHttpResponse().getHttpContext().getRealm();
1107            if (realm != null) return realm.isUserInRole(principal, role);
1108        }
1109        return false;
1110    }
1111
1112    /* ------------------------------------------------------------ */
1113    public String JavaDoc getAuthType()
1114    {
1115        if (_authType == null) getUserPrincipal();
1116        return _authType;
1117    }
1118
1119    /* ------------------------------------------------------------ */
1120    public void setAuthType(String JavaDoc a)
1121    {
1122        _authType = a;
1123    }
1124
1125    /* ------------------------------------------------------------ */
1126    public String JavaDoc getAuthUser()
1127    {
1128        if (_authUser == null) getUserPrincipal();
1129        return _authUser;
1130    }
1131
1132    /* ------------------------------------------------------------ */
1133    public void setAuthUser(String JavaDoc user)
1134    {
1135        _authUser = user;
1136    }
1137
1138    /* ------------------------------------------------------------ */
1139    public boolean hasUserPrincipal()
1140    {
1141        if (_userPrincipal == __NOT_CHECKED) getUserPrincipal();
1142        return _userPrincipal != null && _userPrincipal != __NO_USER;
1143    }
1144
1145    /* ------------------------------------------------------------ */
1146    public Principal JavaDoc getUserPrincipal()
1147    {
1148        if (_userPrincipal == __NO_USER) return null;
1149
1150        if (_userPrincipal == __NOT_CHECKED)
1151        {
1152            _userPrincipal = __NO_USER;
1153
1154            // Try a lazy authentication
1155
HttpContext context = getHttpResponse().getHttpContext();
1156            if (context != null)
1157            {
1158                Authenticator auth = context.getAuthenticator();
1159                UserRealm realm = context.getRealm();
1160                if (realm != null && auth != null)
1161                {
1162                    try
1163                    {
1164                        // TODO - should not need to recalculate this!
1165
String JavaDoc pathInContext = getPath().substring(
1166                                context.getContextPath().length());
1167                        auth.authenticate(realm, pathInContext, this, null);
1168                    }
1169                    catch (Exception JavaDoc e)
1170                    {
1171                        LogSupport.ignore(log, e);
1172                    }
1173                }
1174            }
1175
1176            if (_userPrincipal == __NO_USER) return null;
1177        }
1178        return _userPrincipal;
1179    }
1180
1181    /* ------------------------------------------------------------ */
1182    public void setUserPrincipal(Principal JavaDoc principal)
1183    {
1184        _userPrincipal = principal;
1185    }
1186
1187    /* ------------------------------------------------------------ */
1188    /**
1189     * Recycle the request.
1190     */

1191    void recycle(HttpConnection connection)
1192    {
1193        _method = null;
1194        //_uri=null;
1195
_host = null;
1196        _hostPort = null;
1197        _port = 0;
1198        _te = null;
1199        if (_parameters != null) _parameters.clear();
1200        _paramsExtracted = false;
1201        _handled = false;
1202        _cookiesExtracted = false;
1203        _timeStamp = 0;
1204        _timeStampStr = null;
1205        _authUser = null;
1206        _authType = null;
1207        _userPrincipal = null;
1208        super.recycle(connection);
1209    }
1210
1211    /* ------------------------------------------------------------ */
1212    /**
1213     * Destroy the request. Help the garbage collector by null everything that we can.
1214     */

1215    public void destroy()
1216    {
1217        _parameters = null;
1218        _method = null;
1219        _uri = null;
1220        _host = null;
1221        _hostPort = null;
1222        _te = null;
1223        _cookies = null;
1224        _lastCookies = null;
1225        _timeStampStr = null;
1226        _userPrincipal = null;
1227        _authUser = null;
1228        _authUser = null;
1229        if (_attributes != null) _attributes.clear();
1230        super.destroy();
1231    }
1232
1233    static Principal JavaDoc __NO_USER = new Principal JavaDoc()
1234    {
1235        public String JavaDoc getName()
1236        {
1237            return null;
1238        }
1239    };
1240    static Principal JavaDoc __NOT_CHECKED = new Principal JavaDoc()
1241    {
1242        public String JavaDoc getName()
1243        {
1244            return null;
1245        }
1246    };
1247}
1248
Popular Tags