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

//
//	メール送信 XMO 設定ファイルロードクラス
//	変更履歴
//	2004.01.08 中山雅文    新規作成

package jp.co.ntt.lms.xmo.Mail;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import jp.co.ntt.lms.xmo.XMOEnvironment;
import jp.co.ntt.lms.xmo.util.DebugLog;

/**
 * メール送信 XMO 設定ファイルロードクラスです。<BR>
 */
public class MailEnv extends XMOEnvironment {

	/** 設定ファイルメールパス */
	private static final String mstrFileName = "/conf/xmo/Mail/mail.ini";

	/**
	 * Singltonとして動作するために自分のインスタンスを保持します
	 */
	private static MailEnv objEnv =  new MailEnv();

	// プロパティ定義
	/** SMTPサーバ名 */
	private static final String SMTP_HOST = "SMTP_HOST";
	/** SMTPポート番号 */
	private static final String SMTP_PORT = "SMTP_PORT";
	/** Fromメールアドレス */
	private static final String MAIL_FROM = "MAIL_FROM";

	/** ヘッダ情報*/
	private static final String HEADERTEXT = MailConst.HEADERTEXT;
	/** フッタ情報*/
	private static final String FOOTERTEXT = MailConst.FOOTERTEXT;
	/** サイト管理者メールアドレス */
	private static final String SITE_ADMINISTRATOR_MAIL
		= MailConst.SITE_ADMINISTRATOR_MAIL;
	/** サイト管理用メーラアドレス*/
	private static final String SITE_MAILER_MAIL = MailConst.SITE_MAILER_MAIL;
	/** ヘルプデスクメールアドレス*/
	private static final String HELPDESK_MAIL = MailConst.HELPDESK_MAIL;

	/**
	 * コード変換プロパティ名称プレフィックス。<br>
	 * メール送信時にあらかじめ文字コードを変換する必要のある文字について、
	 * 設定ファイルに定義しておきます。
	 * 設定ファイルには、この定数をプレフィックスとする
	 * 変換すべき文字の文字コード名称とし、
	 * 変換後の文字コードを値とする形式で宣言します。<br>
	 * 例えば、OxFF5Eで表される文字（全角チルダ）を
	 * 0x301Cに変換する必要がある場合、以下のように宣言します。<br>
	 * <pre>
	 * CONV_ISO2022_FF5E=301C
	 * </pre>
	 * （&quot;CONV_ISO2022_&quot;は、この定数の定義により異なります。)<br>
	 * この定数は、getConvertCharactorMatrixメソッドの戻り値を
	 * 生成する際に使用します。
	 *
	 * @see #getConvertCharactorMatrix()
	 */
	public static final String KEY_PREFIX_CONVERT_ISO2022 = "CONV_ISO2022_";

	/**
	 * 変換前文字列プロパティ・キーのプレフィックス。
	 */
	public static final String KEY_PREFIX_REPLACE_TARGET
		= "REPLACE_TARGET_";

	/**
	 * 変換後文字列プロパティ・キーのプレフィックス。
	 */
	public static final String KEY_PREFIX_REPLACE_REPLACEMENT
		= "REPLACE_REPLACEMENT_";

	/**
	 * コード変換表。<br>
	 * 以下の文字配列の配列を保持します。
	 * <table border="1">
	 *   <tr>
	 *     <td>インデックス</td>
	 *     <td align="center">内容</td>
	 *   </tr>
	 *   <tr>
	 *     <td>0</td>
	 *     <td>変換後の文字コード</td>
	 *   </tr>
	 *   <tr>
	 *     <td>0</td>
	 *     <td>変換後の文字コード</td>
	 *   </tr>
	 * </table>
	 * <br>
	 * @see #getConvertCharactorMatrix()
	 */
	private char[][] convertCharactorMatrix;

	/**
	 * 文字列変換表。<br>
	 * 以下の形式の文字列配列の配列を保持します。<br>
	 * <table border="1">
	 *   <tr>
	 *     <td>添え字</td>
	 *     <td>内容</td>
	 *   </tr>
	 *   <tr>
	 *     <td>０</td>
	 *     <td>変換前の文字列</td>
	 *   </tr>
	 *   <tr>
	 *     <td>１</td>
	 *     <td>変換後の文字列</td>
	 *   </tr>
	 * </table>
	 * <br>
	 * @see #getReplaceStringMatrix()
	 */
	private String[][] replaceStringMatrix;

	/**
	 * コンストラクタです
	 * @exception XMOException
	 */
	private MailEnv() {
		// 親クラスのコンストラクタを呼び設定ファイルをロードします
		super( mstrFileName );
	}

