/*
 * @(#)SiteTransferServlet.java
 *
 * Copyright (C) 2006 Infocity Inc. All Rights Reserved.
 */
package info.dragonlady.sso.servlet;

import info.dragonlady.cluster.AssertionServiceWrapper;
import info.dragonlady.sso.helper.AttributeGenerator;
import info.dragonlady.sso.helper.AuthenticationException;
import info.dragonlady.sso.helper.Authenticator;
import info.dragonlady.sso.helper.GenerationException;
import info.dragonlady.sso.helper.SSOServletConfig;

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

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import info.dragonlady.sso.AssertionManager;
import info.dragonlady.sso.SSOException;
import info.dragonlady.sso.SiteTransfer;

/**
 * サイト転送処理サーブレット。
 * 
 * @author Hiroshi.Ebata(INFOCITY)
 * @version $Revision: 1.0 $ $Date: 2006/10/19 17:38:54 $
 */
public class SiteTransferServlet extends HttpServlet {

	protected String paramNameKind = "kind";

	/**
	 * コンストラクタ。
	 */
	public SiteTransferServlet() {
		super();
	}

	/**
	 * サイト転送処理。
	 * 
	 * @param request HTTP要求オブジェクト
	 * @param response HTTP応答オブジェクト
	 * @throws ServletException
	 * @throws IOException
	 * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			// 認証関連の設定種別
			String kind = this.getInitParameter(this.paramNameKind);

			// アサーション管理ID（セッションID等）
			String id = request.getSession().getId();
			// ユーザの認証ID
			String authId = null;
			if(SSOServletConfig.isAuthRequired(kind)) {
				Authenticator authenticator = (Authenticator)Class.forName(SSOServletConfig.getAuthClassName(kind)).newInstance();
				if(!authenticator.authenticate(request)) {
					throw new AuthenticationException("Failed to authenticate user.");
				}
			}
			authId = (String)request.getSession().getAttribute(SSOServletConfig.getSessionLoginKey()); // セッション内から認証IDを取得

			// ユーザの属性情報
			AttributeGenerator attrGenerator = (AttributeGenerator)Class.forName(SSOServletConfig.getAttributesClassName(kind)).newInstance();
			Map attributes = attrGenerator.generateAttributesMap(request);

			// 認証アサーション作成及び目的サイトへのリダイレクト
			SiteTransfer st = new SiteTransfer(request, response);
			st.forwardTo(id, authId, attributes);

			// 分散環境でのアサーション共有処理
			if(!SSOServletConfig.isClusterStandalone()) {
				AssertionServiceWrapper.put(id, AssertionManager.getInstance().get(id));
			}
		} catch(AuthenticationException e) {
			processException(e, response, HttpServletResponse.SC_FORBIDDEN);
		} catch(GenerationException e) {
			processException(e, response, HttpServletResponse.SC_FORBIDDEN);
		} catch(SSOException e) {
			processException(e, response, HttpServletResponse.SC_FORBIDDEN);
		} catch(Exception e) {
			processException(e, response, HttpServletResponse.SC_NOT_FOUND);
		}
	}

	private void processException(Exception e, HttpServletResponse response, int statusCode) throws ServletException {
		try {
			e.printStackTrace();
			if(!response.isCommitted()) {
				String redirectionUrl = SSOServletConfig.getRedirection();
				if(redirectionUrl != null && redirectionUrl.length() > 0) {
					response.sendRedirect(redirectionUrl);
				} else {
					response.sendError(statusCode);
				}
			}
		} catch(Exception ex) {
			throw new ServletException(ex);
		}
	}

}
