001: package pygmy.core;
002:
003: import java.io.*;
004: import java.util.*;
005: import java.net.*;
006:
007: /**
008: * This holds the http request data a given request.
009: */
010: public class HttpRequest extends Request {
011:
012: private static int nextRequestId = 0;
013:
014: private Integer requestId = null;
015:
016: private String scheme;
017:
018: private String method;
019:
020: private String url;
021:
022: private String query;
023:
024: private String protocol;
025:
026: private int major;
027:
028: private int minor;
029:
030: private HttpHeaders headers;
031:
032: private byte[] postData;
033:
034: private Map httpVariableMap;
035:
036: private String connectionHeader;
037:
038: private long timeStamp;
039:
040: public HttpRequest(String aScheme, Socket aConnection,
041: Properties serverConfig) {
042: super (aConnection, serverConfig);
043: scheme = aScheme;
044: connection = aConnection;
045: init();
046: }
047:
048: public HttpRequest(String url, Properties serverConfig,
049: boolean isInternal) {
050: super (null, serverConfig);
051: init();
052: method = "GET";
053: scheme = "http";
054: parseUrl(url);
055: protocol = "HTTP/1.0";
056: major = 1;
057: minor = 0;
058: headers = new HttpHeaders();
059: setIsInternal(isInternal);
060: }
061:
062: public boolean readRequest(InputStream aStream) throws IOException {
063: InternetInputStream stream = new InternetInputStream(aStream);
064: String startLine = null;
065: try {
066: startLine = readHttpCommand(stream);
067: if (startLine == null) {
068: return false;
069: }
070: if (protocol.equals("HTTP/1.0")) {
071: major = 1;
072: minor = 0;
073: } else if (protocol.equals("HTTP/1.1")) {
074: major = 1;
075: minor = 1;
076: } else {
077: throw new HttpProtocolException(
078: HttpURLConnection.HTTP_VERSION, "Protocol "
079: + protocol + " not supported.");
080: }
081:
082: headers = new HttpHeaders(stream);
083: readPostData(stream);
084: } catch (NoSuchElementException e) {
085: throw new HttpProtocolException(
086: HttpURLConnection.HTTP_NOT_FOUND, "Bad request "
087: + startLine);
088: } catch (NumberFormatException e) {
089: throw new HttpProtocolException(
090: HttpURLConnection.HTTP_LENGTH_REQUIRED,
091: "Content Length was not a number or not supplied.");
092: }
093: return true;
094: }
095:
096: private void init() {
097: method = null;
098: url = null;
099: query = null;
100: protocol = null;
101: connectionHeader = null;
102: postData = null;
103: httpVariableMap = null;
104: timeStamp = System.currentTimeMillis();
105: connectionHeader = "Connection";
106: requestId = new Integer(nextRequestId++);
107: }
108:
109: public Integer getRequestId() {
110: return requestId;
111: }
112:
113: private String readHttpCommand(InternetInputStream stream)
114: throws IOException {
115: String startLine = null;
116: do {
117: startLine = stream.readline();
118: if (startLine == null)
119: return null;
120: } while (startLine.trim().length() == 0);
121:
122: StringTokenizer tokenizer = new StringTokenizer(startLine);
123: method = tokenizer.nextToken();
124: parseUrl(tokenizer.nextToken());
125: protocol = tokenizer.nextToken();
126:
127: return startLine;
128: }
129:
130: private void readPostData(InternetInputStream stream)
131: throws IOException {
132: String contenLength = getRequestHeader("Content-Length");
133: if (contenLength == null)
134: return;
135:
136: int postLength = Integer.parseInt(contenLength);
137: postData = new byte[postLength];
138:
139: int length = -1;
140: int offset = stream.read(postData);
141: while (offset >= 0 && offset < postData.length) {
142: length = stream.read(postData, offset, postData.length
143: - offset);
144: if (length == -1) {
145: break;
146: }
147: offset += length;
148: }
149: }
150:
151: private void parseUrl(String aUrl) {
152: int queryIndex = aUrl.indexOf('?');
153: if (queryIndex < 0) {
154: url = aUrl;
155: } else {
156: url = aUrl.substring(0, queryIndex);
157: if ((queryIndex + 1) < aUrl.length())
158: query = aUrl.substring(queryIndex + 1);
159: }
160: }
161:
162: public String getRequestHeader(String key) {
163: return headers.get(key);
164: }
165:
166: public String getRequestHeader(String key, String defaultValue) {
167: String val = getRequestHeader(key);
168: return (val == null) ? defaultValue : val;
169: }
170:
171: public String getMethod() {
172: return method;
173: }
174:
175: public String getUrl() {
176: return url;
177: }
178:
179: public String getQuery() {
180: return query;
181: }
182:
183: public String getParameter(String key) {
184: if (httpVariableMap == null) {
185: httpVariableMap = createQueryMap(query);
186: if (postData != null) {
187: String contentType = headers.get("Content-Type");
188: if ("application/x-www-form-urlencoded"
189: .equals(contentType)) {
190: httpVariableMap.putAll(createQueryMap(new String(
191: postData)));
192: }
193: }
194: }
195: return (String) httpVariableMap.get(key);
196: }
197:
198: public Set getParameterNames() {
199: return httpVariableMap.keySet();
200: }
201:
202: private Map createQueryMap(String query) {
203: Map queryMap = new TreeMap();
204: if (query == null) {
205: return queryMap;
206: }
207:
208: query = query.replace('+', ' ');
209: StringTokenizer st = new StringTokenizer(query, "&");
210: try {
211: while (st.hasMoreTokens()) {
212: String field = st.nextToken();
213: int index = field.indexOf('=');
214: if (index < 0) {
215: queryMap.put(URLDecoder.decode(field, "UTF-8"), "");
216: } else {
217: queryMap.put(URLDecoder.decode(field.substring(0,
218: index), "UTF-8"), URLDecoder.decode(field
219: .substring(index + 1), "UTF-8"));
220: }
221: }
222: } catch (UnsupportedEncodingException e) {
223: }
224:
225: return queryMap;
226: }
227:
228: public String getScheme() {
229: return scheme;
230: }
231:
232: public String getProtocol() {
233: return protocol;
234: }
235:
236: public byte[] getPostData() {
237: return postData;
238: }
239:
240: public boolean isKeepAlive() {
241: if ("Keep-Alive"
242: .equalsIgnoreCase(getRequestHeader(connectionHeader))) {
243: return true;
244: } else if ("close"
245: .equalsIgnoreCase(getRequestHeader(connectionHeader))) {
246: return false;
247: } else if (major >= 1 && minor > 0) {
248: return true;
249: } else {
250: return false;
251: }
252: }
253:
254: public int getMajorVersion() {
255: return major;
256: }
257:
258: public int getMinorVersion() {
259: return minor;
260: }
261:
262: public String getConnectionHeader() {
263: return connectionHeader;
264: }
265:
266: public long getTimestamp() {
267: return timeStamp;
268: }
269:
270: public String getProperty(String key) {
271: return getProperty(key, null);
272: }
273:
274: public HttpHeaders getHeaders() {
275: return headers;
276: }
277:
278: public String toString() {
279: return method + " " + url
280: + ((query != null) ? "?" + query : "") + " " + protocol;
281: }
282:
283: public String serverUrl() {
284: return getProperty("url");
285: }
286:
287: public String createUrl(String absolutePath) throws IOException {
288: return absolutePath;
289: }
290:
291: public boolean isProtocolVersionLessThan(int aMajor, int aMinor) {
292: return (major <= aMajor && minor < aMinor);
293: }
294:
295: }
|