You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/04/07 11:07:38 UTC

svn commit: r392225 [2/6] - in /incubator/harmony/enhanced/classlib/trunk/modules/nio: make/common/ src/main/java/java/nio/ src/main/java/java/nio/channels/spi/ src/main/java/org/apache/harmony/nio/internal/ src/test/java/org/apache/harmony/tests/java/...

Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java?rev=392225&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java Fri Apr  7 02:07:34 2006
@@ -0,0 +1,732 @@
+/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.InterruptedIOException;
+import java.net.ConnectException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.DatagramSocketImpl;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.spi.SelectorProvider;
+
+import org.apache.harmony.luni.net.NetUtil;
+import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.platform.FileDescriptorHandler;
+import org.apache.harmony.luni.platform.INetworkSystem;
+import org.apache.harmony.luni.platform.Platform;
+
+
+
+/*
+ * The default implementation class of java.nio.channels.DatagramChannel.
+ * 
+ */
+class DatagramChannelImpl extends DatagramChannel implements FileDescriptorHandler{
+
+    // -------------------------------------------------------------------
+    // Class variables
+    // -------------------------------------------------------------------
+
+    // The singleton to do the native network operation.
+    private static final INetworkSystem networkSystem = Platform
+            .getNetworkSystem();
+
+    // default timeout used to nonblocking mode.
+    private static final int DEFAULT_TIMEOUT = 100;
+
+    // error messages, for native dependent.
+    private static final String ERRMSG_TIMEOUT = "The operation timed out";
+
+    private static final String ERRMSG_NONBLOKING_OUT = "The socket is marked as nonblocking operation would block";
+
+    private static final String ERRMSG_ASYNCHRONOUSCLOSE = "The call was cancelled";
+
+    // -------------------------------------------------------------------
+    // Instance variables
+    // -------------------------------------------------------------------
+
+    // The fd to interact with native code
+    private FileDescriptor fd;
+
+    // Our internal DatagramSocket.
+    private DatagramSocket socket = null;
+
+    // The address to be connected.
+    InetSocketAddress connectAddress = null;
+
+    // local port
+    private int localPort;
+
+    // At first, uninitialized.
+    boolean connected = false;
+
+    // whether the socket is bound
+    boolean isBound = false;
+
+    // lock for read and receive
+    private final Object readLock = new Object();
+
+    // lock for write and receive
+    private final Object writeLock = new Object();
+
+    // 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
+    // -------------------------------------------------------------------
+
+    /*
+     * Constructor
+     */
+    protected DatagramChannelImpl(SelectorProvider selectorProvider)
+            throws IOException {
+        super(selectorProvider);
+        fd = new FileDescriptor();
+        networkSystem.createDatagramSocket(fd, true);
+    }
+
+    // -------------------------------------------------------------------
+    // Methods for getting internal DatagramSocket.
+    // -------------------------------------------------------------------
+
+    /*
+     * Getting the internal DatagramSocket If we have not the socket, we create
+     * a new one.
+     */
+    synchronized public DatagramSocket socket() {
+        if (null == socket) {
+//            DatagramSocketImpl datagramSocketImpl = new DatagramSocketImplAdapter(
+//                    fd, localPort, this);
+            socket = new DatagramSocketAdapter(SocketImplProvider.getDatagramSocketImpl(fd, localPort), this);
+        }
+        return socket;
+    }
+    
+    /**
+     * Answer the local address from the IP stack. This method should not be
+     * called directly as it does not check the security policy.
+     * 
+     * @return InetAddress the local address to which the socket is bound.
+     * @see DatagramSocket
+     */
+    InetAddress getLocalAddress() {
+        return networkSystem.getSocketLocalAddress(fd, NetUtil.preferIPv6Addresses());
+    }
+
+    // -------------------------------------------------------------------
+    // Methods for connect and disconnect
+    // -------------------------------------------------------------------
+
+    /*
+     * 
+     * @see java.nio.channels.DatagramChannel#isConnected()
+     */
+    synchronized public boolean isConnected() {
+        return connected;
+    }
+
+    /*
+     * 
+     * @see java.nio.channels.DatagramChannel#connect(java.net.SocketAddress)
+     */
+    synchronized public DatagramChannel connect(SocketAddress address)
+            throws IOException {
+        // must open
+        checkOpen();
+        // status must be un-connected.
+        if (connected) {
+            throw new IllegalStateException();
+        }
+
+        // check the address
+        InetSocketAddress inetSocketAddress = SocketChannelImpl
+                .validateAddress(address);
+
+        // security check
+        SecurityManager sm = System.getSecurityManager();
+        if (null != sm) {
+            if (inetSocketAddress.getAddress().isMulticastAddress()) {
+                sm.checkMulticast(inetSocketAddress.getAddress());
+            } else {
+                sm.checkConnect(inetSocketAddress.getAddress().getHostName(),
+                        inetSocketAddress.getPort());
+            }
+        }
+
+        try {
+            begin();
+            networkSystem.connectDatagram(fd, inetSocketAddress.getPort(),
+                    trafficClass, inetSocketAddress.getAddress());
+        } catch (ConnectException e) {
+            // ConnectException means connect fail, not exception
+        } finally {
+            end(true);
+        }
+
+        // set the connected address.
+        connectAddress = inetSocketAddress;
+        connected = true;
+        isBound = true;
+        return this;
+    }
+
+    /*
+     * 
+     * @see java.nio.channels.DatagramChannel#disconnect()
+     */
+    synchronized public DatagramChannel disconnect() throws IOException {
+        if (!isConnected() || !isOpen()) {
+            return this;
+        }
+        connected = false;
+        connectAddress = null;
+        networkSystem.disconnectDatagram(fd);
+        if (null != socket) {
+            socket.disconnect();
+        }
+        return this;
+    }
+
+    // -------------------------------------------------------------------
+    // Methods for send and receive
+    // -------------------------------------------------------------------
+
+    /*
+     * 
+     * @see java.nio.channels.DatagramChannel#receive(java.nio.ByteBuffer)
+     */
+    public SocketAddress receive(ByteBuffer target) throws IOException {
+        // must not null and not readonly
+        checkNotNullNotReadOnly(target);
+        // must open
+        checkOpen();
+
+        if (!isBound) {
+            // FIXME RI seems does not perform as datagram socket
+            // SecurityManager security = System.getSecurityManager();
+            // if (security != null)
+            // security.checkListen(0);
+            // final byte[] any = new byte[] { 0, 0, 0, 0 };
+            // try {
+            // networkSystem.bind(fd, 0, InetAddress.getByAddress(any));
+            // } catch (UnknownHostException e) {
+            // // impossible,do nothing
+            // }
+            // isBound = true;
+            return null;
+        }
+
+        SocketAddress retAddr = null;
+        try {
+            begin();
+
+            // // FIXME donot peek at time,see if can improve
+            // DatagramPacket peekPack = new DatagramPacket(new byte[1], 1);
+            // synchronized (dataLock) {
+            // networkSystem.receiveDatagram(fd, peekPack, peekPack.getData(),
+            // peekPack.getOffset(), peekPack.getLength(),
+            // isBlocking() ? 0 : DEFAULT_TIMEOUT, true);
+            // }
+            // if (null == peekPack.getAddress()) {
+            // // if no new packet peeked
+            // return null;
+            // }
+
+            // receive real data packet, (not peek)
+            synchronized (readLock) {
+                boolean loop = isBlocking();
+                do {
+                    DatagramPacket receivePacket = new DatagramPacket(
+                            new byte[target.remaining()], target.remaining());
+
+                    if (isConnected()) {
+                        networkSystem.recvConnectedDatagram(fd, receivePacket,
+                                receivePacket.getData(), receivePacket
+                                        .getOffset(),
+                                receivePacket.getLength(), isBlocking()?0:DEFAULT_TIMEOUT, false);
+                    } else {
+                        networkSystem.receiveDatagram(fd, receivePacket,
+                                receivePacket.getData(), receivePacket
+                                        .getOffset(),
+                                receivePacket.getLength(), isBlocking()?0:DEFAULT_TIMEOUT, false);
+                    }
+
+                    // security check
+                    SecurityManager sm = System.getSecurityManager();
+                    if (!isConnected() && null != sm) {
+                        try {
+                            sm.checkAccept(receivePacket.getAddress()
+                                    .getHostAddress(), receivePacket.getPort());
+                        } catch (SecurityException e) {
+                            // do discard the datagram packet
+                            receivePacket = null;
+                        }
+                    }
+                    if (null != receivePacket
+                            && null != receivePacket.getAddress()) {
+                        // copy the data of received packet
+                        target.put(ByteBuffer.wrap(receivePacket.getData()));
+                        retAddr = receivePacket.getSocketAddress();
+                        break;
+                    }
+                } while (loop);
+            }
+        } catch (SocketException e) {
+            // FIXME Depend on former function,it's a work round, wait for
+            // native improve.
+            String msg = e.getMessage();
+            if (ERRMSG_ASYNCHRONOUSCLOSE.equals(msg)) {
+                throw new AsynchronousCloseException();
+            }
+            if (ERRMSG_NONBLOKING_OUT.equals(msg)) {
+                return null;
+            }
+            throw e;
+        } catch (InterruptedIOException e) {
+            // this line used in Linux
+            return null;
+        } finally {
+            end(null != retAddr);
+        }
+        return retAddr;
+    }
+
+    /*
+     * @see java.nio.channels.DatagramChannel#send(java.nio.ByteBuffer,
+     *      java.net.SocketAddress)
+     */
+    public int send(ByteBuffer source, SocketAddress address)
+            throws IOException {
+        // must open
+        checkOpen();
+        // must not null
+        checkNotNull(source);
+
+        // transfer address
+        InetSocketAddress isa = (InetSocketAddress) address;
+        if (null == isa.getAddress()) {
+            throw new IOException();
+        }
+
+        if (isConnected()) {
+            if (!connectAddress.equals(isa)) {
+                throw new IllegalArgumentException();
+            }
+        } else {
+            // not connected, check security
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                if (isa.getAddress().isMulticastAddress()) {
+                    sm.checkMulticast(isa.getAddress());
+                } else {
+                    sm.checkConnect(isa.getAddress().getHostAddress(), isa
+                            .getPort());
+                }
+            }
+        }
+
+        // the return value.
+        int sendCount = 0;
+
+        try {
+            begin();
+
+            byte[] array;
+            // FIXME enhence the performance
+            if (source.hasArray()) {
+                array = source.array();
+            } else {
+                array = new byte[source.remaining()];
+                source.get(array);
+            }
+            DatagramPacket pack = new DatagramPacket(array, array.length, isa);
+
+            synchronized (writeLock) {
+                sendCount = networkSystem.sendDatagram(fd, pack.getData(), 0,
+                        pack.getLength(), isa.getPort(), false, trafficClass,
+                        isa.getAddress());
+            }
+            return sendCount;
+        } finally {
+            end(sendCount >= 0);
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // Methods for read and write.
+    // -------------------------------------------------------------------
+
+    /*
+     * 
+     * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer)
+     */
+    public int read(ByteBuffer target) throws IOException {
+        // status must be open and connected
+        checkOpenConnected();
+        // target buffer must be not null and not readonly
+        checkNotNullNotReadOnly(target);
+
+        synchronized (readLock) {
+            return readImpl(target);
+        }
+    }
+
+    /*
+     * 
+     * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer[], int,
+     *      int)
+     */
+    public long read(ByteBuffer[] targets, int offset, int length)
+            throws IOException {
+        if (length >= 0 && offset >= 0 && length + offset <= targets.length) {
+            // status must be open and connected
+            checkOpenConnected();
+            synchronized (readLock) {
+                long readCount = 0;
+                for (int val = offset; val < length; val++) {
+                    // target buffer must be not null and not readonly
+                    checkNotNullNotReadOnly(targets[val]);
+                    readCount = readCount + readImpl(targets[val]);
+                }
+                return readCount;
+            }
+        }
+        throw new ArrayIndexOutOfBoundsException();
+    }
+
+    /*
+     * read from channel, and store the result in the target.
+     */
+    private int readImpl(ByteBuffer target) throws IOException {
+        // the return value
+        int readCount = 0;
+
+        try {
+            begin();
+            // timeout == 0 means block read.
+            // DEFAULT_TIMEOUT is used in non-block mode.
+            int timeout = isBlocking() ? 0 : DEFAULT_TIMEOUT;
+            DatagramPacket pack;
+            if (target.hasRemaining()) {
+                pack = new DatagramPacket(new byte[target.remaining()], target
+                        .remaining());
+            } else {
+                return 0;
+            }
+            boolean loop = isBlocking();
+            do {
+                // handle asynchronous closing
+                if (!isOpen()) {
+                    throw new AsynchronousCloseException();
+                }
+                if (isConnected()) {
+                    readCount = networkSystem
+                            .recvConnectedDatagram(fd, pack, pack.getData(), 0,
+                                    pack.getLength(), timeout, false);
+                } else {
+                    readCount = networkSystem.receiveDatagram(fd, pack, pack
+                            .getData(), 0, pack.getLength(), timeout, false);
+                }
+                if (0 < readCount) {
+                    target.put(pack.getData());
+                    return readCount;
+                }
+            } while (loop);
+            return readCount;
+        } catch (SocketException e) {
+            // FIXME it's a work round, wait for native improve.
+            if (e.getMessage().equals(ERRMSG_ASYNCHRONOUSCLOSE)) {
+                throw new AsynchronousCloseException();
+            }
+            throw e;
+        } catch (InterruptedIOException e) {
+            // FIXME improve native code.
+            if (e.getMessage().equals(ERRMSG_TIMEOUT)) {
+                return 0;
+            }
+            throw e;
+        } finally {
+            end(readCount >= 0);
+        }
+    }
+
+    /*
+     * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer)
+     */
+    public int write(ByteBuffer source) throws IOException {
+        // source buffer must be not null
+        checkNotNull(source);
+        // status must be open and connected
+        checkOpenConnected();
+
+        synchronized (writeLock) {
+            return writeImpl(source);
+        }
+    }
+
+    /*
+     * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer[], int,
+     *      int)
+     */
+    public long write(ByteBuffer[] sources, int offset, int length)
+            throws IOException {
+        if (length >= 0 && offset >= 0 && length + offset <= sources.length) {
+            // status must be open and connected
+            checkOpenConnected();
+            synchronized (writeLock) {
+                int count = 0;
+                for (int val = offset; val < length; val++) {
+                    // source buffer must be not null
+                    checkNotNull(sources[val]);
+                    // add all to avoid bugs in Linux
+                    count = count + sources[val].remaining();
+                }
+                ByteBuffer writeBuf = ByteBuffer.allocate(count);
+                for (int val = offset; val < length; val++) {
+                    writeBuf.put(sources[val]);
+                }
+                return writeImpl(writeBuf);
+            }
+        }
+        throw new ArrayIndexOutOfBoundsException();
+    }
+
+    /*
+     * wirte the source. return the count of bytes written.
+     */
+    private int writeImpl(ByteBuffer buf) throws IOException {
+        // the return value
+        int result = 0;
+
+        try {
+            begin();
+            byte[] array;
+            // FIXME enhence the perform
+            if (buf.hasArray()) {
+                array = buf.array();
+            } else {
+                array = new byte[buf.remaining()];
+                buf.get(array);
+            }
+            DatagramPacket pack = new DatagramPacket(array, array.length);
+            result = networkSystem.sendConnectedDatagram(fd, pack.getData(), 0,
+                    pack.getLength(), isBound);
+            return result;
+        } finally {
+            end(result > 0);
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // Protected Inherited methods
+    // -------------------------------------------------------------------
+
+    /*
+     * do really closing action here
+     */
+    synchronized protected void implCloseSelectableChannel() throws IOException {
+        connected = false;
+        if (null != socket && !socket.isClosed()) {
+            socket.close();
+        } else {
+            networkSystem.socketClose(fd);
+        }
+    }
+
+    /*
+     * 
+     * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean)
+     */
+    protected void implConfigureBlocking(boolean blockingMode)
+            throws IOException {
+        networkSystem.setNonBlocking(fd, !blockingMode);
+    }
+
+    // -------------------------------------------------------------------
+    // Share methods for checking.
+    // -------------------------------------------------------------------
+
+    /*
+     * status check, must be open.
+     */
+    private void checkOpen() throws IOException {
+        if (!isOpen()) {
+            throw new ClosedChannelException();
+        }
+    }
+
+    /*
+     * status check, must be open and connected, for read and write.
+     */
+    private void checkOpenConnected() throws IOException {
+        checkOpen();
+        if (!isConnected()) {
+            throw new NotYetConnectedException();
+        }
+    }
+
+    /*
+     * buffer check, must not null
+     */
+    private void checkNotNull(ByteBuffer source) {
+        if (null == source) {
+            throw new NullPointerException();
+        }
+    }
+
+    /*
+     * buffer check, must not null and not read only buffer, for read and
+     * receive.
+     */
+    private void checkNotNullNotReadOnly(ByteBuffer target) {
+        // including checking of NPE.
+        if (target.isReadOnly()) {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // Adapter classes for internal socket.
+    // -------------------------------------------------------------------
+
+    /*
+     * get the fd for internal use.
+     */
+    public FileDescriptor getFD() {
+        return fd;
+    }
+
+    /*
+     * The adapter class of DatagramSocket
+     */
+    private static class DatagramSocketAdapter extends DatagramSocket {
+
+        /*
+         * The internal datagramChannelImpl.
+         */
+        private DatagramChannelImpl channelImpl;
+        
+        /*
+         * init the datagramSocketImpl and datagramChannelImpl
+         */
+        DatagramSocketAdapter(DatagramSocketImpl socketimpl,
+                DatagramChannelImpl channelImpl) {
+            super(socketimpl);
+            this.channelImpl = channelImpl;            
+        }
+
+        /*
+         * get the internal datagramChannelImpl
+         */
+        public DatagramChannel getChannel() {
+            return channelImpl;
+        }
+
+        /*
+         * @see java.net.DatagramSocket#isBound()
+         */
+        public boolean isBound() {
+            return channelImpl.isBound;
+        }
+
+        /*
+         * @see java.net.DatagramSocket#isConnected()
+         */
+        public boolean isConnected() {
+            return channelImpl.isConnected();
+        }
+
+        /*
+         * @see java.net.DatagramSocket#getInetAddress()
+         */
+        public InetAddress getInetAddress() {
+            if (null == channelImpl.connectAddress) {
+                return null;
+            }
+            return channelImpl.connectAddress.getAddress();
+        }
+        
+        /*
+         * @see java.net.DatagramSocket#getLocalAddress()
+         */
+        public InetAddress getLocalAddress(){
+            return channelImpl.getLocalAddress();
+        }
+
+        /*
+         * @see java.net.DatagramSocket#getPort()
+         */
+        public int getPort() {
+            if (null == channelImpl.connectAddress) {
+                return -1;
+            }
+            return channelImpl.connectAddress.getPort();
+        }
+
+        /*
+         * @see java.net.DatagramSocket#bind(java.net.SocketAddress)
+         */
+        public void bind(SocketAddress localAddr) throws SocketException {
+            if (channelImpl.isConnected()) {
+                throw new AlreadyConnectedException();
+            }
+            super.bind(localAddr);
+            channelImpl.isBound = true;
+        }
+
+        /*
+         * @see java.net.DatagramSocket#close()
+         */
+        public void close() {
+            synchronized (channelImpl) {
+                if (channelImpl.isOpen()) {
+                    try {
+                        channelImpl.close();
+                    } catch (IOException e) {
+                        // Ignore
+                    }
+                }
+                super.close();
+            }
+        }
+
+        /*
+         * @see java.net.DatagramSocket#disconnect()
+         */
+        public void disconnect() {
+            try {
+                channelImpl.disconnect();
+            } catch (IOException e) {
+                // Ignore
+            }
+            super.disconnect();
+        }
+    }
+}
\ No newline at end of file

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java?rev=392225&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java Fri Apr  7 02:07:34 2006
@@ -0,0 +1,83 @@
+/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.IOException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.Pipe;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+
+
+/*
+ * Internal implementation of SelectorProvider.
+ * 
+ */
+public class SelectorProviderImpl extends SelectorProvider {
+
+	/*
+	 * Constructor for this class.
+	 */
+	public SelectorProviderImpl() {
+		super();
+	}
+
+	/*
+	 * 
+	 * @see java.nio.channels.spi.SelectorProvider#openDatagramChannel()
+	 */
+	public DatagramChannel openDatagramChannel() throws IOException {
+		return new DatagramChannelImpl(this);
+	}
+
+	/*
+	 * 
+	 * @see java.nio.channels.spi.SelectorProvider#openPipe()
+	 */
+	public Pipe openPipe() throws IOException {
+//	    return new PipeImpl();
+		//FIXME: waiting for JIRA-41
+		return null;
+	}
+
+	/*
+	 * 
+	 * @see java.nio.channels.spi.SelectorProvider#openSelector()
+	 */
+	public AbstractSelector openSelector() throws IOException {
+//		return new SelectorImpl(this);
+		//FIXME: wait for JIRA-41
+		return null;
+	}
+
+	/*
+	 * 
+	 * @see java.nio.channels.spi.SelectorProvider#openServerSocketChannel()
+	 */
+	public ServerSocketChannel openServerSocketChannel() throws IOException {
+		return new ServerSocketChannelImpl(this);
+	}
+
+	/*
+	 * 
+	 * @see java.nio.channels.spi.SelectorProvider#openSocketChannel()
+	 */
+	public SocketChannel openSocketChannel() throws IOException {
+		return new SocketChannelImpl(this);
+	}
+
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java?rev=392225&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java Fri Apr  7 02:07:34 2006
@@ -0,0 +1,324 @@
+/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.net.BindException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketImpl;
+import java.net.SocketTimeoutException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.NotYetBoundException;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+import org.apache.harmony.luni.net.NetUtil;
+import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.platform.FileDescriptorHandler;
+import org.apache.harmony.luni.platform.Platform;
+import org.apache.harmony.luni.util.Msg;
+
+/*
+ * The default implementation class of java.nio.channels.ServerSocketChannel.
+ */
+public class ServerSocketChannelImpl extends ServerSocketChannel implements
+        FileDescriptorHandler {
+
+    // ----------------------------------------------------
+    // Class Variables
+    // ----------------------------------------------------
+
+    // status un-init, not initialized.
+    private static final int SERVER_STATUS_UNINIT = -1;
+
+    // status after open and before closed.
+    private static final int SERVER_STATUS_OPEN = 0;
+
+    // status closed.
+    private static final int SERVER_STATUS_CLOSED = 1;
+
+    // default timeout used to nonblocking mode.
+    private static final int DEFAULT_TIMEOUT = 100;
+
+    // error message, for native dependent.
+    private static final String ERRMSG_ASYNCHRONOUS = "The call was cancelled"; //$NON-NLS-1$
+
+    // -------------------------------------------------------------------
+    // Instance variables
+    // -------------------------------------------------------------------
+
+    // The fd to interact with native code
+    private final FileDescriptor fd;
+
+    // The interanl ServerSocket
+    private final ServerSocket socket;
+
+    private final SocketImpl impl;
+
+    int status = SERVER_STATUS_UNINIT;
+
+    // whether the socket is bound
+    boolean isBound = false;
+
+    // lock for accept
+    private final Object acceptLock = new Object();
+
+    // lock for status
+    // final Object statusLock = new Object();
+
+    // ----------------------------------------------------
+    // Constructor
+    // ----------------------------------------------------
+
+    /*
+     * Constructor
+     */
+    public ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
+        super(sp);
+        status = SERVER_STATUS_OPEN;
+        fd = new FileDescriptor();
+        Platform.getNetworkSystem().createServerStreamSocket(fd,
+                NetUtil.preferIPv4Stack());
+        impl = SocketImplProvider.getServerSocketImpl(fd);
+        socket = new ServerSocketAdapter(impl, this);
+    }
+
+    // ----------------------------------------------------
+    // Methods
+    // ----------------------------------------------------
+
+    /*
+     * Getting the internal Socket If we have not the socket, we create a new
+     * one.
+     */
+    public ServerSocket socket() {
+        return socket;
+    }
+
+    /*
+     * 
+     * @see java.nio.channels.ServerSocketChannel#accept()
+     */
+    public SocketChannel accept() throws IOException {
+        if (!isOpen()) {
+            throw new ClosedChannelException();
+        }
+        if (!isBound || !socket.isBound()) {
+            throw new NotYetBoundException();
+        }
+
+        SocketChannel sockChannel = SocketChannel.open();
+        Socket socketGot = sockChannel.socket();
+
+        try {
+            begin();
+
+            synchronized (acceptLock) {
+                synchronized (blockingLock()) {
+                    int oldtime = socket.getSoTimeout();
+                    // timeout, 0 means blocking.
+                    socket.setSoTimeout(isBlocking() ? 0 : DEFAULT_TIMEOUT);
+                    ((ServerSocketAdapter) socket).accept(socketGot,
+                            (SocketChannelImpl) sockChannel);
+                    socket.setSoTimeout(oldtime);
+                }
+            }
+        } catch (BindException e) {
+            // FIXME improve native code.
+            if (ERRMSG_ASYNCHRONOUS.equals(e.getMessage())) {
+                throw new AsynchronousCloseException();
+            }
+        } catch (SocketTimeoutException e) {
+            // nonblocking mode.
+            return null;
+        } finally {
+            end(socketGot.isConnected());
+        }
+
+        // security check
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            try {
+                sm.checkAccept(socketGot.getInetAddress().getHostAddress(),
+                        socketGot.getPort());
+            } catch (SecurityException e) {
+                sockChannel.close();
+                throw e;
+            }
+        }
+        return sockChannel;
+    }
+
+    // -------------------------------------------------------------------
+    // Protected inherited methods
+    // -------------------------------------------------------------------
+
+    /*
+     * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking
+     * 
+     * (boolean)
+     */
+    protected void implConfigureBlocking(boolean blockingMode)
+            throws IOException {
+        Platform.getNetworkSystem().setNonBlocking(getFD(), blockingMode);
+    }
+
+    /*
+     * 
+     * @see java.nio.channels.spi.AbstractSelectableChannel#implCloseSelectableChannel()
+     */
+    synchronized protected void implCloseSelectableChannel() throws IOException {
+        status = SERVER_STATUS_CLOSED;     
+        if (!socket.isClosed()) {
+            socket.close();
+        }
+    }
+
+    // ----------------------------------------------------
+    // Adapter classes.
+    // ----------------------------------------------------
+
+    /*
+     * get the fd
+     */
+    public FileDescriptor getFD() {
+        return fd;
+    }
+
+    /*
+     * The adapter class of ServerSocekt.
+     */
+    private class ServerSocketAdapter extends ServerSocket {
+        /*
+         * Internal impl.
+         */
+        ServerSocketChannelImpl channelImpl;
+
+        /*
+         * init the impl.
+         */
+        ServerSocketAdapter(SocketImpl impl,
+                ServerSocketChannelImpl aChannelImpl){
+            super(impl);
+            this.channelImpl = aChannelImpl;
+        }
+
+        /*
+         * 
+         * @see java.net.ServerSocket#bind(java.net.SocketAddress, int)
+         */
+        public void bind(SocketAddress localAddr, int backlog)
+                throws IOException {
+            super.bind(localAddr, backlog);
+        }
+
+        /*
+         * do the accept.
+         */
+        public Socket accept(Socket aSocket, SocketChannelImpl sockChannel)
+                throws IOException {
+            if (isClosed()) {
+                throw new SocketException(Msg.getString("K003d")); //$NON-NLS-1$
+            }
+            if (!isBound()) {
+                throw new SocketException(Msg.getString("K031f")); //$NON-NLS-1$
+            }
+
+            // If a SOCKS proxy is being used, accept does strange things.
+            // Instead of returning a new Socket and allowing this ServerSocket
+            // to be used for another accept, it actually uses the current
+            // ServerSocket
+            // as the accepted Socket. So, closing the returned socket will
+            // close the
+            // ServerSocket as well. The ServerSocket cannot be used for a
+            // second accept.
+            if (NetUtil.usingSocks()) {
+                return super.accept();
+            }
+
+            // a new socket is pass in so we do not need to "Socket aSocket =
+            // new Socket();"
+            boolean connectOK = false;
+            try {
+                synchronized (this) {
+                    super.implAccept(aSocket);
+                    // FIXME wait for fix.
+                    // if (aSocket.isConnected()) {
+                    sockChannel.setConnected();
+                    // }
+                }
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null) {
+                    sm.checkAccept(aSocket.getInetAddress().getHostAddress(),
+                            aSocket.getPort());
+                }
+                connectOK = true;
+            } catch (SocketException e) {
+                if (ERRMSG_ASYNCHRONOUS.equals(e.getMessage())) {
+                    throw new AsynchronousCloseException();
+                }
+            } finally {
+                if (!connectOK) {
+                    aSocket.close();
+                }
+            }
+            return aSocket;
+        }
+
+        /*
+         * getting internal channel.
+         */
+        public ServerSocketChannel getChannel() {
+            return channelImpl;
+        }
+
+        /*
+         * 
+         * @see java.net.ServerSocket#isBound()
+         */
+        public boolean isBound() {
+            return channelImpl.isBound;
+        }
+
+        /*
+         * 
+         * @see java.net.ServerSocket#bind(java.net.SocketAddress)
+         */
+        public void bind(SocketAddress localAddr) throws IOException {
+            super.bind(localAddr);
+            channelImpl.isBound = true;
+        }
+
+        /*
+         * @see java.net.ServerSocket#close()
+         */
+        public void close() throws IOException {
+            synchronized (channelImpl) {
+                if(channelImpl.isOpen()){
+                    channelImpl.close();
+                } else {
+                    super.close();
+                }
+                channelImpl.status = SERVER_STATUS_CLOSED;
+            }
+        }
+    }
+}
\ No newline at end of file

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java?rev=392225&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java Fri Apr  7 02:07:34 2006
@@ -0,0 +1,905 @@
+/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed 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.AsynchronousCloseException;
+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.SocketImplProvider;
+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.Msg;
+
+
+/*
+ * 
+ * The default implementation class of java.nio.channels.SocketChannel.
+ * 
+ */
+class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler {
+
+    // -------------------------------------------------------------------
+    // Class variables
+    // -------------------------------------------------------------------
+
+    private static final String ERRORMSG_SOCKET_INVALID = "The socket argument is not a socket";
+
+    private static final int MAX_PORT_NUMBER = 65535;
+
+    private static final int EOF = -1;
+
+    private static final String ERRMSG_SOCKET_NONBLOCKING_WOULD_BLOCK = "The socket is marked as nonblocking operation would block";
+
+    // 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;
+
+    // error msg
+    private static final String ERRCODE_PORT_ERROR = "K0032"; //$NON-NLS-1$
+
+    // error messages, for native dependent.
+    private static final String ERRORMSG_ASYNCHRONOUSCLOSE = "The call was cancelled";
+
+    // a address of localhost
+    private static final byte[] localAddrArray = { 127, 0, 0, 1 };
+
+    // -------------------------------------------------------------------
+    // Instance Variables
+    // -------------------------------------------------------------------
+
+    // The fd 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
+    int localPort;
+
+    // At first, uninitialized.
+    int status = SOCKET_STATUS_UNINIT;
+
+    // whether the socket is bound
+    boolean isBound = false;
+
+    // lock for read and write
+    private final Object readLock = new Object();
+
+    private final Object writeLock = new Object();
+
+    // lock for status
+    // private final Object statusLock = new Object();
+
+    // this content is a point used to set in connect_withtimeout() in pending
+    // mode
+    private Long connectContext = Long.valueOf("0"); //$NON-NLS-1$
+
+    // 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
+    // -------------------------------------------------------------------
+
+    /*
+     * Constructor
+     */
+    public SocketChannelImpl(SelectorProvider selectorProvider)
+            throws IOException {
+        super(selectorProvider);
+        fd = new FileDescriptor();
+        status = SOCKET_STATUS_UNCONNECTED;
+        networkSystem.createSocket(fd, true);
+    }
+
+    // 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;
+    }
+
+    // -------------------------------------------------------------------
+    // Methods for getting internal Socket.
+    // -------------------------------------------------------------------
+
+    /*
+     * Getting the internal Socket If we have not the socket, we create a new
+     * one.
+     */
+    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(SocketImplProvider.getSocketImpl(fd,
+                        localPort, addr, port), this);
+            } catch (SocketException e) {
+                return null;
+            }
+        }
+        return socket;
+    }
+
+    // -------------------------------------------------------------------
+    // Methods for connect and finishConnect
+    // -------------------------------------------------------------------
+
+    /*
+     * @see java.nio.channels.SocketChannel#isConnected()
+     */
+    synchronized public boolean isConnected() {
+        return status == SOCKET_STATUS_CONNECTED;
+    }
+
+    /*
+     * status setting used by other class.
+     */
+    synchronized void setConnected() {
+        status = SOCKET_STATUS_CONNECTED;
+    }
+
+    /*
+     * @see java.nio.channels.SocketChannel#isConnectionPending()
+     */
+    synchronized public boolean isConnectionPending() {
+        return status == SOCKET_STATUS_PENDING;
+    }
+
+    /*
+     * @see java.nio.channels.SocketChannel#connect(java.net.SocketAddress)
+     */
+    public boolean connect(SocketAddress socketAddress) throws IOException {
+        // status must be open and unconnected
+        checkUnconnected();
+
+        // check the address
+        InetSocketAddress inetSocketAddress = validateAddress(socketAddress);
+
+        int port = inetSocketAddress.getPort();
+        String hostName = inetSocketAddress.getAddress().getHostName();
+        if (port < 0 || port > MAX_PORT_NUMBER) {
+            throw new IllegalArgumentException(Msg
+                    .getString(ERRCODE_PORT_ERROR));
+        }
+        // security check
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkConnect(hostName, port);
+        }
+
+        // connect result
+        int result = EOF;
+        boolean success = false;
+
+        try {
+            begin();
+            if (!isBound) {
+                // bind
+                networkSystem.bind2(fd, 0, true, InetAddress
+                        .getByAddress(localAddrArray));
+            }
+
+            localPort = networkSystem.getSocketLocalPort(fd, false);
+            localAddress = networkSystem.getSocketLocalAddress(fd, false);
+
+            if (isBlocking()) {
+                result = networkSystem.connect(fd, trafficClass,
+                        inetSocketAddress.getAddress(), inetSocketAddress
+                                .getPort());
+
+            } else {
+                result = networkSystem.connectWithTimeout(fd, 0, trafficClass,
+                        inetSocketAddress.getAddress(), inetSocketAddress
+                                .getPort(), HY_SOCK_STEP_START, connectContext);
+            }
+
+            success = (CONNECT_SUCCESS == result);
+
+            isBound = success;
+        } catch (IOException e) {
+            if (e instanceof ConnectException && !isBlocking()) {
+                status = SOCKET_STATUS_PENDING;
+            } else {
+                close();
+                throw e;
+            }
+        } finally {
+            end(success);
+        }
+
+        // set the connected address.
+        connectAddress = inetSocketAddress;
+        synchronized (this) {
+            if (isBlocking()) {
+                status = (success ? SOCKET_STATUS_CONNECTED
+                        : SOCKET_STATUS_UNCONNECTED);
+            } else {
+                status = SOCKET_STATUS_PENDING;
+            }
+        }
+        return success;
+    }
+
+    /*
+     * @see java.nio.channels.SocketChannel#finishConnect()
+     */
+    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 success = false;
+
+        try {
+            begin();
+            if (isBlocking()) {
+                result = networkSystem.connect(fd, trafficClass, connectAddress
+                        .getAddress(), connectAddress.getPort());
+
+            } else {
+                result = networkSystem.connectWithTimeout(fd, 0, trafficClass,
+                        connectAddress.getAddress(), connectAddress.getPort(),
+                        HY_PORT_SOCKET_STEP_CHECK, connectContext);
+            }
+            success = (result == CONNECT_SUCCESS);
+        } catch (ConnectException e) {
+            close();
+            throw e;
+        } finally {
+            end(success);
+        }
+
+        synchronized (this) {
+            status = (success ? SOCKET_STATUS_CONNECTED : status);
+            isBound = success;
+        }
+        return success;
+    }
+
+    // -------------------------------------------------------------------
+    // Methods for read and write
+    // -------------------------------------------------------------------
+    /*
+     * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer)
+     */
+    public int read(ByteBuffer target) throws IOException {
+        if (null == target) {
+            throw new NullPointerException();
+        }
+        checkOpenConnected();
+
+        synchronized (readLock) {
+            return readImpl(target);
+        }
+    }
+
+    /*
+     * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer[], int,
+     *      int)
+     */
+    public long read(ByteBuffer[] targets, int offset, int length)
+            throws IOException {
+        if (isIndexValid(targets, offset, length)) {
+            checkOpenConnected();
+            synchronized (readLock) {
+                long totalCount = 0;
+                for (int val = offset; val < offset + length; val++) {
+                    int readCount = readImpl(targets[val]);
+                    // only -1 or a integer >=0 may return
+                    if (EOF != readCount) {
+                        totalCount = totalCount + readCount;
+                    } else {
+                        break;
+                    }
+                }
+                return totalCount;
+            }
+        }
+        throw new ArrayIndexOutOfBoundsException();
+    }
+
+    private boolean isIndexValid(ByteBuffer[] targets, int offset, int length) {
+        return (length >= 0) && (offset >= 0)
+                && (length + offset <= targets.length);
+    }
+
+    /*
+     * read from channel, and store the result in the target.
+     * 
+     */
+    private int readImpl(ByteBuffer target) throws IOException {
+        if (!target.hasRemaining()) {
+            return 0;
+        }
+
+        int readCount = 0;
+
+        try {
+            begin();
+            byte[] readArray = new byte[target.remaining()];
+            readCount = networkSystem.read(fd, readArray, 0, readArray.length,
+                    (isBlocking() ? TIMEOUT_BLOCK : TIMEOUT_NONBLOCK));
+            if (EOF != readCount) {
+                target.put(readArray, 0, readCount);
+            }
+            return readCount;
+        } catch (SocketException e) {
+            // FIXME improve native code
+            if (ERRORMSG_ASYNCHRONOUSCLOSE.equals(e.getMessage())
+                    || ERRORMSG_SOCKET_INVALID.equals(e.getMessage())) {
+                throw new AsynchronousCloseException();
+            }
+            throw e;
+        } finally {
+            end(readCount > 0);
+        }
+    }
+
+    /*
+     * 
+     * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer)
+     */
+    public int write(ByteBuffer source) throws IOException {
+        checkOpenConnected();
+        synchronized (writeLock) {
+            return writeImpl(source);
+        }
+    }
+
+    /*
+     * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer[], int,
+     *      int)
+     */
+    public long write(ByteBuffer[] sources, int offset, int length)
+            throws IOException {
+        if (isIndexValid(sources, offset, length)) {
+            checkOpenConnected();
+            synchronized (writeLock) {
+                long writeCount = 0;
+                for (int val = offset; val < offset + length; val++) {
+                    writeCount = writeCount + writeImpl(sources[val]);
+                }
+                return writeCount;
+            }
+        }
+        throw new ArrayIndexOutOfBoundsException();
+    }
+
+    /*
+     * wirte the source. return the count of bytes written.
+     */
+    private int writeImpl(ByteBuffer source) throws IOException {
+        if (!source.hasRemaining()) {
+            return 0;
+        }
+        int writeCount = 0;
+        try {
+            begin();
+            int pos = source.position();
+            byte[] array;
+            // FIXME enhance the perform
+            if (source.hasArray()) {
+                array = source.array();
+            } else {
+                array = new byte[source.remaining()];
+                source.get(array);
+            }
+            networkSystem.setNonBlocking(fd, !this.isBlocking());
+            writeCount = networkSystem.write(fd, array, 0, array.length);
+            source.position(pos + writeCount);
+            return writeCount;
+        } catch (SocketException e) {
+            if (ERRMSG_SOCKET_NONBLOCKING_WOULD_BLOCK.equals(e.getMessage())) {
+                return writeCount;
+            }
+            if (ERRORMSG_ASYNCHRONOUSCLOSE.equals(e.getMessage())) {
+                throw new AsynchronousCloseException();
+            }
+            throw e;
+        } finally {
+            end(writeCount >= 0);
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // Shared methods
+    // -------------------------------------------------------------------
+
+    /*
+     * 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;
+    }
+
+    // -------------------------------------------------------------------
+    // Protected inherited methods
+    // -------------------------------------------------------------------
+    /*
+     * do really closing action here
+     */
+    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)
+     */
+    protected void implConfigureBlocking(boolean blockMode) throws IOException {
+        synchronized (blockingLock()) {
+            networkSystem.setNonBlocking(fd, !blockMode);
+        }
+    }
+
+    // -------------------------------------------------------------------
+    // Adapter classes for internal socket.
+    // -------------------------------------------------------------------
+
+    /*
+     * get the fd
+     */
+    public FileDescriptor getFD() {
+        return fd;
+    }
+
+    public InetAddress getAddress() {
+        return (null == this.connectAddress) ? null : this.connectAddress
+                .getAddress();
+    }
+
+    public int getPort() {
+        return (null == this.connectAddress) ? 0 : this.connectAddress
+                .getPort();
+    }
+
+    public int getLocalPort() {
+        return this.localPort;
+    }
+
+    private static class SocketAdapter extends Socket {
+
+        // ----------------------------------------------------
+        // Class Variables
+        // ----------------------------------------------------
+
+        private static final String ERRCODE_CHANNEL_NOT_CONNECTED = "K0320"; //$NON-NLS-1$
+
+        private static final String ERRCODE_CHANNEL_CLOSED = "K003d"; //$NON-NLS-1$
+
+        SocketChannelImpl channel;
+
+        SocketImpl socketImpl;
+
+        // ----------------------------------------------------
+        // Methods
+        // ----------------------------------------------------
+
+        SocketAdapter(SocketImpl socketimpl, SocketChannelImpl channel)
+                throws SocketException {
+            super(socketimpl);
+            socketImpl = socketimpl;
+            this.channel = channel;
+        }
+
+        /*
+         * 
+         * @see java.net.Socket#getChannel()
+         */
+        public SocketChannel getChannel() {
+            return channel;
+        }
+
+        /*
+         * 
+         * @see java.net.Socket#isBound()
+         */
+        public boolean isBound() {
+            return channel.isBound;
+        }
+
+        /*
+         * 
+         * @see java.net.Socket#isConnected()
+         */
+        public boolean isConnected() {
+            return channel.isConnected();
+        }
+
+        /*
+         * 
+         * @see java.net.Socket#getLocalAddress()
+         */
+        public InetAddress getLocalAddress() {
+            try {
+                return channel.getLocalAddress();
+            } catch (UnknownHostException e) {
+                return null;
+            }
+        }
+
+        /*
+         * 
+         * @see java.net.Socket#connect(java.net.SocketAddress, int)
+         */
+        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)
+         */
+        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()
+         */
+        public void close() throws IOException {
+            synchronized (channel) {
+                if (channel.isOpen()) {
+                    channel.close();
+                } else {
+                    super.close();
+                }
+                channel.status = SocketChannelImpl.SOCKET_STATUS_CLOSED;
+            }
+        }
+
+        /*
+         * 
+         * @see java.net.Socket#getKeepAlive()
+         */
+        public boolean getKeepAlive() throws SocketException {
+            checkClosedAndCreate(true);
+            return ((Boolean) socketImpl.getOption(SocketOptions.SO_KEEPALIVE))
+                    .booleanValue();
+        }
+
+        /*
+         * 
+         * @see java.net.Socket#getOOBInline()
+         */
+        public boolean getOOBInline() throws SocketException {
+            checkClosedAndCreate(true);
+            return ((Boolean) socketImpl.getOption(SocketOptions.SO_OOBINLINE))
+                    .booleanValue();
+        }
+
+        /*
+         * 
+         * @see java.net.Socket#getSoLinger()
+         */
+        public int getSoLinger() throws SocketException {
+            checkClosedAndCreate(true);
+            return ((Integer) socketImpl.getOption(SocketOptions.SO_LINGER))
+                    .intValue();
+        }
+
+        /*
+         * 
+         * @see java.net.Socket#getTcpNoDelay()
+         */
+        public boolean getTcpNoDelay() throws SocketException {
+            checkClosedAndCreate(true);
+            return ((Boolean) socketImpl.getOption(SocketOptions.TCP_NODELAY))
+                    .booleanValue();
+        }
+
+        /*
+         * 
+         * @see java.net.Socket#getOutputStream()
+         */
+        public OutputStream getOutputStream() throws IOException {
+            return new SocketChannelOutputStream(super.getOutputStream(),
+                    channel);
+        }
+
+        /*
+         * 
+         * @see java.net.Socket#getInputStream()
+         */
+        public InputStream getInputStream() throws IOException {
+            return new SocketChannelInputStream(super.getInputStream(), channel);
+        }
+
+        /*
+         * checl if channel is close or create a new one.
+         */
+        private void checkClosedAndCreate(boolean create)
+                throws SocketException {
+            if (isClosed()) {
+                throw new SocketException(Msg.getString(ERRCODE_CHANNEL_CLOSED));
+            }
+            if (!create && !isConnected()) {
+                throw new SocketException(Msg
+                        .getString(ERRCODE_CHANNEL_NOT_CONNECTED));
+            }
+            // FIXME check if need cread fd
+        }
+
+        /*
+         * used for net and nio exchange
+         */
+        public SocketImpl getImpl() {
+            return socketImpl;
+        }
+    }
+
+    private static class SocketChannelOutputStream extends OutputStream {
+        SocketChannel channel;
+
+        OutputStream wrapped;
+
+        public SocketChannelOutputStream(OutputStream wrapped,
+                SocketChannel channel) {
+            this.channel = channel;
+            this.wrapped = wrapped;
+        }
+
+        /*
+         * 
+         * @see com.ibm.io.nio.SocketOutputStream#write(byte[], int, int)
+         */
+        public void write(byte[] buffer, int offset, int count)
+                throws IOException {
+            if (!channel.isBlocking()) {
+                throw new IllegalBlockingModeException();
+            }
+            wrapped.write(buffer, offset, count);
+        }
+
+        /*
+         * 
+         * @see com.ibm.io.nio.SocketOutputStream#write(byte[])
+         */
+        public void write(byte[] buffer) throws IOException {
+            if (!channel.isBlocking()) {
+                throw new IllegalBlockingModeException();
+            }
+            wrapped.write(buffer);
+        }
+
+        /*
+         * 
+         * @see com.ibm.io.nio.SocketOutputStream#write(int)
+         */
+        public void write(int oneByte) throws IOException {
+            if (!channel.isBlocking()) {
+                throw new IllegalBlockingModeException();
+            }
+            wrapped.write(oneByte);
+        }
+    }
+
+    private static class SocketChannelInputStream extends InputStream {
+        SocketChannel channel;
+
+        InputStream wrapped;
+
+        public SocketChannelInputStream(InputStream wrapped,
+                SocketChannel channel) {
+            this.channel = channel;
+            this.wrapped = wrapped;
+        }
+
+        /*
+         * 
+         * @see com.ibm.io.nio.SocketInputStream#read()
+         */
+        public int read() throws IOException {
+            if (!channel.isBlocking()) {
+                throw new IllegalBlockingModeException();
+            }
+            return wrapped.read();
+        }
+
+        /*
+         * 
+         * @see com.ibm.io.nio.SocketInputStream#read(byte[], int, int)
+         */
+        public int read(byte[] buffer, int offset, int count)
+                throws IOException {
+            if (!channel.isBlocking()) {
+                throw new IllegalBlockingModeException();
+            }
+            return wrapped.read(buffer, offset, count);
+        }
+
+        /*
+         * 
+         * @see com.ibm.io.nio.SocketInputStream#read(byte[])
+         */
+        public int read(byte[] buffer) throws IOException {
+            if (!channel.isBlocking()) {
+                throw new IllegalBlockingModeException();
+            }
+            return wrapped.read(buffer);
+        }
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/AllTests.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/AllTests.java?rev=392225&r1=392224&r2=392225&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/AllTests.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/AllTests.java Fri Apr  7 02:07:34 2006
@@ -24,7 +24,10 @@
 		TestSuite suite = new TestSuite(
 				"Test for org.apache.harmony.tests.java.nio.channels");
 		//$JUnit-BEGIN$
+		suite.addTestSuite(ServerSocketChannelTest.class);
+		suite.addTestSuite(SocketChannelTest.class);
 		suite.addTestSuite(FileChannelTest.class);
+		suite.addTestSuite(DatagramChannelTest.class);
 		//$JUnit-END$
 		return suite;
 	}