package com.eactive.eai.outbound;

import java.util.Properties;

import javax.jms.JMSException;

import org.apache.commons.lang3.StringUtils;

import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.AdapterPropManager;
import com.eactive.eai.adapter.AdapterVO;
import com.eactive.eai.adapter.amq.AMQAdapterConstants;
import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
import com.eactive.eai.common.EAIKeys;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.header.HeaderAction;
import com.eactive.eai.common.header.HeaderActionFactory;
import com.eactive.eai.common.header.HeaderActionKeys;
import com.eactive.eai.common.logger.Keys;
import com.eactive.eai.common.message.EAIMessage;
import com.eactive.eai.common.message.EAIMessageKeys;
import com.eactive.eai.common.message.MessageType;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.routing.RouteKeys;
import com.eactive.eai.common.server.EAIServerManager;
import com.eactive.eai.common.stdmessage.STDMessageMapper;
import com.eactive.eai.common.util.MessageUtil;
import com.eactive.eai.common.util.StringUtil;
import com.eactive.eai.common.util.TranLogUtil;
import com.eactive.eai.common.worker.Future;
import com.eactive.eai.common.worker.ResponseMap;
import com.eactive.eai.control.AMQSender;
import com.eactive.eai.control.LogSender;
import com.eactive.eai.control.Transform;
import com.eactive.eai.env.ElinkConfig;
import com.eactive.eai.inbound.processor.Processor;
import com.eactive.eai.message.StandardMessage;
import com.eactive.eai.message.manager.StandardMessageManager;
import com.eactive.eai.message.parser.StandardReader;
import com.ext.eai.common.stdmessage.STDMessageKeys;

public class AMQProcess extends DefaultProcess {

	@Override
	public void logSenderCtrlSendReq() throws Exception {
		try {
			LogSender.send(this.logPssSno, this.reqEaiMsg, this.prop);
		} catch (Exception e) {
			String[] msgArgs = new String[1];
			msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
			String rspErrorCode = "RECEAIOHP021";
			String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
			if (logger.isWarn())
				logger.warn(rspErrorMsg);
		}
	}

	@Override
	public void logSenderCtrlSendRes() throws Exception {
		try {
			LogSender.send(this.logPssSno, this.resEaiMsg, this.prop);
		} catch (Exception e) {
			String[] msgArgs = new String[1];
			msgArgs[0] = this.resEaiMsg.getEAISvcCd();
			String rspErrorCode = "RECEAIOHP021";
			String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
			if (logger.isWarn())
				logger.warn(rspErrorMsg);
		}
	}

	@Override
	public void outboundCtrlCallService() throws Exception {
		// 인터페이스에 셋팅된 타임아웃설정
		int iTimeoutValue = getTimeoutCodeToValue();
		this.timeout = iTimeoutValue * 1000;
		this.tempProp.put(INTERFACE_TIME_OUT, "" + this.timeout);
		try {
			this.resObject = AMQSender.callService(this.adapterGroupName, this.outboundProp, this.reqObject,
					this.tempProp);

			// 응답코드에 대한 처리
			this.resEaiMsg = setResponseForOutbound(this.resEaiMsg);

			if (!com.eactive.eai.adapter.Keys.IF_STANDARD.equals(this.adptrMsgPtrnCd)) {
				this.resEaiMsg = setSendTime(this.resEaiMsg);
			}
		} catch (JMSException jmse) {
			String[] msgArgs = new String[1];
			msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
			String rspErrorCode = "RECEAICUL001";
			String rspErrorMsg = ExceptionUtil.make(jmse, rspErrorCode, msgArgs);
			if (logger.isError())
				logger.error(guidLogPrefix + rspErrorMsg, jmse);
//			this.resEaiMsg.setRspErrCd(rspErrorCode);
//			this.resEaiMsg.setRspErrMsg(rspErrorMsg);
			this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
			throw new RuntimeException(rspErrorCode);
		} catch (Exception e) {
			String[] msgArgs = new String[1];
			msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
			String rspErrorCode = "RECEAIOHP001";
			String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
			if (logger.isError())
				logger.error(guidLogPrefix + rspErrorMsg, e);
//			this.resEaiMsg.setRspErrCd(rspErrorCode);
//			this.resEaiMsg.setRspErrMsg(rspErrorMsg);
			this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
			throw new RuntimeException(rspErrorCode);
		}
	}

