/*
 * LOGICAL-PARADOX.ORG
 * Copyright (C)2005 satoshi akabane(akabane@logical-paradox.org)
 * $Id: ClientRequest.java,v 1.1 2005/05/11 17:48:20 rampil Exp $
 */
package org.logical_paradox.httpd;

import java.util.HashMap;
import java.util.Iterator;

import org.logical_paradox.common.util.StringUtils;
import org.logical_paradox.httpd.exception.*;

/**
 * クライアントからのリクエスト情報を格納するオブジェクト
 * @author satoshi akabane@logical-paradox.org
 * @version $Revision: 1.1 $
 */
public class ClientRequest {
	/** HTTPメソッド */
	private String method;
	/** プロトコル */
	private String protocol;
	/** バージョン */
	private String version;
	/** クエリー */
	private String query;
	/** サーバーの起動オプション */
	private final Config config;

	/** ヘッダ */
	private HashMap header = new HashMap();

	/**
	 * コンストラクタ
	 * @param line クライアントから送信されてきた文字列
	 */
	public ClientRequest(String line, Config c) throws HttpException {
		parser(line);
		config = c;
	}

	/**
	 * 送信されてきたリクエストを分解する
	 * @param line リクエスト文字列
	 */
	protected void parser(String line) throws HttpException {
		line = line.replaceAll("\r", "");
		String[] lines = line.split("\n");
		if(lines == null || lines.length == 0) {
			throw new HttpException(400,"request parameter is empty.");
		}
		String[] tokens = StringUtils.trimEmptyLines(lines[0].split(" "));

		// リクエストの書式 GET / HTTP/1.1
		if(tokens.length < 2 || tokens.length > 3) {
			// トークン数が2より少ないか，3より多い場合は書式エラー
			throw new HttpException(400,line);
		}
		// メソッド
		method = tokens[0].toUpperCase();
		// クエリー
		query = tokens[1];
		// プロトコル
		String p = "HTTP/1.0";
		if(tokens.length >= 3) {
			p = tokens[2].toUpperCase();
		}
		String[] protocolAndVersion = p.split("/");
		if(protocolAndVersion.length != 2) {
			// プロトコルのフォーマットエラー
			throw new HttpException(400,"invalid protocol format has been specified.");
		}
		protocol = protocolAndVersion[0];
		version = protocolAndVersion[1];

		// ヘッダの取り込み
		int linecnt = 1;
		while(linecnt < lines.length) {
			String l = lines[linecnt++];
			// ヘッダの取り込み
			int pos = l.indexOf(":");
			if(pos > 1) {
				String key = l.substring(0, pos).trim();
				String value = l.substring(pos+1).trim();
				// ヘッダ情報として取り込む
				header.put(key, value);
			}
		}
	}
	/**
	 * HTTPメソッドを返す
	 * @return HTTPメソッド
	 */
	public String getMethod() {
		return method;
	}
	/**
	 * プロトコルを返す
	 * @return プロトコル
	 */
	public String getProtocol() {
		return protocol;
	}
	/**
	 * HTTPのバージョンを返す
	 * @return HTTPのバージョン
	 */
	public String getVersion() {
		return version;
	}
	/**
	 * クエリー文字列を返す
	 * @return クエリー文字列
	 */
	public String getQuery() {
		return query;
	}
	/**
	 * サーバーの起動オプションを返す
	 * @return 起動オプション
	 */
	public Config getConfig() {
		return config;
	}
	/**
	 * ヘッダのキーを返す
	 * @return キーを格納したコレクションに対するイテレータ
	 */
	public Iterator headerKeys() {
		return header.keySet().iterator();
	}
	/**
	 * 指定されたヘッダに対する設定値を返す
	 * @param key ヘッダ
	 * @return 設定値(null:未設定)
	 */
	public String getHeaderValue(String key) {
		return (String)header.get(key);
	}
}
