/*
このファイルの中身は、NTT オープンソースライセンス　バージョン 1.0（「本
契約」という）の適用を受けます。
本契約を遵守しない限り、このファイルを使用してはなりません。
本契約のコピーは、次のＵＲＬから入手できます。
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

本契約に基づき頒布されるソフトウェアは、現状のまま、明示又は黙示のあらゆ
る種類の保証なしで、頒布されます。本契約に基づく権利及び制限を律する特定
の文言については、本契約を参照してください。

「オリジナルコード」は、 NTT Cyber Space Laboratories Code です。 
「オリジナルコード」の「初期開発者」は、日本電信電話株式会社です。  
日本電信電話株式会社により創作された部分は、Copyright (C) 2004 
日本電信電話株式会社 です。
全ての権利が留保されます。 
「コントリビュータ」：_____________________________________ 


The contents of this file are subject to the NTT Opensource License
Version 1.0 (the License); you may not use this file except in
compliance with the License. You may obtain a copy of the License at
【配布サイトのURL】 http://www.oss.ecl.ntt.co.jp/lms/

Software distributed under the License is distributed on an AS IS
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific language governing rights and limitations
under the License.

The Original Code is NTT Cyber Space Laboratories Code .

The Initial Developer of the Original Code is NIPPON TELEGRAPH AND 
TELEPHONE CORPORATION.
Portions created by the NIPPON TELEGRAPH AND TELEPHONE CORPORATION 
are Copyright (C) 2004 NIPPON TELEGRAPH AND TELEPHONE CORPORATION. 
All Rights Reserved.

Contributor(s) ______________________________________.
*/

//
//	（学習開始用サーブレット）クラス
//			変更履歴
//				2004.01.08	新規作成	五木田　泰史
//
package jp.co.ntt.lms.lo;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.io.UnsupportedEncodingException;

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

import jp.co.ntt.lms.xmo.Environment;
import jp.co.ntt.lms.xmo.Lo.LoClient;
import jp.co.ntt.lms.xmo.util.DebugLog;
import jp.co.ntt.lms.xmo.util.HtmlEscape;

/**
 * タイトル:		StartLearnServlet
 * 説明:			学習の開始制御を行うServletクラス
 * @author		Y.Gokita
 * @version		1.0
 * 修正履歴		2004.01.08 新規作成
 */