	/**
	 * インスタンスを返却します
	 * @return MailEnv
	 */
	public static MailEnv getInstance() {
		return objEnv;
	}

	/**
	 * SMTPサーバ名を返却します
	 * @return String Smtpサーバ情報
	 * @throws Exception 定義されていないなど情報取得に失敗した場合
	 */
	public static String getSmtpHost()
			throws Exception {
		return (String)objEnv.getProperty(SMTP_HOST);
	}

	/**
	 * SMTPポート番号を返却します。<BR>
	 * @return int ポート番号
	 * @throws Exception 定義されていないなど情報取得に失敗した場合
	 */
	public static Integer getSmtpPort()
			throws Exception {
		int iPort;

		try {
			iPort = Integer.parseInt( objEnv.getProperty( MailEnv.SMTP_PORT ) );
		}
		catch ( NumberFormatException ex ) {
			return null;
		}
		return new Integer(iPort);
	}

	/**
	 * FROMメールアドレスを返却します。
	 * @return String FROMメールアドレス
	 * @throws Exception 定義されていないなど情報取得に失敗した場合
	 */
	public static String getMailFrom()
			throws Exception {
		return (String)objEnv.getProperty(MAIL_FROM);
	}

	/**
	 * ヘッダー情報を返却します。<BR>
	 * @return String ヘッダー情報
	 * @throws Exception 定義されていないなど情報取得に失敗した場合
	 */
	public static String getHeadertext()
			throws Exception {
		return (String)objEnv.getProperty(HEADERTEXT);
	}

	/**
	 * フッター情報を返却します。<BR>
	 * @return String フッター情報
	 * @throws Exception 定義されていないなど情報取得に失敗した場合
	 */
	public static String getFootertext()
			throws Exception {
		return (String)objEnv.getProperty(FOOTERTEXT);
	}

	/**
	 * サイト管理者用メールアドレスを返却します。<BR>
	 * @return String サイト管理者用メールアドレス
	 * @throws Exception 定義されていないなど情報取得に失敗した場合
	 */
	public static String getSiteAdministratorMail()
			throws Exception {
		return (String)objEnv.getProperty(SITE_ADMINISTRATOR_MAIL);
	}

	/**
	 * サイトメーラーメールアドレスを返却します。<BR>
	 * @return String サイトメーラーメールアドレス
	 * @throws Exception 定義されていないなど情報取得に失敗した場合
	 */
	public static String getSiteMailerMail()
			throws Exception {
		return (String)objEnv.getProperty(SITE_MAILER_MAIL);
	}

	/**
	 * ヘルプデスクメールアドレスを返却します。<BR>
	 * @return String ヘルプデスクメールアドレス
	 * @throws Exception 定義されていないなど情報取得に失敗した場合
	 */
	public static String getHelpdeskMail()
			throws Exception {
		return (String)objEnv.getProperty(HELPDESK_MAIL);
	}

	/**
	 * メール送信環境が設定されているか判定します。
	 * @return boolean true:メール環境設定有り、false：メール環境設定なし
	 * @throws Exception 定義されていないなど情報取得に失敗した場合
	 */
	public static boolean isExistSmtpEnv()
			throws Exception {

		// mail.ini にSMTP_HOST 環境が設定されているか判定します。
		String strHost = getSmtpHost();
		if ( strHost.equals("") != true ) {
			// SMTP_HOST環境が設定されている場合
			// SMTP_PORT番号が設定されている場合
			Integer iPort = getSmtpPort();
			if ( iPort.intValue() != 0 ) {
				return true;
			}
		}
		return false;
	}