	@Override
	public void outboundCtrlCallServiceAsync() throws Exception {
		/**
		 * async에서는 인터페이스 값을 설정하지 않고 Adapter의 타임아웃을 쓰기위해서 설정하지 않음
		 */
		try {
			

			this.resObject = AMQSender.callService(this.adapterGroupName, this.outboundProp, this.reqObject,
					this.tempProp);
		} catch (JMSException jmse) {
			String[] msgArgs = new String[1];
			msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
			String rspErrorCode = "RECEAICUL001";
			String rspErrorMsg = ExceptionUtil.make(jmse, rspErrorCode, msgArgs);
			if (logger.isError())
				logger.error(guidLogPrefix + rspErrorMsg, jmse);
//			this.resEaiMsg.setRspErrCd(rspErrorCode);
//			this.resEaiMsg.setRspErrMsg(rspErrorMsg);
			this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
			throw new RuntimeException(rspErrorCode);
		} catch (Exception e) {
			String[] msgArgs = new String[1];
			msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
			String rspErrorCode = "RECEAIOHP001";
			String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
			if (logger.isError())
				logger.error(guidLogPrefix + rspErrorMsg, e);
//			this.resEaiMsg.setRspErrCd(rspErrorCode);
//			this.resEaiMsg.setRspErrMsg(rspErrorMsg);
			this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
			throw new RuntimeException(rspErrorCode);
		}
	}

	@Override
	public void transControlTransformSingleRes() throws Exception {
		try {
			this.srcTranObject = this.resObject;
			this.tgtTranObject = Transform.transformSingle(this.guidLogPrefix, false, this.diURI, this.srcTranObject);
		} catch (Exception e) {
			if (logger.isError())
				logger.error(guidLogPrefix + " 300 변환오류", e);
			String[] msgArgs = new String[1];
			msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
			String rspErrorCode = "RECEAIOHP030";
			String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
			if (logger.isError())
				logger.error(guidLogPrefix + rspErrorMsg, e);
//			this.resEaiMsg.setRspErrCd(rspErrorCode);
//			this.resEaiMsg.setRspErrMsg(rspErrorMsg);
			this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
		}
	}

	@Override
	public void transControlTransformSingleReq() throws Exception {
		try {
			String bizData = this.reqEaiMsg.getStandardMessage().getBizData();
			if (bizData != null && bizData.length() > 0) {
				this.srcTranObject = bizData;
			}
			this.tgtTranObject = Transform.transformSingle(this.guidLogPrefix, true, this.diURI, this.srcTranObject);
		} catch (Exception e) {
			if (logger.isError())
				logger.error(guidLogPrefix + " 200 변환오류", e);
			String[] msgArgs = new String[1];
			msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
			String rspErrorCode = "RECEAIOHP020";
			String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
			if (logger.isError())
				logger.error(guidLogPrefix + rspErrorMsg, e);
//			this.resEaiMsg.setRspErrCd(rspErrorCode);
//			this.resEaiMsg.setRspErrMsg(rspErrorMsg);
			this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
			throw new Exception(rspErrorMsg);
		}
	}

	@Override
	public void printCallError(Exception e1) throws Exception {
		this.resObject = "";

		if ("RECEAICUL001".equals(this.resEaiMsg.getRspErrCd())) {
			if (logger.isDebug()) {
				logger.debug(guidLogPrefix + " UUID[" + this.reqEaiMsg.getSvcOgNo() + "] Queue Transfer Error - "
						+ e1.getMessage());
			}
		} else {
			// REST 는 TEST Call을 할수 없음.20200813.최준호
			if (logger.isDebug()) {
				logger.debug(guidLogPrefix + " UUID[" + this.reqEaiMsg.getSvcOgNo() + "] 수동시스템 오류 ");
			}
		}
	}

