/*********************************************************************
*	All Rights reserved,Copyright (c) K-Opticom
**********************************************************************
*＜プログラム内容＞
*	システム名		：eo顧客基幹システム
*	モジュール名	：JFUejbFUA0010001SecProc
*	ソースファイル名：JFUejbFUA0010001SecProc.java
*	作成者			：富士通
*	日付			：2023年07月03日
*＜機能概要＞
*	口座振替契約申込結果(取引検索)部品に対する副次処理を行う部品です。
*	※FUIFE211_口座振替契約申込結果(取引検索)
*
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*   v67.00.00   2023/07/03  FJ		    【ANK-4415-00-00】口振請求及びWeb申込システム移行 STEP1
*
**********************************************************************/

package eo.ejb.common.db;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.ws.http.HTTPException;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.fujitsu.futurity.model.base.CAANMsg;
import com.fujitsu.futurity.model.common.JCMAPLConstMgr;
import com.fujitsu.futurity.model.ejb.common.JSYejbLog;
import com.fujitsu.futurity.model.ejb.common.fw.AgentDispatchContext;

import eo.common.constant.JFUStrConst;
import eo.common.util.JFUCommonUtil;
import eo.ejb.cbs.cbsmsg.EFUA0010001CBSMsg;
import eo.ejb.cbs.cbsmsg.EFUA0010001CBSMsg1List;


/**
 * <p>
 * 口座振替契約申込結果(取引検索)処理を行う部品です。
 * </p>
 * @author 富士通
 */
public class JFUejbFUA0010001SecProc
{
	/** 部品ID*/
	private static final String PGID = "JFUejbFUA0010001SecProc";
	
	/** HTTP リターンコード */
	private static final String HTTP_OK = "200";

	/** パラメータセパレート文字:=*/
	protected static final String S_SEP_EQ = "=";

	/** パラメータセパレート文字:& */
	private static final String S_SEP_AN = "&";
	
	/** 通信方式パラメータ */
	private static final String S_SSL = "SSL";
	
	/** リクエスト種別パラメータ */
	private static final String S_POST = "POST";

	/** 文字コード*/
	protected static final String S_CHR_CODE = "Shift_JIS";

	/** APIシステムエラー*/
	protected static final String S_AUTH_SYSERR = "9000000";

	/** 通信方式SSL*/
	protected static final String S_HTTPS = "https";

	/**
	 * レコード ※現状、SOAP通信で設定されている
	 */
	public static final String RECORD = "record";

	/**
	 * サービスIF ※現状、SOAP通信で設定されている
	 */
	public static final String SERVICEIF = "service_if";

	/**
	 * タグ属性(=TYPE)
	 */
	private static final String[] typeValues = { "service_if", "service_if_list" };

	/**
	 * タグ名
	 * SOAP通信:"Envelope","Body","Header","initResponse"
	 * API:"result"
	 */
	private static final String[] tagNames = { "Envelope", "Body", "Header", "initResponse", "result" };

	/**
	 * SOAPFAULT[SOAP通信用]（処理例外）
	 */
	private static final String SOAP_FAULT = "fault";

	/**
	 * SOAPFAULT[SOAP通信用]（エラーコード）
	 */
	private static final String SOAP_FAULT_CODE = "reason";

	/**
	 * SOAPFAULT[SOAP通信用]（エラー詳細）
	 */
	private static final String SOAP_FAULT_STRING = "detail";


	// レスポンス　配列インデックス
	/** レコード区分 */
	private static final int I_RECORD_KBN = 0;
	/** ヘッダ部：結果コード */
	private static final int I_RESULT_CD = 1;
	/** ヘッダ部：結果内容 */
	private static final int I_RESULT_NM = 2;

	/** データ部：口座振替受付番号 */
	private static final int I_DTL_KHRI_UKNO = 11;
	/** データ部：明細顧客番号 */
	private static final int I_DTL_MSKM_BILL_NO = 22;
	/** データ部：顧客カナ名 */
	private static final int I_DTL_NAME_KANA = 25;
	/** データ部：口座振替受付ステータス */
	private static final int I_DTL_KHRI_UK_STATUS = 40;
	/** データ部：委託者コード */
	private static final int I_DTL_ITKSHA_CD = 58;
	/** データ部：明細顧客番号 */
	private static final int I_DTL_BILL_NO = 59;
	/** データ部：金融機関コード */
	private static final int I_DTL_BANK_CD = 60;
	/** データ部：金融機関名 */
	private static final int I_DTL_BANK_NM = 61;
	/** データ部：支店コード */
	private static final int I_DTL_BRANCH_CD = 62;
	/** データ部：支店名 */
	private static final int I_DTL_BRANCH_NM = 63;
	/** データ部：預金種目コード */
	private static final int I_DTL_DEPODIT_ITEM = 64;
	/** データ部：預金種目名 */
	private static final int I_DTL_DEPODIT_ITEM_NM = 65;
	/** データ部：口座番号 */
	private static final int I_DTL_ACCOUNT_NUMBER = 66;
	/** データ部：口座名義 */
	private static final int I_DTL_ACCOUNT_HOLDER = 67;

	/** ＥＮＤ部：取得件数 */
	private static final int I_TOTAL_CNT = 1;

	/** レコード区分 ヘッダ部 */
	private static final String RECORD_KBN_HEADER = "10";
	/** レコード区分 データ部 */
	private static final String RECORD_KBN_DATA = "20";
	/** レコード区分 エンド部 */
	private static final String RECORD_KBN_END = "80";
	/** 結果コード 正常 */
	private static final String RESULT_CD_NORMAL = "000000";

