/*
このファイルの中身は、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 新規作成	T.Nishiki
//  2007/09    権限チェックを変更 yasu
//
package jp.co.ntt.lms.xms.framework;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import jp.co.ntt.lms.xmo.util.DebugLog;
import jp.co.ntt.lms.xms.common.user.User;

/**
 * 業務振分処理クラス。<br>
 * 
 * @author T.Nishiki
 */
public class XmsBusinessControl {


	/**
	 *  業務振分処理を実行する。
	 * @param xmsRequest リクエスト・オブジェクト。
	 * @param xmsResponse レスポンス・オブジェクト。
	 * @throws XmsException 処理中に例外が発生した場合。
	 */
	public void processRequest(XmsRequest xmsRequest, XmsResponse xmsResponse)
		throws XmsException {

		DebugLog.write(XmsBusinessControl.class,
			"HEAD processRequest()", DebugLog.ROW );

		// 起動するアクションクラス
		XmsBusinessAction action = null;
		// アクションクラスを実行した結果データ。
		XmsBusinessBean bean    = null;
		try {
			
			////////////////////////////////////////////////////////////////
			//権限チェック
			checkPermission(xmsRequest);
			////////////////////////////////////////////////////////////////
			// 実行するクラスの選定
			action = getBusinessAction(xmsRequest);
			if ( action != null ) {
				// 処理を実行
				action.perform(xmsRequest, xmsResponse);
				// 返却値オブジェクトから画面情報を取り出す。
				bean = xmsResponse.getBusinessBean();
		
				// スコープによる画面情報オブジェクトの設定
				if( bean != null ) {
					HttpServletRequest request = null;
					request = xmsRequest.getRequest();
					// スコープがセッションの場合
					if( xmsResponse.getScope() == XmsResponse.SESSION ) {
						
						HttpSession session = request.getSession();
						session.setAttribute(xmsResponse.getBusinessBeanName(), bean);
					}
					// スコープがリクエストの場合
					else if( xmsResponse.getScope() == XmsResponse.REQUEST ) {
						request.setAttribute(xmsResponse.getBusinessBeanName(), bean);
					}
				}
			}

		} catch (XmsException e) {
			throw e;
		} catch ( Exception e ) {
			throw new XmsSystemException(e);
		} finally {
			DebugLog.write(XmsBusinessControl.class,
				"TAIL processRequest()", DebugLog.ROW );
		}
	}
	
	
	/**
	 * リクエストに対応するアクションクラスを取得する。<br>
	 * 指定したリクエストからアクションIDを取得し、
	 * 対応するアクションクラス・インスタンスを生成して戻す。
	 * クラス名を設定していない場合、nullを戻す。
	 * 
	 * @param xmsRequest HTTPリクエスト。
	 * @return XmsScreenAction アクションIDに対応するアクションクラス。
	 * @throws XmsException アクションIDが含まれない場合、
	 * 対応するアクションクラスが存在しない場合。
	 */
	private XmsBusinessAction getBusinessAction( XmsRequest xmsRequest )
			throws XmsException {

		// アクションＩＤ
		String actionId = null;
		// アクションクラス名
		String className = null;
		// アクションクラスロード用
		Class actionClass = null;
		// 起動するアクションクラス
		XmsBusinessAction action = null;

		try {
			// アクションＩＤを取得。
			actionId = xmsRequest.getParameter(Constant.REQUEST_ACTION_ID);
			// 実行するクラスの選定
			className =
				XmsBusinessXMLPerser.getBusinessActionName( actionId );
			if ( className != null ) {
				actionClass = Class.forName(className);
				action = (XmsBusinessAction) actionClass.newInstance();
			} else {
				action = null;
			}
		} catch (XmsException e) {
			throw e;
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
		DebugLog.write(this.getClass(), action, DebugLog.MID);
		return action;
	}
	
	/**
	* ユーザーがリクエストしたアクションを実行する権限があるか判定する。<br>
	*
	* @param xmsRequest リクエスト・オブジェクト。
	* @throws XmsSystemException 権限がない場合、もしくは処理中に例外が発生した場合。
	*/
	private void checkPermission(XmsRequest xmsRequest)
		throws XmsException {
		
		boolean permission = isPermittedUser(xmsRequest);
		if ( permission == false ) {
			throw new XmsSystemException( "No Authority to perform Action." );
		}
		
		try {
			// アクションＩＤを取得。
			String actionId = xmsRequest.getParameter(Constant.REQUEST_ACTION_ID);
			XmsPermissionCheck check = null;
			// 実行するクラスの選定
			String className =
				XmsBusinessXMLPerser.getPermissionCheckName( actionId );
			if ( className != null ) {
				Class checkClass = Class.forName(className);
				check = (XmsPermissionCheck) checkClass.newInstance();
			} else {
				check = null;
			}
			
			if (check != null) {
				boolean result = check.execute(xmsRequest);
				if (result == false) {
					throw new XmsSystemException( "Not permitted to perform this action." );
				}
			}
		} catch (XmsException e) {
			throw e;
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

	/**
	 * リクエストしたユーザに指定したアクションを実行する権限があるか判定する。<br>
	 * 
	 * @param xmsRequest リクエスト・オブジェクト。
	 * @return ユーザに権限があればtrue、権限がない場合はfalseを戻す。
	 * @throws XmsException 処理中に例外が発生した場合。
	 */
	private boolean isPermittedUser(XmsRequest xmsRequest)
		throws XmsException {

		// このメソッドの戻り値		
		boolean isPermitted = true;
		// アクションＩＤ
		String actionId = null;
		// 許可リスト
		List permittedList = null;
		
		// 操作ユーザの権限
		Set xmoIdsOfCurrentUser = null;

		try {
			// アクションＩＤを取得。
			actionId = xmsRequest.getParameter(Constant.REQUEST_ACTION_ID);
			permittedList = XmsBusinessXMLPerser.getPermittedList( actionId );
			
			if ( permittedList == null || permittedList.size() == 0 ) {
				// 無指定の場合、無条件許可
				isPermitted = true;
			} else {
				// 指定がある場合、ユーザの権限を取得し、
				// １つでも権限が含まれているか判定する。
				xmoIdsOfCurrentUser = this.getXmoIdsOfCurrentUser(xmsRequest);
				// ユーザの権限の集合から、設定してある権限のリストと
				// 共通となる要素のみを残す演算を実施し、
				// 演算後１要素でもあれば、権限ありとする。
				xmoIdsOfCurrentUser.retainAll(permittedList);
				isPermitted = (xmoIdsOfCurrentUser.size() > 0);
			}
		} catch ( XmsException e ) {
			throw e;	
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
		return isPermitted;
	}

	/**
	 * 現在のユーザが保持している（割り当てられている）ＸＭＯのＩＤの集合を戻す。<br>
	 * セッション登録されるユーザオブジェクトを取得し、
	 * そのオブジェクトからＸＭＯのＩＤを取得し、取得したＩＤを要素とするSetを戻す。
	 * セッションから取得できない場合、ＸＭＯが割りあたっていない場合、
	 * 要素が空のSetを戻す。
	 * @param xmsRequest リクエスト・オブジェクト。
	 * @return ＸＭＯのＩＤの集合
	 * @throws XmsException 処理中に例外が発生した場合
	 * @see User
	 */
	private Set getXmoIdsOfCurrentUser(XmsRequest xmsRequest)
		throws XmsException {
		// このメソッドの戻り値
		Set xmoIds = null;
		// HTTPリクエスト
		HttpServletRequest request = null;
		// HTTPセッション
		HttpSession session = null;
		// ユーザオブジェクト
		User user = null;
		
		try {
			xmoIds = new HashSet();
			// セッションの取得
			request = xmsRequest.getRequest();
			session = request.getSession(false);
			if ( session != null ) {
				// ユーザオブジェクトを取得
				user = (User)session.getAttribute(Constant.KEY_USER);
				// 取得できた場合はオブジェクトからＩＤを取得
				if (user != null ) {
					xmoIds.addAll( user.getXMOIds() );
				}
			}
		} catch ( XmsException e ) {
			throw e;	
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
		return xmoIds;
	}
}
