/*********************************************************************
* All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*   システム名      ：eo顧客基幹システム
*   モジュール名    ：JCCAxMNinsho
*   ソースファイル名：JCCAxMNinsho.java
*   作成者          ：富士通
*   日付            ：2011年08月01日
*＜機能概要＞
* AxM認証部品です。
*＜修正履歴＞
*   バージョン  修正日       修正者      修正内容
*
**********************************************************************/

package eo.web.webview.common;

import static com.fujitsu.futurity.web.x31.X31SWebLog.DEBUG_LOG;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import sirrus.connect.ConnectionDescriptor;
import sirrus.runtime.APIFactory;
import sirrus.runtime.AuthTypes;
import sirrus.runtime.CredentialConstants;
import sirrus.runtime.OptionConstants;
import sirrus.runtime.ResultConstants;
import sirrus.runtime.RuntimeAPI;
import sirrus.runtime.RuntimeAPIException;
import sirrus.runtime.TokenKeys;
import sirrus.runtime.UserConstants;

import com.fujitsu.futurity.web.x33.HttpDispatchContext;
import com.fujitsu.futurity.web.x33.X33CUtil;
import com.fujitsu.futurity.web.x33.X33WSessionController;

import eo.common.util.JCCFrameworkException;
import eo.web.webview.JCCWebBusinessLogic;

public class JCCAxMNinsho {

	// DISPATCHERサーバー名取得用のキー
	private static final String HOST_KEY = "AXM_DISPATCHER_HOST";

	// DISPATCHERサーバーポート番号取得用のキー
	private static final String PORT_KEY = "AXM_DISPATCHER_PORT";

	// DISPATCHERサーバー名(サブ)取得用のキー
	private static final String SUB_HOST_KEY = "AXM_DISPATCHER_SUB_HOST";

	// DISPATCHERサーバーポート番号(サブ)取得用のキー
	private static final String SUB_PORT_KEY = "AXM_DISPATCHER_SUB_PORT";

	// DISPATCHERサーバータイムアウト時間取得用のキー
	private static final String TIMEOUT_KEY = "AXM_DISPATCHER_TIMEOUT";

	// テストモード取得用キー
	private static final String MODE_KEY = "AXM_TEST_MODE";

	// 返却値の状態設定用キー
	private static final String RESULT = "RESULT";

	// 返却値のSYSID設定用キー
	private static final String SYSID = "SYSID";

	// 返却値の会員種別設定用キー
	private static final String KIIN_SHUBT = "KIIN_SHUBT";

	// 返却値のニックネーム設定用キー
	private static final String NK_NM = "NK_NM";

	// 返却値の連絡先メールアドレス設定用キー
	private static final String RNRKSK_MR = "RNRKSK_MR";

	// 返却値の年齢フラグ設定用キー
	private static final String AGE_FLG = "AGE_FLG";

	// 返却値の標準コンテンツ同意フラグ設定用キー
	private static final String HYOJUN_KNTNT_DUI_FLG = "HYOJUN_KNTNT_DUI_FLG";

	// 返却値のISP利用停止フラグ設定用キー
	private static final String ISP_RYU_TIS_FLG = "ISP_RYU_TIS_FLG";

	// 返却値の会員状態設定用キー
	private static final String JYOUTAI = "JYOUTAI";

	// 返却値の会員種別特定フラグ設定用キー
	private static final String KIIN_TOKUTEI = "KIIN_TOKUTEI";

	// 返却値の性別設定用キー
	private static final String SIBT = "SIBT";

	// 返却値のテスト用IDフラグ設定用キー
	private static final String TST_ID_FLG = "TST_ID_FLG";

	// 返却値の登録フラグ設定用キー
	private static final String TURK_FLG = "TURK_FLG";

	// 返却値の管理者用フラグ(1)設定用キー
	private static final String ADMIN_FLG1 = "ADMIN_FLG1";