	/**
	 * 処理結果コード 0:正常、1：パラメータエラー、2：エラー、9：その他（SOAP通信エラー）
	 */
	public static String TRN_RSLT_CD = null;
	/** 処理結果コード 0:正常 */
	public static final String TRN_RSLT_CD_NORMAL = "0";
	/** 処理結果コード 1：パラメータエラー */
	public static final String TRN_RSLT_CD_ERR_PARAM = "1";
	/** 処理結果コード 2：エラー */
	public static final String TRN_RSLT_CD_ERR = "2";
	/** 処理結果コード 3：業務エラー */
	public static final String TRN_RSLT_CD_GYOMU_ERR1 = "3";
	/** 処理結果コード 4：業務エラー */
	public static final String TRN_RSLT_CD_GYOMU_ERR2 = "4";
	/** 処理結果コード 5：業務エラー */
	public static final String TRN_RSLT_CD_GYOMU_ERR3 = "5";
	/** 処理結果コード CC：呼出元CCで設定する業務エラー */
	public static final String TRN_RSLT_CD_GYOMU_ERR_CC = "CC";
	/** 処理結果コード 9：SOAP通信エラー（現状、判定不要） */
	public static final String TRN_RSLT_CD_ERR_SOAP = "9";

	/**
	 * コマンド実行結果（エラー）
	 */
	public static final String CMD_ERROR_MESSAGE = "CMD_ERROR_MESSAGE";

	// API処理結果
	/** サイトコード（受信） */
	public static final String OUT_SHOPID = "out_shopid";

	/** 処理区分（受信） */
	public static final String OUT_PROCTYPE = "out_proctype";

	/** サイト管理番号（受信） */
	public static final String OUT_ORDERNO = "out_orderno";

	/** 受付番号（受信） */
	public static final String OUT_RECEIVENO = "out_receiveNo";

	/** ステータス（受信） */
	public static final String OUT_STATUS = "out_status";

	/** 結果コード（受信）0:正常終了、1:形式エラー、2:業務エラー、9:システムエラー */
	public static final String OUT_RESULT = "out_result";

	/** 結果コード詳細（受信） */
	public static final String OUT_RESULTDET = "out_resultdet";

	/** 結果内容（受信） */
	public static final String OUT_RESULTCONTENT = "out_resultcontent";

	/** 応答日時（受信） */
	public static final String OUT_ENDTIME = "out_endtime";


	/**
	 * HTTPSリクエスト独自処理部品です。
	 * @param inMap メッセージ
	 * @throws Exception エラー全般
	 */
	public void execute(CAANMsg msgList, AgentDispatchContext inContext) throws Exception
	{
		
		// 開始ログ出力を実施。
		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#execute start");
		JSYejbLog.println(JSYejbLog.EXECUTION, this.getClass(), PGID + "#execute start");

		HttpURLConnection conn = null;
		BufferedReader reader = null;
		URL url = null;
		String strUrl = null;
		int timeout = 0;
		int dataTimeout = 0;
		int retryCount = 0;
		int retryInterval = 0;
		List<String> retryResultCodeList = new ArrayList<String>();
		String resultCdId = JCMAPLConstMgr.getString("FU_SMBCFS_KHRI_RESULTCODE_ID");
		String mainteCode = JCMAPLConstMgr.getString("FU_SMBCFS_KHRI_MAINTE_RESULTCODE");

		TRN_RSLT_CD = TRN_RSLT_CD_ERR;
		/*-----------------------------
		 * パラメータ設定
		 *----------------------------*/
		try
		{
			//property設定値取得
			strUrl = JCMAPLConstMgr.getString("FU_SMBCFS_KHRI_GET_URL");

			timeout = Integer.parseInt(JCMAPLConstMgr.getString("FU_SMBCFS_KHRI_GET_TIMEOUT"));
			dataTimeout = Integer.parseInt(JCMAPLConstMgr.getString("FU_SMBCFS_KHRI_DATA_TIMEOUT"));
			retryCount = Integer.parseInt(JCMAPLConstMgr.getString("FU_SMBCFS_KHRI_RETRYCOUNT"));
			retryInterval = Integer.parseInt(JCMAPLConstMgr.getString("FU_SMBCFS_KHRI_RETRYINTERVAL"));
			String resultCode = JCMAPLConstMgr.getString("FU_SMBCFS_KHRI_RETRY_RESULTCODE");
			if (resultCode != null)
			{
				// リトライ対象となる結果コード
				String[] sisakCds = resultCode.split(JFUStrConst.COMMA);
				retryResultCodeList = Arrays.asList(sisakCds);
			}

			// アプリケーションプロパティ設定チェック
			if (isNullBlunk(strUrl))
			{
				TRN_RSLT_CD = TRN_RSLT_CD_ERR_PARAM;
				JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#Properties Error");
				
				CAANMsg[] l_EFUA0010001csvmsg1list = null;
				
				l_EFUA0010001csvmsg1list =  new CAANMsg[1];
				CAANMsg msg = new CAANMsg("eo.ejb.cbs.cbsmsg.EFUA0010001CBSMsg1List");
				l_EFUA0010001csvmsg1list[0] = msg;
				// コマンド実行結果
				msg.set(EFUA0010001CBSMsg1List.TRN_RSLT_CD, TRN_RSLT_CD);
				msgList.set(EFUA0010001CBSMsg.EFUA0010001CBSMSG1LIST, l_EFUA0010001csvmsg1list);

				return;
			}
		}
		catch (NumberFormatException ne)
		{
			TRN_RSLT_CD = TRN_RSLT_CD_ERR_PARAM;
			JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#NumberFormatException");
			
			CAANMsg[] l_EFUA0010001csvmsg1list = null;
			
			l_EFUA0010001csvmsg1list =  new CAANMsg[1];
			CAANMsg msg = new CAANMsg("eo.ejb.cbs.cbsmsg.EFUA0010001CBSMsg1List");
			l_EFUA0010001csvmsg1list[0] = msg;
			// コマンド実行結果
			msg.set(EFUA0010001CBSMsg1List.TRN_RSLT_CD, TRN_RSLT_CD);
			msgList.set(EFUA0010001CBSMsg.EFUA0010001CBSMSG1LIST, l_EFUA0010001csvmsg1list);

			return;
		}

		/*-----------------------------
		 * ＳＳＬ通信設定
		 *----------------------------*/
		// 通信方式判定
		boolean bSslFlg = false;
		if (strUrl.startsWith(S_HTTPS))
		{
			bSslFlg = true;
		}

		// SSL通信の場合、キーマネージャを生成
		if (bSslFlg)
		{
			KeyManager[] km = null;
			TrustManager[] tm = { new X509TrustManager()
			{

				/**
				 * X509Certificateスタブメソッド
				 * @return null
				 */
				public java.security.cert.X509Certificate[] getAcceptedIssuers()
				{
					return null;
				}

				/**
				 * checkClientTrustedスタブメソッド
				 * @param arg0
				 * @param arg1
				 * @throws CertificateException
				 */
				public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws CertificateException
				{
					// 自動生成されたメソッドスタブ
				}

				/**
				 * checkServerTrustedスタブメソッド
				 * @param arg0
				 * @param arg1
				 * @throws CertificateException
				 */
				public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws CertificateException
				{
					// 自動生成されたメソッドスタブ
				}
			} };
			SSLContext sslcontext = SSLContext.getInstance(S_SSL);
			sslcontext.init(km, tm, new SecureRandom());
			HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
			{

				/**
				 * verifyスタブメソッド
				 * @param aHostname
				 * @param aSession
				 * @return CASHPOSTAPIへのリクエストパラメータ
				 */
				public boolean verify(String aHostname, SSLSession aSession)
				{
					return true;
				}
			});
			HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
		}