	@Override
	public void setRcvLogInfo() throws Exception {
		this.logPssSno = TranLogUtil.getResLogSeq(this.svcPssTp, this.svcPssSeq, this.isComp); // 300

		this.prop = new Properties();
		if (this.isSuccess) {
			prop.setProperty(Keys.ERROR_MESSAGE, Keys.FALSE);
		} else {
			prop.setProperty(Keys.ERROR_MESSAGE, Keys.TRUE);
		}

		if (MessageUtil.checkRspErrCd(this.resEaiMsg.getRspErrCd())) {
			if (com.eactive.eai.adapter.Keys.IF_STANDARD.equals(this.adptrMsgPtrnCd)) {
				if (logger.isDebug())
					logger.debug(guidLogPrefix + " 내부표준 추출");
				try {
					resEaiMsg = setRcvLogInfo(resEaiMsg, this.adptrMsgType, this.resObject, this.outboundCharset);
					this.resObject = resEaiMsg.getStandardMessage().getBizData();
				} catch (Exception e) {
					String[] msgArgs = new String[1];
					msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
					String rspErrorCode = "RECEAIOHP002";
					String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
					if (logger.isError()) {
						logger.error(guidLogPrefix + rspErrorMsg, e);
					}
//					this.resEaiMsg.setRspErrCd(rspErrorCode);
//					this.resEaiMsg.setRspErrMsg(rspErrorMsg);
					this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
				}
			} else if (com.eactive.eai.adapter.Keys.IF_SUBSTANDARD.equals(this.adptrMsgPtrnCd)) {
				if (logger.isDebug())
					logger.debug(guidLogPrefix + "SUB표준 업무데이터 추출");
				try {
					this.resEaiMsg = convertToStandardMessage(resEaiMsg, adptrMsgType, this.resObject,
							this.outboundCharset);
					this.resObject = resEaiMsg.getStandardMessage().getBizData();
				} catch (Exception e) {
					e.printStackTrace();
					String[] msgArgs = new String[1];
					msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
					String rspErrorCode = "RECEAIOSP031"; // 잘못된 내부표준메시지 수신[{1}]
					String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
					if (logger.isError())
						logger.error(guidLogPrefix + rspErrorMsg, e);

//					this.resEaiMsg.setRspErrCd(rspErrorCode);
//					this.resEaiMsg.setRspErrMsg(rspErrorMsg);
					this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
				}
			}
		}
	}

	@Override
	public void setTopicResult() throws Exception {
		try {
			this.jmsRespObject = future.value(this.timeout);
			if (this.jmsRespObject == null) {
				throw new Exception("RECEAIOHP010");
			}
			resEaiMsg = setResponseForOutbound(this.resEaiMsg);
		} catch (Exception e) {
			String[] msgArgs = new String[1];
			msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
			String rspErrorCode = "RECEAIOHP010";
			String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
			if (logger.isError())
				logger.error(guidLogPrefix + rspErrorMsg, e);
//			this.resEaiMsg.setRspErrCd(rspErrorCode);
//			this.resEaiMsg.setRspErrMsg(rspErrorMsg);
			this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
			throw new RuntimeException(rspErrorCode);
		} finally {
			if (jmsRespAction != null) {
				this.jmsRespAction.doEnd();
			}
		}

		if (this.jmsRespObject == null) {
			this.resObject = new byte[0];
		} else if (this.jmsRespObject instanceof EAIMessage) {
			EAIMessage topicEaiMsg = (EAIMessage) this.jmsRespObject;
			this.resObject = topicEaiMsg.getStandardMessage().getBizDataBytes();
		} else if (this.jmsRespObject instanceof byte[]) {
			this.resObject = (byte[]) this.jmsRespObject;
		} else {
			this.resObject = new byte[0];
		}
	}