	// 返却値の管理者用フラグ(2)設定用キー
	private static final String ADMIN_FLG2 = "ADMIN_FLG2";

	// 返却値の管理者用フラグ(3)設定用キー
	private static final String ADMIN_FLG3 = "ADMIN_FLG3";

	// 返却値の更新年月日時分秒設定用キー
	private static final String U_DATE = "U_DATE";

	// 返却値のCTSESSION設定用キー
	private static final String CTSESSION = "CTSESSION";

	// SSOワンタイム継続時間取得用のキー
	private static final String SSO_IDLE_TIME_KEY = "SSO_IDLE_TIME";

	// SSO最大継続時間取得用のキー
	private static final String SSO_LIFE_TIME_KEY = "SSO_LIFE_TIME";

	// 時間フォーマットキー
	private static final String YYYYMMDD_HHMMSS_SSS = "yyyyMMddHHmmssSSS";

	// URLデコードの文字コード
	private static final String UTF8 = "UTF-8";

	// 多重ログイン
	private static final String MULTIPLE_LOGIN = "MULTIPLE_LOGIN";

	/**
	 * AxMシステムに対して、認証処理を要求し結果を返却します。
	 * <br>
	 * @param vlObj Viewロジックインスタンス
	 * @param userId ユーザーID
	 * @param password パスワード
	 * @param beforeUserId 以前のユーザーID
	 * @param isCreateCookie 認証成功時のクッキー情報生成有無 true:有り、false:無し
	 * @param trgtMemSbtCdList クッキー情報を生成する対象の会員種別コードリスト(nullの場合は、すべての会員種別コードが対象とする)
	 * @return 結果
	 */
	public static HashMap<String, String> getAxMCertifyResult(JCCWebBusinessLogic vlObj, String userId, String password, String beforeUserId,
			boolean isCreateCookie, List<String> trgtMemSbtCdList)
	{
		// パラメータチェック
		//Viewロジックインスタンスのチェック
		if (null == vlObj)
		{
			throw new JCCFrameworkException("引数のViewロジックインスタンスがnullです。");
		}

		// 結果返却処理
		HashMap<String, String> resultMap = new HashMap<String, String>();

		// ユーザーIDのチェック
		if (null == userId || "".equals(userId))
		{
			resultMap.put(RESULT, ResultConstants.UNKNOWN_USER);
			resultMap.put(SYSID, "");
			return resultMap;
		}
		// パスワードのチェック
		if (null == password || "".equals(password))
		{
			resultMap.put(RESULT, ResultConstants.INVALID_PASSWORD);
			resultMap.put(SYSID, "");
			return resultMap;
		}

		// Dispatcherサーバー接続情報の取得
		// ホスト名取得
		String host = checkDispatcherVal(HOST_KEY, "ホスト名", false);
		String subHost = checkDispatcherVal(SUB_HOST_KEY, "ホスト名(サブ)", false);

		// ポート番号取得
		String port = checkDispatcherVal(PORT_KEY, "ポート番号", true);
		String subPort = checkDispatcherVal(SUB_PORT_KEY, "ポート番号(サブ)", true);

		// タイムアウト時間取得
		String timeOut = checkDispatcherVal(TIMEOUT_KEY, "タイムアウト時間", true);

		// テストモード設定の取得
		String testMode = JCCWebCommon.getApplicationConst(MODE_KEY);
		if (null != testMode && "ON".equals(testMode.toUpperCase()))
		{
			// テストモードの実施
			return getTestCertifyResult(userId);
		}

		// ConnectionDescriptorオブジェクトの生成
		ConnectionDescriptor[] disCon =
				{ new ConnectionDescriptor(host, Integer.parseInt(port), ConnectionDescriptor.SSL_ANON),
						new ConnectionDescriptor(subHost, Integer.parseInt(subPort), ConnectionDescriptor.SSL_ANON) };

		RuntimeAPI runtimeAPI = null;
		HashMap returnMap = null;

		try
		{

			Map<String, String> options = new HashMap<String, String>();
			options.put(OptionConstants.SUBMODE, OptionConstants.ADAPTIVE);
			runtimeAPI = APIFactory.createFromServerDispatchers(options, disCon, Integer.parseInt(timeOut), true, null);

			// 設定情報の格納
			HashMap userMap = new HashMap();
			// ユーザーIDの設定
			userMap.put(UserConstants.SC_USER_ID, userId);
			// パスワードの設定
			userMap.put(UserConstants.CREDENTIALS, password);
			// 認証方式の設定
			userMap.put(UserConstants.AUTHENTICATION_TYPE, AuthTypes.SC_BASIC);
			// 戻り値にSSOトークンを含めるオプション設定
			userMap.put(OptionConstants.TOKENS_OPTION, OptionConstants.ON);
			// 戻り値にユーザープロパティファイルを含めるオプション設定
			userMap.put(OptionConstants.PROPERTIES_OPTION, OptionConstants.ON);
			// 戻り値にユーザーグループ情報を含めりオプション設定
			userMap.put(OptionConstants.GROUPS_OPTION, OptionConstants.OFF);
			userMap.put(CredentialConstants.SC_TOKENS_ENABLED, OptionConstants.ON);

			returnMap = (HashMap)runtimeAPI.authenticate(userMap);
		}
		catch (RuntimeAPIException e)
		{
			JCCFrameworkException fe = new JCCFrameworkException();
			fe.initCause(e);
			throw fe;
		}
		finally
		{
			if (runtimeAPI != null)
			{
				runtimeAPI.close();
			}
		}

		// 認証状態の取得
		String userStatus = (String)returnMap.get(ResultConstants.AUTHENTICATION_RESULT);
		DEBUG_LOG.info("userStatus　：　" + userStatus);

		// resultMapの初期化
		resultMap.put(SYSID, "");
		resultMap.put(KIIN_SHUBT, "");
		resultMap.put(NK_NM, "");
		resultMap.put(RNRKSK_MR, "");
		resultMap.put(AGE_FLG, "");
		resultMap.put(HYOJUN_KNTNT_DUI_FLG, "");
		resultMap.put(ISP_RYU_TIS_FLG, "");
		resultMap.put(JYOUTAI, "");
		resultMap.put(KIIN_TOKUTEI, "");
		resultMap.put(SIBT, "");
		resultMap.put(TST_ID_FLG, "");
		resultMap.put(TURK_FLG, "");
		resultMap.put(ADMIN_FLG1, "");
		resultMap.put(ADMIN_FLG2, "");
		resultMap.put(ADMIN_FLG3, "");
		resultMap.put(U_DATE, "");

		if (userStatus.equals(ResultConstants.VALID_USER))
		{

			resultMap.put(RESULT, userStatus);
			// RSAより公開されるプロパティ情報の設定
			Map<String, HashSet<?>> prop = (Map<String, HashSet<?>>)returnMap.get("CT_USER_PROPERTIES");

			if(prop != null)
			{

				// 会員種別コード(AxMの返却値)を取得。
				String kiinShubt = null;
				if (prop.get("kiin_shubt") != null)
				{
					kiinShubt = (String)((HashSet)prop.get("kiin_shubt")).iterator().next();
				}

				DEBUG_LOG.info("kiinShubt　：　" + kiinShubt);
				DEBUG_LOG.info("headerReqUserId　：　" + beforeUserId);
				DEBUG_LOG.info("userId　：　" + userId);

				if (!JFUWebCommon.isNull(beforeUserId) && !userId.equals(beforeUserId))
				{
					// 前回ログイン時のSSO情報が残っており、そのeoIDと認証するeoIDが異なっている場合

					// 多重ログインエラーとして、「RESULT」に「MULTIPLE_LOGIN」を設定。
					resultMap.put(RESULT, MULTIPLE_LOGIN);

					// 処理を終了し呼び出し元に設定情報を返却する。
					return resultMap;
				}

				// CTSESSION設定処理
				String ctsession = setCtSession(returnMap, vlObj);
				if (isCreateCookie
						&& ((trgtMemSbtCdList == null || trgtMemSbtCdList.size() == 0) || (trgtMemSbtCdList.contains(kiinShubt))))
				{
					// 認証成功時のクッキー情報生成有無が「true:有り」で、且つ下記のどちらかの条件に一致する場合
					// ・会員種別コードリストが「null」の場合
					// ・会員種別コードリストに会員種別コード(AxMの返却値)が含まれている場合

					//認証成功時の処理
					String sessionId = vlObj.getSession().getViewParamId().getSessionID();
					// クッキー情報生成処理
					createCookie(sessionId, returnMap);
				}

				if(prop.get("sysid") != null)
				{
					resultMap.put(SYSID, (String)((HashSet)prop.get("sysid")).iterator().next());
				}
				if (kiinShubt != null)
				{
					resultMap.put(KIIN_SHUBT, kiinShubt);
				}
				if(prop.get("nk_nm") != null)
				{
					resultMap.put(NK_NM, (String)((HashSet)prop.get("nk_nm")).iterator().next());
				}
				if(prop.get("rnrksk_mr") != null)
				{
					resultMap.put(RNRKSK_MR, (String)((HashSet)prop.get("rnrksk_mr")).iterator().next());
				}
				if(prop.get("age_flg") != null)
				{
					resultMap.put(AGE_FLG, (String)((HashSet)prop.get("age_flg")).iterator().next());
				}
				if(prop.get("hyojun_kntnt_dui_flg") != null)
				{
					resultMap.put(HYOJUN_KNTNT_DUI_FLG, (String)((HashSet)prop.get("hyojun_kntnt_dui_flg")).iterator().next());
				}
				if(prop.get("isp_ryu_tis_flg") != null)
				{
					resultMap.put(ISP_RYU_TIS_FLG, (String)((HashSet)prop.get("isp_ryu_tis_flg")).iterator().next());
				}
				if(prop.get("jyoutai") != null)
				{
					resultMap.put(JYOUTAI, (String)((HashSet)prop.get("jyoutai")).iterator().next());
				}
				if(prop.get("kiin_tokutei") != null)
				{
					resultMap.put(KIIN_TOKUTEI, (String)((HashSet)prop.get("kiin_tokutei")).iterator().next());
				}
				if(prop.get("sibt") != null)
				{
					resultMap.put(SIBT, (String)((HashSet)prop.get("sibt")).iterator().next());
				}
				if(prop.get("tst_id_flg") != null)
				{
					resultMap.put(TST_ID_FLG, (String)((HashSet)prop.get("tst_id_flg")).iterator().next());
				}
				if(prop.get("turk_flg") != null)
				{
					resultMap.put(TURK_FLG, (String)((HashSet)prop.get("turk_flg")).iterator().next());
				}
				if(prop.get("admin_flg1") != null)
				{
					resultMap.put(ADMIN_FLG1, (String)((HashSet)prop.get("admin_flg1")).iterator().next());
				}
				if(prop.get("admin_flg2") != null)
				{
					resultMap.put(ADMIN_FLG2, (String)((HashSet)prop.get("admin_flg2")).iterator().next());
				}
				if(prop.get("admin_flg3") != null)
				{
					resultMap.put(ADMIN_FLG3, (String)((HashSet)prop.get("admin_flg3")).iterator().next());
				}
				if(prop.get("u_date") != null)
				{
					resultMap.put(U_DATE, (String)((HashSet)prop.get("u_date")).iterator().next());
				}

				if(ctsession != null)
				{
					resultMap.put(CTSESSION, ctsession);
				}

			}
		} else {
			resultMap.put(RESULT, userStatus);
		}

		// ログ
		setLog(resultMap);

		return resultMap;
	}

