/*
 * Copyright (c) 2003, Morpho Project.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of the Morpho Project nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package jp.morpho.webapp.servlet;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import jp.morpho.util.ConversionMap;

/**
 * <P>
 * このクラスは、Filter インタフェースのスケルトン実装を提供し、このインタフェースを実装するのに必要な作業量を最小限に抑えます。
 * Filter は、リソース (サーブレット、静的コンテンツ) の要求、リソースからの応答、またはその両方に対してフィルタリング作業を実行するオブジェクトです。
 * </P>
 * <P>
 * Filter は、doFilter メソッドにおいてフィルタリングを実行します。すべての Filter は FilterConfig オブジェクトへアクセスでき、このオブジェクトから、初期化パラメータと、フィルタリングに必要なリソースのロードなどに使用できる ServletContext への参照を取得することができます。
 * </P>
 * <P>
 * Filter は、Web アプリケーションの配備記述子内で設定されます。
 * </P>
 * <P>
 * Filter の例には、次のものがあります。
 * <BR>1) 認証フィルタ
 * <BR>2) ログおよび監査のフィルタ
 * <BR>3) イメージ変換フィルタ
 * <BR>4) データ圧縮フィルタ
 * <BR>5) 暗号化フィルタ
 * <BR>6) トークン化フィルタ
 * <BR>7) リソースへのアクセスイベントを発生させるフィルタ
 * <BR>8) XSL/T フィルタ
 * <BR>9) MiME タイプチェ−ンフィルタ
 * </P>
 * @author Kumiko Hiroi
 */