	@Override
	public void checkResultMessage() throws Exception {
		if (logger.isDebug()) {
			logger.debug(guidLogPrefix + " SYNC - QUEUE RESPONSE MESSAGE : "
					+ MessageUtil.toAdapterTypeString(this.resObject, this.outboundCharset));
		}
	}

	@Override
	public void checkSendResult() throws Exception {
		if (MessageUtil.checkRspErrCd(this.resEaiMsg.getRspErrCd())) {
			if (logger.isDebug()) {
				logger.debug(guidLogPrefix + " ASYNC - QUEUE RESPONSE MESSAGE : "
						+ MessageUtil.toAdapterTypeString(this.resObject, this.outboundCharset));
			}
		}
	}

	@Override
	public void init() throws Exception {
		this.prop = null;
		this.adapterName = null;
		this.resEaiMsg = this.reqEaiMsg;
		this.adapterGroupName = reqEaiMsg.getCurrentSvcMsg().getPsvSysItfTp();

		// DefaultProcess 이관시 누락된 부분 추가
		this.svcTsmtUsgTp = this.reqEaiMsg.getSvcTsmtUsgTp(); // Inbound 호출방식
		this.psvItfTp = this.reqEaiMsg.getCurrentSvcMsg().getPsvItfTp(); // 호출방식

		// 복합거래의 보상거래여부를 확인
		this.svcPssTp = this.reqEaiMsg.getSvcPssTp();
		this.svcPssSeq = this.reqEaiMsg.getSvcPssSeq();

		if (this.callProp != null) {
			logger.debug(guidLogPrefix + " COMP_VALUE[" + this.callProp.getProperty(EAIKeys.CALL_COMP_KEY) + "]");
			if (EAIKeys.CALL_COMP_VALUE.equals(this.callProp.getProperty(EAIKeys.CALL_COMP_KEY))) {
				this.isComp = true;
				try {
					this.svcPssSeq = Integer.parseInt(this.callProp.getProperty(EAIKeys.CALL_COMP_SVC_SEQ));
					logger.debug(guidLogPrefix + " CALL_COMP_SVC_SEQ[" + this.svcPssSeq + "]");
				} catch (Exception e) {
					logger.warn(guidLogPrefix + " CALL_COMP_SVC_SEQ Get Error");
				}
			} else {
				this.isComp = false;
			}
		} else {
			this.isComp = false;
		}

		String returnType = getReturnType(reqEaiMsg);

		if (STDMessageKeys.SEND_RECV_CD_RECV.equals(returnType)) {
			this.logPssSno = 400;
		} else {
			this.logPssSno = TranLogUtil.getReqLogSeq(this.svcPssTp, this.svcPssSeq, this.isComp);
		}

		// Inbound Adapter mesageType
		AdapterManager adapterManager = AdapterManager.getInstance();
		AdapterGroupVO inAdptGrpVO = adapterManager.getAdapterGroupVO(this.reqEaiMsg.getSngSysItfTp());
		this.inAdapterMsgType = MessageType.ASC;

		if (inAdptGrpVO == null) {
			if (logger.isWarn()) {
				if (this.prop == null) {
					logger.warn(guidLogPrefix + "Source Adapter is null, TAS Inbound ");
				} else {
					logger.warn(guidLogPrefix + "Source Adapter is null, TAS Inbound = "
							+ this.prop.getProperty(Processor.TAS_ADAPTER_GROUP_NAME));
				}
			}
			this.inAdapterMsgType = MessageType.ASC;
		} else {
			this.inAdapterMsgType = inAdptGrpVO.getMessageType();
		}
	}

