/*
* $Id: Request.java,v 1.10 2002/09/16 08:05:06 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.server.listener;
import java.net.Socket;
import java.net.InetAddress;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.StringTokenizer;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.RequestDispatcher;
import java.security.Principal;
import anvil.java.util.Hashlist;
import anvil.java.util.Holder;
import anvil.util.Conversions;
import anvil.util.HttpDate;
import anvil.server.Zone;
/**
* class Request
*
* @author: Jani Lehtim�ki
*/
public class Request implements HttpServletRequest
{
private Zone _zone;
private InetAddress _remoteaddress;
private int _remoteport;
private InetAddress _localaddress;
private int _localport;
private RequestInputStream _input;
private BufferedReader _reader;
private int _inputstate = 0;
private String _host = "localhost";
private String _pathinfo;
private String _method;
private String _querystring;
private int _version = 10; // 11, 12
private int _contentlength = -1;
private String _contenttype = null;
private Hashtable _headers = new Hashtable();
private Hashlist _attributes = new Hashlist();
private ArrayList _cookies = null;
public Request(Zone zone, Socket socket, RequestInputStream input, String line) throws IOException
{
_zone = zone;
_input = input;
_remoteaddress = socket.getInetAddress();
_remoteport = socket.getPort();
_localaddress = socket.getLocalAddress();
_localport = socket.getLocalPort();
init(line);
}
void destroy()
{
_zone = null;
_remoteaddress = null;
_localaddress = null;
_input = null;
_reader = null;
_host = null;
_pathinfo = null;
_method = null;
_querystring = null;
_headers.clear();
_headers = null;
_attributes.clear();
_attributes = null;
if (_cookies != null) {
_cookies.clear();
_cookies = null;
}
}
protected String readLine() throws IOException
{
String line = _input.readLine();
if (line == null) {
throw new InvalidRequestException("Unexpected end of headers");
}
return line;
}
protected void init(String line) throws IOException
{
if (line.length()<3) {
throw new InvalidRequestException("Too short request header");
}
int i = line.indexOf(' ');
if (i<0) {
throw new InvalidRequestException("HTTP Method missing");
}
String method = line.substring(0, i);
if (method.equals("GET") ||
method.equals("POST"))
{
_method = method;
} else if (method.equals("HEAD") ||
method.equals("OPTIONS") ||
method.equals("PUT") ||
method.equals("DELETE") ||
method.equals("TRACE") ||
method.equals("CONNECT") ||
method.equals(""))
{
throw new InvalidRequestException("Unsupported HTTP method");
} else {
throw new InvalidRequestException("Invalid HTTP method");
}
int j = line.lastIndexOf(' ');
if (j <= i) {
j = line.length();
}
String pathinfo;
String query = line.substring(i+1, j);
String protocol = line.substring(j+1);
if (protocol.equals("HTTP/1.0")) {
_version = 10;
} else if (protocol.equals("HTTP/1.1")) {
_version = 11;
} else if (protocol.equals("HTTP/1.2")) {
_version = 12;
} else {
throw new InvalidRequestException("Unsupported HTTP version");
}
i = query.indexOf('?');
if (i>=0) {
pathinfo = query.substring(0, i);
query = query.substring(i+1);
} else {
pathinfo = query;
query = null;
}
_pathinfo = pathinfo;
_querystring = query;
while(true) {
line = readLine();
if (line == null) {
break;
}
if (line.length() == 0) {
break;
}
i = line.indexOf(':');
String name;
String value;
if (i>0) {
name = line.substring(0, i).trim();
value = line.substring(i+1).trim();
} else {
name = line.trim();
value = "";
}
name = name.toLowerCase();
addHeader(name, value);
if (name.equals("cookie")) {
parseCookies(value);
}
}
_host = getHeader("Host");
if (_host == null) {
_host = _localaddress.getHostName();
}
i = _host.indexOf(':');
if (i>=0) {
_host = _host.substring(0, i);
}
if (query != null) {
parseQuery(query);
}
_contentlength = getIntHeader("Content-length");
_contenttype = getHeader("Content-type");
if (_contenttype != null) {
if (_contenttype.equals("application/x-www-form-urlencoded")) {
if (_contentlength > -1) {
int length = _contentlength;
byte[] content = new byte[length];
int index = 0;
while(index < length) {
int read = _input.read(content, index, length - index);
if (read == -1) {
break;
}
index += read;
}
parseQuery(new String(content));
} else {
throw new InvalidRequestException("Unknown Content-length for POST query");
}
}
}
}
protected void parseQuery(String query)
{
StringTokenizer tok = new StringTokenizer(query, "&");
while(tok.hasMoreTokens()) {
String token = tok.nextToken();
int i = token.indexOf('=');
String key;
String value;
if (i>0) {
key = Conversions.URLDecode(token.substring(0, i));
value = Conversions.URLDecode(token.substring(i+1));
} else {
key = Conversions.URLDecode(token);
value = "";
}
Holder holder = _attributes.getHolder(key);
if (holder != null) {
Object obj = holder.getValue();
if (obj instanceof String[]) {
String[] arr = (String[])obj;
int length = arr.length;
String[] newarr = new String[length+1];
System.arraycopy(arr, 0, newarr, 0, length);
newarr[length] = value;
holder.setValue(newarr);
} else {
holder.setValue(new String[] { obj.toString(), value } );
}
} else {
_attributes.put(key, value);
}
}
}
protected void parseCookies(String cookies)
{
StringTokenizer tok = new StringTokenizer(cookies, ";");
while(tok.hasMoreTokens()) {
String cookie = tok.nextToken();
int i = cookie.indexOf('=');
String name;
String value;
if (i>0) {
name = cookie.substring(0, i).trim();
value = cookie.substring(i+1).trim();
} else {
name = cookie.trim();
value = "";
}
if (_cookies == null) {
_cookies = new ArrayList();
}
_cookies.add(new Cookie(name, value));
}
}
protected void addHeader(String name, String value)
{
Header header = (Header)_headers.get(name);
if (header == null) {
header = new Header(name, value);
_headers.put(name, header);
} else {
header.addValue(value);
}
}
public boolean keepAlive()
{
if (_version >= 11) {
String conn = getHeader("connection");
if ((conn != null) && conn.equalsIgnoreCase("Keep-Alive")) {
return true;
}
}
return false;
}
public int getVersion()
{
return _version;
}
public String getMethod()
{
return _method;
}
public String getPathInfo()
{
return _pathinfo;
}
public String getPathTranslated()
{
return _pathinfo;
}
public String getQueryString()
{
return _querystring;
}
public String getRemoteUser()
{
return null;
}
public Enumeration getHeaderNames()
{
return _headers.keys();
}
public Enumeration getHeaders(String name)
{
Header header = (Header)_headers.get(name);
if (header != null) {
return header.getValues();
} else {
return new Enumeration() {
public boolean hasMoreElements()
{
return false;
}
public Object nextElement()
{
return null;
}
};
}
}
public String getHeader(String name)
{
Header header = (Header)_headers.get(name.toLowerCase());
if (header != null) {
return header.getValue();
} else {
return null;
}
}
public int getIntHeader(String name)
{
String str = getHeader(name.toLowerCase());
if (str != null) {
return Integer.parseInt(str);
}
return -1;
}
public long getDateHeader(String name)
{
String str = getHeader(name.toLowerCase());
if (str != null) {
return new HttpDate(str).getTime();
}
return -1;
}
public Enumeration getAttributeNames()
{
return _attributes.keys();
}
public Enumeration getParameterNames()
{
return _attributes.keys();
}
public String getParameter(String name)
{
Object obj = _attributes.get(name);
if (obj != null) {
if (obj instanceof String[]) {
return ((String[])obj)[0];
} else {
return obj.toString();
}
}
return null;
}
public String[] getParameterValues(String name)
{
Object obj = _attributes.get(name);
if (obj != null) {
if (obj instanceof String[]) {
return (String[])obj;
} else {
return new String[] { obj.toString() };
}
}
return null;
}
public Object getAttribute(String name)
{
return _attributes.get(name);
}
public void removeAttribute(String name)
{
_attributes.remove(name);
}
public void setAttribute(String name, Object obj)
{
_attributes.put(name, obj);
}
public synchronized ServletInputStream getInputStream()
{
switch(_inputstate) {
case 0:
_inputstate = 1;
case 1:
break;
case 2:
throw new IllegalStateException("getReader() already called");
}
return _input;
}
public synchronized BufferedReader getReader()
{
switch(_inputstate) {
case 0:
_reader = new BufferedReader(new InputStreamReader(_input));
_inputstate = 2;
break;
case 1:
throw new IllegalStateException("getInputStream() already called");
case 2:
}
return _reader;
}
public String getProtocol()
{
return "HTTP/1.1";
}
public String getScheme()
{
return "http";
}
public String getServerName()
{
return _host;
}
public int getServerPort()
{
return _localport;
}
public String getRemoteAddr()
{
return _remoteaddress.getHostAddress();
}
public String getRemoteHost()
{
return _remoteaddress.getHostName();
}
public int getContentLength()
{
return _contentlength;
}
public String getContentType()
{
return _contenttype;
}
public String getCharacterEncoding()
{
return null;
}
public Locale getLocale()
{
return Locale.getDefault();
}
public Enumeration getLocales()
{
return new Enumeration() {
private boolean _hasmore = true;
public boolean hasMoreElements()
{
return _hasmore;
}
public Object nextElement()
{
return Locale.getDefault();
}
};
}
public boolean isSecure()
{
return false;
}
public RequestDispatcher getRequestDispatcher(java.lang.String path)
{
throw new UnsupportedOperationException("getRequestDispatcher() not supported");
}
public String getContextPath()
{
return "";
}
public String getRealPath(String path)
{
return path;
}
public String getAuthType()
{
return null;
}
public Cookie[] getCookies()
{
if (_cookies != null) {
return (Cookie[])_cookies.toArray(new Cookie[_cookies.size()]);
} else {
return null;
}
}
public String getRequestedSessionId()
{
return null;
}
public String getRequestURI()
{
return _pathinfo;
}
public String getServletPath()
{
return "";
}
public HttpSession getSession()
{
throw new UnsupportedOperationException("getSession() not supported");
}
public HttpSession getSession(boolean create)
{
throw new UnsupportedOperationException("getSession(boolean) not supported");
}
public boolean isRequestedSessionIdValid()
{
return false;
}
public boolean isRequestedSessionIdFromCookie()
{
return false;
}
public boolean isRequestedSessionIdFromURL()
{
return false;
}
public boolean isRequestedSessionIdFromUrl()
{
return false;
}
public boolean isUserInRole(String role)
{
return false;
}
public Principal getUserPrincipal()
{
return null;
}
}