	/**
	 * メール送信用の文字コード変換表を戻します。<br>
	 * 設定ファイルより、KEY_PREFIX_CONVERT_ISO2022の値から始まるプロパティを取得し、
	 * 変換前の文字コードと変換後の文字コードを組としてcharの配列の配列として戻します。
	 * 戻す配列の各要素は以下の形式のchar配列となります。
	 * <table border="1">
	 *   <tr>
	 *     <td>添え字</td>
	 *     <td>内容</td>
	 *   </tr>
	 *   <tr>
	 *     <td>０</td>
	 *     <td>変換前の文字コード</td>
	 *   </tr>
	 *   <tr>
	 *     <td>１</td>
	 *     <td>変換後の文字コード</td>
	 *   </tr>
	 * </table>
	 *
	 * 例えば、設定ファイル上以下の定義がされていた場合、
	 * （&quot;CONV_ISO2022_&quot;の部分は、
	 * {@link #KEY_PREFIX_CONVERT_ISO2022 定数}の定義により異なります。)<br>
	 * <pre>
	 * CONV_ISO2022_FF5E=301C
	 * CONV_ISO2022_FFE2=00AC
	 * CONV_ISO2022_2225=2016
	 * </pre>
	 * このメソッドは、以下のようなcharの配列の配列を戻します。<br>
	 * <table border="1">
	 *   <tr>
	 *     <td>　</td>
	 *     <td align="center">0</td>
	 *     <td align="center">1</td>
	 *   </tr>
	 *   <tr>
	 *     <td>0</td>
	 *     <td>'&#165;uFF5E'</td>
	 *     <td>'&#165;u301C'</td>
	 *   </tr>
	 *   <tr>
	 *     <td>1</td>
	 *     <td>'&#165;uFFE2'</td>
	 *     <td>'&#165;u00AC'</td>
	 *   </tr>
	 *   <tr>
	 *     <td>2</td>
	 *     <td>'&#165;u2225'</td>
	 *     <td>'&#165;u2016'</td>
	 *   </tr>
	 * </table>
	 * <br>
	 * 設定ファイルに上記設定がない場合、要素数０の配列を戻します。<br>
	 *
	 * @return 説明を参照。
	 * @see #KEY_PREFIX_CONVERT_ISO2022
	 */
	public synchronized char[][] getConvertCharactorMatrix() {
		// プロパティ名称の集合
		Set propertyNameSet = null;
		// プロパティ名称
		String propertyName = null;
		// プロパティ名称の文字コード表記部分（変換元）
		String propertyCodeOrigin = null;
		// プロパティ値（変換先文字コード）
		String propertyCodeConverted = null;
		// 変換元文字コード
		int codeOrigin = 0;
		// 変換先文字コード
		int codeCoverted = 0;
		// 変換元文字コード、変換先文字コードを要素とする配列。
		// conversionListの要素となる。
		char[] convertCodes = null;
		// 変換表作成用List。
		List conversionList = null;

		// コンバート表がnullの場合、取得生成して戻します。
		if (convertCharactorMatrix == null ) {
			// 変換用Listを生成
			conversionList = new ArrayList();
			// 設定ファイルのプロパティを取得。
			propertyNameSet = getPropertyNames();
			////////////////////////////////////////////////////////////////////
			// プロパティを１件ずつ確認する。
			for ( Iterator iterator = propertyNameSet.iterator();
				iterator.hasNext() ;) {
				// =============================================================
				// プロパティ名称の取得
				propertyName = (String)iterator.next();
				// プロパティが指定のプレフィックスで始まらない場合は無視。
				if ( propertyName.startsWith(KEY_PREFIX_CONVERT_ISO2022)
						== false ) {
					continue;
				}
				// =============================================================
				// プロパティを取得
				// 取得できない場合は無視。
				try {
					propertyCodeConverted = getProperty(propertyName);
				}
				catch (Exception e) {
					DebugLog.write(this.getClass(),
						e.getMessage(), DebugLog.MID);
					continue;
				}
				// プロパティ名称のコード部分を取得
				propertyCodeOrigin = propertyName.substring(
					KEY_PREFIX_CONVERT_ISO2022.length());
				// =============================================================
				// 文字コード文字列を数値化
				// 数値にできない場合は無視。
				try {
					codeOrigin = Integer.parseInt(propertyCodeOrigin, 16);
					codeCoverted = Integer.parseInt(propertyCodeConverted, 16);
				}
				catch (Exception e) {
					DebugLog.write(this.getClass(),
						e.getMessage(), DebugLog.MID);
					continue;
				}
				// =============================================================
				// 配列としてまとめて、リストに追加。
				convertCodes = new char[] {
					(char)codeOrigin, (char)codeCoverted };
				DebugLog.write(this.getClass(),
					"Find conversion"
					+ " from[" + convertCodes[0]
						+ "(0x" + Integer.toHexString(convertCodes[0]) + ")]"
					+ " to[" + convertCodes[1]
						+ "(0x" + Integer.toHexString(convertCodes[1]) + ")]"
				, DebugLog.MID);
				conversionList.add(convertCodes);
			}

			////////////////////////////////////////////////////////////////////
			// リストから配列に変換
			convertCharactorMatrix = new char[conversionList.size()][];
			conversionList.toArray(convertCharactorMatrix);
		}

		// コンバート表を戻す。
		return convertCharactorMatrix;
	}


