//package com.eactive.eai.adapter.socket.service;
//
//import java.io.IOException;
//import java.net.Socket;
//import java.nio.BufferOverflowException;
//import java.nio.ByteBuffer;
//import java.nio.channels.ClosedSelectorException;
//import java.nio.channels.SelectionKey;
//import java.nio.channels.Selector;
//import java.nio.channels.SocketChannel;
//import java.util.Iterator;
//
//import com.eactive.eai.adapter.socket.common.CommonLib;
//import com.eactive.eai.adapter.socket.common.DiagLogger;
//import com.eactive.eai.adapter.socket.common.SocketAdapterException;
//import com.eactive.eai.adapter.socket.config.ConfigurationContext;
//import com.eactive.eai.adapter.socket.config.SocketAdapterManager;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//
//public class ReaderServer extends Thread implements SocketService {
//
//	private	ConfigurationContext	context;
//	private SocketChannel 			socketChannel;
//	private SocketServer 			proxy;
//	private Selector                selector;
//    private SelectionKey            key;
//
//    private boolean					active;
//
//    // 상태정보
//	private int					 	sendCount;
//	private int					 	recvCount;
//    private long				 	firstActivity;
//    private long				 	lastActivity;
//
//    // IO BUFFER
//    private ByteBuffer              incomingMessage;
//    private ByteBuffer              lenBuffer;
//
//    // pending message for checking operation
//    private ByteBuffer              pendingMessage;
//    // Logger
//    private Logger                  logger;
//    private static Logger           errLogger = SocketLogManager.getInstance().getErrLogger();
//    private WriterServer            writer;
//    private boolean                 shutdownFlag;
//    private String                  remoteIPAddress;
//
//    public ReaderServer(ConfigurationContext context, SocketChannel socketChannel, SocketServer proxy) {
//        String name = this.getName();
//        this.setName( context.getAdapterName() + "-CONNECTION-READER" + name.substring( name.lastIndexOf("-")) );
//
//    	this.context 		= context;
//    	this.socketChannel 	= socketChannel;
//    	this.proxy 			= proxy;
//        this.writer         = null;
//
//    	sendCount			= 0;
//        recvCount			= 0;
//        firstActivity		= System.currentTimeMillis();
//        lastActivity		= System.currentTimeMillis();
//
//		incomingMessage     = null;
//
//		lenBuffer           = ByteBuffer.allocate( this.context.getLlFieldLength() );
//		lenBuffer.clear();
//
//        pendingMessage      = ByteBuffer.allocate( 4096 );
//        pendingMessage.clear();
//
//        logger              = SocketLogManager.getInstance().getLogger( context.getAdapterGroupName());
//
//        remoteIPAddress     = this.socketChannel.socket().getInetAddress().getHostAddress();
//        active              = true;
//        shutdownFlag        = false;
//    }
//
////    private boolean isSyncMode() {
////    	return this.context.isSyncMode();
////    }
////
////    private boolean isAckProtocol() {
////    	return this.context.isAckProtocol();
////    }
//
//    private long getTimeout() {
//    	return	( this.context.getTimeout() * 1000L );
//    }
//
////    private boolean isSocketReuse() {
////    	return this.context.getSocketReuse().equals( ConfigurationContext.TRUE_FLAG );
////	}
//
//    private int getTraceLevel() {
//    	return context.getTraceLevel();
//    }
//	/**
//	 * @return Returns the context.
//	 */
//	public ConfigurationContext getContext() {
//		return context;
//	}
//
//    public String getRemoteIPAddress() {
//        return this.remoteIPAddress;
//    }
//
//    public void run() {
//    	SocketAdapterManager.getInstance().addConnection( this );
//    	String  socketInfo = this.getSocketInfo(this.socketChannel);
//
//        if ( getTraceLevel() >= DiagLogger.INFO ) {
//            logger.info( CommonLib.getMessage("BICEAIASI002", new String[]{ context.getAdapterName(), socketInfo , Thread.currentThread().getName() }) );
//        }
//
//    	try {
//            openSelector();
//        } catch(IOException e) {
//            String errMsg = CommonLib.getMessage("BECEAIASI002", new String[]{context.getAdapterName(), "openSelector", e.getMessage(), "", "" } );
//            logger.error( errMsg, e );
//        	active = false;
//        }
//
//
////        Iterator        iterator;
//        if ( active ) {
//            try {
//                writer = new WriterServer( this.context, this.socketChannel, this, this.selector );
//                writer.start();
//            } catch( Exception e ) { }
//        }
//
//        long    start = System.currentTimeMillis();
//
//        while( active ) {
//            try {
//                int selected = selector.select( 1000L );
//                if( selected == 0 ) {
//                    long waitTime = System.currentTimeMillis() - start;
//                	if ( lenBuffer.position() > 0 && waitTime >= getTimeout() ) {
//                        String errMsg = CommonLib.getMessage("BECEAIASI006", new String[]{context.getAdapterName(), socketInfo, Long.toString(getTimeout()), "수신", getReadingMessage()  });
//                        logger.error( errMsg );
//                        if ( logger != errLogger ) {
//                            errLogger.error( errMsg );
//                        }
//                    	active = false;
//                	} else if ( lenBuffer.position() > 0 ){
//                        active = isConnected();
//                    } else if ( shutdownFlag && lenBuffer.position() == 0 ) {
//                        active = false;
//                    }
//                    continue;
//                }
//                //* 2005.10.17
//                if ( shutdownFlag && lenBuffer.position() == 0 ) {
//                    active = false;
//                    continue;
//                }
//            } catch(IOException e) {
//                if ( lenBuffer.position() > 0 ) {
//                    String errMsg = CommonLib.getMessage("BECEAIASI002", new String[]{context.getAdapterName(), "select", e.getMessage(), "수신메시지", getReadingMessage() } );
//                    logger.error( errMsg , e);
//                    if ( logger != errLogger ) {
//                        errLogger.error( errMsg, e );
//                    }
//                }
//                active = false;
//            } catch(ClosedSelectorException e ) {
//            	continue;
//            } catch(Exception e) {}
//
//            if ( selector == null || !selector.isOpen() ) continue;
//
//            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
//
//            while( iterator.hasNext() ) {
//                key    = iterator.next();
//                iterator.remove();
//                socketChannel   = (SocketChannel)key.channel();
//                if(key.isReadable()) {   	// is Readable ? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
//                    try {
//                        start   = System.currentTimeMillis();
//                        if( processReadMessage() ) {    	    // Read Done
//                            byte[]	message  = incomingMessage.array();
//
//                            if ( getTraceLevel() >= DiagLogger.DEBUG ) {
//                                logger.debug( CommonLib.getMessage("BDCEAIASI001", new String[]{context.getAdapterName(), "RECV", CommonLib.getTimestamp(), socketInfo, CommonLib.getDumpMessage(incomingMessage.array())}));
//                            }
//                            this.checkActivity();
//                            lastActivity	= System.currentTimeMillis();
//                			recvCount++;
//
//                            incomingMessage.clear();
//                            lenBuffer.clear();
//
//                            InboundControl	control = new InboundControl( context.getAdapterGroupName(), context.getAdapterName(), getTimeout() );
//                            control.setRequest( message );
//                            control.setResponseType( context.getResponseType() );
//
////                            byte[] rtnValue = null;
//
//                            try {
//                                control.request();
//                            } catch( Exception e ) {
////                                rtnValue = e.getMessage().getBytes();
//                                logger.error( e.getMessage(), e );
//                                logger.error( CommonLib.getMessage("BDCEAIASI001", new String[]{context.getAdapterName(), "RECV", CommonLib.getTimestamp(), socketInfo,CommonLib.getDumpMessage( control.getRequest() )}));
//                                if ( logger != errLogger ) {
//                                    errLogger.error( e.getMessage(), e );
//                                    errLogger.error( CommonLib.getMessage("BDCEAIASI001", new String[]{context.getAdapterName(), "RECV", CommonLib.getTimestamp(), socketInfo, CommonLib.getDumpMessage( control.getRequest() )}));
//                                }
//                            }
//
//                            start   = System.currentTimeMillis();
//
//                            socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
//
//                            if ( shutdownFlag ) active = false;
//                        }
//                    } catch(Exception e) {
//                        if ( lenBuffer.position() > 0 ) {
//                            String errMsg = CommonLib.getMessage("BECEAIASI002", new String[]{context.getAdapterName(), "processReadMessage", e.getMessage(), "수신메시지", getReadingMessage() } );
//                            logger.error( errMsg , e);
//                            if ( logger != errLogger ) {
//                                errLogger.error( errMsg, e );
//                            }
//                        }
//                        active = false;
//
//                    } finally {
//                        if(!active) continue;
//                    }
//                } // end of readable...
//            } // End of while(iterator.hasNext())
//        } // enf of while - active
//
//        try {
//            try {
//                if ( writer != null ) {
//                    writer.shutdown();
//                }
//            } catch( Throwable e ) {}
//            closeSelector();
//        } catch(Throwable e) {}
//
//        SocketAdapterManager.getInstance().removeConnection( this );
//
//        if ( getTraceLevel() >= DiagLogger.INFO ) {
//            logger.info( CommonLib.getMessage("BICEAIASI003", new String[]{ context.getAdapterName(), socketInfo, Thread.currentThread().getName() }) );
//        }
//
//        proxy.quiesceShutdown(this);
//
//        interrupt();
//
//    }
//
//    private String  getReadingMessage() {
//        String rMsg = "";
//        if ( incomingMessage != null && incomingMessage.position() > 0 ) {
//            byte[] dMsg = new byte[ incomingMessage.position() ];
//            System.arraycopy( incomingMessage.array(), 0, dMsg, 0, dMsg.length );
//            rMsg = CommonLib.getDumpMessage( dMsg );
//        }
//        return rMsg;
//    }
//
//    private String  getSocketInfo(SocketChannel channel) {
//        StringBuffer connInfo = new StringBuffer();
//
//        connInfo.append("Local Address=");
//        connInfo.append( channel.socket().getLocalAddress().getHostAddress()).append(":").append(channel.socket().getLocalPort()).append(", ");
//        connInfo.append("Remote Address=");
//        connInfo.append( channel.socket().getInetAddress().getHostAddress()).append(":").append(channel.socket().getPort());
//
//        return connInfo.toString();
//    }
//
//    public boolean idle(long timeout) {
//        long idleTime   = System.currentTimeMillis() - this.lastActivity;
//        return ( idleTime > timeout );
//    }
//
//    public void addSendCount() {
//        this.sendCount++;
//    }
//
//    public void setLastActivity(long lastAccess) {
//        this.lastActivity = lastAccess;
//    }
//
//    public void shutdownWriter() {
//        shutdown();
//        writer = null;
//    }
//
//    public boolean isActive() {
//        return shutdownFlag;
//    }
//
//    public synchronized void shutdown() {
//        //* 2005.10.17
//        active          = false;
//        shutdownFlag    = true;
//
//        try {
//            notify();
//        } catch( Exception e ) {}
//
//         try {
//            if ( selector != null && selector.isOpen() ) {
//                selector.wakeup();
//            }
//        } catch (Throwable e) {}
//
//        //* to gracefully shutdown the thread
//        //* 2005.10.17
//        //try {
//        //    writer.shutdown();
//        //} catch( Exception e ) {}
//
//        try {
//            closeSelector();
//        } catch( Exception e ) {}
//        //*/
//        //interrupt();
//    }
//
//    public Socket getCurrentSocket() {
//    	return socketChannel.socket();
//    }
//
//    public boolean connect() {
//    	return true;
//    }
//
//    public void disconnect() {
//    	shutdown();
//        proxy.quiesceShutdown(this);
//    }
//
//    private void openSelector() throws IOException {
//
//    	if ( selector == null || !selector.isOpen() ) {
//    		selector = Selector.open();
//            // Connection 시 통계자료 RESET
//            this.firstActivity  = System.currentTimeMillis();
//            this.lastActivity   = this.firstActivity;
//            this.sendCount      = 0;
//            this.recvCount      = 0;
//
//            socketChannel.socket().setTcpNoDelay(true);
//            socketChannel.configureBlocking(false);
//            socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE );
//    	}
//
//    }
//
//    private void closeSelector() throws IOException {
//        if(selector != null) {
//            selector.wakeup();
//
//            for(Iterator<SelectionKey> iterator = selector.keys().iterator(); iterator.hasNext();) {
//                try {
//                    key    = iterator.next();
//                    iterator.remove();
//                    socketChannel   = (SocketChannel)key.channel();
//                    key.cancel();
//                    if(socketChannel != null) {
//                        Socket socket = socketChannel.socket();
//                        if(socket != null) {
//                            socket.setSoLinger(false, 0);
//                            try { socket.close(); } catch(Exception e) {}
//                        }
//                        socketChannel.close();
//                    }
//                } catch(IOException ioexception) { }
//            }
//            selector.close();
//        }
//        selector = null;
//    }
//
//    public void setControl(Object control) {
//    }
//
//    public void notifyMessage() {
//    }
//
//
//    private boolean processReadMessage() throws Exception {
//
//        int     i = 0;
//        boolean flag = false;
//
//        if ( pendingMessage.position() > 0 && lenBuffer.hasRemaining() ) {
//            if ( pendingMessage.position() <= lenBuffer.remaining() ) {
//                byte[] data = new byte[ pendingMessage.position() ];
//                pendingMessage.flip();
//                pendingMessage.get( data );
//                lenBuffer.put( data );
//                pendingMessage.clear();
//            } else {
//                byte[] data = new byte[ lenBuffer.remaining() ];
//                pendingMessage.flip();
//                pendingMessage.get( data );
//                lenBuffer.put( data );
//                pendingMessage.position( pendingMessage.limit() );
//                shiftBuffer( pendingMessage, data.length );
//            }
//            if ( lenBuffer.position() == lenBuffer.capacity() ) flag = true;
//        }
//
//        while ( lenBuffer.position() < lenBuffer.capacity() ) {
//            i = socketChannel.read( lenBuffer );
//            if ( i <= 0 ) break;
//            if ( lenBuffer.position() == lenBuffer.capacity() ) flag = true;
//        }
//
//        if(i == -1) {
//            if ( lenBuffer.position() > 0 ) {
//                throw new SocketAdapterException( CommonLib.getMessage("BECEAIASI003", new String[]{context.getAdapterName(), getSocketInfo(this.socketChannel)}) );
//            } else {
//                String errMsg = CommonLib.getMessage("BICEAIASI004", new String[]{context.getAdapterName(), getSocketInfo(this.socketChannel)});
//                if(logger.isInfoEnabled()){
//                    logger.info( errMsg );
//                }
//                throw new SocketAdapterException( errMsg  );
//            }
//        }
//
//        if ( lenBuffer.position() != lenBuffer.capacity() )     return false;
//
//        int length = 0;
//
//        try {
//            if ( flag ) {
//                length = checkLengthField( lenBuffer );
//                incomingMessage = ByteBuffer.allocate( length );
//                incomingMessage.clear();
//            }
//        } catch(Exception le) {
//            throw le;
//        }
//
//        i = 0;
//
//        if ( pendingMessage.position() > 0 && incomingMessage.hasRemaining()) {
//            if ( pendingMessage.position() <= incomingMessage.remaining() ) {
//                byte[] data = new byte[ pendingMessage.position() ];
//                pendingMessage.flip();
//                pendingMessage.get( data );
//                incomingMessage.put( data );
//                pendingMessage.clear();
//            } else {
//                byte[] data = new byte[ incomingMessage.remaining() ];
//                pendingMessage.flip();
//                pendingMessage.get( data );
//                lenBuffer.put( data );
//                pendingMessage.position( pendingMessage.limit() );
//                shiftBuffer( pendingMessage, data.length );
//            }
//            if ( incomingMessage.position() == incomingMessage.capacity() ) return true;
//        }
//
//        while ( incomingMessage.position() < incomingMessage.capacity()) {
//            i = socketChannel.read(incomingMessage);
//            if ( i <= 0 ) break;
//        }
//
//        if(i == -1) {
//            throw new SocketAdapterException( CommonLib.getMessage("BECEAIASI003", new String[]{context.getAdapterName(), getSocketInfo(this.socketChannel)}) );
//        } else {
//            if ( incomingMessage.position() == incomingMessage.capacity() ) {
//                return true;
//            } else {
//                return false;
//            }
//        }
//    }
//
//    private void shiftBuffer(ByteBuffer buffer, int shiftBytes) {
//        int pos = buffer.position();
//        if ( pos <= shiftBytes ) {
//            buffer.clear();
//            return;
//        }
//        byte[] tmpBuff = new byte[ pos ];
//        buffer.flip();
//        buffer.get( tmpBuff );
//
//        buffer.clear();
//        buffer.put( tmpBuff, shiftBytes, tmpBuff.length - shiftBytes );
//    }
//
//    // Writing전에 확인...
//    public boolean isConnected() throws IOException {
//    	boolean	flag = true;
//
//    	if ( socketChannel.isConnected() && socketChannel.socket().isBound() ) {
//    		ByteBuffer tmpBuffer = ByteBuffer.allocate( 1 );
//            tmpBuffer.clear();
//    		int i = socketChannel.read( tmpBuffer );
//            if ( i > 0 ) {
//                try {
//                    pendingMessage.put( tmpBuffer );
//                } catch ( BufferOverflowException e ) {
//                    throw new IOException("Socket 어플리케이션 프로토콜에러 발생 : " + e.getMessage());
//                }
//            }
//    		if ( i == -1 ) {
//    			flag = false;
//    		}
//    	} else {
//    		flag = false;
//    	}
//
//    	return flag;
//    }
//
//    public int getCurrentState() {
//        return CommonLib.PROCESSING_PROTOCOL;
//    }
//
//    private void resetCount() {
//        this.recvCount = 0;
//        this.sendCount = 0;
//    }
//
//    public void checkActivity() {
//        long currentTime = System.currentTimeMillis();
//        if ( !CommonLib.getDate( this.lastActivity ).equals( CommonLib.getDate( currentTime )) ) {
//            this.resetCount();
//        }
//    }
//
//    private int checkLengthField(ByteBuffer buffer) throws SocketAdapterException {
//    	int length = 0;
//
//    	if ( buffer.capacity() == 2 ) {
//    		length = ( buffer.getShort(0) & 0xFFFF );
//    	} else if ( buffer.capacity() == 4 ) {
//    		length = ( buffer.getInt(0) );
//            if ( length < 0 ) {
//    			throw new SocketAdapterException( CommonLib.getMessage("BECEAIASI009", new String[]{context.getAdapterName(), getSocketInfo(this.socketChannel), CommonLib.byte2Hex( buffer.array() ) }) );
//            }
//    	} else {
//    		String lenStr = new String( buffer.array() );
//    		try {
//    			length = Integer.parseInt( lenStr );
//    		} catch ( NumberFormatException e ) {
//    			throw new SocketAdapterException( CommonLib.getMessage("BECEAIASI009", new String[]{context.getAdapterName(), getSocketInfo(this.socketChannel), CommonLib.byte2Hex( buffer.array() ) }) );
//    		}
//    	}
//    	return length;
//    }
//
//    /**
//	 * @return Returns the socketchannel.
//	 */
//	public SocketChannel getSocketchannel() {
//		return socketChannel;
//	}
//	/**
//	 * @param socketchannel The socketchannel to set.
//	 */
//	public void setSocketchannel(SocketChannel socketchannel) {
//		this.socketChannel = socketchannel;
//	}
//
//    // 1. Connection 리스트정보 - AdapterGroupName,AdapterName,업무코드,INBOUND, CLIENT, LocalIP:Port, RemoteIP:Port, 송신건수, 수신건수, 상태, 최초연결시각, 최종사용시각
//    public String toString() {
//        boolean status = true;
//        StringBuffer strBuff = new StringBuffer();
//        strBuff.append(context.getAdapterGroupName()).append(",");
//        strBuff.append(context.getAdapterName()).append(",");
//        strBuff.append(context.getBwkClsCd()).append(",").append(context.getBoundUsage()).append(",");
//        strBuff.append(context.getSocketType()).append(",");
//        strBuff.append(context.getResponseType()).append(",");
//        try {
//            strBuff.append( getCurrentSocket().getLocalAddress().getHostAddress()).append(":").append(getCurrentSocket().getLocalPort()).append(",");
//        } catch( Throwable e ) {
//            status = false;
//            strBuff.append("?:?,");
//        }
//
//        try {
//            strBuff.append( getCurrentSocket().getInetAddress().getHostAddress()).append(":").append(getCurrentSocket().getPort()).append(",");
//        } catch( Throwable e ) {
//            status = false;
//            strBuff.append("?:?,");
//        }
//        strBuff.append(this.sendCount).append(",");
//        strBuff.append(this.recvCount).append(",");
//        strBuff.append( status ).append(",");
//        strBuff.append( CommonLib.getCurrentTime( this.firstActivity )).append(",");
//        strBuff.append(CommonLib.getCurrentTime( this.lastActivity ));
//
//        return strBuff.toString();
//    }
//    
//    public void setLastActivity() {
//    }
//
//    public long getFirstActivity() {
//        return firstActivity;
//    }
//
//    public long getLastActivity() {
//        return lastActivity;
//    }
//}