	/**
	 * Cookieの生成処理を行う
	 * <br>
	 * @param sessionId Viewロジックインスタンス
	 * @param returnMap
	 */
	private static void createCookie(String sessionId, Map returnMap)
	{
		String token = (String) returnMap.get("SC_TOKEN");

		// AXMより返却されるトークンをURLエンコードする。
		String axm_cokkie_urlencode = JCCWebCommon.getApplicationConst("AXM_COOKIE_URLENCODE");
		// アプリケーションプロパティに設定されていない場合はデフォルト値を設定
		if(axm_cokkie_urlencode == null)
		{
			axm_cokkie_urlencode = "UTF-8";
		}
		String token_encode = null;
		try
		{
			 token_encode = URLEncoder.encode(token, axm_cokkie_urlencode);
		}
		catch (UnsupportedEncodingException ue)
		{
			throw new JCCFrameworkException("不正なエンコードが指定されました。", ue);
		}
		// Cookieオブジェクトの生成
		Cookie cookie = new Cookie("CTSESSION", token_encode);

		// アプリケーションプロパティファイルよりCookieの属性値を取得する。
		String axm_cookie_domain = JCCWebCommon.getApplicationConst("AXM_COOKIE_DOMAIN");
		String axm_cookie_path = JCCWebCommon.getApplicationConst("AXM_COOKIE_PATH");
		String axm_cookie_age = JCCWebCommon.getApplicationConst("AXM_COOKIE_AGE");
		String axm_cookie_secure = JCCWebCommon.getApplicationConst("AXM_COOKIE_SECURE");

		// アプリケーションプロパティファイルの必須チェック
		if(axm_cookie_domain == null)
		{
			throw new JCCFrameworkException("APLConst.propertiesにAXM_COOKIE_DOMAINが設定されていません。");
		}
		if(axm_cookie_path == null)
		{
			throw new JCCFrameworkException("APLConst.propertiesにAXM_COOKIE_PATHが設定されていません。");
		}
		if(axm_cookie_age == null)
		{
			throw new JCCFrameworkException("APLConst.propertiesにAXM_COOKIE_AGEが設定されていません。");
		}
		if(axm_cookie_secure == null)
		{
			throw new JCCFrameworkException("APLConst.propertiesにAXM_COOKIE_SECUREが設定されていません。");
		}

		// Cookieへ属性を設定する。
		cookie.setDomain(axm_cookie_domain); // Cookieの有効ドメインを設定
		cookie.setPath(axm_cookie_path); // Cookieの有効パスを設定
		cookie.setMaxAge(Integer.parseInt(axm_cookie_age)); // Cookieの最長存続期間を設定
		cookie.setSecure(Boolean.parseBoolean(axm_cookie_secure)); // Cookieのsecure属性を設定

		// HttpServletResponseオブジェクトの取得
		X33WSessionController sc = X33CUtil.getSession(sessionId);
		HttpServletResponse res = ((HttpDispatchContext)sc.getContext()).getServletResponse();
		// Cookieのセット
		res.addCookie(cookie);

		DEBUG_LOG.info("Cookie情報(CTSESSION)生成処理");
	}

