You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/04/07 11:07:38 UTC
svn commit: r392225 [2/6] - in
/incubator/harmony/enhanced/classlib/trunk/modules/nio: make/common/
src/main/java/java/nio/ src/main/java/java/nio/channels/spi/
src/main/java/org/apache/harmony/nio/internal/
src/test/java/org/apache/harmony/tests/java/...
Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java?rev=392225&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java Fri Apr 7 02:07:34 2006
@@ -0,0 +1,732 @@
+/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.internal;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.ConnectException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.DatagramSocketImpl;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.spi.SelectorProvider;
+
+import org.apache.harmony.luni.net.NetUtil;
+import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.platform.FileDescriptorHandler;
+import org.apache.harmony.luni.platform.INetworkSystem;
+import org.apache.harmony.luni.platform.Platform;
+
+
+
+/*
+ * The default implementation class of java.nio.channels.DatagramChannel.
+ *
+ */
+class DatagramChannelImpl extends DatagramChannel implements FileDescriptorHandler{
+
+ // -------------------------------------------------------------------
+ // Class variables
+ // -------------------------------------------------------------------
+
+ // The singleton to do the native network operation.
+ private static final INetworkSystem networkSystem = Platform
+ .getNetworkSystem();
+
+ // default timeout used to nonblocking mode.
+ private static final int DEFAULT_TIMEOUT = 100;
+
+ // error messages, for native dependent.
+ private static final String ERRMSG_TIMEOUT = "The operation timed out";
+
+ private static final String ERRMSG_NONBLOKING_OUT = "The socket is marked as nonblocking operation would block";
+
+ private static final String ERRMSG_ASYNCHRONOUSCLOSE = "The call was cancelled";
+
+ // -------------------------------------------------------------------
+ // Instance variables
+ // -------------------------------------------------------------------
+
+ // The fd to interact with native code
+ private FileDescriptor fd;
+
+ // Our internal DatagramSocket.
+ private DatagramSocket socket = null;
+
+ // The address to be connected.
+ InetSocketAddress connectAddress = null;
+
+ // local port
+ private int localPort;
+
+ // At first, uninitialized.
+ boolean connected = false;
+
+ // whether the socket is bound
+ boolean isBound = false;
+
+ // lock for read and receive
+ private final Object readLock = new Object();
+
+ // lock for write and receive
+ private final Object writeLock = new Object();
+
+ // used to store the trafficClass value which is simply returned
+ // as the value that was set. We also need it to pass it to methods
+ // that specify an address packets are going to be sent to
+ private int trafficClass = 0;
+
+ // -------------------------------------------------------------------
+ // Constructor
+ // -------------------------------------------------------------------
+
+ /*
+ * Constructor
+ */
+ protected DatagramChannelImpl(SelectorProvider selectorProvider)
+ throws IOException {
+ super(selectorProvider);
+ fd = new FileDescriptor();
+ networkSystem.createDatagramSocket(fd, true);
+ }
+
+ // -------------------------------------------------------------------
+ // Methods for getting internal DatagramSocket.
+ // -------------------------------------------------------------------
+
+ /*
+ * Getting the internal DatagramSocket If we have not the socket, we create
+ * a new one.
+ */
+ synchronized public DatagramSocket socket() {
+ if (null == socket) {
+// DatagramSocketImpl datagramSocketImpl = new DatagramSocketImplAdapter(
+// fd, localPort, this);
+ socket = new DatagramSocketAdapter(SocketImplProvider.getDatagramSocketImpl(fd, localPort), this);
+ }
+ return socket;
+ }
+
+ /**
+ * Answer the local address from the IP stack. This method should not be
+ * called directly as it does not check the security policy.
+ *
+ * @return InetAddress the local address to which the socket is bound.
+ * @see DatagramSocket
+ */
+ InetAddress getLocalAddress() {
+ return networkSystem.getSocketLocalAddress(fd, NetUtil.preferIPv6Addresses());
+ }
+
+ // -------------------------------------------------------------------
+ // Methods for connect and disconnect
+ // -------------------------------------------------------------------
+
+ /*
+ *
+ * @see java.nio.channels.DatagramChannel#isConnected()
+ */
+ synchronized public boolean isConnected() {
+ return connected;
+ }
+
+ /*
+ *
+ * @see java.nio.channels.DatagramChannel#connect(java.net.SocketAddress)
+ */
+ synchronized public DatagramChannel connect(SocketAddress address)
+ throws IOException {
+ // must open
+ checkOpen();
+ // status must be un-connected.
+ if (connected) {
+ throw new IllegalStateException();
+ }
+
+ // check the address
+ InetSocketAddress inetSocketAddress = SocketChannelImpl
+ .validateAddress(address);
+
+ // security check
+ SecurityManager sm = System.getSecurityManager();
+ if (null != sm) {
+ if (inetSocketAddress.getAddress().isMulticastAddress()) {
+ sm.checkMulticast(inetSocketAddress.getAddress());
+ } else {
+ sm.checkConnect(inetSocketAddress.getAddress().getHostName(),
+ inetSocketAddress.getPort());
+ }
+ }
+
+ try {
+ begin();
+ networkSystem.connectDatagram(fd, inetSocketAddress.getPort(),
+ trafficClass, inetSocketAddress.getAddress());
+ } catch (ConnectException e) {
+ // ConnectException means connect fail, not exception
+ } finally {
+ end(true);
+ }
+
+ // set the connected address.
+ connectAddress = inetSocketAddress;
+ connected = true;
+ isBound = true;
+ return this;
+ }
+
+ /*
+ *
+ * @see java.nio.channels.DatagramChannel#disconnect()
+ */
+ synchronized public DatagramChannel disconnect() throws IOException {
+ if (!isConnected() || !isOpen()) {
+ return this;
+ }
+ connected = false;
+ connectAddress = null;
+ networkSystem.disconnectDatagram(fd);
+ if (null != socket) {
+ socket.disconnect();
+ }
+ return this;
+ }
+
+ // -------------------------------------------------------------------
+ // Methods for send and receive
+ // -------------------------------------------------------------------
+
+ /*
+ *
+ * @see java.nio.channels.DatagramChannel#receive(java.nio.ByteBuffer)
+ */
+ public SocketAddress receive(ByteBuffer target) throws IOException {
+ // must not null and not readonly
+ checkNotNullNotReadOnly(target);
+ // must open
+ checkOpen();
+
+ if (!isBound) {
+ // FIXME RI seems does not perform as datagram socket
+ // SecurityManager security = System.getSecurityManager();
+ // if (security != null)
+ // security.checkListen(0);
+ // final byte[] any = new byte[] { 0, 0, 0, 0 };
+ // try {
+ // networkSystem.bind(fd, 0, InetAddress.getByAddress(any));
+ // } catch (UnknownHostException e) {
+ // // impossible,do nothing
+ // }
+ // isBound = true;
+ return null;
+ }
+
+ SocketAddress retAddr = null;
+ try {
+ begin();
+
+ // // FIXME donot peek at time,see if can improve
+ // DatagramPacket peekPack = new DatagramPacket(new byte[1], 1);
+ // synchronized (dataLock) {
+ // networkSystem.receiveDatagram(fd, peekPack, peekPack.getData(),
+ // peekPack.getOffset(), peekPack.getLength(),
+ // isBlocking() ? 0 : DEFAULT_TIMEOUT, true);
+ // }
+ // if (null == peekPack.getAddress()) {
+ // // if no new packet peeked
+ // return null;
+ // }
+
+ // receive real data packet, (not peek)
+ synchronized (readLock) {
+ boolean loop = isBlocking();
+ do {
+ DatagramPacket receivePacket = new DatagramPacket(
+ new byte[target.remaining()], target.remaining());
+
+ if (isConnected()) {
+ networkSystem.recvConnectedDatagram(fd, receivePacket,
+ receivePacket.getData(), receivePacket
+ .getOffset(),
+ receivePacket.getLength(), isBlocking()?0:DEFAULT_TIMEOUT, false);
+ } else {
+ networkSystem.receiveDatagram(fd, receivePacket,
+ receivePacket.getData(), receivePacket
+ .getOffset(),
+ receivePacket.getLength(), isBlocking()?0:DEFAULT_TIMEOUT, false);
+ }
+
+ // security check
+ SecurityManager sm = System.getSecurityManager();
+ if (!isConnected() && null != sm) {
+ try {
+ sm.checkAccept(receivePacket.getAddress()
+ .getHostAddress(), receivePacket.getPort());
+ } catch (SecurityException e) {
+ // do discard the datagram packet
+ receivePacket = null;
+ }
+ }
+ if (null != receivePacket
+ && null != receivePacket.getAddress()) {
+ // copy the data of received packet
+ target.put(ByteBuffer.wrap(receivePacket.getData()));
+ retAddr = receivePacket.getSocketAddress();
+ break;
+ }
+ } while (loop);
+ }
+ } catch (SocketException e) {
+ // FIXME Depend on former function,it's a work round, wait for
+ // native improve.
+ String msg = e.getMessage();
+ if (ERRMSG_ASYNCHRONOUSCLOSE.equals(msg)) {
+ throw new AsynchronousCloseException();
+ }
+ if (ERRMSG_NONBLOKING_OUT.equals(msg)) {
+ return null;
+ }
+ throw e;
+ } catch (InterruptedIOException e) {
+ // this line used in Linux
+ return null;
+ } finally {
+ end(null != retAddr);
+ }
+ return retAddr;
+ }
+
+ /*
+ * @see java.nio.channels.DatagramChannel#send(java.nio.ByteBuffer,
+ * java.net.SocketAddress)
+ */
+ public int send(ByteBuffer source, SocketAddress address)
+ throws IOException {
+ // must open
+ checkOpen();
+ // must not null
+ checkNotNull(source);
+
+ // transfer address
+ InetSocketAddress isa = (InetSocketAddress) address;
+ if (null == isa.getAddress()) {
+ throw new IOException();
+ }
+
+ if (isConnected()) {
+ if (!connectAddress.equals(isa)) {
+ throw new IllegalArgumentException();
+ }
+ } else {
+ // not connected, check security
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ if (isa.getAddress().isMulticastAddress()) {
+ sm.checkMulticast(isa.getAddress());
+ } else {
+ sm.checkConnect(isa.getAddress().getHostAddress(), isa
+ .getPort());
+ }
+ }
+ }
+
+ // the return value.
+ int sendCount = 0;
+
+ try {
+ begin();
+
+ byte[] array;
+ // FIXME enhence the performance
+ if (source.hasArray()) {
+ array = source.array();
+ } else {
+ array = new byte[source.remaining()];
+ source.get(array);
+ }
+ DatagramPacket pack = new DatagramPacket(array, array.length, isa);
+
+ synchronized (writeLock) {
+ sendCount = networkSystem.sendDatagram(fd, pack.getData(), 0,
+ pack.getLength(), isa.getPort(), false, trafficClass,
+ isa.getAddress());
+ }
+ return sendCount;
+ } finally {
+ end(sendCount >= 0);
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Methods for read and write.
+ // -------------------------------------------------------------------
+
+ /*
+ *
+ * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer)
+ */
+ public int read(ByteBuffer target) throws IOException {
+ // status must be open and connected
+ checkOpenConnected();
+ // target buffer must be not null and not readonly
+ checkNotNullNotReadOnly(target);
+
+ synchronized (readLock) {
+ return readImpl(target);
+ }
+ }
+
+ /*
+ *
+ * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer[], int,
+ * int)
+ */
+ public long read(ByteBuffer[] targets, int offset, int length)
+ throws IOException {
+ if (length >= 0 && offset >= 0 && length + offset <= targets.length) {
+ // status must be open and connected
+ checkOpenConnected();
+ synchronized (readLock) {
+ long readCount = 0;
+ for (int val = offset; val < length; val++) {
+ // target buffer must be not null and not readonly
+ checkNotNullNotReadOnly(targets[val]);
+ readCount = readCount + readImpl(targets[val]);
+ }
+ return readCount;
+ }
+ }
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /*
+ * read from channel, and store the result in the target.
+ */
+ private int readImpl(ByteBuffer target) throws IOException {
+ // the return value
+ int readCount = 0;
+
+ try {
+ begin();
+ // timeout == 0 means block read.
+ // DEFAULT_TIMEOUT is used in non-block mode.
+ int timeout = isBlocking() ? 0 : DEFAULT_TIMEOUT;
+ DatagramPacket pack;
+ if (target.hasRemaining()) {
+ pack = new DatagramPacket(new byte[target.remaining()], target
+ .remaining());
+ } else {
+ return 0;
+ }
+ boolean loop = isBlocking();
+ do {
+ // handle asynchronous closing
+ if (!isOpen()) {
+ throw new AsynchronousCloseException();
+ }
+ if (isConnected()) {
+ readCount = networkSystem
+ .recvConnectedDatagram(fd, pack, pack.getData(), 0,
+ pack.getLength(), timeout, false);
+ } else {
+ readCount = networkSystem.receiveDatagram(fd, pack, pack
+ .getData(), 0, pack.getLength(), timeout, false);
+ }
+ if (0 < readCount) {
+ target.put(pack.getData());
+ return readCount;
+ }
+ } while (loop);
+ return readCount;
+ } catch (SocketException e) {
+ // FIXME it's a work round, wait for native improve.
+ if (e.getMessage().equals(ERRMSG_ASYNCHRONOUSCLOSE)) {
+ throw new AsynchronousCloseException();
+ }
+ throw e;
+ } catch (InterruptedIOException e) {
+ // FIXME improve native code.
+ if (e.getMessage().equals(ERRMSG_TIMEOUT)) {
+ return 0;
+ }
+ throw e;
+ } finally {
+ end(readCount >= 0);
+ }
+ }
+
+ /*
+ * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer)
+ */
+ public int write(ByteBuffer source) throws IOException {
+ // source buffer must be not null
+ checkNotNull(source);
+ // status must be open and connected
+ checkOpenConnected();
+
+ synchronized (writeLock) {
+ return writeImpl(source);
+ }
+ }
+
+ /*
+ * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer[], int,
+ * int)
+ */
+ public long write(ByteBuffer[] sources, int offset, int length)
+ throws IOException {
+ if (length >= 0 && offset >= 0 && length + offset <= sources.length) {
+ // status must be open and connected
+ checkOpenConnected();
+ synchronized (writeLock) {
+ int count = 0;
+ for (int val = offset; val < length; val++) {
+ // source buffer must be not null
+ checkNotNull(sources[val]);
+ // add all to avoid bugs in Linux
+ count = count + sources[val].remaining();
+ }
+ ByteBuffer writeBuf = ByteBuffer.allocate(count);
+ for (int val = offset; val < length; val++) {
+ writeBuf.put(sources[val]);
+ }
+ return writeImpl(writeBuf);
+ }
+ }
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /*
+ * wirte the source. return the count of bytes written.
+ */
+ private int writeImpl(ByteBuffer buf) throws IOException {
+ // the return value
+ int result = 0;
+
+ try {
+ begin();
+ byte[] array;
+ // FIXME enhence the perform
+ if (buf.hasArray()) {
+ array = buf.array();
+ } else {
+ array = new byte[buf.remaining()];
+ buf.get(array);
+ }
+ DatagramPacket pack = new DatagramPacket(array, array.length);
+ result = networkSystem.sendConnectedDatagram(fd, pack.getData(), 0,
+ pack.getLength(), isBound);
+ return result;
+ } finally {
+ end(result > 0);
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Protected Inherited methods
+ // -------------------------------------------------------------------
+
+ /*
+ * do really closing action here
+ */
+ synchronized protected void implCloseSelectableChannel() throws IOException {
+ connected = false;
+ if (null != socket && !socket.isClosed()) {
+ socket.close();
+ } else {
+ networkSystem.socketClose(fd);
+ }
+ }
+
+ /*
+ *
+ * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean)
+ */
+ protected void implConfigureBlocking(boolean blockingMode)
+ throws IOException {
+ networkSystem.setNonBlocking(fd, !blockingMode);
+ }
+
+ // -------------------------------------------------------------------
+ // Share methods for checking.
+ // -------------------------------------------------------------------
+
+ /*
+ * status check, must be open.
+ */
+ private void checkOpen() throws IOException {
+ if (!isOpen()) {
+ throw new ClosedChannelException();
+ }
+ }
+
+ /*
+ * status check, must be open and connected, for read and write.
+ */
+ private void checkOpenConnected() throws IOException {
+ checkOpen();
+ if (!isConnected()) {
+ throw new NotYetConnectedException();
+ }
+ }
+
+ /*
+ * buffer check, must not null
+ */
+ private void checkNotNull(ByteBuffer source) {
+ if (null == source) {
+ throw new NullPointerException();
+ }
+ }
+
+ /*
+ * buffer check, must not null and not read only buffer, for read and
+ * receive.
+ */
+ private void checkNotNullNotReadOnly(ByteBuffer target) {
+ // including checking of NPE.
+ if (target.isReadOnly()) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Adapter classes for internal socket.
+ // -------------------------------------------------------------------
+
+ /*
+ * get the fd for internal use.
+ */
+ public FileDescriptor getFD() {
+ return fd;
+ }
+
+ /*
+ * The adapter class of DatagramSocket
+ */
+ private static class DatagramSocketAdapter extends DatagramSocket {
+
+ /*
+ * The internal datagramChannelImpl.
+ */
+ private DatagramChannelImpl channelImpl;
+
+ /*
+ * init the datagramSocketImpl and datagramChannelImpl
+ */
+ DatagramSocketAdapter(DatagramSocketImpl socketimpl,
+ DatagramChannelImpl channelImpl) {
+ super(socketimpl);
+ this.channelImpl = channelImpl;
+ }
+
+ /*
+ * get the internal datagramChannelImpl
+ */
+ public DatagramChannel getChannel() {
+ return channelImpl;
+ }
+
+ /*
+ * @see java.net.DatagramSocket#isBound()
+ */
+ public boolean isBound() {
+ return channelImpl.isBound;
+ }
+
+ /*
+ * @see java.net.DatagramSocket#isConnected()
+ */
+ public boolean isConnected() {
+ return channelImpl.isConnected();
+ }
+
+ /*
+ * @see java.net.DatagramSocket#getInetAddress()
+ */
+ public InetAddress getInetAddress() {
+ if (null == channelImpl.connectAddress) {
+ return null;
+ }
+ return channelImpl.connectAddress.getAddress();
+ }
+
+ /*
+ * @see java.net.DatagramSocket#getLocalAddress()
+ */
+ public InetAddress getLocalAddress(){
+ return channelImpl.getLocalAddress();
+ }
+
+ /*
+ * @see java.net.DatagramSocket#getPort()
+ */
+ public int getPort() {
+ if (null == channelImpl.connectAddress) {
+ return -1;
+ }
+ return channelImpl.connectAddress.getPort();
+ }
+
+ /*
+ * @see java.net.DatagramSocket#bind(java.net.SocketAddress)
+ */
+ public void bind(SocketAddress localAddr) throws SocketException {
+ if (channelImpl.isConnected()) {
+ throw new AlreadyConnectedException();
+ }
+ super.bind(localAddr);
+ channelImpl.isBound = true;
+ }
+
+ /*
+ * @see java.net.DatagramSocket#close()
+ */
+ public void close() {
+ synchronized (channelImpl) {
+ if (channelImpl.isOpen()) {
+ try {
+ channelImpl.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ super.close();
+ }
+ }
+
+ /*
+ * @see java.net.DatagramSocket#disconnect()
+ */
+ public void disconnect() {
+ try {
+ channelImpl.disconnect();
+ } catch (IOException e) {
+ // Ignore
+ }
+ super.disconnect();
+ }
+ }
+}
\ No newline at end of file
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java?rev=392225&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java Fri Apr 7 02:07:34 2006
@@ -0,0 +1,83 @@
+/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.internal;
+
+import java.io.IOException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.Pipe;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+
+
+/*
+ * Internal implementation of SelectorProvider.
+ *
+ */
+public class SelectorProviderImpl extends SelectorProvider {
+
+ /*
+ * Constructor for this class.
+ */
+ public SelectorProviderImpl() {
+ super();
+ }
+
+ /*
+ *
+ * @see java.nio.channels.spi.SelectorProvider#openDatagramChannel()
+ */
+ public DatagramChannel openDatagramChannel() throws IOException {
+ return new DatagramChannelImpl(this);
+ }
+
+ /*
+ *
+ * @see java.nio.channels.spi.SelectorProvider#openPipe()
+ */
+ public Pipe openPipe() throws IOException {
+// return new PipeImpl();
+ //FIXME: waiting for JIRA-41
+ return null;
+ }
+
+ /*
+ *
+ * @see java.nio.channels.spi.SelectorProvider#openSelector()
+ */
+ public AbstractSelector openSelector() throws IOException {
+// return new SelectorImpl(this);
+ //FIXME: wait for JIRA-41
+ return null;
+ }
+
+ /*
+ *
+ * @see java.nio.channels.spi.SelectorProvider#openServerSocketChannel()
+ */
+ public ServerSocketChannel openServerSocketChannel() throws IOException {
+ return new ServerSocketChannelImpl(this);
+ }
+
+ /*
+ *
+ * @see java.nio.channels.spi.SelectorProvider#openSocketChannel()
+ */
+ public SocketChannel openSocketChannel() throws IOException {
+ return new SocketChannelImpl(this);
+ }
+
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java?rev=392225&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java Fri Apr 7 02:07:34 2006
@@ -0,0 +1,324 @@
+/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.internal;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.BindException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketImpl;
+import java.net.SocketTimeoutException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.NotYetBoundException;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+import org.apache.harmony.luni.net.NetUtil;
+import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.platform.FileDescriptorHandler;
+import org.apache.harmony.luni.platform.Platform;
+import org.apache.harmony.luni.util.Msg;
+
+/*
+ * The default implementation class of java.nio.channels.ServerSocketChannel.
+ */
+public class ServerSocketChannelImpl extends ServerSocketChannel implements
+ FileDescriptorHandler {
+
+ // ----------------------------------------------------
+ // Class Variables
+ // ----------------------------------------------------
+
+ // status un-init, not initialized.
+ private static final int SERVER_STATUS_UNINIT = -1;
+
+ // status after open and before closed.
+ private static final int SERVER_STATUS_OPEN = 0;
+
+ // status closed.
+ private static final int SERVER_STATUS_CLOSED = 1;
+
+ // default timeout used to nonblocking mode.
+ private static final int DEFAULT_TIMEOUT = 100;
+
+ // error message, for native dependent.
+ private static final String ERRMSG_ASYNCHRONOUS = "The call was cancelled"; //$NON-NLS-1$
+
+ // -------------------------------------------------------------------
+ // Instance variables
+ // -------------------------------------------------------------------
+
+ // The fd to interact with native code
+ private final FileDescriptor fd;
+
+ // The interanl ServerSocket
+ private final ServerSocket socket;
+
+ private final SocketImpl impl;
+
+ int status = SERVER_STATUS_UNINIT;
+
+ // whether the socket is bound
+ boolean isBound = false;
+
+ // lock for accept
+ private final Object acceptLock = new Object();
+
+ // lock for status
+ // final Object statusLock = new Object();
+
+ // ----------------------------------------------------
+ // Constructor
+ // ----------------------------------------------------
+
+ /*
+ * Constructor
+ */
+ public ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
+ super(sp);
+ status = SERVER_STATUS_OPEN;
+ fd = new FileDescriptor();
+ Platform.getNetworkSystem().createServerStreamSocket(fd,
+ NetUtil.preferIPv4Stack());
+ impl = SocketImplProvider.getServerSocketImpl(fd);
+ socket = new ServerSocketAdapter(impl, this);
+ }
+
+ // ----------------------------------------------------
+ // Methods
+ // ----------------------------------------------------
+
+ /*
+ * Getting the internal Socket If we have not the socket, we create a new
+ * one.
+ */
+ public ServerSocket socket() {
+ return socket;
+ }
+
+ /*
+ *
+ * @see java.nio.channels.ServerSocketChannel#accept()
+ */
+ public SocketChannel accept() throws IOException {
+ if (!isOpen()) {
+ throw new ClosedChannelException();
+ }
+ if (!isBound || !socket.isBound()) {
+ throw new NotYetBoundException();
+ }
+
+ SocketChannel sockChannel = SocketChannel.open();
+ Socket socketGot = sockChannel.socket();
+
+ try {
+ begin();
+
+ synchronized (acceptLock) {
+ synchronized (blockingLock()) {
+ int oldtime = socket.getSoTimeout();
+ // timeout, 0 means blocking.
+ socket.setSoTimeout(isBlocking() ? 0 : DEFAULT_TIMEOUT);
+ ((ServerSocketAdapter) socket).accept(socketGot,
+ (SocketChannelImpl) sockChannel);
+ socket.setSoTimeout(oldtime);
+ }
+ }
+ } catch (BindException e) {
+ // FIXME improve native code.
+ if (ERRMSG_ASYNCHRONOUS.equals(e.getMessage())) {
+ throw new AsynchronousCloseException();
+ }
+ } catch (SocketTimeoutException e) {
+ // nonblocking mode.
+ return null;
+ } finally {
+ end(socketGot.isConnected());
+ }
+
+ // security check
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ try {
+ sm.checkAccept(socketGot.getInetAddress().getHostAddress(),
+ socketGot.getPort());
+ } catch (SecurityException e) {
+ sockChannel.close();
+ throw e;
+ }
+ }
+ return sockChannel;
+ }
+
+ // -------------------------------------------------------------------
+ // Protected inherited methods
+ // -------------------------------------------------------------------
+
+ /*
+ * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking
+ *
+ * (boolean)
+ */
+ protected void implConfigureBlocking(boolean blockingMode)
+ throws IOException {
+ Platform.getNetworkSystem().setNonBlocking(getFD(), blockingMode);
+ }
+
+ /*
+ *
+ * @see java.nio.channels.spi.AbstractSelectableChannel#implCloseSelectableChannel()
+ */
+ synchronized protected void implCloseSelectableChannel() throws IOException {
+ status = SERVER_STATUS_CLOSED;
+ if (!socket.isClosed()) {
+ socket.close();
+ }
+ }
+
+ // ----------------------------------------------------
+ // Adapter classes.
+ // ----------------------------------------------------
+
+ /*
+ * get the fd
+ */
+ public FileDescriptor getFD() {
+ return fd;
+ }
+
+ /*
+ * The adapter class of ServerSocekt.
+ */
+ private class ServerSocketAdapter extends ServerSocket {
+ /*
+ * Internal impl.
+ */
+ ServerSocketChannelImpl channelImpl;
+
+ /*
+ * init the impl.
+ */
+ ServerSocketAdapter(SocketImpl impl,
+ ServerSocketChannelImpl aChannelImpl){
+ super(impl);
+ this.channelImpl = aChannelImpl;
+ }
+
+ /*
+ *
+ * @see java.net.ServerSocket#bind(java.net.SocketAddress, int)
+ */
+ public void bind(SocketAddress localAddr, int backlog)
+ throws IOException {
+ super.bind(localAddr, backlog);
+ }
+
+ /*
+ * do the accept.
+ */
+ public Socket accept(Socket aSocket, SocketChannelImpl sockChannel)
+ throws IOException {
+ if (isClosed()) {
+ throw new SocketException(Msg.getString("K003d")); //$NON-NLS-1$
+ }
+ if (!isBound()) {
+ throw new SocketException(Msg.getString("K031f")); //$NON-NLS-1$
+ }
+
+ // If a SOCKS proxy is being used, accept does strange things.
+ // Instead of returning a new Socket and allowing this ServerSocket
+ // to be used for another accept, it actually uses the current
+ // ServerSocket
+ // as the accepted Socket. So, closing the returned socket will
+ // close the
+ // ServerSocket as well. The ServerSocket cannot be used for a
+ // second accept.
+ if (NetUtil.usingSocks()) {
+ return super.accept();
+ }
+
+ // a new socket is pass in so we do not need to "Socket aSocket =
+ // new Socket();"
+ boolean connectOK = false;
+ try {
+ synchronized (this) {
+ super.implAccept(aSocket);
+ // FIXME wait for fix.
+ // if (aSocket.isConnected()) {
+ sockChannel.setConnected();
+ // }
+ }
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkAccept(aSocket.getInetAddress().getHostAddress(),
+ aSocket.getPort());
+ }
+ connectOK = true;
+ } catch (SocketException e) {
+ if (ERRMSG_ASYNCHRONOUS.equals(e.getMessage())) {
+ throw new AsynchronousCloseException();
+ }
+ } finally {
+ if (!connectOK) {
+ aSocket.close();
+ }
+ }
+ return aSocket;
+ }
+
+ /*
+ * getting internal channel.
+ */
+ public ServerSocketChannel getChannel() {
+ return channelImpl;
+ }
+
+ /*
+ *
+ * @see java.net.ServerSocket#isBound()
+ */
+ public boolean isBound() {
+ return channelImpl.isBound;
+ }
+
+ /*
+ *
+ * @see java.net.ServerSocket#bind(java.net.SocketAddress)
+ */
+ public void bind(SocketAddress localAddr) throws IOException {
+ super.bind(localAddr);
+ channelImpl.isBound = true;
+ }
+
+ /*
+ * @see java.net.ServerSocket#close()
+ */
+ public void close() throws IOException {
+ synchronized (channelImpl) {
+ if(channelImpl.isOpen()){
+ channelImpl.close();
+ } else {
+ super.close();
+ }
+ channelImpl.status = SERVER_STATUS_CLOSED;
+ }
+ }
+ }
+}
\ No newline at end of file
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java?rev=392225&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java Fri Apr 7 02:07:34 2006
@@ -0,0 +1,905 @@
+/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.internal;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketImpl;
+import java.net.SocketOptions;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ConnectionPendingException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NoConnectionPendingException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.UnresolvedAddressException;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.nio.channels.spi.SelectorProvider;
+
+import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.platform.FileDescriptorHandler;
+import org.apache.harmony.luni.platform.INetworkSystem;
+import org.apache.harmony.luni.platform.Platform;
+import org.apache.harmony.luni.util.Msg;
+
+
+/*
+ *
+ * The default implementation class of java.nio.channels.SocketChannel.
+ *
+ */
+class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler {
+
+ // -------------------------------------------------------------------
+ // Class variables
+ // -------------------------------------------------------------------
+
+ private static final String ERRORMSG_SOCKET_INVALID = "The socket argument is not a socket";
+
+ private static final int MAX_PORT_NUMBER = 65535;
+
+ private static final int EOF = -1;
+
+ private static final String ERRMSG_SOCKET_NONBLOCKING_WOULD_BLOCK = "The socket is marked as nonblocking operation would block";
+
+ // The singleton to do the native network operation.
+ static final INetworkSystem networkSystem = Platform.getNetworkSystem();
+
+ // status un-init, not initialized.
+ static final int SOCKET_STATUS_UNINIT = EOF;
+
+ // status before connect.
+ static final int SOCKET_STATUS_UNCONNECTED = 0;
+
+ // status connection pending
+ static final int SOCKET_STATUS_PENDING = 1;
+
+ // status after connection success
+ static final int SOCKET_STATUS_CONNECTED = 2;
+
+ // status closed.
+ static final int SOCKET_STATUS_CLOSED = 3;
+
+ // timeout used for non-block mode.
+ private static final int TIMEOUT_NONBLOCK = 0;
+
+ // timeout used for block mode.
+ private static final int TIMEOUT_BLOCK = EOF;
+
+ // step used for connect
+ private static final int HY_SOCK_STEP_START = 0;
+
+ // step used for finishConnect
+ private static final int HY_PORT_SOCKET_STEP_CHECK = 1;
+
+ // connect success
+ private static final int CONNECT_SUCCESS = 0;
+
+ // error msg
+ private static final String ERRCODE_PORT_ERROR = "K0032"; //$NON-NLS-1$
+
+ // error messages, for native dependent.
+ private static final String ERRORMSG_ASYNCHRONOUSCLOSE = "The call was cancelled";
+
+ // a address of localhost
+ private static final byte[] localAddrArray = { 127, 0, 0, 1 };
+
+ // -------------------------------------------------------------------
+ // Instance Variables
+ // -------------------------------------------------------------------
+
+ // The fd to interact with native code
+ FileDescriptor fd;
+
+ // Our internal Socket.
+ private Socket socket = null;
+
+ // The address to be connected.
+ InetSocketAddress connectAddress = null;
+
+ // Local address of the this socket (package private for adapter)
+ InetAddress localAddress = null;
+
+ // local port
+ int localPort;
+
+ // At first, uninitialized.
+ int status = SOCKET_STATUS_UNINIT;
+
+ // whether the socket is bound
+ boolean isBound = false;
+
+ // lock for read and write
+ private final Object readLock = new Object();
+
+ private final Object writeLock = new Object();
+
+ // lock for status
+ // private final Object statusLock = new Object();
+
+ // this content is a point used to set in connect_withtimeout() in pending
+ // mode
+ private Long connectContext = Long.valueOf("0"); //$NON-NLS-1$
+
+ // used to store the trafficClass value which is simply returned
+ // as the value that was set. We also need it to pass it to methods
+ // that specify an address packets are going to be sent to
+ private int trafficClass = 0;
+
+ // -------------------------------------------------------------------
+ // Constructor
+ // -------------------------------------------------------------------
+
+ /*
+ * Constructor
+ */
+ public SocketChannelImpl(SelectorProvider selectorProvider)
+ throws IOException {
+ super(selectorProvider);
+ fd = new FileDescriptor();
+ status = SOCKET_STATUS_UNCONNECTED;
+ networkSystem.createSocket(fd, true);
+ }
+
+ // Keep this to see if need next version
+ // SocketChannelImpl(SelectorProvider selectorProvider, FileDescriptor fd,
+ // SocketImpl si) {
+ // super(selectorProvider);
+ // fd = fd;
+ // networkSystem = OSNetworkSystem.getOSNetworkSystem();
+ // status = SOCKET_STATUS_UNCONNECTED;
+ // networkSystem.createSocket(fd, true);
+ // }
+
+ /*
+ * Package private constructor.
+ */
+ SocketChannelImpl(Socket aSocket, FileDescriptor aFd) {
+ super(SelectorProvider.provider());
+ socket = aSocket;
+ fd = aFd;
+ status = SOCKET_STATUS_UNCONNECTED;
+ }
+
+ // -------------------------------------------------------------------
+ // Methods for getting internal Socket.
+ // -------------------------------------------------------------------
+
+ /*
+ * Getting the internal Socket If we have not the socket, we create a new
+ * one.
+ */
+ synchronized public Socket socket() {
+ if (null == socket) {
+ try {
+ InetAddress addr = null;
+ int port = 0;
+ if (connectAddress != null) {
+ addr = connectAddress.getAddress();
+ port = connectAddress.getPort();
+ }
+ socket = new SocketAdapter(SocketImplProvider.getSocketImpl(fd,
+ localPort, addr, port), this);
+ } catch (SocketException e) {
+ return null;
+ }
+ }
+ return socket;
+ }
+
+ // -------------------------------------------------------------------
+ // Methods for connect and finishConnect
+ // -------------------------------------------------------------------
+
+ /*
+ * @see java.nio.channels.SocketChannel#isConnected()
+ */
+ synchronized public boolean isConnected() {
+ return status == SOCKET_STATUS_CONNECTED;
+ }
+
+ /*
+ * status setting used by other class.
+ */
+ synchronized void setConnected() {
+ status = SOCKET_STATUS_CONNECTED;
+ }
+
+ /*
+ * @see java.nio.channels.SocketChannel#isConnectionPending()
+ */
+ synchronized public boolean isConnectionPending() {
+ return status == SOCKET_STATUS_PENDING;
+ }
+
+ /*
+ * @see java.nio.channels.SocketChannel#connect(java.net.SocketAddress)
+ */
+ public boolean connect(SocketAddress socketAddress) throws IOException {
+ // status must be open and unconnected
+ checkUnconnected();
+
+ // check the address
+ InetSocketAddress inetSocketAddress = validateAddress(socketAddress);
+
+ int port = inetSocketAddress.getPort();
+ String hostName = inetSocketAddress.getAddress().getHostName();
+ if (port < 0 || port > MAX_PORT_NUMBER) {
+ throw new IllegalArgumentException(Msg
+ .getString(ERRCODE_PORT_ERROR));
+ }
+ // security check
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkConnect(hostName, port);
+ }
+
+ // connect result
+ int result = EOF;
+ boolean success = false;
+
+ try {
+ begin();
+ if (!isBound) {
+ // bind
+ networkSystem.bind2(fd, 0, true, InetAddress
+ .getByAddress(localAddrArray));
+ }
+
+ localPort = networkSystem.getSocketLocalPort(fd, false);
+ localAddress = networkSystem.getSocketLocalAddress(fd, false);
+
+ if (isBlocking()) {
+ result = networkSystem.connect(fd, trafficClass,
+ inetSocketAddress.getAddress(), inetSocketAddress
+ .getPort());
+
+ } else {
+ result = networkSystem.connectWithTimeout(fd, 0, trafficClass,
+ inetSocketAddress.getAddress(), inetSocketAddress
+ .getPort(), HY_SOCK_STEP_START, connectContext);
+ }
+
+ success = (CONNECT_SUCCESS == result);
+
+ isBound = success;
+ } catch (IOException e) {
+ if (e instanceof ConnectException && !isBlocking()) {
+ status = SOCKET_STATUS_PENDING;
+ } else {
+ close();
+ throw e;
+ }
+ } finally {
+ end(success);
+ }
+
+ // set the connected address.
+ connectAddress = inetSocketAddress;
+ synchronized (this) {
+ if (isBlocking()) {
+ status = (success ? SOCKET_STATUS_CONNECTED
+ : SOCKET_STATUS_UNCONNECTED);
+ } else {
+ status = SOCKET_STATUS_PENDING;
+ }
+ }
+ return success;
+ }
+
+ /*
+ * @see java.nio.channels.SocketChannel#finishConnect()
+ */
+ public boolean finishConnect() throws IOException {
+ // status check
+ synchronized (this) {
+ if (!isOpen()) {
+ throw new ClosedChannelException();
+ }
+ if (status == SOCKET_STATUS_CONNECTED) {
+ return true;
+ }
+ if (status != SOCKET_STATUS_PENDING) {
+ throw new NoConnectionPendingException();
+ }
+ }
+
+ // finish result
+ int result = EOF;
+ boolean success = false;
+
+ try {
+ begin();
+ if (isBlocking()) {
+ result = networkSystem.connect(fd, trafficClass, connectAddress
+ .getAddress(), connectAddress.getPort());
+
+ } else {
+ result = networkSystem.connectWithTimeout(fd, 0, trafficClass,
+ connectAddress.getAddress(), connectAddress.getPort(),
+ HY_PORT_SOCKET_STEP_CHECK, connectContext);
+ }
+ success = (result == CONNECT_SUCCESS);
+ } catch (ConnectException e) {
+ close();
+ throw e;
+ } finally {
+ end(success);
+ }
+
+ synchronized (this) {
+ status = (success ? SOCKET_STATUS_CONNECTED : status);
+ isBound = success;
+ }
+ return success;
+ }
+
+ // -------------------------------------------------------------------
+ // Methods for read and write
+ // -------------------------------------------------------------------
+ /*
+ * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer)
+ */
+ public int read(ByteBuffer target) throws IOException {
+ if (null == target) {
+ throw new NullPointerException();
+ }
+ checkOpenConnected();
+
+ synchronized (readLock) {
+ return readImpl(target);
+ }
+ }
+
+ /*
+ * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer[], int,
+ * int)
+ */
+ public long read(ByteBuffer[] targets, int offset, int length)
+ throws IOException {
+ if (isIndexValid(targets, offset, length)) {
+ checkOpenConnected();
+ synchronized (readLock) {
+ long totalCount = 0;
+ for (int val = offset; val < offset + length; val++) {
+ int readCount = readImpl(targets[val]);
+ // only -1 or a integer >=0 may return
+ if (EOF != readCount) {
+ totalCount = totalCount + readCount;
+ } else {
+ break;
+ }
+ }
+ return totalCount;
+ }
+ }
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ private boolean isIndexValid(ByteBuffer[] targets, int offset, int length) {
+ return (length >= 0) && (offset >= 0)
+ && (length + offset <= targets.length);
+ }
+
+ /*
+ * read from channel, and store the result in the target.
+ *
+ */
+ private int readImpl(ByteBuffer target) throws IOException {
+ if (!target.hasRemaining()) {
+ return 0;
+ }
+
+ int readCount = 0;
+
+ try {
+ begin();
+ byte[] readArray = new byte[target.remaining()];
+ readCount = networkSystem.read(fd, readArray, 0, readArray.length,
+ (isBlocking() ? TIMEOUT_BLOCK : TIMEOUT_NONBLOCK));
+ if (EOF != readCount) {
+ target.put(readArray, 0, readCount);
+ }
+ return readCount;
+ } catch (SocketException e) {
+ // FIXME improve native code
+ if (ERRORMSG_ASYNCHRONOUSCLOSE.equals(e.getMessage())
+ || ERRORMSG_SOCKET_INVALID.equals(e.getMessage())) {
+ throw new AsynchronousCloseException();
+ }
+ throw e;
+ } finally {
+ end(readCount > 0);
+ }
+ }
+
+ /*
+ *
+ * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer)
+ */
+ public int write(ByteBuffer source) throws IOException {
+ checkOpenConnected();
+ synchronized (writeLock) {
+ return writeImpl(source);
+ }
+ }
+
+ /*
+ * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer[], int,
+ * int)
+ */
+ public long write(ByteBuffer[] sources, int offset, int length)
+ throws IOException {
+ if (isIndexValid(sources, offset, length)) {
+ checkOpenConnected();
+ synchronized (writeLock) {
+ long writeCount = 0;
+ for (int val = offset; val < offset + length; val++) {
+ writeCount = writeCount + writeImpl(sources[val]);
+ }
+ return writeCount;
+ }
+ }
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ /*
+ * wirte the source. return the count of bytes written.
+ */
+ private int writeImpl(ByteBuffer source) throws IOException {
+ if (!source.hasRemaining()) {
+ return 0;
+ }
+ int writeCount = 0;
+ try {
+ begin();
+ int pos = source.position();
+ byte[] array;
+ // FIXME enhance the perform
+ if (source.hasArray()) {
+ array = source.array();
+ } else {
+ array = new byte[source.remaining()];
+ source.get(array);
+ }
+ networkSystem.setNonBlocking(fd, !this.isBlocking());
+ writeCount = networkSystem.write(fd, array, 0, array.length);
+ source.position(pos + writeCount);
+ return writeCount;
+ } catch (SocketException e) {
+ if (ERRMSG_SOCKET_NONBLOCKING_WOULD_BLOCK.equals(e.getMessage())) {
+ return writeCount;
+ }
+ if (ERRORMSG_ASYNCHRONOUSCLOSE.equals(e.getMessage())) {
+ throw new AsynchronousCloseException();
+ }
+ throw e;
+ } finally {
+ end(writeCount >= 0);
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Shared methods
+ // -------------------------------------------------------------------
+
+ /*
+ * status check, open and "connected", when read and write.
+ */
+ synchronized private void checkOpenConnected()
+ throws ClosedChannelException {
+ if (!isOpen()) {
+ throw new ClosedChannelException();
+ }
+ if (!isConnected()) {
+ throw new NotYetConnectedException();
+ }
+ }
+
+ /*
+ * status check, open and "unconnected", before connection.
+ */
+ synchronized private void checkUnconnected() throws IOException {
+ if (!isOpen()) {
+ throw new ClosedChannelException();
+ }
+ if (status == SOCKET_STATUS_CONNECTED) {
+ throw new AlreadyConnectedException();
+ }
+ if (status == SOCKET_STATUS_PENDING) {
+ throw new ConnectionPendingException();
+ }
+ }
+
+ /*
+ * shared by this class and DatagramChannelImpl, to do the address transfer
+ * and check.
+ */
+ static InetSocketAddress validateAddress(SocketAddress socketAddress) {
+ if (null == socketAddress) {
+ throw new IllegalArgumentException();
+ }
+ if (!(socketAddress instanceof InetSocketAddress)) {
+ throw new UnsupportedAddressTypeException();
+ }
+ InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
+ if (inetSocketAddress.isUnresolved()) {
+ throw new UnresolvedAddressException();
+ }
+ return inetSocketAddress;
+ }
+
+ /*
+ * get local address
+ */
+ public InetAddress getLocalAddress() throws UnknownHostException {
+ byte[] any_bytes = { 0, 0, 0, 0 };
+ if (!isBound) {
+ return InetAddress.getByAddress(any_bytes);
+ }
+ return localAddress;
+ }
+
+ // -------------------------------------------------------------------
+ // Protected inherited methods
+ // -------------------------------------------------------------------
+ /*
+ * do really closing action here
+ */
+ synchronized protected void implCloseSelectableChannel() throws IOException {
+ if (SOCKET_STATUS_CLOSED != status) {
+ status = SOCKET_STATUS_CLOSED;
+ if (null != socket && !socket.isClosed()) {
+ socket.close();
+ } else {
+ networkSystem.socketClose(fd);
+ }
+ }
+ }
+
+ /*
+ * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean)
+ */
+ protected void implConfigureBlocking(boolean blockMode) throws IOException {
+ synchronized (blockingLock()) {
+ networkSystem.setNonBlocking(fd, !blockMode);
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Adapter classes for internal socket.
+ // -------------------------------------------------------------------
+
+ /*
+ * get the fd
+ */
+ public FileDescriptor getFD() {
+ return fd;
+ }
+
+ public InetAddress getAddress() {
+ return (null == this.connectAddress) ? null : this.connectAddress
+ .getAddress();
+ }
+
+ public int getPort() {
+ return (null == this.connectAddress) ? 0 : this.connectAddress
+ .getPort();
+ }
+
+ public int getLocalPort() {
+ return this.localPort;
+ }
+
+ private static class SocketAdapter extends Socket {
+
+ // ----------------------------------------------------
+ // Class Variables
+ // ----------------------------------------------------
+
+ private static final String ERRCODE_CHANNEL_NOT_CONNECTED = "K0320"; //$NON-NLS-1$
+
+ private static final String ERRCODE_CHANNEL_CLOSED = "K003d"; //$NON-NLS-1$
+
+ SocketChannelImpl channel;
+
+ SocketImpl socketImpl;
+
+ // ----------------------------------------------------
+ // Methods
+ // ----------------------------------------------------
+
+ SocketAdapter(SocketImpl socketimpl, SocketChannelImpl channel)
+ throws SocketException {
+ super(socketimpl);
+ socketImpl = socketimpl;
+ this.channel = channel;
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getChannel()
+ */
+ public SocketChannel getChannel() {
+ return channel;
+ }
+
+ /*
+ *
+ * @see java.net.Socket#isBound()
+ */
+ public boolean isBound() {
+ return channel.isBound;
+ }
+
+ /*
+ *
+ * @see java.net.Socket#isConnected()
+ */
+ public boolean isConnected() {
+ return channel.isConnected();
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getLocalAddress()
+ */
+ public InetAddress getLocalAddress() {
+ try {
+ return channel.getLocalAddress();
+ } catch (UnknownHostException e) {
+ return null;
+ }
+ }
+
+ /*
+ *
+ * @see java.net.Socket#connect(java.net.SocketAddress, int)
+ */
+ public void connect(SocketAddress remoteAddr, int timeout)
+ throws IOException {
+ if (!channel.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ if (isConnected()) {
+ throw new AlreadyConnectedException();
+ }
+ super.connect(remoteAddr, timeout);
+ channel.localAddress = networkSystem.getSocketLocalAddress(
+ channel.fd, false);
+ if (super.isConnected()) {
+ channel.setConnected();
+ channel.isBound = super.isBound();
+ }
+ }
+
+ /*
+ *
+ * @see java.net.Socket#bind(java.net.SocketAddress)
+ */
+ public void bind(SocketAddress localAddr) throws IOException {
+ if (channel.isConnected()) {
+ throw new AlreadyConnectedException();
+ }
+ if (SocketChannelImpl.SOCKET_STATUS_PENDING == channel.status) {
+ throw new ConnectionPendingException();
+ }
+ super.bind(localAddr);
+ // keep here to see if need next version
+ // channel.Address = getLocalSocketAddress();
+ // channel.localport = getLocalPort();
+ channel.isBound = true;
+
+ }
+
+ /*
+ *
+ * @see java.net.Socket#close()
+ */
+ public void close() throws IOException {
+ synchronized (channel) {
+ if (channel.isOpen()) {
+ channel.close();
+ } else {
+ super.close();
+ }
+ channel.status = SocketChannelImpl.SOCKET_STATUS_CLOSED;
+ }
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getKeepAlive()
+ */
+ public boolean getKeepAlive() throws SocketException {
+ checkClosedAndCreate(true);
+ return ((Boolean) socketImpl.getOption(SocketOptions.SO_KEEPALIVE))
+ .booleanValue();
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getOOBInline()
+ */
+ public boolean getOOBInline() throws SocketException {
+ checkClosedAndCreate(true);
+ return ((Boolean) socketImpl.getOption(SocketOptions.SO_OOBINLINE))
+ .booleanValue();
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getSoLinger()
+ */
+ public int getSoLinger() throws SocketException {
+ checkClosedAndCreate(true);
+ return ((Integer) socketImpl.getOption(SocketOptions.SO_LINGER))
+ .intValue();
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getTcpNoDelay()
+ */
+ public boolean getTcpNoDelay() throws SocketException {
+ checkClosedAndCreate(true);
+ return ((Boolean) socketImpl.getOption(SocketOptions.TCP_NODELAY))
+ .booleanValue();
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getOutputStream()
+ */
+ public OutputStream getOutputStream() throws IOException {
+ return new SocketChannelOutputStream(super.getOutputStream(),
+ channel);
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getInputStream()
+ */
+ public InputStream getInputStream() throws IOException {
+ return new SocketChannelInputStream(super.getInputStream(), channel);
+ }
+
+ /*
+ * checl if channel is close or create a new one.
+ */
+ private void checkClosedAndCreate(boolean create)
+ throws SocketException {
+ if (isClosed()) {
+ throw new SocketException(Msg.getString(ERRCODE_CHANNEL_CLOSED));
+ }
+ if (!create && !isConnected()) {
+ throw new SocketException(Msg
+ .getString(ERRCODE_CHANNEL_NOT_CONNECTED));
+ }
+ // FIXME check if need cread fd
+ }
+
+ /*
+ * used for net and nio exchange
+ */
+ public SocketImpl getImpl() {
+ return socketImpl;
+ }
+ }
+
+ private static class SocketChannelOutputStream extends OutputStream {
+ SocketChannel channel;
+
+ OutputStream wrapped;
+
+ public SocketChannelOutputStream(OutputStream wrapped,
+ SocketChannel channel) {
+ this.channel = channel;
+ this.wrapped = wrapped;
+ }
+
+ /*
+ *
+ * @see com.ibm.io.nio.SocketOutputStream#write(byte[], int, int)
+ */
+ public void write(byte[] buffer, int offset, int count)
+ throws IOException {
+ if (!channel.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ wrapped.write(buffer, offset, count);
+ }
+
+ /*
+ *
+ * @see com.ibm.io.nio.SocketOutputStream#write(byte[])
+ */
+ public void write(byte[] buffer) throws IOException {
+ if (!channel.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ wrapped.write(buffer);
+ }
+
+ /*
+ *
+ * @see com.ibm.io.nio.SocketOutputStream#write(int)
+ */
+ public void write(int oneByte) throws IOException {
+ if (!channel.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ wrapped.write(oneByte);
+ }
+ }
+
+ private static class SocketChannelInputStream extends InputStream {
+ SocketChannel channel;
+
+ InputStream wrapped;
+
+ public SocketChannelInputStream(InputStream wrapped,
+ SocketChannel channel) {
+ this.channel = channel;
+ this.wrapped = wrapped;
+ }
+
+ /*
+ *
+ * @see com.ibm.io.nio.SocketInputStream#read()
+ */
+ public int read() throws IOException {
+ if (!channel.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ return wrapped.read();
+ }
+
+ /*
+ *
+ * @see com.ibm.io.nio.SocketInputStream#read(byte[], int, int)
+ */
+ public int read(byte[] buffer, int offset, int count)
+ throws IOException {
+ if (!channel.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ return wrapped.read(buffer, offset, count);
+ }
+
+ /*
+ *
+ * @see com.ibm.io.nio.SocketInputStream#read(byte[])
+ */
+ public int read(byte[] buffer) throws IOException {
+ if (!channel.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ return wrapped.read(buffer);
+ }
+ }
+}
Propchange: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/AllTests.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/AllTests.java?rev=392225&r1=392224&r2=392225&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/AllTests.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/AllTests.java Fri Apr 7 02:07:34 2006
@@ -24,7 +24,10 @@
TestSuite suite = new TestSuite(
"Test for org.apache.harmony.tests.java.nio.channels");
//$JUnit-BEGIN$
+ suite.addTestSuite(ServerSocketChannelTest.class);
+ suite.addTestSuite(SocketChannelTest.class);
suite.addTestSuite(FileChannelTest.class);
+ suite.addTestSuite(DatagramChannelTest.class);
//$JUnit-END$
return suite;
}