// ======================================================================== // $Id: HttpRequest.java,v 1.91 2006/11/23 08:56:52 gregwilkins Exp $ // Copyright 1996-2004 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ======================================================================== package org.browsermob.proxy.jetty.http; import org.apache.commons.logging.Log; import org.browsermob.proxy.jetty.log.LogFactory; import org.browsermob.proxy.jetty.util.*; import javax.servlet.http.Cookie; import java.io.IOException; import java.io.InputStream; import java.io.Writer; import java.net.InetAddress; import java.security.Principal; import java.util.*; /* ------------------------------------------------------------ */ /** * HTTP Request. This class manages the headers, trailers and content streams of a HTTP request. It * can be used for receiving or generating requests. * <P> * This class is not synchronized. It should be explicitly synchronized if it is used by multiple * threads. * * @see HttpResponse * @version $Id: HttpRequest.java,v 1.91 2006/11/23 08:56:52 gregwilkins Exp $ * @author Greg Wilkins (gregw) */ public class HttpRequest extends HttpMessage { private static Log log = LogFactory.getLog(HttpRequest.class); /* ------------------------------------------------------------ */ /** * Request METHODS. */ public static final String __GET = "GET", __POST = "POST", __HEAD = "HEAD", __PUT = "PUT", __OPTIONS = "OPTIONS", __DELETE = "DELETE", __TRACE = "TRACE", __CONNECT = "CONNECT", __MOVE = "MOVE"; /* ------------------------------------------------------------ */ /** * Max size of the form content. Limits the size of the data a client can push at the server. * Set via the org.mortbay.http.HttpRequest.maxContentSize system property. */ public static int __maxFormContentSize = Integer.getInteger( "org.browsermob.proxy.jetty.http.HttpRequest.maxFormContentSize", 200000).intValue(); /* ------------------------------------------------------------ */ /** * Maximum header line length. */ public static int __maxLineLength = 4096; public static final StringMap __methodCache = new StringMap(true); public static final StringMap __versionCache = new StringMap(true); static { __methodCache.put(__GET, null); __methodCache.put(__POST, null); __methodCache.put(__HEAD, null); __methodCache.put(__PUT, null); __methodCache.put(__OPTIONS, null); __methodCache.put(__DELETE, null); __methodCache.put(__TRACE, null); __methodCache.put(__CONNECT, null); __methodCache.put(__MOVE, null); __versionCache.put(__HTTP_1_1, null); __versionCache.put(__HTTP_1_0, null); __versionCache.put(__HTTP_0_9, null); } private static Cookie[] __noCookies = new Cookie[0]; /* ------------------------------------------------------------ */ private String _method = null; private URI _uri = null; private String _host; private String _hostPort; private int _port; private List _te; private MultiMap _parameters; private boolean _paramsExtracted; private boolean _handled; private Cookie[] _cookies; private String[] _lastCookies; private boolean _cookiesExtracted; private long _timeStamp; private String _timeStampStr; private Principal _userPrincipal; private String _authUser; private String _authType; private char[] _uriExpanded; /* ------------------------------------------------------------ */ /** * Constructor. */ public HttpRequest() { } /* ------------------------------------------------------------ */ /** * Constructor. * * @param connection */ public HttpRequest(HttpConnection connection) { super(connection); } /* ------------------------------------------------------------ */ /** * Get Request TimeStamp * * @return The time that the request was received. */ public String getTimeStampStr() { if (_timeStampStr == null && _timeStamp > 0) _timeStampStr = HttpFields.__dateCache.format(_timeStamp); return _timeStampStr; } /* ------------------------------------------------------------ */ /** * Get Request TimeStamp * * @return The time that the request was received. */ public long getTimeStamp() { return _timeStamp; } /* ------------------------------------------------------------ */ public void setTimeStamp(long ts) { _timeStamp = ts; } /* ------------------------------------------------------------ */ /** * @deprecated use getHttpResponse() */ public HttpResponse getResponse() { return getHttpResponse(); } /* ------------------------------------------------------------ */ /** * Get the HTTP Response. Get the HTTP Response associated with this request. * * @return associated response */ public HttpResponse getHttpResponse() { if (_connection == null) return null; return _connection.getResponse(); } /* ------------------------------------------------------------ */ /** * Is the request handled. * * @return True if the request has been set to handled or the associated response is not * editable. */ public boolean isHandled() { if (_handled) return true; HttpResponse response = getHttpResponse(); return (response != null && response.getState() != HttpMessage.__MSG_EDITABLE); } /* ------------------------------------------------------------ */ /** * Set the handled status. * * @param handled true or false */ public void setHandled(boolean handled) { _handled = handled; } /* ------------------------------------------------------------ */ /** * Read the request line and header. * * @param in * @exception IOException */ public void readHeader(LineInput in) throws IOException { _state = __MSG_BAD; // Get start line org.browsermob.proxy.jetty.util.LineInput.LineBuffer line_buffer; do { line_buffer = in.readLineBuffer(); if (line_buffer == null) throw new EOFException(); } while (line_buffer.size == 0); if (line_buffer.size >= __maxLineLength) throw new HttpException(HttpResponse.__414_Request_URI_Too_Large); decodeRequestLine(line_buffer.buffer, line_buffer.size); _timeStamp = System.currentTimeMillis(); // Handle version - replace with fast compare if (__HTTP_1_1.equals(_version)) { _dotVersion = 1; _version = __HTTP_1_1; _header.read(in); updateMimeType(); } else if (__HTTP_0_9.equals(_version)) { _dotVersion = -1; _version = __HTTP_0_9; } else { _dotVersion = 0; _version = __HTTP_1_0; _header.read(in); updateMimeType(); } _handled = false; _state = __MSG_RECEIVED; } /* -------------------------------------------------------------- */ /** * Write the HTTP request line as it was received. */ public void writeRequestLine(Writer writer) throws IOException { writer.write(_method); writer.write(' '); writer.write(_uri != null ? _uri.toString() : "null"); writer.write(' '); writer.write(_version); } /* -------------------------------------------------------------- */ /** * Write the request header. Places the message in __MSG_SENDING state. * * @param writer Http output stream * @exception IOException IO problem */ public void writeHeader(Writer writer) throws IOException { if (_state != __MSG_EDITABLE) throw new IllegalStateException("Not MSG_EDITABLE"); _state = __MSG_BAD; writeRequestLine(writer); writer.write(HttpFields.__CRLF); _header.write(writer); _state = __MSG_SENDING; } /* -------------------------------------------------------------- */ /** * Return the HTTP request line as it was received. */ public String getRequestLine() { return _method + " " + _uri + " " + _version; } /* -------------------------------------------------------------- */ /** * Get the HTTP method for this request. Returns the method with which the request was made. The * returned value can be "GET", "HEAD", "POST", or an extension method. Same as the CGI variable * REQUEST_METHOD. * * @return The method */ public String getMethod() { return _method; } /* ------------------------------------------------------------ */ public void setMethod(String method) { if (getState() != __MSG_EDITABLE) throw new IllegalStateException("Not EDITABLE"); _method = method; } /* ------------------------------------------------------------ */ public String getVersion() { return _version; } /* ------------------------------------------------------------ */ /** * Reconstructs the URL the client used to make the request. The returned URL contains a * protocol, server name, port number, and, but it does not include a path. * <p> * Because this method returns a <code>StringBuffer</code>, not a string, you can modify the * URL easily, for example, to append path and query parameters. * * This method is useful for creating redirect messages and for reporting errors. * * @return "scheme://host:port" */ public StringBuffer getRootURL() { StringBuffer url = new StringBuffer(48); synchronized (url) { String scheme = getScheme(); int port = getPort(); url.append(scheme); url.append("://"); if (_hostPort != null) url.append(_hostPort); else { url.append(getHost()); if (port > 0 && ((scheme.equalsIgnoreCase("http") && port != 80) || (scheme .equalsIgnoreCase("https") && port != 443))) { url.append(':'); url.append(port); } } return url; } } /* ------------------------------------------------------------ */ /** * Reconstructs the URL the client used to make the request. The returned URL contains a * protocol, server name, port number, and server path, but it does not include query string * parameters. * * <p> * Because this method returns a <code>StringBuffer</code>, not a string, you can modify the * URL easily, for example, to append query parameters. * * <p> * This method is useful for creating redirect messages and for reporting errors. * * @return a <code>StringBuffer</code> object containing the reconstructed URL * */ public StringBuffer getRequestURL() { StringBuffer buf = getRootURL(); buf.append(getPath()); return buf; } /* -------------------------------------------------------------- */ /** * Get the full URI. * * @return the request URI (not a clone). */ public URI getURI() { return _uri; } /* ------------------------------------------------------------ */ /** * Get the request Scheme. The scheme is obtained from an absolute URI. If the URI in the * request is not absolute, then the connections default scheme is returned. If there is no * connection "http" is returned. * * @return The request scheme (eg. "http", "https", etc.) */ public String getScheme() { String scheme = _uri.getScheme(); if (scheme == null && _connection != null) scheme = _connection.getDefaultScheme(); return scheme == null ? "http" : scheme; } /* ------------------------------------------------------------ */ /** * @return True if this request came over an integral channel such as SSL */ public boolean isIntegral() { return _connection.getListener().isIntegral(_connection); } /* ------------------------------------------------------------ */ /** * @return True if this request came over an confidential channel such as SSL. */ public boolean isConfidential() { return _connection.getListener().isConfidential(_connection); } /* ------------------------------------------------------------ */ /** * Get the request host. * * @return The host name obtained from an absolute URI, the HTTP header field, the requests * connection or the local host name. */ public String getHost() { // Return already determined host if (_host != null) return _host; // Return host from absolute URI _host = _uri.getHost(); _port = _uri.getPort(); if (_host != null) return _host; // Return host from header field _hostPort = _header.get(HttpFields.__Host); _host = _hostPort; _port = 0; if (_host != null && _host.length() > 0) { int colon = _host.lastIndexOf(':'); if (colon >= 0) { if (colon < _host.length()) { try { _port = TypeUtil.parseInt(_host, colon + 1, -1, 10); } catch (Exception e) { LogSupport.ignore(log, e); } } _host = _host.substring(0, colon); } return _host; } // Return host from connection if (_connection != null) { _host = _connection.getServerName(); _port = _connection.getServerPort(); if (_host != null && !InetAddrPort.__0_0_0_0.equals(_host)) return _host; } // Return the local host try { _host = InetAddress.getLocalHost().getHostAddress(); } catch (java.net.UnknownHostException e) { LogSupport.ignore(log, e); } return _host; } /* ------------------------------------------------------------ */ /** * Get the request port. The port is obtained either from an absolute URI, the HTTP Host header * field, the connection or the default. * * @return The port. 0 should be interpreted as the default port. */ public int getPort() { if (_port > 0) return _port; if (_host != null) return 0; if (_uri.isAbsolute()) _port = _uri.getPort(); else if (_connection != null) _port = _connection.getServerPort(); return _port; } /* ------------------------------------------------------------ */ /** * Get the request path. * * @return The URI path of the request. */ public String getPath() { return _uri.getPath(); } /* ------------------------------------------------------------ */ public void setPath(String path) { if (getState() != __MSG_EDITABLE) throw new IllegalStateException("Not EDITABLE"); if (_uri == null) _uri = new URI(path); else _uri.setURI(path); } /* ------------------------------------------------------------ */ /** * Get the encoded request path. * * @return The path with % encoding. */ public String getEncodedPath() { return _uri.getEncodedPath(); } /* ------------------------------------------------------------ */ /** * Get the request query. * * @return the request query excluding the '?' */ public String getQuery() { return _uri.getQuery(); } /* ------------------------------------------------------------ */ public void setQuery(String q) { if (getState() != __MSG_EDITABLE) throw new IllegalStateException("Not EDITABLE"); _uri.setQuery(q); } /* ------------------------------------------------------------ */ public String getRemoteAddr() { String addr = "127.0.0.1"; HttpConnection connection = getHttpConnection(); if (connection != null) { addr = connection.getRemoteAddr(); if (addr == null) addr = connection.getRemoteHost(); } return addr; } /* ------------------------------------------------------------ */ public String getRemoteHost() { String host = "127.0.0.1"; HttpConnection connection = getHttpConnection(); if (connection != null) { host = connection.getRemoteHost(); if (host == null) host = connection.getRemoteAddr(); } return host; } /* ------------------------------------------------------------ */ /** * Decode HTTP request line. * * @param buf Character buffer * @param len Length of line in buffer. * @exception IOException */ void decodeRequestLine(char[] buf, int len) throws IOException { // Search for first space separated chunk int s1 = -1, s2 = -1, s3 = -1; int state = 0; startloop: for (int i = 0; i < len; i++) { char c = buf[i]; switch (state) { case 0: // leading white if (c == ' ') continue; state = 1; s1 = i; case 1: // reading method if (c == ' ') state = 2; else { s2 = i; if (c >= 'a' && c <= 'z') buf[i] = (char) (c - 'a' + 'A'); } continue; case 2: // skip whitespace after method s3 = i; if (c != ' ') break startloop; } } // Search for last space separated chunk int e1 = -1, e2 = -1, e3 = -1; state = 0; endloop: for (int i = len; i-- > 0;) { char c = buf[i]; switch (state) { case 0: // trailing white if (c == ' ') continue; state = 1; e1 = i; case 1: // reading Version if (c == ' ') state = 2; else e2 = i; continue; case 2: // skip whitespace before version e3 = i; if (c != ' ') break endloop; } } // Check sufficient params if (s3 < 0 || e1 < 0 || e3 < s2) throw new IOException("Bad Request: " + new String(buf, 0, len)); // get method Map.Entry method = __methodCache.getEntry(buf, s1, s2 - s1 + 1); if (method != null) _method = (String) method.getKey(); else _method = new String(buf, s1, s2 - s1 + 1).toUpperCase(); // get version as uppercase if (s2 != e3 || s3 != e2) { Map.Entry version = __versionCache.getEntry(buf, e2, e1 - e2 + 1); if (version != null) _version = (String) version.getKey(); else { for (int i = e2; i <= e1; i++) if (buf[i] >= 'a' && buf[i] <= 'z') buf[i] = (char) (buf[i] - 'a' + 'A'); _version = new String(buf, e2, e1 - e2 + 1); } } else { // missing version _version = __HTTP_0_9; e3 = e1; } // handle URI try { String raw_uri =null; if (URI.__CHARSET_IS_DEFAULT) raw_uri = new String(buf, s3, e3 - s3 + 1); else { int l=e3-s3+1; for (int i=0;i<l;i++) { char c=buf[s3+i]; if (c>=0 && c<0x80) continue; if (_uriExpanded==null || _uriExpanded.length<3*l) _uriExpanded=new char[3*l]; if (i>0) System.arraycopy(buf, s3, _uriExpanded, 0, i); int j=i; for (;i<l;i++) { c=buf[s3+i]; if (c>=0 && c<0x80) _uriExpanded[j++]=c; else { _uriExpanded[j++]='%'; _uriExpanded[j++]=TypeUtil.toHexChar(0xf&(c>>4)); _uriExpanded[j++]=TypeUtil.toHexChar(0xf&c); } } raw_uri=new String(_uriExpanded, 0, j); } if (raw_uri==null) raw_uri = new String(buf, s3, e3 - s3 + 1); } if (_uri == null) _uri = new URI(raw_uri); else _uri.setURI(raw_uri); } catch (IllegalArgumentException e) { LogSupport.ignore(log, e); throw new HttpException(HttpResponse.__400_Bad_Request, new String(buf, s3, e3 - s3 + 1)); } } /* ------------------------------------------------------------ */ /** * Force a removeField. This call ignores the message state and forces a field to be removed * from the request. It is required for the handling of the Connection field. * * @param name The field name * @return The old value or null. */ Object forceRemoveField(String name) { int saved_state = _state; try { _state = __MSG_EDITABLE; return removeField(name); } finally { _state = saved_state; } } /* ------------------------------------------------------------ */ /** * Get the acceptable transfer encodings. The TE field is used to construct a list of acceptable * extension transfer codings in quality order. An empty list implies that only "chunked" is * acceptable. A null list implies that no transfer coding can be applied. * * If the "trailer" coding is found in the TE field, then message trailers are enabled in any * linked response. * * @return List of codings. */ public List getAcceptableTransferCodings() { if (_dotVersion < 1) return null; if (_te != null) return _te; // Decode any TE field Enumeration tenum = getFieldValues(HttpFields.__TE, HttpFields.__separators); if (tenum != null) { // Sort the list List te = HttpFields.qualityList(tenum); int size = te.size(); // Process if something there if (size > 0) { Object acceptable = null; // remove trailer and chunked items. ListIterator iter = te.listIterator(); while (iter.hasNext()) { String coding = StringUtil.asciiToLowerCase(HttpFields.valueParameters(iter .next().toString(), null)); if (!HttpFields.__Chunked.equalsIgnoreCase(coding)) { acceptable = LazyList.ensureSize(acceptable, size); acceptable = LazyList.add(acceptable, coding); } } _te = LazyList.getList(acceptable); } else _te = Collections.EMPTY_LIST; } else _te = Collections.EMPTY_LIST; return _te; } /* ------------------------------------------------------------ */ /* * Extract Paramters from query string and/or form content. */ private void extractParameters() { if (_paramsExtracted) return; _paramsExtracted = true; if (_parameters == null) _parameters = new MultiMap(16); // Handle query string String encoding = getCharacterEncoding(); if (encoding == null) { _uri.putParametersTo(_parameters); } else { // An encoding has been set, so reencode query string. String query = _uri.getQuery(); if (query != null) UrlEncoded.decodeTo(query, _parameters, encoding); } // handle any content. if (_state == __MSG_RECEIVED) { String content_type = getField(HttpFields.__ContentType); if (content_type != null && content_type.length() > 0) { content_type = StringUtil.asciiToLowerCase(content_type); content_type = HttpFields.valueParameters(content_type, null); if (HttpFields.__WwwFormUrlEncode.equalsIgnoreCase(content_type) && HttpRequest.__POST.equals(getMethod())) { int content_length = getIntField(HttpFields.__ContentLength); if (content_length == 0) log.debug("No form content"); else { try { int max = content_length; if (__maxFormContentSize > 0) { if (max < 0) max = __maxFormContentSize; else if (max > __maxFormContentSize) throw new IllegalStateException("Form too large"); } // Read the content ByteArrayOutputStream2 bout = new ByteArrayOutputStream2(max > 0 ? max : 4096); InputStream in = getInputStream(); // Copy to a byte array. // TODO - this is very inefficient and we could // save lots of memory by streaming this!!!! IO.copy(in, bout, max); if (bout.size()==__maxFormContentSize && in.available()>0) throw new IllegalStateException("Form too large"); // Add form params to query params UrlEncoded.decodeTo(bout.getBuf(), 0, bout.getCount(), _parameters,encoding); } catch (EOFException e) { LogSupport.ignore(log, e); } catch (IOException e) { if (log.isDebugEnabled()) log.warn(LogSupport.EXCEPTION, e); else log.warn(e.toString()); } } } } } } /* ------------------------------------------------------------ */ /** * @return Map of parameters */ public MultiMap getParameters() { if (!_paramsExtracted) extractParameters(); return _parameters; } /* ------------------------------------------------------------ */ /** * Get the set of parameter names. * * @return Set of parameter names. */ public Set getParameterNames() { if (!_paramsExtracted) extractParameters(); return _parameters.keySet(); } /* ------------------------------------------------------------ */ /** * Get a parameter value. * * @param name Parameter name * @return Parameter value */ public String getParameter(String name) { if (!_paramsExtracted) extractParameters(); return (String) _parameters.getValue(name, 0); } /* ------------------------------------------------------------ */ /** * Get multi valued paramater. * * @param name Parameter name * @return Parameter values */ public List getParameterValues(String name) { if (!_paramsExtracted) extractParameters(); return _parameters.getValues(name); } /* ------------------------------------------------------------ */ /** * @return Parameters as a map of String arrays */ public Map getParameterStringArrayMap() { if (!_paramsExtracted) extractParameters(); return _parameters.toStringArrayMap(); } /* -------------------------------------------------------------- */ /** * Extract received cookies from a header. * * @return Array of Cookies. */ public Cookie[] getCookies() { if (_cookies != null && _cookiesExtracted) return _cookies; try { // Handle no cookies if (!_header.containsKey(HttpFields.__Cookie)) { _cookies = __noCookies; _cookiesExtracted = true; _lastCookies = null; return _cookies; } // Check if cookie headers match last cookies if (_lastCookies != null) { int last = 0; Enumeration enm = _header.getValues(HttpFields.__Cookie); while (enm.hasMoreElements()) { String c = (String) enm.nextElement(); if (last >= _lastCookies.length || !c.equals(_lastCookies[last])) { _lastCookies = null; break; } last++; } if (_lastCookies != null) { _cookiesExtracted = true; return _cookies; } } // Get ready to parse cookies (Expensive!!!) Object cookies = null; Object lastCookies = null; int version = 0; Cookie cookie = null; // For each cookie header Enumeration enm = _header.getValues(HttpFields.__Cookie); while (enm.hasMoreElements()) { // Save a copy of the unparsed header as cache. String hdr = enm.nextElement().toString(); lastCookies = LazyList.add(lastCookies, hdr); // Parse the header QuotedStringTokenizer tok = new QuotedStringTokenizer(hdr, ",;", false, false); tok.setSingle(false); while (tok.hasMoreElements()) { String c = (String) tok.nextElement(); if (c == null) continue; c = c.trim(); try { String n; String v; int e = c.indexOf('='); if (e > 0) { n = c.substring(0, e); v = c.substring(e + 1); } else { n = c; v = ""; } // Handle quoted values if (version > 0) v = StringUtil.unquote(v); // Ignore $ names if (n.startsWith("$")) { if ("$version".equalsIgnoreCase(n)) version = Integer.parseInt(QuotedStringTokenizer.unquoteDouble(v)); else if ("$path".equalsIgnoreCase(n) && cookie != null) cookie.setPath(v); else if ("$domain".equalsIgnoreCase(n) && cookie != null) cookie.setDomain(v); continue; } v = URI.decodePath(v); cookie = new Cookie(n, v); if (version > 0) cookie.setVersion(version); cookies = LazyList.add(cookies, cookie); } catch (Exception ex) { LogSupport.ignore(log, ex); } } } int l = LazyList.size(cookies); if (_cookies == null || _cookies.length != l) _cookies = new Cookie[l]; for (int i = 0; i < l; i++) _cookies[i] = (Cookie) LazyList.get(cookies, i); _cookiesExtracted = true; l = LazyList.size(lastCookies); _lastCookies = new String[l]; for (int i = 0; i < l; i++) _lastCookies[i] = (String) LazyList.get(lastCookies, i); } catch (Exception e) { log.warn(LogSupport.EXCEPTION, e); } return _cookies; } /* ------------------------------------------------------------ */ public boolean isUserInRole(String role) { Principal principal = getUserPrincipal(); if (principal != null) { UserRealm realm = getHttpResponse().getHttpContext().getRealm(); if (realm != null) return realm.isUserInRole(principal, role); } return false; } /* ------------------------------------------------------------ */ public String getAuthType() { if (_authType == null) getUserPrincipal(); return _authType; } /* ------------------------------------------------------------ */ public void setAuthType(String a) { _authType = a; } /* ------------------------------------------------------------ */ public String getAuthUser() { if (_authUser == null) getUserPrincipal(); return _authUser; } /* ------------------------------------------------------------ */ public void setAuthUser(String user) { _authUser = user; } /* ------------------------------------------------------------ */ public boolean hasUserPrincipal() { if (_userPrincipal == __NOT_CHECKED) getUserPrincipal(); return _userPrincipal != null && _userPrincipal != __NO_USER; } /* ------------------------------------------------------------ */ public Principal getUserPrincipal() { if (_userPrincipal == __NO_USER) return null; if (_userPrincipal == __NOT_CHECKED) { _userPrincipal = __NO_USER; // Try a lazy authentication HttpContext context = getHttpResponse().getHttpContext(); if (context != null) { Authenticator auth = context.getAuthenticator(); UserRealm realm = context.getRealm(); if (realm != null && auth != null) { try { // TODO - should not need to recalculate this! String pathInContext = getPath().substring( context.getContextPath().length()); auth.authenticate(realm, pathInContext, this, null); } catch (Exception e) { LogSupport.ignore(log, e); } } } if (_userPrincipal == __NO_USER) return null; } return _userPrincipal; } /* ------------------------------------------------------------ */ public void setUserPrincipal(Principal principal) { _userPrincipal = principal; } /* ------------------------------------------------------------ */ /** * Recycle the request. */ void recycle(HttpConnection connection) { _method = null; //_uri=null; _host = null; _hostPort = null; _port = 0; _te = null; if (_parameters != null) _parameters.clear(); _paramsExtracted = false; _handled = false; _cookiesExtracted = false; _timeStamp = 0; _timeStampStr = null; _authUser = null; _authType = null; _userPrincipal = null; super.recycle(connection); } /* ------------------------------------------------------------ */ /** * Destroy the request. Help the garbage collector by null everything that we can. */ public void destroy() { _parameters = null; _method = null; _uri = null; _host = null; _hostPort = null; _te = null; _cookies = null; _lastCookies = null; _timeStampStr = null; _userPrincipal = null; _authUser = null; _authUser = null; if (_attributes != null) _attributes.clear(); super.destroy(); } static Principal __NO_USER = new Principal() { public String getName() { return null; } }; static Principal __NOT_CHECKED = new Principal() { public String getName() { return null; } }; public void setURI(URI uri) { _uri = uri; } }