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

import info.dragonlady.sso.message.SSOMessageResource;

import java.net.URL;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.opensaml.SAMLAssertion;
import org.opensaml.SAMLException;
import org.opensaml.SAMLResponse;
import org.opensaml.artifact.Artifact;

/**
 * アーティファクトプロファイルによる目的Webサイトへの転送処理クラス。
 * 
 * @author Hiroshi.Ebata(INFOCITY)
 * @version $Revision: 1.0 $ $Date: 2006/04/13 22:30:39 $
 */
public class SiteTransfer {

	private HttpServletRequest request = null;

	private HttpServletResponse response = null;

	private final String defaultEncoding = "ISO-2022-JP";

	/**
	 * コンストラクタ
	 * 
	 * @param request 要求オブジェクト
	 * @param response 応答オブジェクト
	 */
	public SiteTransfer(HttpServletRequest request, HttpServletResponse response) {
		super();
		this.request = request;
		this.response = response;
	}

	/**
	 * アーティファクトとパラメータを指定して、目的サイトのアーティファクトレシーバへリダイレクトする。
	 * 
	 * @param artifacts アーティファクト
	 * @param params 目的サイトへ送信する任意のパラメータ
	 * @throws SSOException
	 */
	public void forward(List<Artifact> artifacts, Map<String, String> params) throws SSOException {
		try {
			if(artifacts == null) {
				throw new SSOException(SSOMessageResource.getMessage("1002", toArray(null, null, params)));
			}

			StringBuffer redirectURL = new StringBuffer();
			String target = request.getParameter(SSOConstants.NAME_TARGET);

			// リダイレクションURLの作成
			String encodeStr = request.getCharacterEncoding();
			if(encodeStr == null || encodeStr.length() < 1) {
				encodeStr = defaultEncoding;
			}
			URL targetUrl = new URL(target);
			redirectURL.append(ReceiverResource.getReceiver(targetUrl.getHost(), getContext(targetUrl)));
			redirectURL.append("?" + SSOConstants.NAME_TARGET + "=" + URLEncoder.encode(target, encodeStr));
			for(int i = 0; i < artifacts.size(); i++) {
				redirectURL.append("&" + SSOConstants.NAME_SAMLART + "=" + URLEncoder.encode(artifacts.get(i).encode(), encodeStr));
			}
			if(params != null) {
				Iterator itr = params.keySet().iterator();
				while(itr.hasNext()) {
					Object key = itr.next();
					Object value = params.get(key);
					redirectURL.append("&" + key + "=" + value);
				}
			}

			response.sendRedirect(redirectURL.toString());
		} catch(SSOException e) {
			throw e;
		} catch(Exception e) {
			throw new SSOException(SSOMessageResource.getMessage("1001", toArray(null, null, params)), e);
		}
	}

	/**
	 * アサーションとパラメータを指定して、指定されたPOSTフォーム生成用のパスへフォーワードする。
	 * 
	 * @param assertions アサーション
	 * @param params 目的サイトへ送信する任意のパラメータ
	 * @param path POSTフォーム生成パス
	 * @throws SSOException
	 */
	public void forward(List<SAMLAssertion> assertions, Map<String, String> params, String path) throws SSOException {
		try {
			String target = request.getParameter(SSOConstants.NAME_TARGET);
			URL targetUrl = new URL(target);
			String consumerUrl = ConsumerResource.getConsumer(targetUrl.getHost(), getContext(targetUrl));
			// TODO
			SAMLException samlException = new SAMLException(SAMLException.SUCCESS, "");
			SAMLResponse samlResponse = new SAMLResponse(null, consumerUrl, assertions, samlException);

			// セッションにPOST用のデータを格納
			HttpSession session = request.getSession();
			session.setAttribute(SSOConstants.NAME_SAMLRESPONSE, samlResponse.toBase64());
			session.setAttribute(SSOConstants.NAME_TARGET, target);
			session.setAttribute(SSOConstants.NAME_CONSUMER, consumerUrl);
			if(params != null) {
				session.setAttribute(SSOConstants.NAME_POSTPARAM, params);
			}

			// POSTフォームのパスへ転送
			request.getRequestDispatcher(path).forward(request, response);
		} catch (Exception e) {
			// TODO
			throw new SSOException("", e);
		}
	}

	private String getContext(URL targetUrl) {
		String context = "";
		String[] s = targetUrl.getPath().split("/");
		for(int i = 0; i < s.length; i++) {
			if(s[i].length() > 0) {
				context = s[i];
				break;
			}
		}
		return context;
	}

	private Object[] toArray(String id, String authId, Map attributes) {
		Object[] array = new Object[3];
		array[0] = id;
		array[1] = authId;
		array[2] = attributes;
		return array;
	}

}