	/**
	 * テストモードでの認証処理
	 * <br>
	 * ユーザーIDにより返却値が変わる
	 * @param userId ユーザID
	 * @return テストモードでの認証結果
	 */
	private static HashMap<String, String> getTestCertifyResult(String userId)
	{

		int num = 0;
		HashMap<String, String> resultMap = new HashMap<String, String>();

		//ユーザーが存在しないときの設定
		resultMap.put(RESULT, ResultConstants.UNKNOWN_USER);
		resultMap.put(SYSID, "");

		// ユーザーIDが4ケタ以上あるかどうかの確認
		if (! (userId.length() >= 4))
		{
			return resultMap;
		}

		// 先頭がTどうかの確認
		if (! "T".equals(userId.substring(0, 1)))
		{
			return resultMap;
		}

		// 2桁目〜4桁目が整数値として扱えない場合
		String id2to4 = userId.substring(1, 4);
		try {
			num = Integer.parseInt(id2to4);
		} catch (NumberFormatException e) {
			return resultMap;
		}

		// 認証成功のユーザーID
		if ((num >= 0) && (num <= 9))
		{
			resultMap.put(RESULT, ResultConstants.VALID_USER);
			resultMap.put(SYSID, "9999");
		}

		// アカウント有効期限切れのユーザーID
		if ((num >= 10) && (num <= 19))
		{
			resultMap.put(RESULT, ResultConstants.EXPIRED_ACCOUNT);
			resultMap.put(SYSID, "");
		}

		// アカウントが無効のユーザーID
		if ((num >= 20) && (num <= 29))
		{
			resultMap.put(RESULT, ResultConstants.INACTIVE_ACCOUNT);
			resultMap.put(SYSID, "");
		}

		// アカウントがロックされているユーザーID
		if ((num >= 30) && (num <= 39))
		{
			resultMap.put(RESULT, ResultConstants.ADMIN_LOCKOUT);
			resultMap.put(SYSID, "");
		}

		// パスワードが無効のユーザーID
		if ((num >= 40) && (num <= 49))
		{
			resultMap.put(RESULT, ResultConstants.INVALID_PASSWORD);
			resultMap.put(SYSID, "");
		}

		// パスワードが有効期限切れのユーザーID
		if ((num >= 50) && (num <= 59))
		{
			resultMap.put(RESULT, ResultConstants.EXPIRED_PASSWORD);
			resultMap.put(SYSID, "");
		}

		// 管理者による強制的なパスワード有効期限切れのユーザーID
		if ((num >= 60) && (num <= 69))
		{
			resultMap.put(RESULT, ResultConstants.EXPIRED_PASSWORD_FORCED);
			resultMap.put(SYSID, "");
		}

		// アカウントが作成されてから一度もパスワードが設定されていないユーザーID
		if ((num >= 70) && (num <= 79))
		{
			resultMap.put(RESULT, ResultConstants.EXPIRED_PASSWORD_NEW_USER);
			resultMap.put(SYSID, "");
		}

		// アカウントが作成されてから一度もパスワードが設定されていないユーザーID
		if ((num >= 80) && (num <= 89))
		{
			resultMap.put(RESULT, MULTIPLE_LOGIN);
			resultMap.put(SYSID, "");
		}

		return resultMap;
	}