		/*-----------------------------
		 * 送信先呼び出し
		 *----------------------------*/
		// URL生成
		url = new URL(strUrl);
		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#送信URLパラメータ" + url);
		// リクエスト結果読込用ストリーム
		InputStream inputStream = null;
		InputStreamReader isReader = null;
		String reqStr = "";

		for (int i = 0; i < retryCount; i++)
		{
			try
			{
				reqStr = "";
				// アプリケーションプロパティよりProxy設定値を取得
				String strPrxyHost = JCMAPLConstMgr.getString("KK_CASHPOST_GETSTATUS_HTTPS_PROXY_HOST");
				String strPrxyPort = JCMAPLConstMgr.getString("KK_CASHPOST_GETSTATUS_HTTPS_PROXY_PORT");

				int intProxyPort = 0;
				if (strPrxyHost != null && !"".equals(strPrxyHost))
				{
					intProxyPort = Integer.parseInt(strPrxyPort);
				}

				// SSLの場合、HttpsURLConnectionへキャスト
				if (bSslFlg)
				{
					// Proxy設定値がある場合はProxyをセットしてコネクションをオープン
					if (strPrxyHost != null && !"".equals(strPrxyHost) && strPrxyPort != null && !"".equals(strPrxyPort))
					{
						Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(strPrxyHost, intProxyPort));
						conn = (HttpsURLConnection)url.openConnection(proxy);
					}
					else
					{
						conn = (HttpsURLConnection)url.openConnection();
					}
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#HttpsURLConnection openConnection");
					
				}
				else
				{
					conn = (HttpURLConnection)url.openConnection();
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#HttpURLConnection openConnection");
				}

				// リクエスト設定
				conn.setRequestMethod(S_POST);
				conn.setDoOutput(true);
				conn.setInstanceFollowRedirects(true);
				conn.setRequestProperty("Accept-Language", "jp");
				// 未設定の場合は「Content-Type:application/x-www-form-urlencoded」となる
				conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + S_CHR_CODE);

				//タイムアウト設定
				conn.setConnectTimeout(timeout);
				conn.setReadTimeout(dataTimeout);

				//POSTパラメータストリームの生成
				OutputStream os = conn.getOutputStream();
				PrintStream ps = new PrintStream(os);

				/*
				 * 送信パラメータ作成
				 */
				reqStr = requestParamMake(msgList);
				JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#reqParam=" + reqStr);
				JSYejbLog.println(JSYejbLog.EXECUTION, this.getClass(), PGID + "#reqParam=" + reqStr);
				ps.print(reqStr);
				ps.close();

				// 接続開始ログ
				JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#connect start");

				//********************//
				// 接続実行
				//********************//
				conn.connect();

				// 接続終了ログ
				JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#connect end");

