/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.harmony.nio.internal;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketImpl;
import java.net.SocketOptions;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.AlreadyConnectedException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.ConnectionPendingException;
import java.nio.channels.IllegalBlockingModeException;
import java.nio.channels.NoConnectionPendingException;
import java.nio.channels.NotYetConnectedException;
import java.nio.channels.SocketChannel;
import java.nio.channels.UnresolvedAddressException;
import java.nio.channels.UnsupportedAddressTypeException;
import java.nio.channels.spi.SelectorProvider;

import org.apache.harmony.luni.net.PlainSocketImpl;
import org.apache.harmony.luni.platform.FileDescriptorHandler;
import org.apache.harmony.luni.platform.INetworkSystem;
import org.apache.harmony.luni.platform.Platform;
import org.apache.harmony.luni.util.ErrorCodeException;
import org.apache.harmony.luni.util.Msg;
import org.apache.harmony.nio.AddressUtil;
import org.apache.harmony.nio.internal.nls.Messages;

/*
 * The default implementation class of java.nio.channels.SocketChannel.
 */
class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler {

    private static final int EOF = -1;

    private static final int ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK = -211;

    // The singleton to do the native network operation.
    static final INetworkSystem networkSystem = Platform.getNetworkSystem();

    // Status un-init, not initialized.
    static final int SOCKET_STATUS_UNINIT = EOF;

    // Status before connect.
    static final int SOCKET_STATUS_UNCONNECTED = 0;

    // Status connection pending.
    static final int SOCKET_STATUS_PENDING = 1;

    // Status after connection success.
    static final int SOCKET_STATUS_CONNECTED = 2;

    // Status closed.
    static final int SOCKET_STATUS_CLOSED = 3;

    // Timeout used for non-block mode.
    private static final int TIMEOUT_NONBLOCK = 0;

    // Timeout used for block mode.
    private static final int TIMEOUT_BLOCK = EOF;

    // Step used for connect.
    private static final int HY_SOCK_STEP_START = 0;

    // Step used for finishConnect.
    private static final int HY_PORT_SOCKET_STEP_CHECK = 1;

    // Connect success.
    private static final int CONNECT_SUCCESS = 0;

    // The descriptor to interact with native code.
    FileDescriptor fd;

    // Our internal Socket.
    private Socket socket = null;

    // The address to be connected.
    InetSocketAddress connectAddress = null;

    // Local address of the this socket (package private for adapter).
    InetAddress localAddress = null;

    // Local port number.
    int localPort;

    // At first, uninitialized.
    int status = SOCKET_STATUS_UNINIT;

    // Whether the socket is bound.
    volatile boolean isBound = false;

    private static class ReadLock {}
    private final Object readLock = new ReadLock();

    private static class WriteLock {}
    private final Object writeLock = new WriteLock();

    // This content is a point used to set in connect_withtimeout() in pending
    // mode.
    // Must be a new instance of Long (i.e. not valueOf) as it's value may
    // be modified by native code.
    private Long connectContext = new Long(0L);

    // Used to store the trafficClass value which is simply returned
    // as the value that was set. We also need it to pass it to methods
    // that specify an address packets are going to be sent to.
    private int trafficClass = 0;

    /*
     * Constructor for creating a connected socket channel.
     */
    public SocketChannelImpl(SelectorProvider selectorProvider)
            throws IOException {
        this(selectorProvider, true);
    }

    /*
     * Constructor for creating an optionally connected socket channel.
     */
    public SocketChannelImpl(SelectorProvider selectorProvider, boolean connect)
            throws IOException {
        super(selectorProvider);
        fd = new FileDescriptor();
        status = SOCKET_STATUS_UNCONNECTED;
        if (connect) {
            networkSystem.createStreamSocket(fd, true);
        }
    }

    /*
     * For native call.
     */
    @SuppressWarnings("unused")
    private SocketChannelImpl() {
        super(SelectorProvider.provider());
        fd = new FileDescriptor();
        connectAddress = new InetSocketAddress(0);
        status = SOCKET_STATUS_CONNECTED;
    }