public class StartLearnServlet extends HttpServlet
	implements LoPropertyDef
{

	// エラー画面
	private static final String LEARN_ERR_URL = "/jsp/lo/Com/ComErr.jsp?message";
	// WbtLO学習開始時は同一Windowを開く
	private String strWinEvaluate = "_blank";

	public StartLearnServlet() {
	}

	/**
	 * 端末からのＧＥＴ要求を処理するメソッド<br>
	 * @param HttpServletRequest	ＨＴＴＰリクエスト
	 * @param HttpServletResponse	ＨＴＴＰレスポンス
	 * @return void
	 * @exception javax.servlet.ServletException	サーブレット例外
	 * @exception java.io.IOException				入出力例外
	 */
	public void doGet(HttpServletRequest request,HttpServletResponse response)
			throws ServletException, IOException
	{
		// リクエスト処理を呼び出します
		this.doRequest(request, response);
	}

	/**
	 * 端末からのＰＯＳＴ要求を処理するメソッド<br>
	 * @param HttpServletRequest	ＨＴＴＰリクエスト
	 * @param HttpServletResponse	ＨＴＴＰレスポンス
	 * @return void
	 * @exception javax.servlet.ServletException	サーブレット例外
	 * @exception java.io.IOException				入出力例外
	 */
	public void doPost(HttpServletRequest request,HttpServletResponse response)
			throws ServletException, IOException
	{
		// リクエスト処理を呼び出します
		this.doRequest(request, response);
	}

	/**
	 * 端末からの要求を処理するメソッド<br>
	 * @param HttpServletRequest	ＨＴＴＰリクエスト
	 * @param HttpServletResponse	ＨＴＴＰレスポンス
	 * @return void
	 */
	private void doRequest(
		HttpServletRequest request, HttpServletResponse response)
	{

		String strSystemUrl = "";
		try {
			Environment objEnv = new Environment();
			strSystemUrl = objEnv.getSystemURL();
		}
		catch( Exception ex ) {
		}

		// request要求からLO情報を取得します。
		String  strUserID      = HtmlEscape.escape(request.getParameter( USER ));
		String  strPassword    = request.getParameter( PASSWD );
		String  strLoID        = HtmlEscape.escape(request.getParameter( LOID ));
		String  strLoType      = HtmlEscape.escape(request.getParameter( LO_TYPE ));
		String  strSessionID = HtmlEscape.escape(request.getParameter( SESSIONID ));
		String  strReturnURL   = request.getParameter( RETURN_URL );

		String strHttpSessionID = request.getSession().getId();
		DebugLog.write( this.getClass(), "SessionID = " + strSessionID, DebugLog.ROW );
		DebugLog.write( this.getClass(), "UserID = " + strUserID, DebugLog.ROW );
		DebugLog.write( this.getClass(), "Password = " + strPassword, DebugLog.ROW );
		DebugLog.write( this.getClass(), "LoType = " + strLoType, DebugLog.ROW );
		DebugLog.write( this.getClass(), "ReturnURL = " + strReturnURL, DebugLog.ROW );
		DebugLog.write( this.getClass(), "loID = " + strLoID, DebugLog.ROW );

		try
		{

			// RealLOIDを取得します
			String strRealLOID = null;
			LoClient objLoClient = new LoClient();
			if(!objLoClient.getRealLOIDFromLOID( strLoID )){
				new LOException("RealLOIDリストの取得失敗しました。");
			}else{
				strRealLOID = objLoClient.getRealLOIDResult();
			}

			String strXCServerNo = null;
			String strCookieXCSNo = null;

			// セッション情報有無の確認
			boolean bExist = false;
			if( strSessionID != null && !strSessionID.equals( "" ) ) {
				// WBTLOの場合
				if( strLoType.equals("1") ) {
					// 全セッションファイルを検索し前回学習Server番号を取得する
					LearnSession objLs = new LearnSession();
					String[] Filelist = objLs.getFileList( strUserID );
					if ( Filelist != null && Filelist.length != 0 ){
						for (int i = 0; i < Filelist.length; i++) {
							String strLearnSession = null;
							strLearnSession = Filelist[i];
							// セッションファイルの存在チェック
							if( LearnSession.isExitSession2( strUserID, strLearnSession ) ) {
								// ファイルが存在した場合ロードする
								objLs.setUserID(strUserID);
								objLs.setSessionID(strLearnSession);
								objLs.setLoType(strLoType);
								objLs.load();
								// 前回使用したServer番号をセットする
								strXCServerNo = objLs.getServerNo();
								// WBTLOのセッションファイルが存在する場合
								if ( strXCServerNo != null && !strXCServerNo.equals("") ){
									bExist = true;
									break;
								}
							}
						}
					}
					// セッションファイルから前回使用Server番号が取得できなかった場合はクッキーから取得する
					if ( strXCServerNo == null || strXCServerNo.equals("") ){
						strCookieXCSNo = getCookie( strUserID + "WBTServer", request, response );
					}
				}
				// セッション管理が必要な教材のみチェックする
				else if( LearnSession.isExitSession( strUserID, strSessionID ) ) {
					// ファイルが存在した場合ロードする
					LearnSession objLs = new LearnSession();
					objLs.setUserID(strUserID);
					objLs.setSessionID(strSessionID);
					objLs.setLoType(strLoType);
					objLs.load();
					if( strHttpSessionID.equals( objLs.getHttpSessionID() ) ) {
					}
				}
			}

			// LO保持情報（戻り先URL）を格納する際に使用する
			// ＨＴＴＰセッションを取得します
			HttpSession session = request.getSession(true);

			session.setAttribute("returnURL",strReturnURL);

			// サーバ名称の取得
			Environment objEnv = new Environment();
			String strServerName = objEnv.getServerName();
			// Loクライアントのインスタンスを生成します
			LoTopClient objLoCli = new LoTopClient(strServerName,strLoType);

			// Loクライアントの学習開始メソッドを実行します。
			// 　入力パラメータ：
			//      LoID
			//      ユーザID
			//      パスワード
			//      戻り先URL
			// 　返却値：
			// 　   正否（true：正常、false：異常）
			boolean bLearn = objLoCli.startLearn(	strUserID,
													strPassword,
													strLoID,
													strReturnURL,
													strRealLOID,
													strXCServerNo,
													strCookieXCSNo
													);

			if ( bLearn == false )
			{
				DebugLog.write( this.getClass(), "学習開始確認 = エラー", DebugLog.ROW );

				// 学習を開始できない場合は、エラー画面へのリダイレクト処理を行います。
				try
				{
					String strErrUrl = objLoCli.getLearnErrorURL();
					strReturnURL = strSystemUrl + strErrUrl;
					response.sendRedirect(strReturnURL);
				}
				catch(IOException ie)
				{
					DebugLog.write( this.getClass(), "エラーページリダイレクト失敗", DebugLog.HIGHT );
				}
				return;
			}
			else
			{
				// 学習を開始できる場合、学習データオブジェクトから学習するURLを取得し、
				// リダイレクト処理を行います。
				LearnData objLearnData = objLoCli.getLearnData();
				String strLearnURL     = objLearnData.getLearnURL();
				String strEstimation   = objLearnData.getEstimation();
				// サーバ番号の取得
				strXCServerNo = objLearnData.getServerNo();

				DebugLog.write( this.getClass(), "学習開始確認 = OK " + strLearnURL, DebugLog.ROW );

				// 日本語部分をURLEncodeする
				strLearnURL = urlEncode(strLearnURL);
				if(strEstimation != null && strEstimation.equals("ON"))
				{
				//EDIT START セッションファイルを使用する全てのLOは評価画面名を指定するよう変更します　2006/3/9 NTT-R MNM
				//DEL START 以下の分岐を全てコメントアウト 2006/3/9 NTT-R MNM
					// セッション管理が必要なLOの場合（WBTLO,およびPerceptionLO）
					//LO評価管理Windowの名前を設定する
					//if( strLoType.equals("1") )
					//{
					//	strWinEvaluate = "wbtEvWin";
					//}
					//else if( strLoType.equals("18") )
					//{ 
					//	strWinEvaluate = "PerceptionEvWin";
					//}
				//DEL END 2006/3/9 NTT-R MNM
					strWinEvaluate = "WinEvaluate";
				//EDIT END 2006/3/9 NTT-R MNM
					
					// XMS2のシステムURLを取得
					String strSystemURL = objEnv.getSystemURL();
					
					// 評価画面表示URLパラメータ作成
					StringBuffer strBufParam = new StringBuffer();
					strBufParam.append( "?SYSTEM_URL=" + strSystemURL );
					strBufParam.append( "&LO_ID=" + strLoID );
					strBufParam.append( "&USER_ID=" + strUserID );

					// 評価画面表示URL作成
					String strEvaluateURL = strSystemURL + "/xmo/Evaluate/Evaluate.do" + strBufParam.toString();

					// リクエスト先にHTMLを出力する。
					// WbtLO学習開始時は同一Windowを開く
					PrintWriter out = response.getWriter();
					out.println("<html>");
					out.println("<body>");
					out.println("</body>");
					out.println("<script language=\"JavaScript\">");
					out.println("var selfW = document.body.clientWidth + 17;");
					out.println("var selfH = document.body.clientHeight;");
					// リクエスト先のlocaionを学習ページURLに変更する。
					out.println("window.location.href=\"" + strLearnURL + "\";");
					// リクエスト先にて、ウィンドウをオープンし評価画面を表示する。
					out.println("window.open(");
					out.println("\"" + strEvaluateURL + "\",");
					out.println("\"" + strWinEvaluate + "\",");
					out.println("\"top=0,left=0,width=\" + selfW + \",height=\" + selfH + \",resizable=yes,scrollbars=yes\"");
					out.println(");");
					out.println("window.focus();");
					out.println("</script>");
					out.println("</html>");
				}
				else
				{
					response.setContentType("text/html; charset=Windows-31J");
					PrintWriter out = response.getWriter();
					out.println("<html>");
					out.println("<script language=\"JavaScript\">");
					out.println("window.location.href=\"" + strLearnURL + "\";");
					out.println("window.focus();");
					out.println("</script>");
					out.println("</html>");
				}
				//LO評価画面のWindow名をクリアする
				strWinEvaluate = "_blank";
			}
			try
			{
				// セッションIDの指定があった場合のみ以下の処理を行う
				if( strSessionID != null && !strSessionID.equals("") ) {
					if( strLoType.equals("1") ) {
						// 今回使用ServerをユーザID＋WBTServer でクッキーにセット
						setCookie( strUserID + "WBTServer", strXCServerNo, request, response );
					}
					// 学習セッションファイル書込み処理
					LearnSession objLs = new LearnSession();
					objLs.initialize();
					objLs.setHttpSessionID( strHttpSessionID );
					objLs.setUserID(strUserID);
					objLs.setSessionID(strSessionID);
					objLs.setLoID(strRealLOID);
					objLs.setLoType(strLoType);
					objLs.setReturnURL(strReturnURL);
					// 学習対象LOIDの設定
					objLs.setTargetLOID(strLoID);
					// 学習サーバ番号の設定
					objLs.setServerNo(strXCServerNo);
					// WBTLO不正終了後の学習開始以外の場合はセッションファイル作成
					if ( bExist != true ){
						objLs.save();
					}
					bExist = false;
				}
			}
			catch(Exception ex)
			{
				ex.printStackTrace();
			}
			return;
		}
		catch( Exception e ) {
			// 上記以外に失敗（システム障害）した場合、Exception例外をスローする。
			// キャッチしたら、メッセージを取得する。
			String  strErrMessage = e.getMessage();
			if (strErrMessage == "") {
				strErrMessage = "例外が発生していますが、該当するメッセージがありません。";
			}
			DebugLog.write( this.getClass(), e, DebugLog.HIGHT );
			// エラー画面へのリダイレクト処理を行います
			String strErrURL = strSystemUrl + LEARN_ERR_URL + strErrMessage;
			try
			{
				response.sendRedirect( strErrURL );
			}
			catch(IOException ie)
			{
				DebugLog.write( this.getClass(), "エラーページリダイレクト失敗", DebugLog.HIGHT );
			}
			return;
		}
	}

	/**
	 * URL文字列中の日本語をURLエンコーディングします。
	 *
	 * @param url URL文字列
	 * @return String エンコード結果
	 */
	private static String urlEncode(String url)
		throws UnsupportedEncodingException
	{
		String retUrl = "";		// 結果URL

		// nullチェック
		if((url==null) || (url.length()==0)){
			return url;
		}
		
		try{
			for(int i=0; i<url.length(); i++){
				// 日本語だったらURLエンコーディングする
				String oneChar = url.substring(i, i+1);
				if(isDoubleByte(oneChar) == true){
					retUrl += URLEncoder.encode(oneChar, "UTF-8");
				}else{
					retUrl += oneChar;
				}
			}
		} catch(UnsupportedEncodingException e) {
			throw e;	
		}
		return retUrl;
	}

	/**
	 * 全角文字かチェックします。
	 *
	 * @param oneChar １文字分のString
	 * @return true:全角文字 false:半角文字
	 */
	private static boolean isDoubleByte(String oneChar){

		// byte変換して2byte以上の場合は全角
		byte[] len = oneChar.getBytes();
		if(len.length > 1){
			return true;
		}else{
			return false;
		}

	}

	/**
	 * 使用サーバ番号のクッキーを作成します。
	 * @param strCookieName クッキー名
	 * @param strCookieValue クッキー値
	 * @param request HTTPリクエスト
	 * @param response HTTPレスポンス
	 * @exception 設定ファイル読み込みエラー
	 */
	private void setCookie( String strCookieName,
							String strCookieValue,
							HttpServletRequest request,
							HttpServletResponse response)
		throws Exception
	{
		Cookie cookie = new Cookie(strCookieName, strCookieValue);
		String strContextPath = request.getContextPath();
		// パスの設定を閲覧画面のみに設定する。
		cookie.setPath( strContextPath + "/" );
		response.addCookie( cookie );
	}

	/**
	 * 使用サーバ番号のクッキーを作成します。
	 * @param strCookieName クッキー名
	 * @param strCookieValue クッキー値
	 * @param request HTTPリクエスト
	 * @param response HTTPレスポンス
	 * @exception 設定ファイル読み込みエラー
	 */
	private String getCookie( String strCookieName,
						HttpServletRequest request,
						HttpServletResponse response)
		throws Exception
	{
		// 保存されているすべてのクッキーの配列を取得します
		Cookie[] cookies = request.getCookies();

		// 目的のクッキーを保存するためのクッキーオブジェクト
		String strSVNo = null;
		if (cookies!=null) {
			for (int i=0;i<cookies.length;i++) {
				// 名前が"message"のクッキーかどうかチェック
				if (cookies[i].getName().equals(strCookieName)) {
					// 該当するクッキーを取得します
					strSVNo = cookies[i].getValue();
					break;
			  	}
			}
		}
		return strSVNo;
	}

}