	@Override
	public void setSendMsg() throws Exception {
		try {
			// 200 로그를 위한 변환된 메시지부를 설정
			this.reqEaiMsg.getStandardMessage().setBizData(tgtTranObject, this.outboundCharset);

			if (this.tgtTranObject instanceof String) {
				this.reqObject = (String) this.tgtTranObject;
			} else {
				throw new Exception("Invlid Transform output message (" + this.tgtTranObject + ")");
			}

			AdapterGroupVO adptGrpVO = null;
			try {
				AdapterManager adapterManager = AdapterManager.getInstance();
				adptGrpVO = adapterManager.getAdapterGroupVO(this.adapterGroupName);

				if (adptGrpVO == null) {
					throw new Exception("adapter group not found");
				}

				AdapterVO adptVO = adptGrpVO.nextAdapterVO();

				if (adptVO == null) {
					throw new Exception("adapter not found");
				}
				this.adapterName = adptVO.getName();
				
				this.adptrMsgType = adptGrpVO.getMessageType();

				AdapterPropManager manager = AdapterPropManager.getInstance();
				this.outboundProp = (Properties) manager.getProperties(adptVO.getPropGroupName());// clone 안함으로 변경
				if (this.tempProp == null) {
					this.tempProp = new Properties();
				}
				this.tempProp.setProperty(HttpClientAdapterServiceKey.ADAPTER_GROUP_NAME, this.adapterGroupName);
				this.tempProp.setProperty(HttpClientAdapterServiceKey.ADAPTER_NAME, adptVO.getName());

				this.tempProp.setProperty(AMQAdapterConstants.TEMP_INTERFACE_RESPONSE_TYPE, this.psvItfTp);
				this.tempProp.setProperty(AMQAdapterConstants.TEMP_MESSAGE_TYPE, this.adptrMsgType);

				String svcName = getServiceId(this.reqEaiMsg);
				if (svcName == null) {
					svcName = "";
				} else {
					svcName = svcName.trim();
				}
				this.tempProp.setProperty(HttpClientAdapterServiceKey.TRAN_CODE, svcName);

				this.adptrMsgPtrnCd = adptGrpVO.getAdptrMsgPtrnCd();
				this.adptrMsgType = adptGrpVO.getMessageType();
			} catch (Exception e) {
				throw new Exception("Target Adapter Fail (" + this.adapterGroupName + ") ");
			}

			// 표준메시지 방식일 경우 KESA메시지에 업무메시지를 설정하여 전달한다.
			// migration - boolean 값이 아니라 [S, N, C] 값을 가짐
			if (com.eactive.eai.adapter.Keys.IF_STANDARD.equals(this.adptrMsgPtrnCd)) {
				this.reqObject = makeStandardMessageData(this.reqEaiMsg, this.adptrMsgType, this.reqObject,
						this.outboundCharset);
			} else if (com.eactive.eai.adapter.Keys.IF_SUBSTANDARD.equals(this.adptrMsgPtrnCd)) {
				this.reqObject = makeSubStandardMessageData(this.reqEaiMsg, this.adptrMsgType, this.reqObject,
						this.outboundCharset);
				if (this.reqObject instanceof String) {
					this.reqObject = ((String) this.reqObject).getBytes(this.outboundCharset);
				}
			} else {
				// 변환을 수행하고 결과가 비표준 XML일 경우에만
				if (EAIMessageKeys.YES_FLAG.equals(this.reqEaiMsg.getCurrentSvcMsg().getCnvEn())
						&& MessageType.XML.equals(adptGrpVO.getMessageType())) {
					if (logger.isDebug()) {
						logger.debug(guidLogPrefix + " Add Xml Header Tag to NONSTANDARD XML Message");
					}

					String reqString = (String) this.reqObject;
					if (!StringUtils.startsWith(reqString, "<?xml")) {
						reqString = "<?xml version=\"1.0\" encoding=\"" + this.outboundCharset + "\"?>\n" + reqString;
						this.reqObject = reqString;
					}
				}

				if (logger.isDebug())
					logger.debug(guidLogPrefix + " HTTP NONSTANDARD Request Message : "
							+ MessageUtil.toAdapterTypeString(this.reqObject, this.inboundCharset));
			}
			// TAS 선택시 시뮬레이터 url로 변경
			EAIServerManager eaiServerManager = EAIServerManager.getInstance();
			if (eaiServerManager.isTASEnabledEAIServer() && EAIMessageKeys.TRANTYPE_TAS.equals(reqEaiMsg.getTranType())
					&& StringUtils.equals(adptGrpVO.getType(), "AMQ")) {
				PropManager manager = PropManager.getInstance();
				Properties prop = manager.getProperties(RouteKeys.SIM);
				String simAddr = prop.getProperty(RouteKeys.SIM_REST_MOCKSERVER);
				if (StringUtils.isBlank(simAddr)) {
					throw new Exception(String.format("Properties %s > %s not setted", RouteKeys.SIM,
							RouteKeys.SIM_REST_MOCKSERVER));
				}

				String url = StringUtils.removeEnd(simAddr, "/") + "/mockapi/" + this.reqEaiMsg.getEAISvcCd();
				this.outboundProp.put(HttpClientAdapterServiceKey.URL, url);
				logger.debug("simUrl=" + url);
			}

		} catch (Exception e) {
			String[] msgArgs = new String[1];
			msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
			String rspErrorCode = "RECEAIOHP022";
			String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
			if (logger.isError())
				logger.error(guidLogPrefix + rspErrorMsg, e);
//			this.resEaiMsg.setRspErrCd(rspErrorCode);
//			this.resEaiMsg.setRspErrMsg(rspErrorMsg);
			this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
			throw new Exception(rspErrorMsg);
		}
	}