				int responseCode = 500;
				responseCode = conn.getResponseCode();
				if (responseCode >= 200 && responseCode < 300)
				{
					// HttpsURLConnection.HTTP_OK: // HTTP OK
					Hashtable<String, Object> ret = new Hashtable<String, Object>();
					Transformer transformer = null;
//////////					Document responseXml = null;
//////////					StringWriter sw = null;

					TransformerFactory transformerFactory = TransformerFactory.newInstance();
					transformer = transformerFactory.newTransformer();

					//XML形式
					transformer.setOutputProperty(OutputKeys.METHOD, "xml");
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#レスポンス受信 START");

					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#ContentEncoding=[" + conn.getContentEncoding() + "]");

					String encoding = "MS932";
//					String encoding = S_CHR_CODE;

					isReader = new InputStreamReader(conn.getInputStream(), encoding);
//////////					DOMResult dr = new DOMResult();
//////////					transformer.transform(new StreamSource(isReader), dr);

//////////					responseXml = (Document)dr.getNode();

					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#レスポンス受信 END");

					/**
					 * 下り電文のログ出力
					 */
//////////					sw = new StringWriter();
//////////					transformer.transform(new DOMSource(responseXml), new StreamResult(sw));

					/**
					 * レスポンス読込処理
					 */
//////////					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#レスポンス読込処理 START");
//////////					ret = read(responseXml);
//////////					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#retParam=" + ret);
//////////					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#レスポンス読込処理 END");

					StringBuffer sb = new StringBuffer();
					sb.append("口座振替契約申込結果(取引検索) 結果 responseCode=[");
					sb.append(responseCode + "]   ");
					sb.append(makeLogStr(ret));
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#" + sb.toString());
					JSYejbLog.println(JSYejbLog.EXECUTION, this.getClass(), PGID + "#" + sb.toString());
					/*
					 * HTTP 応答メッセージから状態コードを取得し設定する。 
					 * HTTP/1.0 200 OK
					 * HTTP/1.0 401 Unauthorized
					 */
					if (HTTP_OK.equals(Integer.toString(responseCode)))
					{
						// ステータス=200：CASHPOST連携正常とする。
						TRN_RSLT_CD = TRN_RSLT_CD_NORMAL;
					}
					//********************//
					// 処理結果返却
					//********************//
					resultPut(msgList, ret, isReader, retryResultCodeList, resultCdId, mainteCode);

				}
				else
				{
					TRN_RSLT_CD = TRN_RSLT_CD_ERR;
					JSYejbLog.println(JSYejbLog.EXECUTION, this.getClass(), PGID + "#HttpStatusCd Error HttpStatusCd=[" + responseCode+ "]");
					
					CAANMsg[] l_EFUA0010001csvmsg1list = null;
					
					l_EFUA0010001csvmsg1list =  new CAANMsg[1];
					CAANMsg msg = new CAANMsg("eo.ejb.cbs.cbsmsg.EFUA0010001CBSMsg1List");
					l_EFUA0010001csvmsg1list[0] = msg;
					// コマンド実行結果
					msg.set(EFUA0010001CBSMsg1List.TRN_RSLT_CD, TRN_RSLT_CD);
					msgList.set(EFUA0010001CBSMsg.EFUA0010001CBSMSG1LIST, l_EFUA0010001csvmsg1list);

					return;
					
				}

			}

			catch (HTTPException he)
			{
				if (i < retryCount - 1)
				{
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(HTTPException)" + he.getMessage());
					// スリープした後、再度API呼び出し
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(HTTPException)sleep start");
					Thread.sleep(retryInterval);
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(HTTPException)sleep end");
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(HTTPException)retryCount=" + i);
					continue;
				}
				else
				{
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(HTTPException)" + he.getMessage());
					JSYejbLog.println(JSYejbLog.EXECUTION, this.getClass(), PGID + "#(HTTPException)" + he.getMessage());
					
					
					CAANMsg[] l_EFUA0010001csvmsg1list = null;
					TRN_RSLT_CD = TRN_RSLT_CD_ERR;
					l_EFUA0010001csvmsg1list =  new CAANMsg[1];
					CAANMsg msg = new CAANMsg("eo.ejb.cbs.cbsmsg.EFUA0010001CBSMsg1List");
					l_EFUA0010001csvmsg1list[0] = msg;
					// 処理結果コード
					msg.set(EFUA0010001CBSMsg1List.TRN_RSLT_CD, TRN_RSLT_CD);
					msgList.set(EFUA0010001CBSMsg.EFUA0010001CBSMSG1LIST, l_EFUA0010001csvmsg1list);
				}
			}
			catch (TransformerException trnEx)
			{
				// タグが不正（文字化けなどでも発生）
				if (i < retryCount - 1)
				{
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(TransformerException)" + trnEx.getMessage());
					// スリープした後、再度API呼び出し
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(TransformerException)sleep start");
					Thread.sleep(retryInterval);
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(TransformerException)sleep end");
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(TransformerException)retryCount=" + i);
					continue;
				}
				else
				{
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(TransformerException)" + trnEx.getMessage());
					JSYejbLog.println(JSYejbLog.EXECUTION, this.getClass(), PGID + "#(TransformerException)" + trnEx.getMessage());
					
					CAANMsg[] l_EFUA0010001csvmsg1list = null;
					TRN_RSLT_CD = TRN_RSLT_CD_ERR;
					l_EFUA0010001csvmsg1list =  new CAANMsg[1];
					CAANMsg msg = new CAANMsg("eo.ejb.cbs.cbsmsg.EFUA0010001CBSMsg1List");
					l_EFUA0010001csvmsg1list[0] = msg;
					// 処理結果コード
					msg.set(EFUA0010001CBSMsg1List.TRN_RSLT_CD, TRN_RSLT_CD);
					msgList.set(EFUA0010001CBSMsg.EFUA0010001CBSMSG1LIST, l_EFUA0010001csvmsg1list);
				}
			}
			catch (IOException ie)
			{
				if (i < retryCount - 1)
				{
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(IOException)" + ie.getMessage());
					// スリープした後、再度API呼び出し
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(IOException)sleep start");
					Thread.sleep(retryInterval);
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(IOException)sleep end");
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(IOException)retryCount=" + i);
					continue;
				}
				else
				{
					JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#(IOException)" + ie.getMessage());
					JSYejbLog.println(JSYejbLog.EXECUTION, this.getClass(), PGID + "#(IOException)" + ie.getMessage());
					
					CAANMsg[] l_EFUA0010001csvmsg1list = null;
					TRN_RSLT_CD = TRN_RSLT_CD_ERR;
					l_EFUA0010001csvmsg1list =  new CAANMsg[1];
					CAANMsg msg = new CAANMsg("eo.ejb.cbs.cbsmsg.EFUA0010001CBSMsg1List");
					l_EFUA0010001csvmsg1list[0] = msg;
					// 処理結果コード
					msg.set(EFUA0010001CBSMsg1List.TRN_RSLT_CD, TRN_RSLT_CD);
					msgList.set(EFUA0010001CBSMsg.EFUA0010001CBSMSG1LIST, l_EFUA0010001csvmsg1list);
				}
			}
			finally
			{
				if (reader != null)
				{
					reader.close();
				}
				if (conn != null)
				{
					conn.disconnect();
					conn = null;
				}
				if (inputStream != null)
				{
					inputStream.close();
				}
				if (isReader != null)
				{
					isReader.close();
				}
				JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#execute end");
				JSYejbLog.println(JSYejbLog.EXECUTION, this.getClass(), PGID + "#execute end");
			}

			break;
		}
	}

	/**
	 * APIに対して送信するリクエストパラメータを作成する。
	 * @param inMap メッセージキャリア
	 * @return APIへのリクエストパラメータ
	 * @throws UnsupportedEncodingException
	 */
	protected String requestParamMake(CAANMsg ccMsg)
	{
		// リクエストパラメータ作成
		StringBuffer strBuf = new StringBuffer();

		// バージョン(APLConst)
		strBuf.append("version");
		strBuf.append(S_SEP_EQ);
		strBuf.append(JCMAPLConstMgr.getString("FU_SMBCFS_VERSION"));
		// 処理区分(APLConst)
		strBuf.append(S_SEP_AN);
		strBuf.append("shori_kbn");
		strBuf.append(S_SEP_EQ);
		strBuf.append(JCMAPLConstMgr.getString("FU_SMBCFS_SHORI_KBN"));
		// 契約コード(APLConst)
		strBuf.append(S_SEP_AN);
		strBuf.append("shop_cd");
		strBuf.append(S_SEP_EQ);
		strBuf.append(JCMAPLConstMgr.getString("FU_SMBCFS_SHOP_CD"));
		// 収納企業コード(APLConst)
		strBuf.append(S_SEP_AN);
		strBuf.append("syuno_co_cd");
		strBuf.append(S_SEP_EQ);
		strBuf.append(JCMAPLConstMgr.getString("FU_SMBCFS_SYUNO_CO_CD"));
		// 取引検索用ショップパスワード(APLConst)
		strBuf.append(S_SEP_AN);
		strBuf.append("shop_pwd");
		strBuf.append(S_SEP_EQ);
		strBuf.append(JCMAPLConstMgr.getString("FU_SMBCFS_SHOP_PWD"));
		// 顧客番号From、顧客番号To
		strBuf.append(S_SEP_AN);
		strBuf.append("bill_no_from");
		strBuf.append(S_SEP_EQ);
		strBuf.append((String)ccMsg.getString(EFUA0010001CBSMsg.BILL_NO));
		strBuf.append(S_SEP_AN);
		strBuf.append("bill_no_to");
		strBuf.append(S_SEP_EQ);
		strBuf.append((String)ccMsg.getString(EFUA0010001CBSMsg.BILL_NO));

		//------------------------------------------//
		// ログ出力
		//------------------------------------------//
		JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#【口座振替契約申込結果】：" + strBuf.toString());

		return strBuf.toString();
	}
		

	/**
	 * API処理結果を格納する。
	 * @param msgList メッセージキャリア
	 * @param resultMap レスポンスキー
	 * @param isReader レスポンスバリュー
	 * @param retryResultCodeList リトライ対象の結果コード
	 * @param resultCdId 結果コード項目名
	 * @param mainteCode メンテナンス時のエラーコード
	 * @throws IOException 
	 */
	private void resultPut(CAANMsg msgList, Hashtable<String, Object> resultMap, InputStreamReader isReader, List<String> retryResultCodeList,
			String resultCdId, String mainteCode) throws IOException
	{
		List<CAANMsg> caanMsg1List = new ArrayList<CAANMsg>();

		CAANMsg caanMsg = new CAANMsg(EFUA0010001CBSMsg1List.class.getName());
		boolean isRetry = false;

		try
		{
			BufferedReader br = new BufferedReader(isReader);
			String strLine = null;
			String[] strSplit = null;
			List<Map<String, String>> resultList = new ArrayList<Map<String, String>>();
			Map<String, String> map = new HashMap<String, String>();
			int headerCount = 0;
			int dtlCount = 0;
			int totalCount = 0;
			String trnRsltCd = JFUStrConst.EMPTY;
			String resultCd = JFUStrConst.EMPTY;
			String errorMessge = JFUStrConst.EMPTY;
			String strTotalCount = JFUStrConst.EMPTY;

			// １行づつ読み込み
			JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#【口座振替契約申込結果】レスポンス ----- start #");
			while ((strLine = br.readLine()) != null)
			{
				if (strLine == null || JFUStrConst.EMPTY.equals(strLine.trim()))
				{
					continue;
				}
				JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "[" + strLine + "]");
				strSplit = splitLine(strLine);
				if (strSplit[0].startsWith(resultCdId + "=" + mainteCode))
				{
					// メンテナンス中
					resultCd = mainteCode;
				}
				else if (RECORD_KBN_HEADER.equals(strSplit[I_RECORD_KBN]))
				{
					// ヘッダ部
					headerCount++;
					resultCd = strSplit[I_RESULT_CD];
					errorMessge = strSplit[I_RESULT_NM];
					if (retryResultCodeList.contains(resultCd)) {
						// 結果コードによっては、リトライ処理へ
						isRetry = true;
						JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#リトライ対象の結果コード[" + resultCd + "]");
						throw new IOException("■■■リトライ対象の結果コードのためthrow  結果コード[" + resultCd + "]■■■");
					}
					continue;
				}
				else if (RECORD_KBN_DATA.equals(strSplit[I_RECORD_KBN]))
				{
					// データ部
					map = new HashMap<String, String>();
					map.put(EFUA0010001CBSMsg1List.DTL_BILL_NO, strSplit[I_DTL_BILL_NO]);
					map.put(EFUA0010001CBSMsg1List.KHRI_UK_STATUS, strSplit[I_DTL_KHRI_UK_STATUS]);
					map.put(EFUA0010001CBSMsg1List.KHRI_UKNO, strSplit[I_DTL_KHRI_UKNO]);
					map.put(EFUA0010001CBSMsg1List.ITKSHA_CD, strSplit[I_DTL_ITKSHA_CD]);

					map.put(EFUA0010001CBSMsg1List.KHRI_UKNO, strSplit[I_DTL_KHRI_UKNO]);
					map.put(EFUA0010001CBSMsg1List.MSKM_BILL_NO, strSplit[I_DTL_MSKM_BILL_NO]);
					map.put(EFUA0010001CBSMsg1List.NAME_KANA, strSplit[I_DTL_NAME_KANA]);
					map.put(EFUA0010001CBSMsg1List.KHRI_UK_STATUS, strSplit[I_DTL_KHRI_UK_STATUS]);
					map.put(EFUA0010001CBSMsg1List.ITKSHA_CD, strSplit[I_DTL_ITKSHA_CD]);
					map.put(EFUA0010001CBSMsg1List.DTL_BILL_NO, strSplit[I_DTL_BILL_NO]);
					map.put(EFUA0010001CBSMsg1List.BANK_CD, strSplit[I_DTL_BANK_CD]);
					map.put(EFUA0010001CBSMsg1List.BANK_NM, strSplit[I_DTL_BANK_NM]);
					map.put(EFUA0010001CBSMsg1List.BRANCH_CD, strSplit[I_DTL_BRANCH_CD]);
					map.put(EFUA0010001CBSMsg1List.BRANCH_NM, strSplit[I_DTL_BRANCH_NM]);
					map.put(EFUA0010001CBSMsg1List.DEPODIT_ITEM, strSplit[I_DTL_DEPODIT_ITEM]);
					map.put(EFUA0010001CBSMsg1List.DEPODIT_ITEM_NM, strSplit[I_DTL_DEPODIT_ITEM_NM]);
					map.put(EFUA0010001CBSMsg1List.ACCOUNT_NUMBER, strSplit[I_DTL_ACCOUNT_NUMBER]);
					map.put(EFUA0010001CBSMsg1List.ACCOUNT_HOLDER, strSplit[I_DTL_ACCOUNT_HOLDER]); // 半角カナ

					resultList.add(map);
					dtlCount++;
				} else  if (RECORD_KBN_END.equals(strSplit[I_RECORD_KBN])) {
					strTotalCount = strSplit[I_TOTAL_CNT];
					if (!JFUCommonUtil.isNull(strTotalCount)) {
						try
						{
							totalCount = Integer.parseInt(strTotalCount);
						}
						catch (Exception e)
						{
						}
						continue;
					}
				}
			}
			JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#【口座振替契約申込結果】レスポンス ----- end #");

			// 処理結果コードの設定
			if (!RESULT_CD_NORMAL.equals(resultCd))
			{
				// 正常でない場合はエラー
				trnRsltCd = TRN_RSLT_CD_GYOMU_ERR1;
			}
			else if (!(headerCount == 1 && dtlCount > 0 && totalCount == dtlCount))
			{
				// ヘッダ部、データ部、エンド部の構成で、データ部の件数があっていない場合はエラー
				trnRsltCd = TRN_RSLT_CD_GYOMU_ERR2;
			}
			else
			{
				// 正常
				trnRsltCd = TRN_RSLT_CD_NORMAL;
			}

			if (TRN_RSLT_CD_NORMAL.equals(trnRsltCd))
			{
				// 正常の場合
				for (Map<String, String> childMap : resultList)
				{
					caanMsg.set(EFUA0010001CBSMsg1List.TRN_RSLT_CD, trnRsltCd);	//処理結果コード
					caanMsg.set(EFUA0010001CBSMsg1List.RESULT_CODE, resultCd); //ヘッダ部情報
					caanMsg.set(EFUA0010001CBSMsg1List.RESULT_MESSAGE, errorMessge); //ヘッダ部情報

					//口座振替受付番号
					caanMsg.set(EFUA0010001CBSMsg1List.KHRI_UKNO,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.KHRI_UKNO), JFUStrConst.EMPTY));
					//申込顧客番号
					caanMsg.set(EFUA0010001CBSMsg1List.MSKM_BILL_NO,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.MSKM_BILL_NO), JFUStrConst.EMPTY));
					//顧客カナ名
					caanMsg.set(EFUA0010001CBSMsg1List.NAME_KANA,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.NAME_KANA), JFUStrConst.EMPTY));

					//口座振替受付ステータス  （01：申込処理中、02：申込完了、03：金融機関でのエラー、04：金融機関での中止）
					caanMsg.set(EFUA0010001CBSMsg1List.KHRI_UK_STATUS,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.KHRI_UK_STATUS), JFUStrConst.EMPTY));
					//委託者コード
					caanMsg.set(EFUA0010001CBSMsg1List.ITKSHA_CD,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.ITKSHA_CD), JFUStrConst.EMPTY));
					//明細顧客番号
					caanMsg.set(EFUA0010001CBSMsg1List.DTL_BILL_NO,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.DTL_BILL_NO), JFUStrConst.EMPTY));
					//金融機関コード
					caanMsg.set(EFUA0010001CBSMsg1List.BANK_CD,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.BANK_CD), JFUStrConst.EMPTY));
					//金融機関名
					caanMsg.set(EFUA0010001CBSMsg1List.BANK_NM,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.BANK_NM), JFUStrConst.EMPTY));
					//支店コード
					caanMsg.set(EFUA0010001CBSMsg1List.BRANCH_CD,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.BRANCH_CD), JFUStrConst.EMPTY));
					//支店名
					caanMsg.set(EFUA0010001CBSMsg1List.BRANCH_NM,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.BRANCH_NM), JFUStrConst.EMPTY));
					//預金種目コード
					caanMsg.set(EFUA0010001CBSMsg1List.DEPODIT_ITEM,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.DEPODIT_ITEM), JFUStrConst.EMPTY));
					//預金種目名
					caanMsg.set(EFUA0010001CBSMsg1List.DEPODIT_ITEM_NM,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.DEPODIT_ITEM_NM), JFUStrConst.EMPTY));
					//口座番号
					caanMsg.set(EFUA0010001CBSMsg1List.ACCOUNT_NUMBER,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.ACCOUNT_NUMBER), JFUStrConst.EMPTY));
					//口座名義
					caanMsg.set(EFUA0010001CBSMsg1List.ACCOUNT_HOLDER,
							JFUCommonUtil.nvl(childMap.get(EFUA0010001CBSMsg1List.ACCOUNT_HOLDER), JFUStrConst.EMPTY));	// 半角カナ

					caanMsg1List.add(caanMsg);
					// Listから配列に変換して設定
					msgList.set(EFUA0010001CBSMsg.EFUA0010001CBSMSG1LIST, caanMsg1List.toArray(new CAANMsg[caanMsg1List.size()]));
				}
			}
			else
			{
				// エラーありの場合
				caanMsg.set(EFUA0010001CBSMsg1List.TRN_RSLT_CD, trnRsltCd);
				caanMsg.set(EFUA0010001CBSMsg1List.RESULT_CODE, resultCd);
				caanMsg.set(EFUA0010001CBSMsg1List.RESULT_MESSAGE, errorMessge);
				caanMsg1List.add(caanMsg);
				msgList.set(EFUA0010001CBSMsg.EFUA0010001CBSMSG1LIST, caanMsg1List.toArray(new CAANMsg[caanMsg1List.size()]));
			}

		}
		catch (IOException e)
		{
			if (!isRetry)
			{
				printErrorLog(e);
			}
			throw e;
		}
		return;
	}

	/**
	 * ＮＵＬＬ、空文字の場合はtrueを返却します。
	 * 
	 * @param str
	 * @return boolean
	 */
	protected boolean isNullBlunk(String str)
	{
		if (str == null || "".equals(str))
		{
			return true;
		}
		return false;
	}