	/**
	 * resultMapのデバッグログ出力
	 *
	 * <br>
	 * @param resultMap
	 */
	private static void setLog(HashMap<String, String> resultMap)
	{
		DEBUG_LOG.info("AxMAuth_sysid　：　" + resultMap.get(SYSID));
		DEBUG_LOG.info("AxMAuth_kiin_shubt　：　" + resultMap.get(KIIN_SHUBT));
		DEBUG_LOG.info("AxMAuth_nk_nm　：　" + resultMap.get(NK_NM));
		DEBUG_LOG.info("AxMAuth_rnrksk_mr　：　" + resultMap.get(RNRKSK_MR));
		DEBUG_LOG.info("AxMAuth_age_flg　：　" + resultMap.get(AGE_FLG));
		DEBUG_LOG.info("AxMAuth_hyojun_kntnt_dui_flg　：　" + resultMap.get(HYOJUN_KNTNT_DUI_FLG));
		DEBUG_LOG.info("AxMAuth_isp_ryu_tis_flg　：　" + resultMap.get(ISP_RYU_TIS_FLG));
		DEBUG_LOG.info("AxMAuth_jyoutai　：　" + resultMap.get(JYOUTAI));
		DEBUG_LOG.info("AxMAuth_kiin_tokutei　：　" + resultMap.get(KIIN_TOKUTEI));
		DEBUG_LOG.info("AxMAuth_sibt　：　" + resultMap.get(SIBT));
		DEBUG_LOG.info("AxMAuth_tst_id_flg　：　" + resultMap.get(TST_ID_FLG));
		DEBUG_LOG.info("AxMAuth_turk_flg　：　" + resultMap.get(TURK_FLG));
		DEBUG_LOG.info("AxMAuth_admin_flg1　：　" + resultMap.get(ADMIN_FLG1));
		DEBUG_LOG.info("AxMAuth_admin_flg2　：　" + resultMap.get(ADMIN_FLG2));
		DEBUG_LOG.info("AxMAuth_admin_flg3　：　" + resultMap.get(ADMIN_FLG3));
		DEBUG_LOG.info("AxMAuth_u_date　：　" + resultMap.get(U_DATE));

		DEBUG_LOG.info("AxMAuth_ctsession　：　" + resultMap.get(CTSESSION));
	}


