SocketChannelImpl.java [plain text]
package gnu.java.nio;
import gnu.java.net.PlainSocketImpl;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.nio.channels.AlreadyConnectedException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.ConnectionPendingException;
import java.nio.channels.NoConnectionPendingException;
import java.nio.channels.NotYetConnectedException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.channels.UnresolvedAddressException;
import java.nio.channels.UnsupportedAddressTypeException;
import java.nio.channels.spi.SelectorProvider;
public final class SocketChannelImpl extends SocketChannel
{
private PlainSocketImpl impl;
private NIOSocket socket;
private boolean connectionPending;
SocketChannelImpl (SelectorProvider provider)
throws IOException
{
super (provider);
impl = new PlainSocketImpl();
socket = new NIOSocket (impl, this);
configureBlocking(true);
}
SocketChannelImpl (SelectorProvider provider,
NIOSocket socket)
throws IOException
{
super (provider);
this.impl = socket.getPlainSocketImpl();
this.socket = socket;
}
public void finalizer()
{
if (isConnected())
{
try
{
close ();
}
catch (Exception e)
{
}
}
}
PlainSocketImpl getPlainSocketImpl()
{
return impl;
}
int getNativeFD()
{
return socket.getPlainSocketImpl().getNativeFD();
}
protected void implCloseSelectableChannel () throws IOException
{
socket.close();
}
protected void implConfigureBlocking (boolean blocking) throws IOException
{
socket.setSoTimeout (blocking ? 0 : NIOConstants.DEFAULT_TIMEOUT);
}
public boolean connect (SocketAddress remote) throws IOException
{
if (!isOpen())
throw new ClosedChannelException();
if (isConnected())
throw new AlreadyConnectedException();
if (connectionPending)
throw new ConnectionPendingException();
if (!(remote instanceof InetSocketAddress))
throw new UnsupportedAddressTypeException();
if (((InetSocketAddress) remote).isUnresolved())
throw new UnresolvedAddressException();
try
{
socket.getPlainSocketImpl().setInChannelOperation(true);
if (isBlocking())
{
socket.connect (remote);
return true;
}
try
{
socket.connect (remote, NIOConstants.DEFAULT_TIMEOUT);
return true;
}
catch (SocketTimeoutException e)
{
connectionPending = true;
return false;
}
}
finally
{
socket.getPlainSocketImpl().setInChannelOperation(false);
}
}
public boolean finishConnect ()
throws IOException
{
if (!isOpen())
throw new ClosedChannelException();
if (!isConnected() && !connectionPending)
throw new NoConnectionPendingException();
if (isConnected())
return true;
Selector selector = provider().openSelector();
register(selector, SelectionKey.OP_CONNECT);
if (isBlocking())
{
selector.select(); connectionPending = false;
return true;
}
int ready = selector.selectNow(); if (ready == 1)
{
connectionPending = false;
return true;
}
return false;
}
public boolean isConnected ()
{
return socket.isConnected();
}
public boolean isConnectionPending ()
{
return connectionPending;
}
public Socket socket ()
{
return socket;
}
public int read(ByteBuffer dst) throws IOException
{
if (!isConnected())
throw new NotYetConnectedException();
byte[] data;
int offset = 0;
InputStream input = socket.getInputStream();
int available = input.available();
int len = dst.capacity() - dst.position();
if ((! isBlocking()) && available == 0)
return 0;
if (dst.hasArray())
{
offset = dst.arrayOffset() + dst.position();
data = dst.array();
}
else
{
data = new byte [len];
}
int readBytes = 0;
boolean completed = false;
try
{
begin();
socket.getPlainSocketImpl().setInChannelOperation(true);
readBytes = input.read (data, offset, len);
completed = true;
}
finally
{
end (completed);
socket.getPlainSocketImpl().setInChannelOperation(false);
}
if (readBytes > 0)
if (dst.hasArray())
{
dst.position (dst.position() + readBytes);
}
else
{
dst.put (data, offset, len);
}
return readBytes;
}
public long read (ByteBuffer[] dsts, int offset, int length)
throws IOException
{
if (!isConnected())
throw new NotYetConnectedException();
if ((offset < 0)
|| (offset > dsts.length)
|| (length < 0)
|| (length > (dsts.length - offset)))
throw new IndexOutOfBoundsException();
long readBytes = 0;
for (int index = offset; index < length; index++)
readBytes += read (dsts [index]);
return readBytes;
}
public int write (ByteBuffer src)
throws IOException
{
if (!isConnected())
throw new NotYetConnectedException();
byte[] data;
int offset = 0;
int len = src.remaining();
if (!src.hasArray())
{
data = new byte [len];
src.get (data, 0, len);
}
else
{
offset = src.arrayOffset() + src.position();
data = src.array();
}
OutputStream output = socket.getOutputStream();
boolean completed = false;
try
{
begin();
socket.getPlainSocketImpl().setInChannelOperation(true);
output.write (data, offset, len);
completed = true;
}
finally
{
end (completed);
socket.getPlainSocketImpl().setInChannelOperation(false);
}
if (src.hasArray())
{
src.position (src.position() + len);
}
return len;
}
public long write (ByteBuffer[] srcs, int offset, int length)
throws IOException
{
if (!isConnected())
throw new NotYetConnectedException();
if ((offset < 0)
|| (offset > srcs.length)
|| (length < 0)
|| (length > (srcs.length - offset)))
throw new IndexOutOfBoundsException();
long writtenBytes = 0;
for (int index = offset; index < length; index++)
writtenBytes += write (srcs [index]);
return writtenBytes;
}
}