/**
 * JLibs: Common Utilities for Java
 * Copyright (C) 2009  Santhosh Kumar T <santhosh.tekuri@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */

package jlibs.core.nio;

import jlibs.core.lang.ByteSequence;
import jlibs.core.lang.Bytes;
import jlibs.core.util.logging.AnsiFormatter;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;

/**
 * @author Santhosh Kumar T
 */
public class EchoClient{
    public static void main(String[] args) throws IOException{
        boolean ssl = false;
        String host = "localhost";
        int port = 1111;
        for(String arg: args){
            if(arg.equals("-ssl"))
                ssl = true;
            else{
                try{
                    port = Integer.parseInt(arg);
                }catch (NumberFormatException ex){
                    host = arg;
                }
            }
        }

        final NIOSelector selector = new NIOSelector(1000, 0);
        final ClientChannel client = selector.newClient();
        final Bytes bytes = new Bytes();

        Thread readThread = new Thread(new Runnable(){
            @Override
            public void run(){
                while(true){
                    try{
                        byte buff[] = new byte[1024];
                        int read = System.in.read(buff, 0, 1024);
                        if(read!=-1)
                            bytes.add(new ByteSequence(buff, 0, read));
                        synchronized(bytes){
                            selector.invokeLater(new Runnable(){
                                public void run(){
                                    try{
                                        if(bytes.isEmpty())
                                            client.shutdownOutput();
                                        else
                                            client.addInterest(ClientChannel.OP_WRITE);
                                    }catch(IOException ex){
                                        ex.printStackTrace();
                                    }
                                }
                            });
                            selector.wakeup();
                            bytes.wait();
                        }
                    }catch(Exception ex){
                        ex.printStackTrace();
                    }
                }
            }
        });
        readThread.setDaemon(true);

        client.connect(new InetSocketAddress(host, port));
        client.addInterest(ClientChannel.OP_CONNECT);

        ByteBuffer readBuffer = ByteBuffer.allocate(1024);
        for(NIOChannel channel: selector){
            assert channel==client;
            if(client.isConnectable()){
                if(client.finishConnect()){
                    System.out.println("connected to "+host+":"+port+(ssl?" with SSL":""));
                    if(ssl)
                        client.enableSSL();
                    readThread.start();
                    client.addInterest(ClientChannel.OP_READ);
                }else
                    client.addInterest(ClientChannel.OP_CONNECT);
            }
            if(client.isWritable()){
                bytes.writeTo(client);
                if(bytes.isEmpty()){
                    synchronized(bytes){
                        bytes.notifyAll();
                    }
                }else
                    client.addInterest(ClientChannel.OP_WRITE);
            }

            if(client.isReadable()){
                if(client.read(readBuffer)>0){
                    AnsiFormatter.WARNING.out(new String(readBuffer.array(), 0, readBuffer.position()));
                    readBuffer.clear();
                }
                if(client.isEOF()){
                    client.close();
                    return;
                }else
                    client.addInterest(ClientChannel.OP_READ);
            }
        }
    }
}

@@ -655,75 +655,8 @@
 o;%0A%0A
-import jlibs.core.lang.ByteSequence;%0Aimport jlibs.core.lang.Bytes;%0A
 impo
@@ -1456,28 +1456,50 @@
 Byte
-s bytes = new Bytes(
+Buffer inBuffer = ByteBuffer.allocate(1024
 );%0A%0A
@@ -1688,36 +1688,24 @@
     
-byte buff%5B%5D = new byte%5B1024%5D
+inBuffer.clear()
 ;%0A  
@@ -1756,21 +1756,49 @@
 ead(
-buff, 0, 1024
+inBuffer.array(), 0, inBuffer.remaining()
 );%0A 
@@ -1865,49 +1865,91 @@
     
-bytes.add(new ByteSequence(buff, 0, read)
+inBuffer.position(inBuffer.position()+read);%0A                        inBuffer.flip(
 );%0A 
@@ -1976,37 +1976,40 @@
    synchronized(
-bytes
+inBuffer
 )%7B%0A             
@@ -2195,29 +2195,37 @@
      if(
-bytes.isEmpty
+inBuffer.hasRemaining
 ())%0A    
@@ -2275,23 +2275,42 @@
 ent.
-shutdownOutput(
+addInterest(ClientChannel.OP_WRITE
 );%0A 
@@ -2408,42 +2408,23 @@
 ent.
-addInterest(ClientChannel.OP_WRITE
+shutdownOutput(
 );%0A 
@@ -2723,21 +2723,24 @@
         
-bytes
+inBuffer
 .wait();
@@ -3719,28 +3719,29 @@
     
-bytes.writeTo(client
+client.write(inBuffer
 );%0A 
@@ -3762,24 +3762,117 @@
  if(
-bytes.isEmpty())
+inBuffer.hasRemaining())%0A                    client.addInterest(ClientChannel.OP_WRITE);%0A                else
 %7B%0A  
@@ -3902,21 +3902,24 @@
 ronized(
-bytes
+inBuffer
 )%7B%0A     
@@ -3941,13 +3941,16 @@
     
-bytes
+inBuffer
 .not
@@ -4002,76 +4002,9 @@
    %7D
-else%0A                    client.addInterest(ClientChannel.OP_WRITE);
+%0A
 %0A   

use ByteBuffer rather than Bytes