/*
このファイルの中身は、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) ______________________________________.
*/

//
//	AD同期処理クラス
//			変更履歴
//				2004.01.08	新規作成	            二條智文
//
package jp.co.ntt.lms.xmo.Ad;

import jp.co.ntt.lms.xmo.LumpInsert.LumpInsertClient;
import jp.co.ntt.lms.xmo.*;
import jp.co.ntt.lms.xmo.util.DebugLog;
import jp.co.ntt.lms.xmo.Message.MessageClient;
import jp.co.ntt.lms.xmo.LumpInsert.*;

import java.util.*;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;
import java.rmi.server.UnicastRemoteObject;
/**
 * AD同期処理クラス。<BR>
 * @author T.Nijou
 * @version 2.0.1.0 2004/01/08
 */
public class ADCorp extends UnicastRemoteObject
	implements XMO, ADCorpMessage, ADCorpParam
{

	/** 同期処理メソッド名です */
	private static final String METHOD_CORP  = "corp";
	/** 設定情報取得メソッド名です。 */
	private static final String METHOD_GETSETUPENV  = "getSetupEnv";
	/** AD認証メソッド名 */
	private static final String METHOD_CERTIFY = "certify";


	/**
	 * コンストラクタです。
	 * ドメイン設定番号を設定します。
	 */
	public ADCorp() throws RemoteException {
		// リモートオブジェクトをエクスポートする
		// java.rmi.server.UnicastRemoteObject の
		// 引数なしのコンストラクタを呼び出す
		super();
	}

	/**
	 * メソッド一覧を返します
	 * @return Vector
	 */
	public Vector getMethodList() {
		return new Vector();
	}

	/**
	 * メニュー一覧を返します
	 * @return Vector メニュー一覧
	 */
	public Vector getMenuList(Hashtable htbParam) {
		return new Vector();
	}

	/**
	 * デフォルトメニューを返します
	 * @return MenuData
	 */
	public MenuData getDefaultMenu() {
		return null;
	}


	/**
	 * 起動確認（必ずtrueを返す）
	 * @return boolean 必ずtrueが返ります
	 */
	public boolean isLaunch() {
		return true;
	}

	/**
	 * このXMOで定義された、メソッドのクライアント側からの入り口になるメソッドです。
	 * @param strMethodName 実行するメソッド名を指定します
	 * @param htData メソッドで実行するパラメータを指定します<BR>
	 *               なお必要なキーと値は各DAOの処理メソッドの説明を参照して下さい。
	 * @retunr Object 戻り値（さまざまな戻り値に対応するためObject型としてあります)<BR>
	 *                受け取り側では適切な値にキャストする必要があります。
	 */
	public Object execute( String strMethodName, Hashtable htData ) {

		Object objReturn = null;

		if(strMethodName.equals(METHOD_CORP))
		{
			objReturn = corp(htData);
		}
		if(strMethodName.equals(METHOD_GETSETUPENV))
		{
			objReturn = getSetupEnv(htData);
		}
		if(strMethodName.equals(METHOD_CERTIFY))
		{
			objReturn = certify(htData);
		}
		return objReturn;
	}

	/**
	 * AD同期処理を実行します。
	 */
	synchronized public Vector corp(Hashtable htbParam) {

		MessageData objMessage = null;
		// ドメイン設定番号
		int intDomainNo = 0;
		try {
			// パラメータの取得
			try {
				intDomainNo = ((Integer)htbParam.get(DOMAIN_NO)).intValue();
			}
			catch( ClassCastException ce ) {
				// @LOG >err >10AD同期処理:ドメイン設定番号が設定されていません。
				DebugLog.write( this.getClass(),
								"AD同期処理:パラメータにドメイン設定番号が設定されていません。",
									DebugLog.HIGHT);

				throw new ADCorpException( PARAM_WAR );
			}

			// ドメイン設定番号が１〜９９以外はエラー
			if( intDomainNo < 1 || intDomainNo > 99 ) {
				// @LOG >debug >10 AD同期処理:ドメイン設定番号が不正です。:ドメイン設定番号:n
				DebugLog.write( this.getClass(),
						"AD同期処理:ドメイン設定番号が不正です。:ドメイン設定番号:" + intDomainNo,
						DebugLog.HIGHT);

				throw new ADCorpException( PARAM_WAR );
			}

			// @LOG >info >5 AD同期処理:AD同期処理を開始します。:ドメイン設定番号:n
			DebugLog.write( this.getClass(),
				"AD同期処理:AD同期処理を開始します。:ドメイン設定番号:" + intDomainNo,
				DebugLog.MID);

			// AD検索処理
			ADCorpEnv objEnv = ADCorpEnv.getInstance();
			// 設定データを取得する。
			ADCorpSetupData objSetupData = objEnv.getSetupData( intDomainNo );

			// ドメイン設定番号の設定データが存在しない場合はエラーとする。
			if( objSetupData == null ) {
				// @LOG >err >1 AD同期処理:指定されたドメイン設定番号の設定が記述されていません。:ドメイン設定番号:n
				DebugLog.write( this.getClass(),
					"AD同期処理:指定されたドメイン設定番号の設定が記述されていません。:" + intDomainNo,
					DebugLog.HIGHT);

				throw new ADCorpException( ADCorpMessage.SETUP_INVALID_ERR );
			}

			// ドメイン設定番号の設定データが不正の場合はエラーとする。
			if( !objSetupData.isValid() ) {
				// @LOG >err >1 AD同期処理:指定されたドメイン設定番号の設定が不正です。:ドメイン設定番号:n
				DebugLog.write( this.getClass(),
						"AD同期処理:指定されたドメイン設定番号の設定が不正です。:ドメイン設定番号:" + intDomainNo +
						"\n" + objSetupData.getInvalidInfo(),
						DebugLog.HIGHT);

				throw new ADCorpException( ADCorpMessage.SETUP_INVALID_ERR );
			}

			// ADからデータを取得して、マッピングを行う。
			ADCorpSearch objSearch = new ADCorpSearch( objSetupData );
			ADCorpNode objMap = objSearch.getADInfo();

			// マッピングデータが取得出来ない場合は検索エラーとする
			if( objMap == null ) {
				// @LOG >err >1 AD同期処理:検索結果からツリーを作成できませんでした。:ドメイン設定番号:n
				DebugLog.write( this.getClass(),
						"AD同期処理:検索結果からツリーを作成できませんでした。:ドメイン設定番号:" + intDomainNo,
						DebugLog.HIGHT);

				throw new ADCorpSearchException();
			}
			// 同期XMLの取得
			String strXML = objMap.getXML();

			// 共通同期処理を呼び出す。
			callCommonCorp( strXML, intDomainNo );

			// @LOG >info >5 AD同期処理:AD同期処理が終了しました。:ドメイン設定番号:n
			DebugLog.write( this.getClass(),
				"AD同期処理:AD同期処理が終了しました。:ドメイン設定番号:" + intDomainNo,
				DebugLog.MID);

		}
		catch( ADCorpException ae ) {
			// @LOG >err >1 AD同期処理:AD同期処理が異常終了しました。メッセージ:ドメイン設定番号:n
			DebugLog.write( this.getClass(),
				"AD同期処理:AD同期処理が異常終了しました。" + ae.getMessage() + ":ドメイン設定番号:" + intDomainNo,
				DebugLog.HIGHT);
			DebugLog.write(this.getClass(), ae, DebugLog.HIGHT );

			objMessage = ae.getMessageData();
		}

		// 結果作成
		Vector vecRes = new Vector();
		vecRes.add(objMessage);
		return vecRes;
	}

	/**
	 * 共通同期処理を呼び出します。
	 * @param strXML 同期XML
	 * @param intDomainNo ドメイン設定番号
	 * @exception ADCorpException
	 */
	private void callCommonCorp( String strXML, int intDomainNo )
		throws ADCorpException
	{

		try {
			// @LOG >info >5 AD同期処理:共通同期処理を開始します。:ドメイン設定番号:n
			DebugLog.write( this.getClass(),
				"AD同期処理:共通同期処理を開始します。:ドメイン設定番号:" + intDomainNo,
				DebugLog.MID);

			// 共通同期処理
			LumpInsertClient objLic = new LumpInsertClient();
			objLic.setEncode("Windows-31J");	// エンコードをWindows-31Jに設定
			objLic.setLumpXML(strXML);	// 共通同期XML設定

			// 共通同期処理をコールします。
			if(!objLic.insert()) {

				if(objLic.isErr()) {
					// システムエラーまたはデータベースエラー
					MessageData objMessageData = objLic.getMessageData();
					if( objMessageData.getMessageID().equals( LumpInsertMessage.DB_ERR ) ) {
						// データベースエラー
						throw new ADCorpException( DB_ERR );
					}
					else {
						// システムエラー
						throw new ADCorpException( SYSTEM_ERR );
					}
				}
				else {
					// 警告
					MessageData objMessageData = objLic.getMessageData();
					// 登録に失敗したグループ・ユーザが存在する
					if( objMessageData.getMessageID().equals( LumpInsertMessage.INSERT_WAR ) ) {
						throw new ADCorpException( AD_INSERT_ERR );
					}
					else {
						// その他は内部エラー
						throw new ADCorpException( INNER_ERR );
					}
				}
			}

			// @LOG >info >5 AD同期処理:共通同期処理が終了しました。:ドメイン設定番号:n
			DebugLog.write( this.getClass(),
				"AD同期処理:共通同期処理が終了しました。:ドメイン設定番号:" + intDomainNo,
				DebugLog.MID);

		}
		catch( ADCorpException ae ) {
			// @LOG >err >1 AD同期処理:共通同期処理が異常終了しました。:ドメイン設定番号:n
			DebugLog.write( this.getClass(),
				"AD同期処理:共通同期処理が異常終了しました。:ドメイン設定番号:" + intDomainNo,
				DebugLog.HIGHT);

			throw ae;
		}
		catch( Exception ex ) {
			// @LOG >err >1 AD同期処理:共通同期処理が異常終了しました。:ドメイン設定番号:n
			DebugLog.write( this.getClass(),
				"AD同期処理:共通同期処理が異常終了しました。:ドメイン設定番号:" + intDomainNo,
				DebugLog.HIGHT);
			DebugLog.write( this.getClass(), ex, DebugLog.HIGHT );

			// システムエラー
			throw new ADCorpException( SYSTEM_ERR );
		}
	}

	/**
	 * 設定ファイル取得処理を行います。
	 */
	public Vector getSetupEnv(Hashtable htbParam) {
		MessageData objMessage = null;
		Vector vecRes = new Vector();

		try {
			// AD設定ファイルデータ取得
			ADCorpEnv objEnv = ADCorpEnv.getInstance();

			// 整合性チェック
			if( !objEnv.isValid() ) {
				ADCorpSetupInvalidException aie = objEnv.getInvalidInfo();
				// @LOG >err >1 AD同期処理:設定ファイルの記述に誤りがあります。詳細
				DebugLog.write( this.getClass(),
					"AD同期処理:設定ファイルの記述に誤りがあります。\n" + aie.getInvalidInfo(),
					DebugLog.HIGHT );

				objMessage = aie.getMessageData();
			}
			// メッセージオブジェクトを格納
			vecRes.add(objMessage);
			// 設定データリストを格納
			vecRes.add(objEnv);
		}
		catch( ADCorpException ae ) {
			// @LOG >err >1 AD同期処理:設定ファイルの読み込みに失敗しました。
			DebugLog.write( this.getClass(),
				"AD同期処理:設定ファイルの読み込みに失敗しました。",
				DebugLog.HIGHT );

			DebugLog.write(this.getClass(), ae, DebugLog.HIGHT );
			objMessage = ae.getMessageData();
		}
		return vecRes;
	}

	/**
	 * Active Directoryによる認証処理を実行します。
	 *
	 * @param strLogonUser ログオンユーザー名
	 * @param strDomainName ログインドメイン名
	 * @return ログオンID 認証に失敗した場合は nullを返す。
	 */
	public Vector certify(Hashtable htbParam)
	{
		MessageData objMessage = null;
		Vector vecRes = new Vector();

		String strLogonUser = null;
		String strDomainName = null;
		String strUserID = null;
		try {
			// パラメータの取得
			try {
				strLogonUser = (String)htbParam.get(LOGON_USER);
				strDomainName = (String)htbParam.get(DOMAIN_NAME);
			}
			catch( ClassCastException ce ) {
				// @LOG >err >10AD同期処理:ドメイン設定番号が設定されていません。
				DebugLog.write( this.getClass(),
								"AD認証処理:パラメータが不正です。",
									DebugLog.HIGHT);

				throw new ADCorpException( PARAM_WAR );
			}

			if( strLogonUser == null || strDomainName == null ) {
				// @LOG >err >10AD同期処理:ドメイン設定番号が設定されていません。
				DebugLog.write( this.getClass(),
								"AD認証処理:ログオンユーザ名、ドメイン名を設定してください。",
									DebugLog.HIGHT);
				throw new ADCorpException( PARAM_WAR );
			}

			// @LOG >info >5 AD認証処理:認証処理を開始します。:ログオンユーザ名: domain\name
			DebugLog.write(this.getClass(),
						"AD認証処理:認証処理を開始します。:ログオンユーザ名: " + strDomainName + "\\" + strLogonUser,
						DebugLog.MID );

			// AD設定データ取得
			ADCorpEnv objEnv = ADCorpEnv.getInstance();

			ADCorpSetupData objSetup = objEnv.getDomainSetupData( strDomainName );

			if( objSetup != null ) {
				// 設定データのコピーを作成する
				ADCorpSetupData objSetupCopy = objSetup.copy();
				// 検索フィルタを設定
				objSetupCopy.setADFilter("(&(objectClass=user)(sAMAccountName=" + strLogonUser + "))");
				ADCorpSearch objSearch = new ADCorpSearch( objSetupCopy );
				strUserID = objSearch.certify();
			}
			// メッセージオブジェクトを格納
			vecRes.add(objMessage);
			// ログインIDを格納
			vecRes.add(strUserID);

			// @LOG >info >5 AD認証処理:認証処理が終了しました。:結果: OK or NG :ログオンユーザ名: domain\name
			DebugLog.write(this.getClass(),
						"AD認証処理:認証処理が終了しました。:ログオンユーザ名: " + strDomainName + "\\" + strLogonUser +
						" :認証結果: " + (strUserID == null ? "NG": "OK" ),
						DebugLog.MID );
		}
		catch( ADCorpException ae ) {
			// @LOG >err >1 AD認証処理:認証に失敗しました。
			DebugLog.write( this.getClass(),
				"AD認証処理:認証に失敗しました。",
				DebugLog.HIGHT );

			DebugLog.write(this.getClass(), ae, DebugLog.HIGHT );
			objMessage = ae.getMessageData();
		}
		return vecRes;
	}

	/**
	 * メッセージオブジェクトを作成します
	 * @param strMessageID メッセージID
	 * @return MessageData メッセージオブジェクト 例外発生時はnullを返します
	 */
	private MessageData getMessageData( String strMessageID) {
		MessageData objMessage = null;
		try {
			MessageClient objMessageClient = new MessageClient( MSG_FIEL_PATH, MSG_FILE_NAME );
			objMessage = objMessageClient.getMessageData( strMessageID );
		}
		catch( Exception e ) {

		}
		return objMessage;
	}

}