	/**
	 * CTSESSIONの値を返却する。
	 *
	 * @param returnMap
	 * @param vlObj
	 */
	private static String setCtSession(HashMap returnMap, JCCWebBusinessLogic vlObj)
	{
		// nullチェック
		if (returnMap == null)
		{
			return null;
		}

		// キーチェック
		if (!returnMap.containsKey("SC_TOKEN"))
		{
			return null;
		}

		// nullチェック
		if (vlObj == null)
		{
			return null;
		}

		String token = (String) returnMap.get("SC_TOKEN");

		// AXMより返却されるトークンをURLエンコードする。
		String axm_cokkie_urlencode = JCCWebCommon.getApplicationConst("AXM_COOKIE_URLENCODE");
		// アプリケーションプロパティに設定されていない場合はデフォルト値を設定
		if(axm_cokkie_urlencode == null)
		{
			axm_cokkie_urlencode = "UTF-8";
		}

		String token_encode = null;
		try
		{
			 token_encode = URLEncoder.encode(token, axm_cokkie_urlencode);
		}
		catch (UnsupportedEncodingException ue)
		{
			throw new JCCFrameworkException("不正なエンコードが指定されました。", ue);
		}

		return token_encode;
	}

	/**
	 * Dispatcherサーバーへの接続情報のチェックを行います。
	 *
	 * @param key アプリケーションプロパティファイル取得キー
	 * @param targetName 対象名
	 * @param isNumCheck 数値チェック実施有無 true：有 false：無
	 * @return アプリケーションプロパティファイルより取得した値
	 */
	private static String checkDispatcherVal(String key, String targetName, boolean isNumCheck)
	{
		// Dispatcherサーバー接続情報の取得
		String value = JCCWebCommon.getApplicationConst(key);
		if (null == value || "".equals(value))
		{
			throw new JCCFrameworkException("アプリケーションプロパティファイルにDispatcherサーバーの" + targetName + "が設定されていません。");
		}

		if (isNumCheck)
		{
			// 数値チェック
			try
			{
				// 文字列→数値への変換
				Integer.parseInt(value);
			}
			catch (NumberFormatException e)
			{
				throw new JCCFrameworkException("アプリケーションプロパティファイルに設定されているDispatcherサーバーの" + targetName + "が不正です。");
			}
		}
		return value;
	}