	@Override
	public void getTopicProperty() throws Exception {
		PropManager propManager = PropManager.getInstance();

		this.topicConFactory = propManager.getProperty(RouteKeys.GROUP_NAME,
				RouteKeys.ROUTING_TOPIC_CONNECTION_FACTORY);
		this.topicName = propManager.getProperty(RouteKeys.GROUP_NAME, RouteKeys.ROUTING_TOPIC);
		int iTimeoutValue = getTimeoutCodeToValue();
		this.timeout = iTimeoutValue * 1000;
		this.tracekey = this.reqEaiMsg.getCurrentSvcMsg().getKeyMgtMsgVl();

		if (ElinkConfig.isUseCacheTopic()) {
			this.future = new Future();
			try {
				ResponseMap.getInstance().put(this.tracekey, future);
			} catch (Exception e) {
				logger.error(guidLogPrefix + "Cannot start the Cache Response Future. - " + e.getMessage(), e);
				String[] msgArgs = new String[1];
				msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
				String rspErrorCode = "RECEAIOHP060";
				String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
//				this.resEaiMsg.setRspErrCd(rspErrorCode);
//				this.resEaiMsg.setRspErrMsg(rspErrorMsg);
				this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
				throw new Exception(rspErrorMsg);
			}
		} else {
			jmsRespAction = new com.eactive.eai.common.worker.JMSListenerAction(this.topicConFactory, this.topicName,
					this.timeout);
			jmsRespAction.doInit(this.tracekey);
			this.future = new Future();
			try {
				jmsRespAction.doStart(future.getSlot());
			} catch (Exception e) {
				logger.error(guidLogPrefix + "Cannot start the JMSListenerAction. - " + e.getMessage(), e);
				String[] msgArgs = new String[1];
				msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
				String rspErrorCode = "RECEAIOHP060";
				String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
//				this.resEaiMsg.setRspErrCd(rspErrorCode);
//				this.resEaiMsg.setRspErrMsg(rspErrorMsg);
				this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
				throw new Exception(rspErrorMsg);
			}
		}
	}

