/*
 * Copyright (C) 2005-2006 Kouji Sugisawa. All rights reserved.
 */

package jp.sourceforge.livez.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import jp.sourceforge.livez.MobilePhone;
import jp.sourceforge.livez.MobilePhoneFactory;
import jp.sourceforge.livez.ServiceNotFoundException;

/**
 * 携帯端末情報の生成及び破棄を管理するサーブレットフィルタクラスです。<p>
 * フィルタの初期化パラメータに指定可能なパラメータについては以下を参照して下さい。
 * <ul>
 * <li><b>url</b>&nbsp;-&nbsp;リクエストが携帯端末からではない場合のリダイレクト先を指定します。
 * このパラメータを使用しない場合はクライアントに不正なリクエスト (400) を表す HTTP ステータスコードが返されます。</li>
 * </ul>
 * </p>
 * 
 * @author 杉澤 浩二
 */
public final class MobilePhoneFilter implements Filter {

	/**
	 * 共通ログインスタンスです。
	 */
	private static final Log log = LogFactory.getLog(MobilePhoneFilter.class);

	private WebApplicationContext context;

	/**
	 * 不明なデバイスの場合のリダイレクトパスを保持します。
	 */
	private String url;

	/*
	 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
	 */
	public void init(final FilterConfig filterConfig) {
		this.context = WebApplicationContextUtils.getWebApplicationContext(filterConfig.getServletContext());
		this.url = filterConfig.getInitParameter("url");
	}

	/*
	 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
	 */
	public void doFilter(
		final ServletRequest request,
		final ServletResponse response,
		final FilterChain chain)
		throws IOException, ServletException {

		try {
			request.setAttribute(MobilePhone.BEAN_KEY, MobilePhoneFactory.getMobilePhone((HttpServletRequest)request, this.context));
		} catch (ServiceNotFoundException e) {
			if (log.isDebugEnabled())
				log.debug(e.getMessage(), e);

			redirect(request, response);
			return;
		}

		if (response.isCommitted())
			return;

		chain.doFilter(request, response);
	}

	/*
	 * @see javax.servlet.Filter#destroy()
	 */
	public void destroy() {
		this.context = null;
		this.url = null;
	}

	private void redirect(final ServletRequest request, final ServletResponse response) throws IOException {
		HttpServletResponse res = (HttpServletResponse) response;

		if (url != null) {
			res.sendRedirect(url);
		} else
			res.sendError(HttpServletResponse.SC_BAD_REQUEST);
	}

}