	/**
	 * メール送信用の文字列置換表を戻します。<br>
	 * 設定ファイルより、変換前の文字列と変換後の文字列の組を取得し、
	 * 文字列配列の配列として戻します。<br>
	 * 戻す配列の各要素は以下の形式の文字列配列となります。<br>
	 * <table border="1">
	 *   <tr>
	 *     <td>添え字</td>
	 *     <td>内容</td>
	 *   </tr>
	 *   <tr>
	 *     <td>０</td>
	 *     <td>変換前の文字列</td>
	 *   </tr>
	 *   <tr>
	 *     <td>１</td>
	 *     <td>変換後の文字列</td>
	 *   </tr>
	 * </table>
	 *
	 * 変換前候補文字列を定義するプロパティのプレフィックスは、
	 * {@link #KEY_PREFIX_REPLACE_TARGET}、
	 * 変換後文字列を定義するプロパティのプレフィックスは、
	 * {@link #KEY_PREFIX_REPLACE_REPLACEMENT}です。
	 * それぞれ、「プレフィックス＋数字（１以上の整数）」でキーとなり、
	 * 数字の一致で、変換前・変換後の文字列の組とします。
	 * <br>
	 * 例えば、設定ファイルに以下の定義がされていた場合、
	 * （&quot;REPLACE_TARGET_&quot;、&quot;REPLACE_REPLACEMENT_&quot;の部分は、
	 * {@link #KEY_PREFIX_REPLACE_TARGET}、
	 * {@link #KEY_PREFIX_REPLACE_REPLACEMENT}の定義により異なります。)<br>
	 * <pre>
	 * REPLACE_TARGET_1=①
	 * REPLACE_REPLACEMENT_1=１
	 * REPLACE_TARGET_2=ⅰ
	 * REPLACE_REPLACEMENT_2=ｉ
	 * REPLACE_TARGET_3=ⅱ
	 * REPLACE_REPLACEMENT_3=ii
	 * REPLACE_TARGET_4=ⅲ
	 * REPLACE_REPLACEMENT_4=iii
	 * REPLACE_TARGET_5=ⅳ
	 * REPLACE_REPLACEMENT_5=iv
	 * </pre>
	 * このメソッドは、以下のような文字列配列の配列を戻します。<br>
	 * <table border="1">
	 *   <tr>
	 *     <td>　</td>
	 *     <td align="center">0</td>
	 *     <td align="center">1</td>
	 *   </tr>
	 *   <tr>
	 *     <td>0</td>
	 *     <td>&quot;①&quot;</td>
	 *     <td>&quot;ｉ&quot;</td>
	 *   </tr>
	 *   <tr>
	 *     <td>1</td>
	 *     <td>&quot;ⅰ&quot;</td>
	 *     <td>&quot;１&quot;</td>
	 *   </tr>
	 *   <tr>
	 *     <td>2</td>
	 *     <td>&quot;ⅱ&quot;</td>
	 *     <td>&quot;ii&quot;</td>
	 *   </tr>
	 *   <tr>
	 *     <td>3</td>
	 *     <td>&quot;ⅲ&quot;</td>
	 *     <td>&quot;iii&quot;</td>
	 *   </tr>
	 *   <tr>
	 *     <td>4</td>
	 *     <td>&quot;ⅳ&quot;</td>
	 *     <td>&quot;iv&quot;</td>
	 *   </tr>
	 * </table>
	 * <br>
	 * 設定ファイルに上記設定がない場合、要素数０の配列を戻します。<br>
	 *
	 * @return 説明を参照。
	 * @see #KEY_PREFIX_REPLACE_TARGET
	 *      変換前文字列プロパティ・キーのプレフィックス
	 * @see #KEY_PREFIX_REPLACE_REPLACEMENT
	 *       変換後文字列プロパティ・キーのプレフィックス
	 */
	public synchronized String[][] getReplaceStringMatrix() {

		if (replaceStringMatrix == null) {
			List replaceStringList = new ArrayList();
			for ( int i = 0; true; i++) {
				// 変換前文字列キーの生成
				String keyTarget = KEY_PREFIX_REPLACE_TARGET + (i + 1);
				// 変換後文字列キーの生成
				String keyReplacement
					= KEY_PREFIX_REPLACE_REPLACEMENT + (i + 1);
				// 変換前・変換後とも設定ファイルから取得
				String target = null;
				String replacement = null;
				try {
					target = getProperty(keyTarget);
					replacement = getProperty(keyReplacement);
				}
				// 取得失敗した場合は終了
				catch (Exception e) {
					break;
				}
				// いずれか片方が取得できない場合は終了
				if (target == null || replacement == null) {
					break;
				}
				// 両方取得できた場合、配列にして、リストに登録。
				String[] replacePattern = new String[] {
					target, replacement
				};
				replaceStringList.add(replacePattern);
			}
			// 文字列配列の配列に変換
			replaceStringMatrix = new String[replaceStringList.size()][];
			replaceStringList.toArray(replaceStringMatrix);
		}
		return replaceStringMatrix;
	}
}