	@Override
	public void performSend() throws Exception {
		try {
			String headerActionName = this.reqEaiMsg.getCurrentSvcMsg().getHdrRefClsName();
			String headerContolType = StringUtil.getNullStr(this.reqEaiMsg.getCurrentSvcMsg().getHdrCtrlDstcd());

			if (logger.isDebug()) {
				logger.debug(guidLogPrefix + " Header 로직을 실행합니다.");
				logger.debug(guidLogPrefix + " headerActionName :  [" + headerActionName + "]");
				logger.debug(guidLogPrefix + " 전송 Type :  [" + HeaderActionKeys.MESSAGE_SEND + "]");
				logger.debug(guidLogPrefix + " Header Control Type :  [" + headerContolType + "]");
			}

			HeaderAction action = HeaderActionFactory.createAction(headerActionName);

			if (this.tgtTranObject instanceof byte[]) {
				this.orgData = new byte[((byte[]) this.tgtTranObject).length];
				System.arraycopy(this.tgtTranObject, 0, this.orgData, 0, ((byte[]) this.tgtTranObject).length);

				this.tgtTranObject = action.excute(this.orgData, (byte[]) this.tgtTranObject,
						HeaderActionKeys.MESSAGE_SEND, headerContolType);

				if (logger.isDebug()) {
					logger.debug(guidLogPrefix + " this.orgMessage"
							+ MessageUtil.toAdapterTypeString((byte[]) this.tgtTranObject, this.inboundCharset));
				}

			} else {
				if (logger.isWarn()) {
					logger.warn(guidLogPrefix + " byte[] 만허용됩니다. 업무메시지타입을 확인하세요" + this.tgtTranObject);
				}

			}
			if (logger.isDebug()) {
				logger.debug(guidLogPrefix + " Header 로직을 종료합니다.");
			}
		} catch (Exception e) {
			String[] msgArgs = new String[1];
			msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
			String rspErrorCode = "RECEAIOHP040";
			String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
			if (logger.isError())
				logger.error(guidLogPrefix + rspErrorMsg, e);
//			this.resEaiMsg.setRspErrCd(rspErrorCode);
//			this.resEaiMsg.setRspErrMsg(rspErrorMsg);
			this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
			throw new Exception(rspErrorMsg);
		}
	}

	@Override
	public void performRecv() throws Exception {
		try {
			String headerActionName = this.reqEaiMsg.getCurrentSvcMsg().getHdrRefClsName();
			String headerContolType = StringUtil.getNullStr(this.reqEaiMsg.getCurrentSvcMsg().getHdrCtrlDstcd());

			if (logger.isDebug()) {
				logger.debug(guidLogPrefix + " Header 로직을 실행합니다.");
				logger.debug(guidLogPrefix + " headerActionName :  [" + headerActionName + "]");
				logger.debug(guidLogPrefix + " 전송 Type :  [" + HeaderActionKeys.MESSAGE_RECV + "]");
				logger.debug(guidLogPrefix + " Header Control Type :  [" + headerContolType + "]");
			}

			HeaderAction action = HeaderActionFactory.createAction(headerActionName);
			String bizData = this.resEaiMsg.getStandardMessage().getBizData();

			if (bizData != null && bizData.length() > 0) {
				this.tgtTranObject = bizData;
			}

			if (this.tgtTranObject instanceof byte[]) {
				this.tgtTranObject = action.excute(this.orgData, (byte[]) this.tgtTranObject,
						HeaderActionKeys.MESSAGE_RECV, headerContolType);
				this.resEaiMsg.getStandardMessage().setBizData(tgtTranObject, this.inboundCharset);

				if (logger.isDebug()) {
					logger.debug(guidLogPrefix + " this.tgtTranObject"
							+ MessageUtil.toAdapterTypeString((byte[]) this.tgtTranObject, this.outboundCharset));
				}
			} else {
				if (logger.isWarn()) {
					logger.warn(guidLogPrefix + " byte[] 만허용됩니다. 업무메시지타입을 확인하세요" + this.tgtTranObject);
				}
			}
			if (logger.isDebug()) {
				logger.debug(guidLogPrefix + " Header 로직을 종료합니다.");
			}
		} catch (Exception e) {
			String[] msgArgs = new String[1];
			msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
			String rspErrorCode = "RECEAIOHP040";
			String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
			if (logger.isError())
				logger.error(guidLogPrefix + rspErrorMsg, e);
//			this.resEaiMsg.setRspErrCd(rspErrorCode);
//			this.resEaiMsg.setRspErrMsg(rspErrorMsg);
			this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
			throw new Exception(rspErrorMsg);
		}
	}

