package de.tum.in.www1.jReto.niotools; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.LinkedList; import java.util.Queue; public class ChannelWriter implements Dispatcher.WriteHandler<SocketChannel> { public static interface WriteHandler { void onCompletedWriteRequest(); } public final SocketChannel socketChannel; public final Queue<ByteBuffer> writeRequests; public final Dispatcher dispatcher; public final WriteHandler writeHandler; private ByteBuffer currentBuffer; public ChannelWriter(SocketChannel socketChannel, Dispatcher dispatcher, WriteHandler writeHandler) { if (socketChannel == null) throw new IllegalArgumentException("socketChannel may not be null"); if (dispatcher == null) throw new IllegalArgumentException("dispatcher may not be null"); this.socketChannel = socketChannel; this.dispatcher = dispatcher; this.writeHandler = writeHandler; writeRequests = new LinkedList<ByteBuffer>(); } public void write(ByteBuffer buffer) { if (buffer == null) throw new IllegalArgumentException("buffer may not be null"); if (!buffer.hasRemaining()) throw new IllegalArgumentException("Attempted to write a buffer with no remaining bytes. Did you forget to call clear()?"); if (this.writeRequests.size() == 0 && this.currentBuffer == null) { this.dispatcher.registerWriteHandler(this, this.socketChannel); } writeRequests.add(buffer); processWriteRequests(); } private void processWriteRequests() { if (currentBuffer != null || writeRequests.size() == 0) return; currentBuffer = writeRequests.poll(); } private void processCurrentBuffer() { if (currentBuffer == null) return; try { socketChannel.write(currentBuffer); } catch (IOException e) { System.err.println("An error occured while trying to write to the socket."); e.printStackTrace(); } if (!currentBuffer.hasRemaining()) { currentBuffer = null; this.writeHandler.onCompletedWriteRequest(); if (this.writeRequests.size() == 0) this.dispatcher.unregisterWrite(this.socketChannel); } processWriteRequests(); } public void onWriteable(SocketChannel socket) { processCurrentBuffer(); } }