	/**
	 * SSO認証チェックを行います。
	 * <br>
	 * @param req リクエスト情報
	 * @return true 認証済み false それ以外
	 */
	public static boolean checkSsoToken(HttpServletRequest req) {

		// テストモード設定の取得
		String testMode = JCCWebCommon.getApplicationConst(MODE_KEY);
		if (null != testMode && "ON".equals(testMode.toUpperCase())) {
			// テストモードの実施
			return true;
		}

		if (req == null) {
			// リクエスト情報が設定されていない場合
			return false;
		}

		// クッキー情報取得
		Cookie[] cookies = req.getCookies();
		if (cookies == null || cookies.length == 0) {
			DEBUG_LOG.info("※クッキーが存在しませんでした。");
			return false;
		}

		String ssoToken = null;
		for (int i = 0; i < cookies.length; i++) {
			Cookie cookie = cookies[i];

			if (CTSESSION.equals(cookie.getName())) {
				// クッキー情報よりCTSESSIONキーの値を取得
				ssoToken = cookie.getValue();
				break;
			}
		}

		if (ssoToken == null) {
			return false;
		}

		// Dispatcherサーバー接続情報の取得
		// ホスト名取得
		String host = checkDispatcherVal(HOST_KEY, "ホスト名", false);
		String subHost = checkDispatcherVal(SUB_HOST_KEY, "ホスト名(サブ)", false);

		// ポート番号取得
		String port = checkDispatcherVal(PORT_KEY, "ポート番号", true);
		String subPort = checkDispatcherVal(SUB_PORT_KEY, "ポート番号(サブ)", true);

		// タイムアウト時間取得
		String timeOut = checkDispatcherVal(TIMEOUT_KEY, "タイムアウト時間", true);

		// SSO最大継続時間取得
		String ssoLifetime = checkDispatcherVal(SSO_LIFE_TIME_KEY,
				"SSO最大継続時間", false);

		// SSOワンタイム継続時間取得
		String ssoIdletime = checkDispatcherVal(SSO_IDLE_TIME_KEY,
				"SSOワンタイム継続時間", false);

		ConnectionDescriptor[] disCon = {
				new ConnectionDescriptor(host, Integer.parseInt(port),
						ConnectionDescriptor.SSL_ANON),
				new ConnectionDescriptor(subHost,
						Integer.parseInt(subPort),
						ConnectionDescriptor.SSL_ANON) };

		RuntimeAPI runtimeAPI = null;

		try {

			Map<String, String> options = new HashMap<String, String>();
			options.put(OptionConstants.SUBMODE, OptionConstants.ADAPTIVE);
			runtimeAPI = APIFactory.createFromServerDispatchers(options,
					disCon, Integer.parseInt(timeOut), true, null);

			// CTSESSION値をURLデコード変換
			ssoToken = URLDecoder.decode(ssoToken, UTF8);

			// CTSESSIONを取得
			Map tokenMap = runtimeAPI.getTokenValues(ssoToken);

			if (tokenMap == null) {

				return false;

			} else {
				// SSO初回アクセス時間を取得
				long tokenInitTime = Long.parseLong((String) tokenMap
						.get(TokenKeys.SC_CREATION_TIME));

				// SSO最終アクセス時間を取得
				long tokenLastTouchTime = Long.parseLong((String) tokenMap
						.get(TokenKeys.SC_TOUCH_TIME));

				// システム時間を取得
				long longSysDate = new SimpleDateFormat(YYYYMMDD_HHMMSS_SSS)
						.parse(JCCWebCommon.getSysDateTimeStamp())
						.getTime();

				if (longSysDate - tokenInitTime > Long
						.parseLong(ssoLifetime)) {
					// SSO最大継続時間内かのチェックを行う。

					return false;
				} else if (longSysDate - tokenLastTouchTime > Long
						.parseLong(ssoIdletime)) {
					// SSOワンタイム継続時間内かのチェックを行う。

					return false;
				}
			}
		}
		catch (RuntimeAPIException e)
		{
			JCCFrameworkException fe = new JCCFrameworkException();
			fe.initCause(e);
			throw fe;
		} catch (UnsupportedEncodingException ue) {
				throw new JCCFrameworkException("不正なエンコードが指定されました。", ue);
		} catch (ParseException pe) {
			throw new JCCFrameworkException("日付の解析に失敗しました。", pe);
		}
		finally
		{
			if (runtimeAPI != null)
			{
				runtimeAPI.close();
			}
		}
		return true;
	}
}