//	/**
//	 * 電文読み込み処理
//	 * @param soapResponse
//	 * @return XML電文解析結果
//	 * @throws IOException
//	 * @throws ParserConfigurationException
//	 * @throws SAXException
//	 */
//	private Hashtable<String, Object> read(Document soapResponse) throws IOException, ParserConfigurationException, SAXException
//	{
//		if (soapResponse == null)
//		{
//			return null;
//		}
//		// レスポンス解析
//		Element root = soapResponse.getDocumentElement();//ルート要素(SOAP通信の例：<SOAP-ENV:Envelope>)	
//		Hashtable<String, Object> result = analyzeXml(root, true);
//
//		return result;
//	}

	/**
	 * XMLFAULT電文解析処理
	 * 
	 * @param elem XMLFAULT電文
	 * @return ArrayListエラー情報
	 */
	private String analyzeFaultXml(Node elem)
	{
		Node node = elem.getFirstChild();
		String errmsg = "";

		while (node != null)
		{
			if (node.getNodeType() == Node.ELEMENT_NODE)
			{
				String nodename = node.getLocalName();

				if (SOAP_FAULT_CODE.equals(nodename.toLowerCase()))
				{
					Node child = node.getFirstChild();
					if (child != null)
					{
						errmsg = errmsg + "エラーコード：" + child.getTextContent();
					}
				}
				if (SOAP_FAULT_STRING.equals(nodename.toLowerCase()))
				{
					errmsg = errmsg + "エラー詳細：" + node.getTextContent();
				}
			}

			node = node.getNextSibling();
		}

		return errmsg;
	}

	/**
	 * コマンド送信戻り電文解析処理
	 * @param elem コマンド解析電文rootXML要素
	 * @param rootflag ルートフラグ
	 * @return XML解析結果
	 */
	public Hashtable<String, Object> analyzeXml(Node elem, boolean rootflag)
	{
		Node node = elem.getFirstChild();
		Hashtable<String, Object> resultMap = null;
		List<Map<String, Object>> Bodynodelist = new ArrayList<Map<String, Object>>();

		//電文の要素をすべて解析する。
		while (node != null)
		{
			JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#" + node.getLocalName() + "：" + node.getTextContent());

			if (node.getNodeType() == Node.ELEMENT_NODE)
			{

				String nodename = node.getLocalName();
				String typeValue = null;
				if (node.getAttributes().getNamedItem("type") != null)
				{
					typeValue = node.getAttributes().getNamedItem("type").getNodeValue();
				}

				String childname = "";

				NodeList nodelist = node.getChildNodes();
				if (nodelist != null)
				{
					for (int i = 0; i < nodelist.getLength(); i++)
					{
						Node child = nodelist.item(i);

						if (child.getNodeType() == Node.ELEMENT_NODE)
						{
							childname = child.getLocalName();
							break;
						}
					}
				}

				// SOAP例外の場合
				if (SOAP_FAULT.equals(nodename.toLowerCase()) || SOAP_FAULT.equals(childname.toLowerCase()))
				{
					resultMap = new Hashtable<String, Object>();
					String faultinfo = analyzeFaultXml(node);
					TRN_RSLT_CD = TRN_RSLT_CD_ERR_SOAP;
					resultMap.put(TRN_RSLT_CD, TRN_RSLT_CD);
					resultMap.put(CMD_ERROR_MESSAGE, faultinfo);
					return resultMap;
				}
				else
				{
					if (resultMap == null)
					{
						resultMap = new Hashtable<String, Object>();
					}
					Hashtable<String, Object> resultinfo = analyzeXml(node, false);
					if (RECORD.equals(nodename) || SERVICEIF.equals(nodename) || Arrays.asList(typeValues).contains(typeValue))
					{
						if (resultinfo != null && !resultinfo.isEmpty())
						{
							Bodynodelist.add(resultinfo);
						}

						resultMap.put(nodename, Bodynodelist);

					}

					else if (Arrays.asList(tagNames).contains(nodename))
					{
						resultMap.putAll(analyzeXml(node, false));
					}
					else
					{
						resultMap.put(nodename, node.getTextContent());
						if (node.getAttributes().getNamedItem("err") != null)
						{
							String StrErr = node.getAttributes().getNamedItem("err").getTextContent();
							resultMap.put(nodename + "_ERR", StrErr);
						}
					}

				}
			}

			node = node.getNextSibling();
		}

		if (rootflag)
		{
			if (resultMap == null)
			{
				resultMap = new Hashtable<String, Object>();
			}

			// OK
			JSYejbLog.println(JSYejbLog.DEBUG, this.getClass(), PGID + "#analyzeXml root read");
			return resultMap;
		}

		return resultMap;
	}

	/**
	 * APIの返却結果をログに出力するため編集を行う
	 * @param ret APIからの返却結果
	 * @return ログ出力用文字列
	 */
	@SuppressWarnings("unchecked")
	private String makeLogStr(Hashtable<String, Object> ret)
	{

		if (ret == null)
		{
			return "";
		}
		//ログ用文字列組み立て用の変数を宣言する
		StringBuilder sb = new StringBuilder();

		//返却結果よりkeyリストを取得する
		Enumeration keys = ret.keys();

		//取得したkeyの件数分ループを行う
		while (keys.hasMoreElements())
		{

			//valueを取得するためkeyを取得する
			String key = (String)keys.nextElement();
			//keyを元にvalueを取得する
			String value = (String)ret.get(key);

			//返却結果のそのまま出力する
			sb.append(key + "=" + value + ",");

		}

		return sb.toString();
	}

	/**
	 * エラーログ出力
	 * @param e 発生した例外
	 */
	static private void printErrorLog(Exception e)
	{
		StringBuffer sb = new StringBuffer();
		sb.append(e.getMessage()+ "\n");
		sb.append(e.getClass().getName()+ "\n");
		StackTraceElement[] steAll = e.getStackTrace();
		for (StackTraceElement ste : steAll) {
			sb.append("	at " + ste.getClassName() + "." + ste.getMethodName() + "(" + ste.getFileName() + ":" + ste.getLineNumber()+")"+ "\n");
		}
		JSYejbLog.println(JSYejbLog.ERROR, JFUejbFUA0010001SecProc.class, sb.toString());
	}

	/**
	 * 行データを項目毎に変換。<br/>
	 * 
	 * 
	 * @param strLine 行データ
	 * @return
	 */
	private String[] splitLine(String strLine)
	{
		String[] valList = strLine.split("\",");
		for (int idx = 0; idx < valList.length; idx++)
		{
			String val = valList[idx];
			if (val == null || JFUStrConst.EMPTY.equals(val))
			{
				valList[idx] = JFUStrConst.EMPTY;
			}
			if (val.startsWith(JFUStrConst.S_DUBLLEQ))
			{
				valList[idx] = val.substring(1);
			}
		}

		if (valList.length > 0)
		{
			int lastIndex = valList.length - 1;
			String str = valList[lastIndex];
			if (str.endsWith(JFUStrConst.S_DUBLLEQ))
			{
				valList[lastIndex] = str.substring(0, str.length() - 1);
			}
		}
		return valList;
	}
}
