Index: D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/ServerSocketChannel.java
===================================================================
--- D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/ServerSocketChannel.java (revision 0)
+++ D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/ServerSocketChannel.java (revision 0)
@@ -0,0 +1,116 @@
+/* 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 java.nio.channels;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+/**
+ * A ServerSocketChannel is a partly abstracted stream-oriented listening socket
+ * which is selectable. Binding and manipulation of socket options can only be done
+ * through the associated ServerSocket object, returned by calling
+ * socket method. ServerSocketChannels can not be constructed for a pre-existing
+ * server socket, nor can it be assigned a SocketImpl.
+ *
+ * A Server-Socket channel is open but not bound when created by
+ * open method. (Calling accept before bound will cause a
+ * NotYetBoundException). It can be bound by calling the bind method
+ * of a related ServerSocket instance.
+ * This channel is got by calling openServerSocketChannel
+ * method of the default SelectorProvider instance.
+ *
SelectionKey.OP_ACCEPT.
+ *
+ * @see java.nio.channels.SelectableChannel#validOps()
+ * @return Valid operations in bit-set.
+ */
+ public final int validOps() {
+ return SelectionKey.OP_ACCEPT;
+ }
+
+ /**
+ * Return the related server-socket of this channel.
+ * All public methods declared in returned object should be declared in ServerSocket.
+ *
+ * @return The related ServerSocket instance.
+ */
+ public abstract ServerSocket socket();
+
+ /**
+ * Accepts a connection to this socket.
+ * + * It returns null when the channel is non-blocking and no connections available, otherwise it + * blocks indefinitely until a new connection is available or an I/O error occurs. + * The returned channel will be in blocking mode any way. + *
+ * + *
+ * This method just execute the same security checks as the accept method of
+ * the ServerSocket class.
+ *
+ * In this class, there are methods about registring/deregistering a channel, + * about channel closing. It realize the multi-thread safe. + *
* */ -public abstract class AbstractSelectableChannel extends SelectableChannel - implements Channel, InterruptibleChannel { +public abstract class AbstractSelectableChannel extends SelectableChannel { - /** - * @param provider - */ - public AbstractSelectableChannel(SelectorProvider provider) { + private final SelectorProvider provider; - // TODO Auto-generated constructor stub - } + /* + * The collection of key. + */ + private List keyList = new ArrayList(); + private final Object blockingLock = new Object(); + + boolean isBlocking = true; + + /** + * Constructor for this class. + * + * @param selectorProvider + * A instance of SelectorProvider + */ + protected AbstractSelectableChannel(SelectorProvider selectorProvider) { + super(); + provider = selectorProvider; + } + + /** + * Answer the SelectorProvider of this channel. + * + * @see java.nio.channels.SelectableChannel#provider() + * @return The provider of this channel. + */ + public final SelectorProvider provider() { + return provider; + } + + /** + * @see java.nio.channels.SelectableChannel#isRegistered() + */ + synchronized public final boolean isRegistered() { + return !keyList.isEmpty(); + } + + /** + * @see java.nio.channels.SelectableChannel#keyFor(java.nio.channels.Selector) + */ + synchronized public final SelectionKey keyFor(Selector selector) { + for (int i = 0; i < keyList.size(); i++) { + SelectionKey key = (SelectionKey) keyList.get(i); + if (null != key && key.selector() == selector) { + return key; + } + } + return null; + } + + /** + * Realize the register function. + *
+ * It registers current channel to the selector, then answer the selection
+ * key. The channel must be open and the interest op set must be valid. If
+ * the current channel is already registered to the selector, the method
+ * only set the new interest op set; otherwise it will call the
+ * register in selector, and add the relative
+ * key to the key set of the current channel.
+ *
true for blocking mode; false
+ * for non-blocking mode.
+ */
+ public final SelectableChannel configureBlocking(boolean blockingMode)
+ throws IOException {
+ if (isOpen()) {
+ synchronized (blockingLock) {
+ if (isBlocking == blockingMode) {
+ return this;
+ }
+ if (blockingMode && isRegistered()) {
+ throw new IllegalBlockingModeException();
+ }
+ implConfigureBlocking(blockingMode);
+ isBlocking = blockingMode;
+ }
+ return this;
+ }
+ throw new ClosedChannelException();
+
+ }
+
+ /**
+ * Implement the setting of blocking mode.
+ *
+ * @param blockingMode
+ * true for blocking mode; false
+ * for non-blocking mode.
+ * @throws IOException
+ * If some I/O exception occured.
+ */
+ protected abstract void implConfigureBlocking(boolean blockingMode)
+ throws IOException;
+
+ /*
+ * package private for deregister method in AbstractSelector.
+ */
+ synchronized void deRegister(SelectionKey k) {
+ if (null != keyList) {
+ keyList.remove(k);
+ }
+ }
+
}
Index: D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java
===================================================================
--- D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java (revision 386040)
+++ D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java (working copy)
@@ -1,4 +1,4 @@
-/* Copyright 2005 The Apache Software Foundation or its licensors, as applicable
+/* 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.
@@ -15,25 +15,234 @@
package java.nio.channels.spi;
-
+import java.io.BufferedReader;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.nio.channels.Channel;
+import java.nio.channels.DatagramChannel;
import java.nio.channels.Pipe;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Enumeration;
+import org.apache.harmony.nio.internal.SelectorProviderImpl;
+
/**
- * TODO Type description
+ * Provider for nio selector and selectable channel.
+ *
+ * The provider can be got by system property or the configuration file in a jar
+ * file, if not, the system default provider will return. The main function of
+ * this class is to return the instance of implementation class of
+ * DatagramChannel, Pipe, Selector ,
+ * ServerSocketChannel, and SocketChannel. All
+ * the methods of this class are multi-thread safe.
+ *
+ *
DatagramChannel.
+ *
+ * @return The channel.
+ * @throws IOException
+ * If some I/O exception occured.
+ */
+ public abstract DatagramChannel openDatagramChannel() throws IOException;
+
+ /**
+ * Create a new Pipe.
+ *
+ * @return The pipe.
+ * @throws IOException
+ * If some I/O exception occured.
+ */
+ public abstract Pipe openPipe() throws IOException;
+
+ /**
+ * Create a new selector.
+ *
+ * @return The selector.
+ * @throws IOException
+ * If some I/O exception occured.
+ */
+ public abstract AbstractSelector openSelector() throws IOException;
+
+ /**
+ * Create a new open ServerSocketChannel.
+ *
+ * @return The channel.
+ * @throws IOException
+ * If some I/O exception occured.
+ */
+ public abstract ServerSocketChannel openServerSocketChannel()
+ throws IOException;
+
+ /**
+ * Create a new open SocketChannel.
+ *
+ * @return The channel.
+ * @throws IOException
+ * If some I/O exception occured.
+ */
+ public abstract SocketChannel openSocketChannel() throws IOException;
+
+ /**
+ * Answer the channel inherited from the instance which created this JVM.
+ *
+ * @return The channel.
+ * @throws IOException
+ * If some I/O exception occured.
+ * @throws SecurityException
+ * If there is a security manager, and it denies
+ * RuntimePermission("selectorProvider").
+ */
+ public Channel inheritedChannel() throws IOException {
+ return null;
+// FIXME waiting for VM support
+// if (null == inheritedChannel) {
+// inheritedChannel = OSComponentFactory.getNetworkSystem()
+// .inheritedChannel();
+// }
+// return inheritedChannel;
+ }
}
Index: D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/SocketChannel.java
===================================================================
--- D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/SocketChannel.java (revision 0)
+++ D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/SocketChannel.java (revision 0)
@@ -0,0 +1,475 @@
+/* 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 java.nio.channels;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+/**
+ * A SocketChannel is a selectable channel for part abstraction of stream
+ * connecting socket. The socket method of this class can return
+ * the related Socket instance, which can handle the socket.
+ *
+ * A socket channel is open but not connected when created by open
+ * method. After connected by calling the connect method, it will
+ * keep connected before closed. The connection is non-blocking that the
+ * connect method is for the initial connection and following
+ * finishConnect method is for the final steps of connection. The
+ * isConnectionPending method can tell the connection is blocked
+ * or not; the isConnected method can tell the socket is
+ * connected finally or not.
+ *
+ * The shut down operation can be independent and asynchronous for input and
+ * output. The shutdownInput method is for input, and can make
+ * the following read operation fail as end of stream. If the input is shut down
+ * and another thread is pending in read operation, the read will end without
+ * effect and return end of stream. The shutdownOutput method is
+ * for output, and can make the following write operation throwing a
+ * ClosedChannelException. If the output is shut down and
+ * another is pending in a write operation, an
+ * AsynchronousCloseException will thrown to the pending thread.
+ *
+ * Socket channels are thread-safe, no more than one thread can read or write at
+ * given time. The connect and finishConnect
+ * methods are concurrent each other, when they are processing, other read and
+ * write will block.
+ *
+ * This channel is got by openSocketChannel method of the
+ * default SelectorProvider instance.
+ *
+ * This method perform just as open method following by the
+ * connect method.
+ *
SelectionKey.OP_CONNECT |
+ * SelectionKey.OP_READ | SelectionKey.OP_WRITE ).
+ *
+ * @see java.nio.channels.SelectableChannel#validOps()
+ * @return Valid operations in bit-set.
+ */
+ public final int validOps() {
+ return (SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE);
+ }
+
+ /**
+ * Return the related socket of this channel, which won't declare public
+ * methods that not declared in Socket.
+ *
+ * @return The related Socket instance.
+ */
+ public abstract Socket socket();
+
+ /**
+ * Answer whether this channel's socket is connected or not.
+ *
+ * @return true for this channel's socket is connected;
+ * false otherwise.
+ */
+ public abstract boolean isConnected();
+
+ /**
+ * Answer whether this channel's socket is in connecting or not.
+ *
+ * @return true for the connection is initiated but not
+ * finished; false otherwise.
+ */
+ public abstract boolean isConnectionPending();
+
+ /**
+ * Connect the socket to remote address.
+ *
+ * If the channel is blocking, this method will suspend before connection
+ * finished or an I/O exception. If the channel is non-blocking, this method
+ * will return true if the connection is finished at once or
+ * return false and the connection must wait
+ * finishConnect to finished otherwise.
+ *
+ * This method can be called at any moment, and can block other read and + * write operations while connecting. + *
+ *
+ * This method just execute the same security checks as the connect method
+ * of the Socket class.
+ *
true if connection is finished,false
+ * otherwise.
+ * @throws AlreadyConnectedException
+ * If the channel is connected already.
+ * @throws ConnectionPendingException
+ * A non-blocking connecting is doing on this channel.
+ * @throws ClosedChannelException
+ * If the channel is already closed.
+ * @throws AsynchronousCloseException
+ * If the channel is closed by another thread while this method
+ * is in operation.
+ * @throws ClosedByInterruptException
+ * If another thread interrupts the calling thread while the
+ * operation is in progress. The calling thread will have the
+ * interrupt state set, and the channel will be closed.
+ * @throws UnresolvedAddressException
+ * If the address is not resolved.
+ * @throws UnsupportedAddressTypeException
+ * If the address type is not supported.
+ * @throws SecurityException
+ * If there is a security manager, and the address is not
+ * permitted to access.
+ * @throws IOException
+ * Some other IO error occurred.
+ *
+ */
+ public abstract boolean connect(SocketAddress address) throws IOException;
+
+ /**
+ * Complete the connection.
+ *
+ * This method is used when the channel is connectable to finish the
+ * connection, and the connectable status of a channel means the channel is
+ * after initiating in non-blocking mode and calling its
+ * connect method. It will throw related
+ * IOException if the connection failed.
+ *
+ * This method will return true if the connection is finished
+ * already, and return false if the channel is non-blocking
+ * and the connection is not finished yet.
+ *
+ * If the channel is in blocking mode, this method will suspend, and return
+ * true for connection finished or throw some exception
+ * otherwise. The channel will be closed if the connection failed and this
+ * method thrown some exception.
+ *
+ * This method can be called at any moment, and can block other read and + * write operations while connecting. + *
+ * + * @returntrue if the connection is successfully finished,
+ * false otherwise.
+ * @throws NoConnectionPendingException
+ * If the channel is not connected and the connection is not
+ * initiated.
+ * @throws ClosedChannelException
+ * If the channel is already closed.
+ * @throws AsynchronousCloseException
+ * If the channel is closed by another thread while this method
+ * is in operation.
+ * @throws ClosedByInterruptException
+ * If another thread interrupts the calling thread while the
+ * operation is in progress. The calling thread will have the
+ * interrupt state set, and the channel will be closed.
+ * @throws IOException
+ * Some other IO error occurred.
+ *
+ */
+ public abstract boolean finishConnect() throws IOException;
+
+ /**
+ * Reads bytes from the channel into the given buffer.
+ *
+ * The maximum number of bytes that will be read is the
+ * remaining() number of bytes in the buffer when the method
+ * invoked. The bytes will be read into the buffer starting at the buffer's
+ * position.
+ *
+ * The call may block if other threads are also attempting to read on the + * same channel. + *
+ *
+ * Upon completion, the buffer's position() is updated to the
+ * end of the bytes that were read. The buffer's limit() is
+ * unmodified.
+ *
+ * This method attempts to read all of the remaining() bytes
+ * from length byte buffers, in order, starting at
+ * targets[offset]. The number of bytes actually read is
+ * returned.
+ *
+ * If a read operation is in progress, subsequent threads will block until + * the read is completed, and will then contend for the ability to read. + *
+ * + * @see java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[], + * int, int) + * @param targets + * the array of byte buffers into which the bytes will be read. + * @param offset + * the index of the first buffer to read. + * @param length + * the maximum number of buffers to read. + * @throws NotYetConnectedException + * If the channel is not connected yet. + * @throws ClosedChannelException + * If the channel is already closed. + * @throws AsynchronousCloseException + * If the channel is closed by another thread while this method + * is in operation. + * @throws ClosedByInterruptException + * If another thread interrupts the calling thread while the + * operation is in progress. The calling thread will have the + * interrupt state set, and the channel will be closed. + * @throws IOException + * Some other IO error occurred. + * + */ + public abstract long read(ByteBuffer[] targets, int offset, int length) + throws IOException; + + /** + * Reads bytes from the channel into all the given buffers. + *+ * This method is equivalent to: + * + *
+ * read(targets, 0, targets.length); + *+ * + * @see java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[]) + * @param targets + * the array of byte buffers to receive the bytes being read. + * @return the number of bytes actually read. + * @throws NotYetConnectedException + * If the channel is not connected yet. + * @throws ClosedChannelException + * If the channel is already closed. + * @throws AsynchronousCloseException + * If the channel is closed by another thread while this method + * is in operation. + * @throws ClosedByInterruptException + * If another thread interrupts the calling thread while the + * operation is in progress. The calling thread will have the + * interrupt state set, and the channel will be closed. + * @throws IOException + * Some other IO error occurred. + * + */ + public synchronized final long read(ByteBuffer[] targets) + throws IOException { + return read(targets, 0, targets.length); + } + + /** + * Writes bytes from the given buffer to the channel. + *
+ * The maximum number of bytes that will be written is the
+ * remaining() number of bytes in the buffer when the method
+ * invoked. The bytes will be written from the buffer starting at the
+ * buffer's position.
+ *
+ * The call may block if other threads are also attempting to write on the + * same channel. + *
+ *
+ * Upon completion, the buffer's position() is updated to the
+ * end of the bytes that were written. The buffer's limit()
+ * is unmodified.
+ *
+ * This method attempts to write all of the remaining() bytes
+ * from length byte buffers, in order, starting at
+ * sources[offset]. The number of bytes actually written is
+ * returned.
+ *
+ * If a write operation is in progress, subsequent threads will block until + * the write is completed, and will then contend for the ability to write. + *
+ * + * @see java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[], + * int, int) + * @param sources + * the array of byte buffers containing the source of remaining + * bytes that will be attempted to be written. + * @param offset + * the index of the first buffer to write. + * @param length + * the number of buffers to write. + * @return the number of bytes actually written. + * @throws NotYetConnectedException + * If the channel is not connected yet. + * @throws ClosedChannelException + * If the channel is already closed. + * @throws AsynchronousCloseException + * If the channel is closed by another thread while this method + * is in operation. + * @throws ClosedByInterruptException + * If another thread interrupts the calling thread while the + * operation is in progress. The calling thread will have the + * interrupt state set, and the channel will be closed. + * @throws IOException + * Some other IO error occurred. + * + */ + public abstract long write(ByteBuffer[] sources, int offset, int length) + throws IOException; + + /** + * Writes bytes from all the given buffers to the channel. + *+ * This method is equivalent to: + * + *
+ * write(buffers, 0, buffers.length); + *+ * + * + * + * @see java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[]) + * @param sources + * the buffers containing bytes to be written. + * @return the number of bytes actually written. + * @throws NotYetConnectedException + * If the channel is not connected yet. + * @throws ClosedChannelException + * If the channel is already closed. + * @throws AsynchronousCloseException + * If the channel is closed by another thread while this method + * is in operation. + * @throws ClosedByInterruptException + * If another thread interrupts the calling thread while the + * operation is in progress. The calling thread will have the + * interrupt state set, and the channel will be closed. + * @throws IOException + * Some other IO error occurred. + * + */ + public synchronized final long write(ByteBuffer[] sources) + throws IOException { + return write(sources, 0, sources.length); + } +} Index: D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/DatagramChannel.java =================================================================== --- D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/DatagramChannel.java (revision 0) +++ D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/DatagramChannel.java (revision 0) @@ -0,0 +1,447 @@ +/* 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 java.nio.channels; + +import java.io.IOException; +import java.net.DatagramSocket; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.spi.AbstractSelectableChannel; +import java.nio.channels.spi.SelectorProvider; + +/** + * A DatagramChannel is a selectable channel for part abstraction of datagram + * socket. The
socket method of this class can return the related
+ * DatagramSocket instance, which can handle the socket.
+ *
+ * A datagram channel is open but not connected when created by
+ * open method. After connected, it will keep the connected
+ * status before disconnecting or closing. The benefit of a connected channel is
+ * the reduced effort of security checks during send and receive. When invoking
+ * read or write, a connected channel is
+ * required.
+ *
+ * Datagram channels are thread-safe, no more than one thread can read or write + * at given time. + *
+ * + */ +public abstract class DatagramChannel extends AbstractSelectableChannel + implements ByteChannel, ScatteringByteChannel, GatheringByteChannel { + + /** + * Constructor for this class. + * + * @param selectorProvider + * A instance of SelectorProvider + */ + protected DatagramChannel(SelectorProvider selectorProvider) { + super(selectorProvider); + } + + /** + * Create a open and not-connected datagram channel. + *
+ * This channel is got by openDatagramChannel method of the
+ * default SelectorProvider instance.
+ *
SelectionKey.OP_READ | SelectionKey.OP_WRITE ).
+ *
+ * @see java.nio.channels.SelectableChannel#validOps()
+ * @return Valid operations in bit-set.
+ */
+ public final int validOps() {
+ return (SelectionKey.OP_READ | SelectionKey.OP_WRITE);
+ }
+
+ /**
+ * Return the related datagram socket of this channel, which won't declare
+ * public methods that not declared in DatagramSocket.
+ *
+ * @return The related DatagramSocket instance.
+ */
+ public abstract DatagramSocket socket();
+
+ /**
+ * Answer whether this channel's socket is connected or not.
+ *
+ * @return true for this channel's socket is connected;
+ * false otherwise.
+ */
+ public abstract boolean isConnected();
+
+ /**
+ * Connect the socket of this channel to a remote address, which is the only
+ * communication peer of getting and sending datagrams after connected.
+ * + * This method can be called at any moment, and won't affect the processing + * read and write operation. The connect status won't changed before + * disconnected and closed. + *
+ *
+ * This method just execute the same security checks as the connect method
+ * of the DatagramSocket class.
+ *
+ * This method can be called at any moment, and won't affect the processing + * read and write operation. It won't has any effect if the socket is not + * connected or the channel is closed. + *
+ * + * @return This channel. + * @throws IOException + * Some other IO error occurred. + */ + public abstract DatagramChannel disconnect() throws IOException; + + /** + * Get a datagram from this channel. + *
+ * This method transfers the datagram from the channel into the target byte
+ * buffer and return the address of the datagram, if the datagram is
+ * available or will be available as this channel is in blocking mode. This
+ * method returns null if the datagram is not available now
+ * and the channel is in non-blocking mode. The transfer start at the
+ * current position of the buffer, and the residual part of the datagram
+ * will be ignored if there is no efficient remaining in the buffer to store
+ * the datagram.
+ *
+ * This method can be called at any moment, and will block if there is + * another thread started a read operation on the channel. + *
+ *
+ * This method just execute the same security checks as the receive method
+ * of the DatagramSocket class.
+ *
+ * The precondition of sending is that whether the channel is in blocking + * mode and enough byte buffer space will be available, or the channel is in + * non-blocking mode and byte buffer space is enough. The transfer action is + * just like a regular write operation. + *
+ *+ * This method can be called at any moment, and will block if there is + * another thread started a read operation on the channel. + *
+ *
+ * This method just execute the same security checks as the send method of
+ * the DatagramSocket class.
+ *
+ * The precondition of calling this method is that the channel is connected
+ * and the coming datagram is from the connected address. If the buffer is
+ * not enough to store the datagram, the residual part of the datagram is
+ * ignored. Otherwise, this method has the same behavior as the read method
+ * in the ReadableByteChannel interface.
+ *
+ * The precondition of calling this method is that the channel is connected
+ * and the coming datagram is from the connected address. If the buffer is
+ * not enough to store the datagram, the residual part of the datagram is
+ * ignored. Otherwise, this method has the same behavior as the read method
+ * in the ScatteringByteChannel interface.
+ *
+ * The precondition of calling this method is that the channel is connected
+ * and the coming datagram is from the connected address. If the buffer is
+ * not enough to store the datagram, the residual part of the datagram is
+ * ignored. Otherwise, this method has the same behavior as the read method
+ * in the ScatteringByteChannel interface.
+ *
+ * The precondition of calling this method is that the channel is connected
+ * and the datagram is sent to the connected address. Otherwise, this method
+ * has the same behavior as the write method in the
+ * WritableByteChannel interface.
+ *
+ * The precondition of calling this method is that the channel is connected
+ * and the datagram is sent to the connected address. Otherwise, this method
+ * has the same behavior as the write method in the
+ * GatheringByteChannel interface.
+ *
+ * @see java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[],
+ * int, int)
+ * @param sources
+ * The byte buffers as the source of the datagram.
+ * @param offset
+ * A non-negative offset in the array of buffer, pointing to the
+ * starting buffer to be retrieved, must no larger than
+ * sources.length.
+ * @param length
+ * A non-negative length to indicate the maximum number of byte
+ * to be written, must no larger than sources.length - offset.
+ * @return The number of written bytes. If this method is called, it returns
+ * the number of bytes that remaining in the byte buffer. If the
+ * channel is in non-blocking mode and no enough space for the
+ * datagram in the buffer, it may returns zero.
+ * @throws NotYetConnectedException
+ * If the channel is not connected yet.
+ * @throws ClosedChannelException
+ * If the channel is already closed.
+ * @throws AsynchronousCloseException
+ * If the channel is closed by another thread while this method
+ * is in operation.
+ * @throws ClosedByInterruptException
+ * If another thread interrupts the calling thread while the
+ * operation is in progress. The calling thread will have the
+ * interrupt state set, and the channel will be closed.
+ * @throws IOException
+ * Some other IO error occurred.
+ *
+ */
+ public abstract long write(ByteBuffer[] sources, int offset, int length)
+ throws IOException;
+
+ /**
+ * Write datagram from the byte buffer into the channel.
+ *
+ * The precondition of calling this method is that the channel is connected
+ * and the datagram is sent to the connected address. Otherwise, this method
+ * has the same behavior as the write method in the
+ * GatheringByteChannel interface.
+ *
+ * @see java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[])
+ * @param sources
+ * The byte buffers as the source of the datagram.
+ * @return The number of written bytes. If this method is called, it returns
+ * the number of bytes that remaining in the byte buffer. If the
+ * channel is in non-blocking mode and no enough space for the
+ * datagram in the buffer, it may returns zero.
+ * @throws NotYetConnectedException
+ * If the channel is not connected yet.
+ * @throws ClosedChannelException
+ * If the channel is already closed.
+ * @throws AsynchronousCloseException
+ * If the channel is closed by another thread while this method
+ * is in operation.
+ * @throws ClosedByInterruptException
+ * If another thread interrupts the calling thread while the
+ * operation is in progress. The calling thread will have the
+ * interrupt state set, and the channel will be closed.
+ * @throws IOException
+ * Some other IO error occurred.
+ *
+ */
+ public synchronized final long write(ByteBuffer[] sources)
+ throws IOException {
+ return write(sources, 0, sources.length);
+ }
+}
Index: D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
===================================================================
--- D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java (revision 0)
+++ D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java (revision 0)
@@ -0,0 +1,906 @@
+/* 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 com.ibm.oti.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"; //$NON-NLS-1$
+
+ 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"; //$NON-NLS-1$
+
+ // 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"; //$NON-NLS-1$
+
+ // 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);
+ }
+ }
+}
Index: D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java
===================================================================
--- D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java (revision 0)
+++ D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java (revision 0)
@@ -0,0 +1,234 @@
+/* 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.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+
+
+/*
+ * Static methods for I/O util. Used by io package and nio package.
+ *
+ */
+public final class IOUtil {
+
+ // -------------------------------------------------------------------
+ // Class variables
+ // -------------------------------------------------------------------
+
+ private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+ // -------------------------------------------------------------------
+ // Constructor
+ // -------------------------------------------------------------------
+
+ /*
+ * No instance.
+ */
+ private IOUtil() {
+ super();
+ }
+
+ // -------------------------------------------------------------------
+ // Routine methods.
+ // -------------------------------------------------------------------
+
+ /*
+ * Read method for InputStreamReader and Channels.
+ */
+ public static int readInputStreamReader(InputStream in, ByteBuffer bytes,
+ CharBuffer chars, CharsetDecoder decoder, Object lock)
+ throws IOException {
+ synchronized (lock) {
+ if (in != null) {
+ if (chars.limit() == chars.position()) {
+ fillBuf(in, bytes, chars, decoder);
+ }
+ if (chars.limit() == 0) {
+ return -1;
+ }
+ return chars.get();
+ }
+ throw new IOException("InputStreamReader is closed."); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * Read method for InputStreamReader and Channels.
+ */
+ public static int readInputStreamReader(char[] buf, int offset, int length,
+ InputStream in, ByteBuffer bytes, CharBuffer chars,
+ CharsetDecoder decoder, Object lock) throws IOException {
+ synchronized (lock) {
+ if (in != null) {
+ if (length == 0) {
+ return 0;
+ }
+ if (offset < 0 || length < 0 || offset + length > buf.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ // read at least once
+ if (chars.limit() == chars.position()) {
+ fillBuf(in, bytes, chars, decoder);
+ }
+ int position = chars.position();
+ int availableChars = chars.limit() - position;
+ // read at least once for one byte
+ int needChars = length;
+ while (availableChars < needChars) {
+ System.arraycopy(chars.array(), position, buf, offset,
+ availableChars);
+ chars.position(position + availableChars);
+ needChars -= availableChars;
+ offset += availableChars;
+ if (in.available() <= 0) {
+ return needChars == length ? -1 : length - needChars;
+ }
+ fillBuf(in, bytes, chars, decoder);
+ position = chars.position();
+ availableChars = chars.limit();
+ if (availableChars == 0) {
+ return needChars == length ? -1 : length - needChars;
+ }
+ }
+ System.arraycopy(chars.array(), position, buf, offset,
+ needChars);
+ chars.position(chars.position() + needChars);
+ return length;
+ }
+ throw new IOException("InputStreamReader is closed."); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * refill the buffer from wrapped InputStream
+ */
+ private static void fillBuf(InputStream in, ByteBuffer bytes,
+ CharBuffer chars, CharsetDecoder decoder) throws IOException {
+ chars.clear();
+ int read = 0;
+ try {
+ read = in.read(bytes.array());
+ } catch (IOException e) {
+ chars.limit(0);
+ throw e;
+ }
+ if (read == -1) {
+ chars.limit(0);
+ return;
+ }
+ bytes.limit(read);
+ boolean endOfInput = read < DEFAULT_BUFFER_SIZE;
+ CoderResult result = decoder.decode(bytes, chars, endOfInput);
+ if (result.isError()) {
+ throw new IOException(result.toString());
+ }
+ bytes.clear();
+ chars.flip();
+ }
+
+ /*
+ * Write method for OutputStreamWriter and Channels.
+ */
+ public static void writeOutputStreamWriter(String str, int offset,
+ int count, OutputStream out, ByteBuffer bytes,
+ CharsetEncoder encoder, Object lock) throws IOException {
+ // avoid int overflow
+ if (offset < 0 || count < 0 || offset + count > str.length()) {
+ throw new StringIndexOutOfBoundsException();
+ }
+ CharBuffer chars = CharBuffer.wrap(str, offset, count + offset);
+ convert(lock, encoder, bytes, chars, out);
+ }
+
+ /*
+ * Write method for OutputStreamWriter and Channels.
+ */
+ public static void writeOutputStreamWriter(int oneChar, OutputStream out,
+ ByteBuffer bytes, CharsetEncoder encoder, Object lock)
+ throws IOException {
+ synchronized (lock) {
+ if (encoder == null) {
+ throw new IOException("This writer has been closed!"); //$NON-NLS-1$
+ }
+ CharBuffer chars = CharBuffer.wrap(new char[] { (char) oneChar });
+ convert(lock, encoder, bytes, chars, out);
+ }
+ }
+
+ /*
+ * Write method for OutputStreamWriter and Channels.
+ */
+ public static void writeOutputStreamWriter(char[] buf, int offset,
+ int count, OutputStream out, ByteBuffer bytes,
+ CharsetEncoder encoder, Object lock) throws IOException {
+ if (offset < 0 || count < 0 || offset + count > buf.length) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ CharBuffer chars = CharBuffer.wrap(buf, offset, count);
+ convert(lock, encoder, bytes, chars, out);
+ }
+
+ /*
+ * Flush method for OutputStreamWriter and Channels.
+ */
+ public static void flushOutputStreamWriter(OutputStream out,
+ ByteBuffer bytes, CharsetEncoder encoder, Object lock)
+ throws IOException {
+ synchronized (lock) {
+ if (encoder == null) {
+ throw new IOException("This writer has been closed!"); //$NON-NLS-1$
+ }
+ int position;
+ if ((position = bytes.position()) > 0) {
+ bytes.flip();
+ out.write(bytes.array(), 0, position);
+ bytes.clear();
+ }
+ out.flush();
+ }
+ }
+
+ /*
+ * convert function used in write.
+ */
+ private static void convert(Object lock, CharsetEncoder encoder,
+ ByteBuffer bytes, CharBuffer chars, OutputStream out)
+ throws IOException {
+ synchronized (lock) {
+ if (encoder == null) {
+ throw new IOException("This writer has been closed!"); //$NON-NLS-1$
+ }
+ CoderResult result = encoder.encode(chars, bytes, true);
+ while (true) {
+ if (result.isError()) {
+ throw new IOException(result.toString());
+ } else if (result.isOverflow()) {
+ // flush the output buffer
+ flushOutputStreamWriter(out, bytes, encoder, lock);
+ result = encoder.encode(chars, bytes, true);
+ continue;
+ }
+ break;
+ }
+ }
+ }
+}
Index: D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
===================================================================
--- D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java (revision 0)
+++ D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java (revision 0)
@@ -0,0 +1,327 @@
+/* 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 com.ibm.oti.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
Index: D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
===================================================================
--- D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java (revision 0)
+++ D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java (revision 0)
@@ -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"; //$NON-NLS-1$
+
+ private static final String ERRMSG_NONBLOKING_OUT = "The socket is marked as nonblocking operation would block"; //$NON-NLS-1$
+
+ private static final String ERRMSG_ASYNCHRONOUSCLOSE = "The call was cancelled"; //$NON-NLS-1$
+
+ // -------------------------------------------------------------------
+ // 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
Index: D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java
===================================================================
--- D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java (revision 0)
+++ D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java (revision 0)
@@ -0,0 +1,79 @@
+/* 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 null;//TODO return new PipeImpl() when Pipe is ready
+ }
+
+ /*
+ *
+ * @see java.nio.channels.spi.SelectorProvider#openSelector()
+ */
+ public AbstractSelector openSelector() throws IOException {
+ return null;//TODO return new SelectorImpl(this) when Selector is ready
+ }
+
+ /*
+ *
+ * @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);
+ }
+
+}