public abstract class AbstractFilter
	implements Filter
{

	/** 初期化パラメータが格納されるマップ */
	private ConversionMap parameters = null;

	/** サーブレットコンテキスト */
	private ServletContext sc = null;

	/**
	 * <P>
	 * AbstractFilter を構築します。
	 * </P>
	 */
	public AbstractFilter()
	{
		super();
		parameters = new ConversionMap();
	}

	/**
	 * <P>
	 * フィルタがサービス開始状態になる際に、Web コンテナによって呼び出されます。
	 * サーブレットコンテナは、フィルタをインスタンス化した後に、init メソッドを 1 回だけ呼び出します。
	 * フィルタにフィルタリング作業を実行するように要求するには、init メソッドが正常に終了していなければなりません。
	 * </P>
	 * <P>
	 * このメソッドは、すべての初期化パラメータを取得するように実装されています。
	 * 取得された初期化パラメータは、getInitParameterMap() メソッドで Map として取得できます。
	 * このメソッドをオーバーライドする場合は、super.init(filterConfig) を呼び出してください。
	 * </P>
	 * <P>
	 * init メソッドが次のいずれかの状態の場合、Web コンテナはフィルタをサービス状態にできません。
	 * <BR>1.ServletException をスローした
	 * <BR>2.Web コンテナによって定義された時間内に、復帰しない
	 * </P>
	 * @param filterConfig サーブレットコンテナによって使用されるフィルタ設定のためのオブジェクト
	 * @exception ServletException フィルタを初期化できなかった場合
	 * @see javax.servlet.Filter#init(FilterConfig)
	 */
	public void init(FilterConfig filterConfig) throws ServletException
	{
		sc = filterConfig.getServletContext();
		for(Enumeration enum = filterConfig.getInitParameterNames(); enum.hasMoreElements();)
		{
			String name = (String)enum.nextElement();
			try
			{
				setInitParameter(name, filterConfig.getInitParameter(name));
			}
			catch (Exception e)
			{
			}
		}
	}

	/**
	 * <P>
	 * Filter の doFilter メソッドは、チェーンの終端にあるリソースをクライアントが要求することをきっかけとして、要求と応答のペアがチェ−ンに沿って渡されていくごとに、コンテナに呼び出されます。
	 * このメソッドへ渡される FilterChain によって、Filter は要求と応答をチェ−ン内の次のエンティティに渡すことができます。
	 * </P>
	 * <P>
	 * <DL>
	 * <DD>Filter の doFilter メソッドは、チェーンの終端にあるリソースをクライアントが要求することをきっかけとして、要求と応答のペアがチェ−ンに沿って渡されていくごとに、コンテナに呼び出されます。このメソッドへ渡される FilterChain によって、Filter は要求と応答をチェ−ン内の次のエンティティに渡すことができます。
	 * <P>
	 * このメソッドの典型的な実装は、次のように行われます。
	 * <BR>1. 要求を検査する
	 * <BR>2. オプションとして、入力フィルタリング用にコンテンツまたはヘッダをフィルタリングするカスタム実装により、要求オブジェクトをラップする
	 * <BR>3. オプションとして、出力フィルタリング用にコンテンツまたはヘッダをフィルタリングするカスタム実装により、応答オブジェクトをラップする
	 * <BR>4. a) FilterChain オブジェクトを使用してチェーン内の次のエンティティを呼び出す (chain.doFilter())
	 * <BR>4. b) または、要求に対する処理を打ち切るため、フィルタチェーン内の次のエンティティに要求と応答のペアを渡さない
	 * <BR>5. フィルタチェーン内の次のエンティティを呼び出した後に、応答に対してヘッダを直接設定する
	 * </P>
	 * </DL>
	 * </P>
	 * <P>
	 * このメソッドは空の定義をしています。
	 * 必要でならば AbstractFilter クラスのサブクラス化によって、このメソッドを実装できます。
	 * </P>
	 * @param request クライアントがサーブレットに行う要求を含む ServletRequest オブジェクト
	 * @param response サーブレットがクライアントに送信する応答を含む ServletResponse オブジェクト
	 * @param chain フィルタチェーン
	 * @exception IOException フィルタが要求を処理するときに、入出力エラーが検出された場合
	 * @exception ServletException 要求を処理できなかった場合
	 * @see javax.servlet.Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(
		ServletRequest request,
		ServletResponse response,
		FilterChain chain)
		throws IOException, ServletException
	{
	}

	/**
	 * <P>
	 * フィルタがサービス状態を終える際に、Web コンテナによって呼び出されます。
	 * フィルタの doFilter メソッド内のすべてのスレッドが終了した後、またはタイムアウト期間が過ぎた後にのみ、このメソッドは呼び出されます。
	 * このメソッドを呼び出した後は、Web コンテナはフィルタのこのインスタンスに対し doFilter を二度と呼び出すことはありません。
	 * </P>
	 * <P>
	 * このメソッドは、メモリ、ファイルハンドラ、スレッドなどの保持されているリソースを解放する機会、およびすべての持続的状態と、メモリ内のフィルタの現在の状態との同期を取るための機会を提供します。
	 * </P>
	 * <P>
	 * このメソッドは空の定義をしています。
	 * 必要でならば AbstractFilter クラスのサブクラス化によって、このメソッドを実装できます。
	 * </P>
	 * @see javax.servlet.Filter#destroy()
	 */
	public void destroy()
	{
	}

	/**
	 * <P>
	 * すべての初期化パラメータのマッピングが格納された Map を返します。
	 * パラメータが存在しない場合は、空の Map を返します。
	 * </P>
	 * <P>
	 * 返される Map の実装は、ConversionMap です。
	 * </P>
	 * @return すべての初期化パラメータのマッピングが格納された Map
	 */
	public Map getInitParameterMap()
	{
		return parameters;
	}

	/**
	 * <P>
	 * 初期化パラメータを Map に格納します。
	 * </P>
	 * @param name 初期化パラメータの名前
	 * @param value 初期化パラメータの値
	 */
	private void setInitParameter(String name, String value)
	{
		parameters.putString(name, value);
	}

	/**
	 * <P>
	 * 呼び出し元が現在実行している ServletContext への参照を返します。
	 * </P>
	 * @return 呼び出し元がサーブレットコンテナとの対話のために使用している ServletContext オブジェクト
	 */
	public ServletContext getServletContext()
	{
		return sc;
	}

}
