
package com.eactive.eai.adapter.http.client.impl;

import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.util.Properties;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;

import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.http.HttpMemoryLogger;
import com.eactive.eai.adapter.http.HttpStatusException;
import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceSupport;
import com.eactive.eai.adapter.http.client.HttpClientAdapterVO;
import com.eactive.eai.adapter.http.secure.CustomHttpsSocketFactory;
import com.eactive.eai.adapter.http.secure.EasySSLProtocolSocketFactory;
import com.eactive.eai.common.exception.ExceptionUtil;
import com.eactive.eai.common.util.CommonLib;
import com.eactive.eai.common.util.MessageUtil;


/** 
* 1. 기능 : EAI HTTP OutBound 용 어댑터로 수동 시스템의 HTTP 웹 컴포넌트를 
*           GET/POST 방식으로 호출할 수 있는 기능을 제공한다.
* 2. 처리 개요 : 
* *     - 2009.11.24 retry 로직 제거  : 요청
* 3. 주의사항 
*
* @author  : 
* @version : v 1.0.0
* @see : WLIAdapterFactory.java, WLIAdapter.java, WLIDefaultAdapter.java
* @since   : 

*/
public class HttpClientAdapterServicePost extends HttpClientAdapterServiceSupport{ 
    
    /** 
    * 1. 기능 :  전문과 같은 Raw Data 통신에 사용
    * 2. 처리 개요 : 
    *     - 속성 정보를 설정 하고 수동 시스템 서비스를 호출 한다.
    * 3. 주의사항 
    *
    * @param    prop    Http Adapter 속성 정보
    * @param    message 송신 전문
    * @return   반환 된 byte[] Object
    * @exception    Exception 수동 시스템 간 통신 중 발생
    **/
    public Object execute(Properties prop, Object data, Properties tempProp) throws Exception
    {
    	HttpClientAdapterVO vo = super.setting(prop, tempProp);
        boolean isAsync = false;
        
        PostMethod method = new PostMethod(vo.getUrl());
        HttpClient mclient = this.client;

        configureHttpClient(mclient, method, vo, vo.getUrl(), vo.getContentType());
        
        String sendData = "";
		if (data instanceof String) {
			sendData = (String) data;
		} else if (data instanceof byte[]) {
			sendData = new String((byte[]) data, vo.getEncode());
		}
		
		mclient.getParams().setContentCharset(vo.getEncode());
        
        if ("Y".equals(vo.getUrlEncodeYn())){
        	sendData = java.net.URLEncoder.encode(sendData);
        }
        
        if(RESPONSE_TYPE_ASYNC.equals(vo.getResponseType())) {
        	isAsync = true;
        	method.addParameter("type", "async");
        }
        
        method.addParameter(vo.getParameterName(), sendData);
        
        String contentTypeValue = null;
        if(StringUtils.isNotEmpty(vo.getContentType())) {
        	if(StringUtils.isNotEmpty(vo.getEncode())) {
        		contentTypeValue = vo.getContentType() +"; charset=" + vo.getEncode();        		
        	}
        	else {
        		contentTypeValue = vo.getContentType();
        	}
        	method.setRequestHeader(CONTENT_TYPE_KEY, contentTypeValue);
        }
        if (vo.getAdapterHeaders() != null){
        	for(String key : vo.getAdapterHeaders().keySet()){
        		method.addRequestHeader(key,  vo.getAdapterHeaders().get(key));
        	}
        }
        if(logger.isInfoEnabled()) {
        	logger.info("HttpClientAdapterServicePost] "+CONTENT_TYPE_KEY+"("+contentTypeValue+")");
        }
        
        int status = -1;
        
        try {
    
            if(logger.isDebug() && "N".equals(vo.getTestCallYn())){
                logger.debug("HttpClientAdapterServicePost] SEND ("+vo.getAdapterGroupName()+") = ["+sendData+"]");
                logger.debug("HttpClientAdapterServicePost] SEND ("+vo.getAdapterGroupName()+") = "+CommonLib.getDumpMessage(sendData));
            }            
    		StopWatch stopWatch = new StopWatch();
    		stopWatch.start();
    		
    		if (vo.getTraceLevel() >= 3){
    			HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(), "SEND ["+sendData+"]"+CommonLib.getDumpMessage(sendData));
    		}    
			if (vo.getUrl() != null && vo.getUrl().startsWith("https")) {
				Protocol.registerProtocol("https",
						new Protocol("https", new CustomHttpsSocketFactory(new EasySSLProtocolSocketFactory()), 443));
			}
    		status = mclient.executeMethod(method);

            stopWatch.stop();
            
            String responseCharSet = getResponseCharSet(method.getResponseCharSet(),vo.getAdapterGroupName());
            
            //status 200(정상) 이외에는 error 처리 
            if (status !=200){
            	try{
            		logger.error("HttpClientAdapterServicePost] receive status["+status+"] data[" + new String(method.getResponseBody()) +"]");
            	}catch(Exception e){
            		logger.error(e);
            	}
               	throw new HttpStatusException("수신시스템을 확인하세요. HTTP 에러[ " + status + "] adapterName="+vo.getAdapterGroupName()+"."+vo.getAdapterName(),status);
            }
            
            byte[] responseMessage = method.getResponseBody();
            if (isAsync && stopWatch.getTime() > vo.getSlowTranTime()) {
        		if (logger.isWarn()){
        			logger.warn("HttpClientAdapterServicePost] URL[" + vo.getUrl() + "] lazy response time = " + stopWatch.toString()+ " responseMessage=" + new String(responseMessage,responseCharSet));
        		}
        	}            
            responseMessage = getEncodingConvert(responseCharSet, vo.getAdapterGroupName(), responseMessage);
//            if(vo.getEncode() != null && vo.getEncode().length() > 0) {
//            	Charset res = null;
//            	Charset adpt = null;
//            	byte[] orgResponse = method.getResponseBody();
//            	try{
//            		res = Charset.forName(responseCharSet);
//            		adpt = Charset.forName(vo.getEncode());
//            		if (res.compareTo(adpt)==0){
//            			responseMessage = orgResponse;
//            		}else{
//            			String encodingString = new String(orgResponse, responseCharSet);
//            			responseMessage = encodingString.getBytes(vo.getEncode()); 
//            		}
//            	}catch(UnsupportedCharsetException e){
//            		responseMessage =  orgResponse;
//            	}
//            }
//            else {
//            	responseMessage = method.getResponseBody();
//            }
            //----------------------------------------------------------
        

            
            if (logger.isDebug() && "N".equals(vo.getTestCallYn())){
            	logger.debug("HttpClientAdapterServicePost] responseType ="+ vo.getResponseType());
                logger.debug("HttpClientAdapterServicePost] RECV ("+vo.getAdapterGroupName()+") = ["+new String(responseMessage,responseCharSet)+"]");
                logger.debug("HttpClientAdapterServicePost] RECV ("+vo.getAdapterGroupName()+") = "+CommonLib.getDumpMessage(responseMessage));
            }
            
    		if (vo.getTraceLevel() >= 3){
    			HttpMemoryLogger.txlog(vo.getAdapterGroupName()+vo.getAdapterName(), "RECV ["+new String(responseMessage,responseCharSet)+"]"+CommonLib.getDumpMessage(responseMessage));
    		}              
            
    		AdapterManager m = AdapterManager.getInstance();
	    	AdapterGroupVO agvo= m.getAdapterGroupVO(vo.getAdapterGroupName());
    		if (MessageUtil.isBytesMessage(agvo.getMessageType())) {
    			return responseMessage;
    		} else {
    			return new String(responseMessage, vo.getEncode());
    		}
        } catch(SocketTimeoutException ste) { // Read Timeout :: HttpClient 3.1일 경우
    		if (vo.getTraceLevel() >= 3){
    			HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServicePost] SocketTimeoutException : " + ste.toString() ,ste);
    		}        	
            if (logger.isError()){
            	logger.error("HttpClientAdapterServicePost] SocketTimeoutException : " + ste.toString() ,ste);
            }
            throw ste;
        } catch(ConnectException ce) {
    		if (vo.getTraceLevel() >= 3){
    			HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServicePost] Connection Exception : " + ce.toString() ,ce);
    		}        	
            if (logger.isError()){
            	logger.error("HttpClientAdapterServicePost] Connection Exception : " + ce.toString() ,ce);
            }
            throw ce;
        } catch(Exception e) {
    		if (vo.getTraceLevel() >= 3){
    			HttpMemoryLogger.error(vo.getAdapterGroupName()+vo.getAdapterName(),"HttpClientAdapterServicePost] Exception : " + e.toString() ,e);
    		}        	
            if (logger.isError()){
            	logger.error("HttpClientAdapterServicePost] Exception : " + e.toString() ,e);
            }
            throw e;
        } finally {
            method.releaseConnection();
            if(status != HttpStatus.SC_OK) {
                String[] msgArgs = new String[1];
                msgArgs[0] = String.valueOf(status);
                String resMsg = ExceptionUtil.make("RDCEAIAHA013", msgArgs);
                if(logger.isDebug()){
                    logger.debug(resMsg);
                }
            }
        }
   
    }
    

} 