    // Keep this to see if need next version
    // SocketChannelImpl(SelectorProvider selectorProvider, FileDescriptor fd,
    // SocketImpl si) {
    // super(selectorProvider);
    // fd = fd;
    // networkSystem = OSNetworkSystem.getOSNetworkSystem();
    // status = SOCKET_STATUS_UNCONNECTED;
    // networkSystem.createSocket(fd, true);
    // }

    /*
     * Package private constructor.
     */
    SocketChannelImpl(Socket aSocket, FileDescriptor aFd) {
        super(SelectorProvider.provider());
        socket = aSocket;
        fd = aFd;
        status = SOCKET_STATUS_UNCONNECTED;
    }

    /*
     * Getting the internal Socket If we have not the socket, we create a new
     * one.
     */
    @Override
    synchronized public Socket socket() {
        if (null == socket) {
            try {
                InetAddress addr = null;
                int port = 0;
                if (connectAddress != null) {
                    addr = connectAddress.getAddress();
                    port = connectAddress.getPort();
                }
                socket = new SocketAdapter(
                        new PlainSocketImpl(fd, localPort, addr, port), this);
            } catch (SocketException e) {
                return null;
            }
        }
        return socket;
    }

    /**
     * @see java.nio.channels.SocketChannel#isConnected()
     */
    @Override
    synchronized public boolean isConnected() {
        return status == SOCKET_STATUS_CONNECTED;
    }

    /*
     * Status setting used by other class.
     */
    synchronized void setConnected() {
        status = SOCKET_STATUS_CONNECTED;
    }

    void setBound(boolean flag) {
        isBound = flag;
    }

    /**
     * @see java.nio.channels.SocketChannel#isConnectionPending()
     */
    @Override
    synchronized public boolean isConnectionPending() {
        return status == SOCKET_STATUS_PENDING;
    }

    /**
     * @see java.nio.channels.SocketChannel#connect(java.net.SocketAddress)
     */
    @Override
    public boolean connect(SocketAddress socketAddress) throws IOException {
        // status must be open and unconnected
        checkUnconnected();

        // check the address
        InetSocketAddress inetSocketAddress = validateAddress(socketAddress);
        InetAddress normalAddr = inetSocketAddress.getAddress();

        // When connecting, map ANY address to Localhost
        if (normalAddr.isAnyLocalAddress()) {
            normalAddr = InetAddress.getLocalHost();
        }

        int port = inetSocketAddress.getPort();
        String hostName = normalAddr.getHostName();
        // security check
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkConnect(hostName, port);
        }

        // connect result
        int result = EOF;
        boolean finished = false;

        try {
            if (isBlocking()) {
                begin();
                result = networkSystem.connect(fd, trafficClass, normalAddr, port);
            } else {
                result = networkSystem.connectWithTimeout(fd, 0, trafficClass,
                        normalAddr, port, HY_SOCK_STEP_START, connectContext);
                // set back to nonblocking to work around with a bug in portlib
                if (!this.isBlocking()) {
                    networkSystem.setNonBlocking(fd, true);
                }
            }
            finished = (CONNECT_SUCCESS == result);
            isBound = finished;
        } catch (IOException e) {
            if (isOpen()) {
                close();
                finished = true;
            }
            throw e;
        } finally {
            if (isBlocking()) {
                end(finished);
            }
        }

        // set local port
        localPort = networkSystem.getSocketLocalPort(fd, false);
        localAddress = networkSystem.getSocketLocalAddress(fd, false);

