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.

+ */ +public abstract class ServerSocketChannel extends AbstractSelectableChannel { + + /** + * Construct a new instance for ServerSocketChannel + * @param selectorProvider + * An instance of SelectorProvider + */ + + protected ServerSocketChannel(SelectorProvider selectorProvider) { + super(selectorProvider); + } + + /** + * Create an open and unbound server-socket channel. + *

+ * This channel is got by calling openServerSocketChannel + * method of the default SelectorProvider instance. + *

+ * + * @return The new created channel which is open but unbound. + * @throws IOException + * If some IO problem occurs. + */ + public static ServerSocketChannel open() throws IOException { + return SelectorProvider.provider().openServerSocketChannel(); + } + + /** + * Get the valid operations of this channel. Server-socket channels support + * accepting operation.Currently the only supported operation is OP_ACCEPT. + * It always returns 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. + *

+ * + * @return The accepted SocketChannel instance, or null as the channel is + * non-blocking and no connections available. + * @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 NotYetBoundException + * If the socket has not yet been bound. + * @throws SecurityException + * If there is a security manager, and the new connection is not + * permitted to access. + * @throws IOException + * Some other IO error occurred. + * + */ + public abstract SocketChannel accept() throws IOException; + +} Index: D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java =================================================================== --- D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java (revision 386040) +++ D:/user/jimmy/WorkSpace_Ongoing/nio/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.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,24 +15,209 @@ package java.nio.channels.spi; - -import java.nio.channels.Channel; -import java.nio.channels.InterruptibleChannel; +import java.io.IOException; +import java.nio.channels.CancelledKeyException; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.IllegalBlockingModeException; import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.util.ArrayList; +import java.util.List; /** - * TODO Type description + * Abstract class for selectable channels. + *

+ * 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. + *

+ * + * @see java.nio.channels.SelectableChannel#register(java.nio.channels.Selector, + * int, java.lang.Object) + */ + public final SelectionKey register(Selector selector, int interestSet, + Object attachment) throws ClosedChannelException { + if (!isOpen()) { + throw new ClosedChannelException(); + } + if (!((interestSet & ~validOps()) == 0)) { + throw new IllegalArgumentException(); + } + if (!selector.isOpen()) { + // throw NPE exactly to keep consistency + throw new NullPointerException(); + } + synchronized (blockingLock) { + if (isBlocking) { + throw new IllegalBlockingModeException(); + } + SelectionKey key = keyFor(selector); + if (null == key) { +// key = ((AbstractSelector) selector).register(this, interestSet, +// attachment); + keyList.add(key); + } else { + if (!key.isValid()) { + throw new CancelledKeyException(); + } + key.interestOps(interestSet); + key.attach(attachment); + } + return key; + } + } + + /** + * Implement the closing function. + * + * @see java.nio.channels.spi.AbstractInterruptibleChannel#implCloseChannel() + */ + synchronized protected final void implCloseChannel() throws IOException { + implCloseSelectableChannel(); + for (int i = 0; i < keyList.size(); i++) { + SelectionKey key = (SelectionKey) keyList.get(i); + if (null != key) { + key.cancel(); + } + } + } + + /** + * Implement the closing function of the SelectableChannel. + * + * @throws IOException + * If some I/O exception occured. + */ + protected abstract void implCloseSelectableChannel() throws IOException; + + /** + * @see java.nio.channels.SelectableChannel#isBlocking() + */ + public final boolean isBlocking() { + synchronized (blockingLock) { + return isBlocking; + } + } + + /** + * @see java.nio.channels.SelectableChannel#blockingLock() + */ + public final Object blockingLock() { + return blockingLock; + } + + /** + * Set the blocking mode of this channel. + * + * @see java.nio.channels.SelectableChannel#configureBlocking(boolean) + * @param blockingMode + * 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. + *

* */ -public abstract class SelectorProvider { +public abstract class SelectorProvider extends Object { - /** - * @return TODO - */ - public static SelectorProvider provider() { - // TODO Auto-generated method stub - return null; - } + private static final String SYMBOL_COMMENT = "#"; //$NON-NLS-1$ - public abstract Pipe openPipe() throws IOException; + private static final String PROVIDER_IN_SYSTEM_PROPERTY = "java.nio.channels.spi.SelectorProvider"; //$NON-NLS-1$ - public abstract AbstractSelector openSelector() throws IOException; + private static final String PROVIDER_IN_JAR_RESOURCE = "META-INF/services/java.nio.channels.spi.SelectorProvider"; //$NON-NLS-1$ + + private static SelectorProvider provider = null; + + private static Channel inheritedChannel = null; + + /** + * Constructor for this class. + * + * @throws SecurityException + * If there is a security manager, and it denies + * RuntimePermission("selectorProvider"). + */ + protected SelectorProvider() { + super(); + if (null != System.getSecurityManager()) { + System.getSecurityManager().checkPermission( + new RuntimePermission("selectorProvider")); //$NON-NLS-1$ + } + } + + /** + * Get the provider by following steps in the first calling. + *

+ *

+ *

+ * + * @return The provider. + */ + synchronized public static SelectorProvider provider() { + if (null == provider) { + provider = loadProviderByProperty(); + if (null == provider) { + provider = loadProviderByJar(); + } + if (null == provider) { + provider = new SelectorProviderImpl(); + } + return provider; + } + return provider; + } + + /* + * load the provider in the jar file of class path. + */ + static SelectorProvider loadProviderByJar() { + Enumeration enumeration = null; + SelectorProvider tempProvider = null; + + ClassLoader classLoader = (ClassLoader) AccessController + .doPrivileged(new PrivilegedAction() { + public Object run() { + return ClassLoader.getSystemClassLoader(); + } + }); + try { + enumeration = classLoader.getResources(PROVIDER_IN_JAR_RESOURCE); + } catch (IOException e) { + throw new Error(); + } + if (null == enumeration) { + return null; + } + // for every jar, read until we find the provider name. + while (enumeration.hasMoreElements()) { + BufferedReader br = null; + String className = null; + try { + br = new BufferedReader(new InputStreamReader( + ((URL) enumeration.nextElement()).openStream())); + } catch (Exception e) { + continue; + } + try { + // only the first class is loaded ,as spec says, not the same as + // we do before. + if ((className = br.readLine()) != null) { + className = className.trim(); + int siteComment = className.indexOf(SYMBOL_COMMENT); + className = (-1 == siteComment) ? className : className + .substring(0, siteComment); + if (0 < className.length()) { + tempProvider = (SelectorProvider) classLoader + .loadClass(className).newInstance(); + if (null != tempProvider) { + return tempProvider; + } + } + } + } catch (Exception e) { + throw new Error(); + } + } + return null; + } + + /* + * load by system property. + */ + static SelectorProvider loadProviderByProperty() { + return (SelectorProvider) AccessController + .doPrivileged(new PrivilegedAction() { + public Object run() { + // FIXME check if use this ClassLoader or system + // ClassLoader + try { + final String className = System + .getProperty(PROVIDER_IN_SYSTEM_PROPERTY); + if (null != className) { + return Thread.currentThread() + .getContextClassLoader().loadClass( + className); + } + return null; + } catch (Exception e) { + throw new Error(); + } + } + }); + + } + + /** + * Create a new open 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. + *

+ */ +public abstract class SocketChannel extends AbstractSelectableChannel implements + ByteChannel, ScatteringByteChannel, GatheringByteChannel { + + /** + * Constructor for this class. + * + * @param selectorProvider + * A instance of SelectorProvider + */ + protected SocketChannel(SelectorProvider selectorProvider) { + super(selectorProvider); + } + + /** + * Create a open and not-connected socket channel. + *

+ * This channel is got by openSocketChannel method of the + * default SelectorProvider instance. + *

+ * + * @return The new created channel which is open but not-connected. + * @throws IOException + * If some IO problem occurs. + */ + public static SocketChannel open() throws IOException { + return SelectorProvider.provider().openSocketChannel(); + } + + /** + * Create a socket channel and connect it to a socket address. + *

+ * This method perform just as open method following by the + * connect method. + *

+ * + * @param address + * The socket address to be connected. + * @return The new opend channel. + * @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 static SocketChannel open(SocketAddress address) throws IOException { + SocketChannel socketChannel = open(); + if (null != socketChannel) { + socketChannel.connect(address); + } + return socketChannel; + } + + /** + * Get the valid operations of this channel. Socket channels support + * connect, read and write operation, so this method returns ( + * 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. + *

+ * + * @param address + * The address to be connected. + * @return 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. + *

+ * + * @return true 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. + *

+ * + * @see java.nio.channels.ReadableByteChannel#read(java.nio.ByteBuffer) + * @param target + * The byte buffer to receive the bytes. + * @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 abstract int read(ByteBuffer target) throws IOException; + + /** + * Reads bytes from the channel into a subset of the given buffers. + *

+ * 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. + *

+ * + * @see java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer) + * @param source + * the byte buffer containing the 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 abstract int write(ByteBuffer source) throws IOException; + + /** + * Writes a subset of the given bytes from the buffers to the channel. + *

+ * 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. + *

+ * + * @return The new created channel which is open but not-connected. + * @throws IOException + * If some IO problem occurs. + */ + public static DatagramChannel open() throws IOException { + return SelectorProvider.provider().openDatagramChannel(); + } + + /** + * Get the valid operations of this channel. Datagram channels support read + * and write operation, so this method returns ( + * 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. + *

+ * + * @param address + * The address to be connected. + * @return 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 SecurityException + * If there is a security manager, and the address is not + * permitted to access. + * @throws IOException + * Some other IO error occurred. + * + */ + public abstract DatagramChannel connect(SocketAddress address) + throws IOException; + + /** + * Disconnect the socket of this channel, which is connected before for + * getting and sending datagrams. + *

+ * 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. + *

+ * + * @param target + * The byte buffer to store the received datagram. + * @return Address of the datagram if the transfer is performed, or null if + * the channel is in non-blocking mode and the datagrama are + * unavailable. + * @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 SecurityException + * If there is a security manager, and the address is not + * permitted to access. + * @throws IOException + * Some other IO error occurred. + * + */ + public abstract SocketAddress receive(ByteBuffer target) throws IOException; + + /** + * Sends out a datagram by the channel. + *

+ * 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. + *

+ * + * @param source + * The byte buffer with the datagram to be sent. + * @param address + * The address to be sent. + * @return The number of sent 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 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 SecurityException + * If there is a security manager, and the address is not + * permitted to access. + * @throws IOException + * Some other IO error occurred. + * + */ + public abstract int send(ByteBuffer source, SocketAddress address) + throws IOException; + + /** + * Reads datagram from the channel into the byte buffer. + *

+ * 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. + *

+ * + * @see java.nio.channels.ReadableByteChannel#read(java.nio.ByteBuffer) + * @param target + * The byte buffer to store the received datagram. + * @return Non-negative number as the number of bytes read, or -1 as the + * read operation reaches the end of stream. + * @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 int read(ByteBuffer target) throws IOException; + + /** + * Reads datagram from the channel into the byte buffer. + *

+ * 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. + *

+ * + * @see java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[], + * int, int) + * @param targets + * The byte buffers to store the received datagram. + * @param offset + * A non-negative offset in the array of buffer, pointing to the + * starting buffer to store the byte transferred, must no larger + * than targets.length. + * @param length + * A non-negative length to indicate the maximum number of byte + * to be read, must no larger than targets.length - offset. + * @return Non-negative number as the number of bytes read, or -1 as the + * read operation reaches the end of stream. + * @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 datagram from the channel into the byte buffer. + *

+ * 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. + *

+ * + * @see java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[]) + * @param targets + * The byte buffers to store the received datagram. + * @return Non-negative number as the number of bytes read, or -1 as the + * read operation reaches the end of stream. + * @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); + } + + /** + * 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 + * WritableByteChannel interface. + *

+ * + * @see java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer) + * @param source + * The byte buffer as the source of the datagram. + * @return Non-negative number of bytes 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 int write(ByteBuffer source) 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[], + * 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); + } + +}