//package com.eactive.eai.adapter.socket.service;
//
//import java.io.IOException;
//import java.net.Socket;
//import java.nio.ByteBuffer;
//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 org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//
//public class WriterServer extends Thread implements SocketService {
//
//	private	ConfigurationContext	context;
//	private SocketChannel 			socketChannel;
//	private ReaderServer 			proxy;
//
//    private boolean					active;
//
//    private ByteBuffer              outgoingMessage;
//
//    private ByteBuffer              lenBuffer;
//
//    private Exception 				lastError;
//    private Logger                  logger;
//    private Selector                selector;
//    private static Logger           errLogger = SocketLogManager.getInstance().getErrLogger();
//
//	private OutboundControl         control;
//    private boolean                 shutdownFlag;
//
//    public WriterServer(ConfigurationContext context, SocketChannel socketChannel, ReaderServer proxy, Selector selector ) throws IOException {
//        String name = this.getName();
//    	this.setName( context.getAdapterName() + "-CONNECTION-WRITER" + name.substring( name.lastIndexOf("-")) );
//
//    	this.context 		= context;
//    	this.socketChannel 	= socketChannel;
//    	this.proxy 			= proxy;
//
//        this.selector       = selector;
//        socketChannel.register( this.selector, SelectionKey.OP_WRITE | SelectionKey.OP_WRITE );
//
//        outgoingMessage     = null;
//        lenBuffer 			= ByteBuffer.allocate( this.context.getLlFieldLength() );
//		lenBuffer.clear();
//
//    	this.control        = null;
//
//		active              = true;
//        shutdownFlag        = false;
//        logger              = SocketLogManager.getInstance().getLogger( this.context.getAdapterGroupName());
//    }
//
////    private boolean isSyncMode() {
////    	return this.context.isSyncMode();
////    }
//
//    private int getTraceLevel() {
//    	return context.getTraceLevel();
//    }
//
//    private long getTimeout() {
//    	return	( this.context.getTimeout() * 1000L );
//    }
//
//    private boolean isSocketReuse() {
//    	return this.context.getSocketReuse().equals( ConfigurationContext.TRUE_FLAG );
//	}
//
//	/**
//	 * @return Returns the context.
//	 */
//	public ConfigurationContext getContext() {
//		return context;
//	}
//
//    public void run() {
//
//        OutboundChannelManager.getInstance().addConnection(context.getAdapterGroupName(), this);
//        String  socketInfo = this.getSocketInfo(this.socketChannel);
//
//        if ( getTraceLevel() >= DiagLogger.INFO ) {
//            logger.info( CommonLib.getMessage("BICEAIASO001", new String[]{ context.getAdapterName(), socketInfo , Thread.currentThread().getName() }) );
//        }
//
//        while ( active ) {
//            try {
//
//            	openSelector();
//
//                onMessage();
//
//            	if ( control == null ) continue;
//
//            	doRequest();
//
//                if ( shutdownFlag ) active = false;
//
//                if ( !isSocketReuse() ) {
//                    active = false;
//                }
//            } catch (Exception e) {
//                String errMsg = CommonLib.getMessage("BECEAIASO001", new String[]{context.getAdapterName(), "openSelector", e.getMessage(), "", "" } );
//                logger.error( errMsg, e );
//                active = false;
//                continue;
//            }
//        }
//
//        try {
//            closeSelector();
//        } catch(IOException e) { }
//
//        OutboundChannelManager.getInstance().removeConnection( context.getAdapterGroupName(), this);
//
//        if ( getTraceLevel() >= DiagLogger.INFO ) {
//            logger.info( CommonLib.getMessage("BICEAIASO002", new String[]{ context.getAdapterName(), socketInfo, Thread.currentThread().getName() }) );
//        }
//
//        if ( !shutdownFlag ) {
//            proxy.shutdownWriter();
//        }
//        interrupt();
//    }
//
//    private String  getWritingMessage() {
//        String rMsg = "";
//        if ( outgoingMessage != null ) {
//            byte[] debugMsg = new byte[ outgoingMessage.capacity() - lenBuffer.capacity() ];
//            System.arraycopy( outgoingMessage.array(), lenBuffer.capacity(), debugMsg, 0, debugMsg.length );
//            rMsg = CommonLib.getDumpMessage( debugMsg );
//        }
//        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();
//    }
//
//
//    private synchronized void onMessage() {
//    	try {
//            this.wait( );
//    		this.lastError = null;
//    	} catch ( InterruptedException ie ) {
//        }
//    }
//
//    public void wakeup() {
//    	this.control.setLastError( this.lastError );
//        this.control.wakeup();
//        this.control = null;
//        if ( active ) {
//            OutboundChannelManager.getInstance().addConnection(context.getAdapterGroupName(), this );
//        }
//    }
//
//    public synchronized void notifyMessage() {
//        this.notify();
//    }
//
//    public synchronized void setControl(Object control) {
//        this.control    = (OutboundControl) control;
//    }
//
//    public void doRequest() {
//
////    	Iterator        iterator;
//
//    	makeFormat( this.control.getRequest() );
//
//    	boolean isDone = false;
//
//    	this.checkActivity();
//    	proxy.setLastActivity( System.currentTimeMillis() );
////        long start = System.currentTimeMillis();
//
//        while( !isDone ) {
//            /**
//             * Write the message to the target
//             */
//            try {
//                if( processWriteMessage() ) {
//
//                    proxy.addSendCount();
//
//                    if ( getTraceLevel() >= DiagLogger.DEBUG) {
//                        logger.debug( CommonLib.getMessage("BDCEAIASO001", new String[]{context.getAdapterName(), "SEND", CommonLib.getTimestamp(), getSocketInfo(this.socketChannel), getWritingMessage()}));
//                    }
//                    wakeup();
//                    return;
//                }
//            } catch(Exception e) {
//                String errMsg = CommonLib.getMessage("BECEAIASO001", new String[]{context.getAdapterName(), "processWriteMessage", e.getMessage(), "송신메시지", getWritingMessage() } );
//                logger.error( errMsg , e);
//                if ( logger != errLogger ) {
//                    errLogger.error( errMsg, e );
//                }
//                lastError = new SocketAdapterException( errMsg );
//
//                active = false;
//                wakeup();
//                return;
//            }
//        } // enf of while - isDone
//    }
//
//    public int getCurrentState() {
//        return proxy.getCurrentState();
//    }
//
////    private void resetCount() {
////    }
//
//    public boolean isConnected() throws IOException {
//        return proxy.isConnected();
//    }
//
//    public void checkActivity() {
//        proxy.checkActivity();
//    }
//
//    public boolean isActive() {
//        return active;
//    }
//
//    public String getRemoteIPAddress() {
//        return null;
//    }
//
//    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 ) {}
//
//    }
//
//    public Socket getCurrentSocket() {
//    	return socketChannel.socket();
//    }
//
//    public boolean connect() {
//    	return true;
//    }
//
//    public void disconnect() {
//    	shutdown();
//    }
//
//    public boolean idle(long timeout) {
//        return false;
//    }
//
//    private void openSelector() throws IOException {
//        if ( socketChannel.socket().isConnected() && socketChannel.socket().isBound() ) {
//            return;
//        } else {
//            throw new IOException("Connection Closed in openSelector");
//        }
//    }
//
//    private void closeSelector() throws IOException {
//        // nothing...
//    }
//
//
//    private boolean processWriteMessage() throws IOException {
//
//        outgoingMessage.flip();
//        long writeStart     = System.currentTimeMillis();
//        int  expectedWrite  = outgoingMessage.capacity();
//        int  writtenByte    = socketChannel.write( outgoingMessage );
//
//        if ( expectedWrite != writtenByte ) {
//            ByteBuffer buf = null;
//            while ( writtenByte < expectedWrite ) {
//
//                buf = ByteBuffer.allocate( expectedWrite - writtenByte );
//                buf.clear();
//                buf.put( outgoingMessage.array(), writtenByte, buf.capacity() );
//                writtenByte +=  write( buf );
//
//                if ( expectedWrite == writtenByte ) return true;
//                long  waitTime = System.currentTimeMillis() - writeStart;
//
//                if ( waitTime >= getTimeout() ) {
//                    throw new IOException("메시지 송신 타임아웃");
//                }
//            }
//        }
//        this.socketChannel.register( this.selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ );
//        return true;
//    }
//
//    public int write(ByteBuffer src) throws IOException {
//
//		this.socketChannel.register( this.selector, SelectionKey.OP_WRITE  );
////        int	 selected = 0;
//
//        try {
//        	//selected = 
//        	selector.select( getTimeout() );
//        } catch(Exception e) {
//        	throw new IOException("Write Select Error");
//        }
//
//        Iterator<SelectionKey> 		it = selector.selectedKeys().iterator();
//        int		 		writtenBytes = 0;
//        SelectionKey 	key = null;
//
//        while ( it.hasNext() ) {
//        	key	= (SelectionKey)it.next();
//        	it.remove();
//        	if ( key.isWritable() ) {
//        		writtenBytes = this.socketChannel.write( src );
//        	}
//        }
//        return  writtenBytes;
//    }
//
//    private byte[] makeLengthField(int length) {
//    	byte[] lenField = new byte[ lenBuffer.capacity() ];
//
//    	if ( lenBuffer.capacity() == 2 ) {
//            ByteBuffer tmpBuffer = ByteBuffer.allocate( lenBuffer.capacity() );
//            tmpBuffer.clear();
//    		tmpBuffer.putShort( (short) (length & 0xFFFF) );
//            lenField    = tmpBuffer.array();
//    	} else if ( lenBuffer.capacity() == 4 ) {
//            ByteBuffer tmpBuffer = ByteBuffer.allocate( lenBuffer.capacity() );
//            tmpBuffer.clear();
//    		tmpBuffer.putInt( length );
//            lenField    = tmpBuffer.array();
//    	} else {
//    		String lenStr = CommonLib.getFormatString( length, lenBuffer.capacity() );
//    		lenField	= lenStr.getBytes();
//    	}
//
//    	return lenField;
//    }
//
//    private void makeFormat( byte[] data ) {
//
//    	int i = data.length + lenBuffer.capacity();
//
//        if(outgoingMessage == null) {
//            outgoingMessage = ByteBuffer.allocate( data.length + lenBuffer.capacity() );
//        } else {
//            if( i != outgoingMessage.capacity() )
//                outgoingMessage = ByteBuffer.allocate( i );
//        }
//        outgoingMessage.clear();
//        outgoingMessage.put( makeLengthField( data.length ) );
//        outgoingMessage.put( data );
//    }
//
//	/**
//	 * @return Returns the socketchannel.
//	 */
//	public SocketChannel getSocketchannel() {
//		return socketChannel;
//	}
//	/**
//	 * @param socketchannel The socketchannel to set.
//	 */
//	public void setSocketchannel(SocketChannel socketchannel) {
//		this.socketChannel = socketchannel;
//	}
//    
//    public void setLastActivity() {
//    }
//
//    public long getFirstActivity() {
//        return 0;
//    }
//
//    public long getLastActivity() {
//        return 0;
//    }
//}