        // set the connected address.
        connectAddress = inetSocketAddress;
        synchronized (this) {
            if (finished) {
                status = SOCKET_STATUS_CONNECTED;
            } else {
                status = isBlocking() ? SOCKET_STATUS_UNCONNECTED
                        : SOCKET_STATUS_PENDING;
            }
        }
        return finished;
    }

    /**
     * @see java.nio.channels.SocketChannel#finishConnect()
     */
    @Override
    public boolean finishConnect() throws IOException {
        // status check
        synchronized (this) {
            if (!isOpen()) {
                throw new ClosedChannelException();
            }
            if (status == SOCKET_STATUS_CONNECTED) {
                return true;
            }
            if (status != SOCKET_STATUS_PENDING) {
                throw new NoConnectionPendingException();
            }
        }

        // finish result
        int result = EOF;
        boolean finished = false;

        try {
            begin();
            result = networkSystem.connectWithTimeout(fd,
                    isBlocking() ? -1 : 0, trafficClass, connectAddress
                            .getAddress(), connectAddress.getPort(),
                    HY_PORT_SOCKET_STEP_CHECK, connectContext);
            finished = (result == CONNECT_SUCCESS);
            isBound = finished;
            localAddress = networkSystem.getSocketLocalAddress(fd, false);
        } catch (ConnectException e) {
            if (isOpen()) {
                close();
                finished = true;
            }
            throw e;
        } finally {
            end(finished);
        }

        synchronized (this) {
            status = (finished ? SOCKET_STATUS_CONNECTED : status);
            isBound = finished;
            // TPE: Workaround for bug that turns socket back to blocking
            if (!isBlocking()) implConfigureBlocking(false);
        }
        return finished;
    }

    /**
     * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer)
     */
    @Override
    public int read(ByteBuffer target) throws IOException {
        if (null == target) {
            throw new NullPointerException();
        }
        checkOpenConnected();
        if (!target.hasRemaining()) {
            return 0;
        }

        int readCount;
        if (target.isDirect() || target.hasArray()) {
            readCount = readImpl(target);
            if (readCount > 0) {
                target.position(target.position() + readCount);
            }
        } else {
            ByteBuffer readBuffer = null;
            byte[] readArray = null;
            readArray = new byte[target.remaining()];
            readBuffer = ByteBuffer.wrap(readArray);
            readCount = readImpl(readBuffer);
            if (readCount > 0) {
                target.put(readArray, 0, readCount);
            }
        }
        return readCount;
    }

    /**
     * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer[], int,
     *      int)
     */
    @Override
    public long read(ByteBuffer[] targets, int offset, int length)
            throws IOException {
        if (!isIndexValid(targets, offset, length)) {
            throw new IndexOutOfBoundsException();
        }

        checkOpenConnected();
        int totalCount = calculateByteBufferArray(targets, offset, length);
        if (0 == totalCount) {
            return 0;
        }
        byte[] readArray = new byte[totalCount];
        ByteBuffer readBuffer = ByteBuffer.wrap(readArray);
        int readCount;
        // read data to readBuffer, and then transfer data from readBuffer to
        // targets.
        readCount = readImpl(readBuffer);
        if (readCount > 0) {
            int left = readCount;
            int index = offset;
            // transfer data from readArray to targets
            while (left > 0) {
                int putLength = Math.min(targets[index].remaining(), left);
                targets[index].put(readArray, readCount - left, putLength);
                index++;
                left -= putLength;
            }
        }
        return readCount;
    }

    private boolean isIndexValid(ByteBuffer[] targets, int offset, int length) {
        return (length >= 0) && (offset >= 0)
                && ((long) length + (long) offset <= targets.length);
    }

    /**
     * Read from channel, and store the result in the target.
     * 
     * @param target
     *            output parameter
     */
    private int readImpl(ByteBuffer target) throws IOException {
        synchronized (readLock) {
            int readCount = 0;
            try {
                if (isBlocking()) {
                    begin();
                }
                int offset = target.position();
                int length = target.remaining();
                if (target.isDirect()) {
                    long address = AddressUtil.getDirectBufferAddress(target);
                    readCount = networkSystem.readDirect(fd, address + offset,
                            length, (isBlocking() ? TIMEOUT_BLOCK
                                    : TIMEOUT_NONBLOCK));
                } else {
                    // target is assured to have array.
                    byte[] array = target.array();
                    offset += target.arrayOffset();
                    readCount = networkSystem.read(fd, array, offset, length,
                            (isBlocking() ? TIMEOUT_BLOCK : TIMEOUT_NONBLOCK));
                }
                return readCount;
            } finally {
                if (isBlocking()) {
                    end(readCount > 0);
                }
            }
        }
    }

    /**
     * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer)
     */
    @Override
    public int write(ByteBuffer source) throws IOException {
        if (null == source) {
            throw new NullPointerException();
        }
        checkOpenConnected();
        if (!source.hasRemaining()) {
            return 0;
        }
        return writeImpl(source);
    }

    /**
     * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer[], int,
     *      int)
     */
    @Override
    public long write(ByteBuffer[] sources, int offset, int length)
            throws IOException {
        if (!isIndexValid(sources, offset, length)) {
            throw new IndexOutOfBoundsException();
        }

        checkOpenConnected();

        Object[] src = new Object[length];
        int[] offsets = new int[length];
        int[] counts = new int[length];
        for (int i = 0; i < length; ++i) {
            ByteBuffer buffer = sources[i + offset];
            if (!buffer.isDirect()) {
                if (buffer.hasArray()) {
                    src[i] = buffer.array();
                    counts[i] = buffer.remaining();
                    offsets[i] = buffer.position();
                } else {
                    ByteBuffer db = ByteBuffer.allocateDirect(buffer.remaining());
                    int oldPosition = buffer.position();
                    db.put(buffer);
                    buffer.position(oldPosition);
                    db.flip();
                    src[i] = db;
                    counts[i] = buffer.remaining();
                    offsets[i] = 0;
                }
            } else {
                src[i] = buffer;
                counts[i] = buffer.remaining();
                offsets[i] = buffer.position();
            }
        }

        if (length == 0) {
            return 0;
        }

        int result = writevImpl(src, offsets, counts);
        int val = offset;
        int written = result;
        while (result > 0) {
            ByteBuffer source = sources[val];
            int gap = Math.min(result, source.remaining());
            source.position(source.position() + gap);
            val++;
            result -= gap;
        }
        return written;
    }

    /*
     * Write the source. return the count of bytes written.
     */
    private int writevImpl(Object[] sources, int[] offsets, int[] counts) throws IOException {
        int writeCount = 0;
        try {
            if (isBlocking()) {
                begin();
            }

            synchronized (writeLock) {
                writeCount = networkSystem.writev(fd, sources, offsets, counts, sources.length);
            }
        } catch (SocketException e) {
            if (e.getCause() instanceof ErrorCodeException) {
                if (ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK == ((ErrorCodeException) e
                        .getCause()).getErrorCode()) {
                    return writeCount;
                }
            }
            throw e;
        } finally {
            if (isBlocking()) {
                end(writeCount >= 0);
            }
        }
        return writeCount;
    }

    private int calculateByteBufferArray(ByteBuffer[] sources, int offset,
            int length) {
        int sum = 0;
        for (int val = offset; val < offset + length; val++) {
            sum = sum + sources[val].remaining();
        }
        return sum;
    }

    /*
     * Write the source. return the count of bytes written.
     */
    private int writeImpl(ByteBuffer source) throws IOException {
        synchronized (writeLock) {
            if (!source.hasRemaining()) {
                return 0;
            }
            int writeCount = 0;
            try {
                int pos = source.position();
                int length = source.remaining();
                if (isBlocking()) {
                    begin();
                }
                if (source.isDirect()) {
                    long address = AddressUtil.getDirectBufferAddress(source);
                    writeCount = networkSystem.writeDirect(fd, address + pos,
                            length);
                } else if (source.hasArray()) {
                    pos += source.arrayOffset();
                    writeCount = networkSystem.write(fd, source.array(), pos,
                            length);
                } else {
                    byte[] array = new byte[length];
                    source.get(array);
                    writeCount = networkSystem.write(fd, array, 0, length);
                }
                source.position(pos + writeCount);
            } catch (SocketException e) {
                if (e.getCause() instanceof ErrorCodeException) {
                    if (ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK == ((ErrorCodeException) e
                            .getCause()).getErrorCode()) {
                        return writeCount;
                    }
                }
                throw e;
            } finally {
                if (isBlocking()) {
                    end(writeCount >= 0);
                }
            }
            return writeCount;
        }
    }

    /*
     * Status check, open and "connected", when read and write.
     */
    synchronized private void checkOpenConnected()
            throws ClosedChannelException {
        if (!isOpen()) {
            throw new ClosedChannelException();
        }
        if (!isConnected()) {
            throw new NotYetConnectedException();
        }
    }

    /*
     * Status check, open and "unconnected", before connection.
     */
    synchronized private void checkUnconnected() throws IOException {
        if (!isOpen()) {
            throw new ClosedChannelException();
        }
        if (status == SOCKET_STATUS_CONNECTED) {
            throw new AlreadyConnectedException();
        }
        if (status == SOCKET_STATUS_PENDING) {
            throw new ConnectionPendingException();
        }
    }

    /*
     * Shared by this class and DatagramChannelImpl, to do the address transfer
     * and check.
     */
    static InetSocketAddress validateAddress(SocketAddress socketAddress) {
        if (null == socketAddress) {
            throw new IllegalArgumentException();
        }
        if (!(socketAddress instanceof InetSocketAddress)) {
            throw new UnsupportedAddressTypeException();
        }
        InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
        if (inetSocketAddress.isUnresolved()) {
            throw new UnresolvedAddressException();
        }
        return inetSocketAddress;
    }

    /*
     * Get local address.
     */
    public InetAddress getLocalAddress() throws UnknownHostException {
        byte[] any_bytes = { 0, 0, 0, 0 };
        if (!isBound) {
            return InetAddress.getByAddress(any_bytes);
        }
        return localAddress;
    }

    /*
     * Do really closing action here.
     */
    @Override
    synchronized protected void implCloseSelectableChannel() throws IOException {
        if (SOCKET_STATUS_CLOSED != status) {
            status = SOCKET_STATUS_CLOSED;
            if (null != socket && !socket.isClosed()) {
                socket.close();
            } else {
                networkSystem.socketClose(fd);
            }
        }
    }

    /**
     * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean)
     */
    @Override
    protected void implConfigureBlocking(boolean blockMode) throws IOException {
        synchronized (blockingLock()) {
            networkSystem.setNonBlocking(fd, !blockMode);
        }
    }

    /*
     * Get the fd.
     */
    public FileDescriptor getFD() {
        return fd;
    }

    /*
     * Adapter classes for internal socket.
     */
    private static class SocketAdapter extends Socket {

        SocketChannelImpl channel;

        SocketImpl socketImpl;

        SocketAdapter(SocketImpl socketimpl, SocketChannelImpl channel)
                throws SocketException {
            super(socketimpl);
            socketImpl = socketimpl;
            this.channel = channel;
        }

        /**
         * @see java.net.Socket#getChannel()
         */
        @Override
        public SocketChannel getChannel() {
            return channel;
        }

        /**
         * @see java.net.Socket#isBound()
         */
        @Override
        public boolean isBound() {
            return channel.isBound;
        }

        /**
         * @see java.net.Socket#isConnected()
         */
        @Override
        public boolean isConnected() {
            return channel.isConnected();
        }

        /**
         * @see java.net.Socket#getLocalAddress()
         */
        @Override
        public InetAddress getLocalAddress() {
            try {
                return channel.getLocalAddress();
            } catch (UnknownHostException e) {
                return null;
            }
        }

        /**
         * @see java.net.Socket#connect(java.net.SocketAddress, int)
         */
        @Override
        public void connect(SocketAddress remoteAddr, int timeout)
                throws IOException {
            if (!channel.isBlocking()) {
                throw new IllegalBlockingModeException();
            }
            if (isConnected()) {
                throw new AlreadyConnectedException();
            }
            super.connect(remoteAddr, timeout);
            channel.localAddress = networkSystem.getSocketLocalAddress(
                    channel.fd, false);
            if (super.isConnected()) {
                channel.setConnected();
                channel.isBound = super.isBound();
            }
        }

        /**
         * @see java.net.Socket#bind(java.net.SocketAddress)
         */
        @Override
        public void bind(SocketAddress localAddr) throws IOException {
            if (channel.isConnected()) {
                throw new AlreadyConnectedException();
            }
            if (SocketChannelImpl.SOCKET_STATUS_PENDING == channel.status) {
                throw new ConnectionPendingException();
            }
            super.bind(localAddr);
            // keep here to see if need next version
            // channel.Address = getLocalSocketAddress();
            // channel.localport = getLocalPort();
            channel.isBound = true;

        }

        /**
         * @see java.net.Socket#close()
         */
        @Override
        public void close() throws IOException {
            synchronized (channel) {
                if (channel.isOpen()) {
                    channel.close();
                } else {
                    super.close();
                }
                channel.status = SocketChannelImpl.SOCKET_STATUS_CLOSED;
            }
        }

        @Override
        public boolean getReuseAddress() throws SocketException {
            checkOpen();
            return ((Boolean) socketImpl.getOption(SocketOptions.SO_REUSEADDR))
                    .booleanValue();
        }

        @Override
        public synchronized int getReceiveBufferSize() throws SocketException {
            checkOpen();
            return ((Integer) socketImpl.getOption(SocketOptions.SO_RCVBUF))
                    .intValue();
        }

        @Override
        public synchronized int getSendBufferSize() throws SocketException {
            checkOpen();
            return ((Integer) socketImpl.getOption(SocketOptions.SO_SNDBUF))
                    .intValue();
        }

        @Override
        public synchronized int getSoTimeout() throws SocketException {
            checkOpen();
            return ((Integer) socketImpl.getOption(SocketOptions.SO_TIMEOUT))
                    .intValue();
        }

        @Override
        public int getTrafficClass() throws SocketException {
            checkOpen();
            return ((Number) socketImpl.getOption(SocketOptions.IP_TOS))
                    .intValue();
        }

        /**
         * @see java.net.Socket#getKeepAlive()
         */
        @Override
        public boolean getKeepAlive() throws SocketException {
            checkOpen();
            return ((Boolean) socketImpl.getOption(SocketOptions.SO_KEEPALIVE))
                    .booleanValue();
        }

        /**
         * @see java.net.Socket#getOOBInline()
         */
        @Override
        public boolean getOOBInline() throws SocketException {
            checkOpen();
            return ((Boolean) socketImpl.getOption(SocketOptions.SO_OOBINLINE))
                    .booleanValue();
        }

        /**
         * @see java.net.Socket#getSoLinger()
         */
        @Override
        public int getSoLinger() throws SocketException {
            checkOpen();
            return ((Integer) socketImpl.getOption(SocketOptions.SO_LINGER))
                    .intValue();
        }

        /**
         * @see java.net.Socket#getTcpNoDelay()
         */
        @Override
        public boolean getTcpNoDelay() throws SocketException {
            checkOpen();
            return ((Boolean) socketImpl.getOption(SocketOptions.TCP_NODELAY))
                    .booleanValue();
        }

        @Override
        public void setKeepAlive(boolean value) throws SocketException {
            checkOpen();
            socketImpl.setOption(SocketOptions.SO_KEEPALIVE, value ? Boolean.TRUE
                    : Boolean.FALSE);
        }

        @Override
        public void setOOBInline(boolean oobinline) throws SocketException {
            checkOpen();
            socketImpl.setOption(SocketOptions.SO_OOBINLINE, oobinline ? Boolean.TRUE
                    : Boolean.FALSE);
        }

        @Override
        public synchronized void setReceiveBufferSize(int size)
                throws SocketException {
            checkOpen();
            if (size < 1) {
                throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$
            }
            socketImpl
                    .setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
        }

        @Override
        public void setReuseAddress(boolean reuse) throws SocketException {
            checkOpen();
            socketImpl.setOption(SocketOptions.SO_REUSEADDR, reuse ? Boolean.TRUE
                    : Boolean.FALSE);
        }

        @Override
        public synchronized void setSendBufferSize(int size) throws SocketException {
            checkOpen();
            if (size < 1) {
                throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$
            }
            socketImpl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
        }

        @Override
        public void setSoLinger(boolean on, int timeout) throws SocketException {
            checkOpen();
            if (on && timeout < 0) {
                throw new IllegalArgumentException(Msg.getString("K0045")); //$NON-NLS-1$
            }
            int val = on ? (65535 < timeout ? 65535 : timeout) : -1;
            socketImpl.setOption(SocketOptions.SO_LINGER, Integer.valueOf(val));
        }

        @Override
        public synchronized void setSoTimeout(int timeout) throws SocketException {
            checkOpen();
            if (timeout < 0) {
                throw new IllegalArgumentException(Msg.getString("K0036")); //$NON-NLS-1$
            }
            socketImpl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
        }

        @Override
        public void setTcpNoDelay(boolean on) throws SocketException {
            checkOpen();
            socketImpl.setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
        }

        @Override
        public void setTrafficClass(int value) throws SocketException {
            checkOpen();
            if (value < 0 || value > 255) {
                throw new IllegalArgumentException();
            }
            socketImpl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value));
        }

        /**
         * @see java.net.Socket#getOutputStream()
         */
        @Override
        public OutputStream getOutputStream() throws IOException {
            if (!channel.isOpen()) {
                // nio.00=Socket is closed
                throw new SocketException(Messages.getString("nio.00")); //$NON-NLS-1$
            }
            if (!channel.isConnected()) {
                // nio.01=Socket is not connected
                throw new SocketException(Messages.getString("nio.01")); //$NON-NLS-1$
            }
            if (isOutputShutdown()) {
                // nio.02=Socket output is shutdown
                throw new SocketException(Messages.getString("nio.02")); //$NON-NLS-1$
            }
            return new SocketChannelOutputStream(channel);
        }

        /**
         * @see java.net.Socket#getInputStream()
         */
        @Override
        public InputStream getInputStream() throws IOException {
            if (!channel.isOpen()) {
                // nio.00=Socket is closed
                throw new SocketException(Messages.getString("nio.00")); //$NON-NLS-1$
            }
            if (!channel.isConnected()) {
                // nio.01=Socket is not connected
                throw new SocketException(Messages.getString("nio.01")); //$NON-NLS-1$
            }
            if (isInputShutdown()) {
                // nio.03=Socket input is shutdown
                throw new SocketException(Messages.getString("nio.03")); //$NON-NLS-1$
            }
            return new SocketChannelInputStream(channel);
        }

        /*
         * Checks whether the channel is open.
         */
        private void checkOpen() throws SocketException {
            if (isClosed()) {
                // nio.00=Socket is closed
                throw new SocketException(Messages.getString("nio.00")); //$NON-NLS-1$
            }
        }

        /*
         * Used for net and nio exchange.
         */
        public SocketImpl getImpl() {
            return socketImpl;
        }
    }

    /*
     * This output stream delegates all operations to the associated channel.
     * Throws an IllegalBlockingModeException if the channel is in non-blocking
     * mode when performing write operations.
     */
    private static class SocketChannelOutputStream extends OutputStream {
        SocketChannel channel;

        public SocketChannelOutputStream(SocketChannel channel) {
            this.channel = channel;
        }

        /*
         * Closes this stream and channel.
         * 
         * @exception IOException thrown if an error occurs during the close
         */
        @Override
        public void close() throws IOException {
            channel.close();
        }

        /**
         * @see java.io.OutputStream#write(byte[], int, int)
         */
        @Override
        public void write(byte[] buffer, int offset, int count)
                throws IOException {
            if (0 > offset || 0 > count || count + offset > buffer.length) {
                throw new IndexOutOfBoundsException();
            }
            ByteBuffer buf = ByteBuffer.wrap(buffer, offset, count);
            if (!channel.isBlocking()) {
                throw new IllegalBlockingModeException();
            }
            channel.write(buf);
        }

        /**
         * @see java.io.OutputStream#write(int)
         */
        @Override
        public void write(int oneByte) throws IOException {
            if (!channel.isBlocking()) {
                throw new IllegalBlockingModeException();
            }
            ByteBuffer buffer = ByteBuffer.allocate(1);
            buffer.put(0, (byte) (oneByte & 0xFF));
            channel.write(buffer);
        }
    }

    /*
     * This input stream delegates all operations to the associated channel.
     * Throws an IllegalBlockingModeException if the channel is in non-blocking
     * mode when performing read operations.
     */
    private static class SocketChannelInputStream extends InputStream {
        SocketChannel channel;

        public SocketChannelInputStream(SocketChannel channel) {
            this.channel = channel;
        }

        /*
         * Closes this stream and channel.
         */
        @Override
        public void close() throws IOException {
            channel.close();
        }

        /**
         * @see java.io.InputStream#read()
         */
        @Override
        public int read() throws IOException {
            if (!channel.isBlocking()) {
                throw new IllegalBlockingModeException();
            }
            ByteBuffer buf = ByteBuffer.allocate(1);
            int result = channel.read(buf);
            return (-1 == result) ? result : buf.get() & 0xFF;
        }

        /**
         * @see java.io.InputStream#read(byte[], int, int)
         */
        @Override
        public int read(byte[] buffer, int offset, int count)
                throws IOException {
            if (0 > offset || 0 > count || count + offset > buffer.length) {
                throw new IndexOutOfBoundsException();
            }
            if (!channel.isBlocking()) {
                throw new IllegalBlockingModeException();
            }
            ByteBuffer buf = ByteBuffer.wrap(buffer, offset, count);
            return channel.read(buf);
        }
    }
}