	@Override
	public void storeMessage() throws Exception {
		// ----------------------------------------------
		// 비동기-비동기 거래 &&
		// 수동이 표준이 아닌 경우
		// 원거래복원 여부가 '1' 일 경우에
		// ----------------------------------------------
		String recoverYn = getRecoverYn(reqEaiMsg);
		if (logger.isDebug()) {
			logger.debug(guidLogPrefix + "Message 복원 Flag [" + recoverYn + "]");
		}
		if (EAIMessageKeys.ASYNC_SVC.equals(this.reqEaiMsg.getSvcTsmtUsgTp())
				&& !com.eactive.eai.adapter.Keys.IF_STANDARD.equals(this.adptrMsgPtrnCd)
				&& STDMessageKeys.RECOVER_YN_YES.equals(recoverYn)) {

			try {
				String keyMgtMsgCtnt = this.reqEaiMsg.getCurrentSvcMsg().getKeyMgtMsgVl();
				if (logger.isDebug()) {
					logger.debug(guidLogPrefix + "Message 복원 실행 KEY[" + keyMgtMsgCtnt + "]");
				}
				String extBizCd = this.reqEaiMsg.getExtBizCd();
				STDMessageMapper.storeMessageHeader(keyMgtMsgCtnt, this.reqEaiMsg.getStandardMessage(), extBizCd,
						this.inAdapterMsgType);
			} catch (Exception e) {
				if (logger.isError()) {
					logger.error(guidLogPrefix + "Message 저장 중 에러 발생", e);
				}

				String[] msgArgs = new String[1];
				msgArgs[0] = this.reqEaiMsg.getEAISvcCd();
				String rspErrorCode = "RECEAIOSP011";
				String rspErrorMsg = ExceptionUtil.make(e, rspErrorCode, msgArgs);
				if (logger.isError())
					logger.error(guidLogPrefix + rspErrorMsg, e);
//				this.resEaiMsg.setRspErrCd(rspErrorCode);
//				this.resEaiMsg.setRspErrMsg(rspErrorMsg);
				this.resEaiMsg.setRspErr(rspErrorCode,rspErrorMsg);
				throw new RuntimeException(rspErrorCode);
			}
		}
		// ---------------------------------------------------------------------
	}

	@Override
	public void getBizMessage() throws Exception {
		// setRcvLogInfo() 에서 이미 호출됨
	}

	@Override
	public void waitCheckForSync() throws Exception {
		/**
		 * Sync - Sync 거래중 Wait 메시지가 올경우 대비
		 *
		 * Async -Sync 는 Flow Control에서 처리 함
		 */
		if (com.eactive.eai.adapter.Keys.IF_STANDARD.equals(this.adptrMsgPtrnCd) && resObject != null) {
			if (EAIMessageKeys.SYNC_SVC.equals(this.reqEaiMsg.getSvcTsmtUsgTp())) {
				StandardMessage standardMessage = null;
				StandardMessageManager standardManager = StandardMessageManager.getInstance();
				StandardReader reader = null;
				try {
					standardMessage = standardManager.getStandardMessage();
					reader = standardManager.getReader(this.adptrMsgType);
					reader.parse(standardMessage, resObject);
					// 표준 전문 파싱 후 어댑터의 charset을 설정한다.
					standardMessage.setBizDataCharset(outboundCharset);
				} catch (Exception e) {
					logger.error("standardMessage parsing error " + e.getMessage(), e);
					return;
				}
				boolean isWait = standardManager.getMessageCoordinator().coordinateIsWaitCheckForSync(standardMessage);
				if (isWait) {
					getTopicProperty();
					try {
						// SA 응답 메시지 설정
						setTopicResult();
					} catch (Exception e) {
						// Timeout
						executeTimeout();
					}
				}
			}
		}
	}

	@Override
	public void transControlHeaderTrnsformSinglesRes() throws Exception {
	}
}
