summaryrefslogtreecommitdiffstats
path: root/nio
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commitfdb2704414a9ed92394ada0d1395e4db86889465 (patch)
tree9b591a4a50054274a197f02b3ccb51313681879f /nio
downloadlibcore-fdb2704414a9ed92394ada0d1395e4db86889465.zip
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.gz
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.bz2
Initial Contribution
Diffstat (limited to 'nio')
-rw-r--r--nio/MODULE_LICENSE_APACHE20
-rw-r--r--nio/src/main/java/java/nio/BaseByteBuffer.java70
-rw-r--r--nio/src/main/java/java/nio/Buffer.java322
-rw-r--r--nio/src/main/java/java/nio/BufferFactory.java208
-rw-r--r--nio/src/main/java/java/nio/BufferOverflowException.java36
-rw-r--r--nio/src/main/java/java/nio/BufferUnderflowException.java36
-rw-r--r--nio/src/main/java/java/nio/ByteBuffer.java1121
-rw-r--r--nio/src/main/java/java/nio/ByteOrder.java73
-rw-r--r--nio/src/main/java/java/nio/CharArrayBuffer.java101
-rw-r--r--nio/src/main/java/java/nio/CharBuffer.java810
-rw-r--r--nio/src/main/java/java/nio/CharSequenceAdapter.java152
-rw-r--r--nio/src/main/java/java/nio/CharToByteBufferAdapter.java214
-rw-r--r--nio/src/main/java/java/nio/DirectByteBuffer.java289
-rw-r--r--nio/src/main/java/java/nio/DirectByteBuffers.java84
-rw-r--r--nio/src/main/java/java/nio/DoubleArrayBuffer.java88
-rw-r--r--nio/src/main/java/java/nio/DoubleBuffer.java565
-rw-r--r--nio/src/main/java/java/nio/DoubleToByteBufferAdapter.java204
-rw-r--r--nio/src/main/java/java/nio/FloatArrayBuffer.java87
-rw-r--r--nio/src/main/java/java/nio/FloatBuffer.java564
-rw-r--r--nio/src/main/java/java/nio/FloatToByteBufferAdapter.java204
-rw-r--r--nio/src/main/java/java/nio/HeapByteBuffer.java250
-rw-r--r--nio/src/main/java/java/nio/IntArrayBuffer.java87
-rw-r--r--nio/src/main/java/java/nio/IntBuffer.java579
-rw-r--r--nio/src/main/java/java/nio/IntToByteBufferAdapter.java216
-rw-r--r--nio/src/main/java/java/nio/InvalidMarkException.java35
-rw-r--r--nio/src/main/java/java/nio/LongArrayBuffer.java87
-rw-r--r--nio/src/main/java/java/nio/LongBuffer.java587
-rw-r--r--nio/src/main/java/java/nio/LongToByteBufferAdapter.java204
-rw-r--r--nio/src/main/java/java/nio/MappedByteBuffer.java107
-rw-r--r--nio/src/main/java/java/nio/MappedByteBufferAdapter.java368
-rw-r--r--nio/src/main/java/java/nio/NIOAccess.java87
-rw-r--r--nio/src/main/java/java/nio/ReadOnlyBufferException.java35
-rw-r--r--nio/src/main/java/java/nio/ReadOnlyCharArrayBuffer.java102
-rw-r--r--nio/src/main/java/java/nio/ReadOnlyDirectByteBuffer.java135
-rw-r--r--nio/src/main/java/java/nio/ReadOnlyDoubleArrayBuffer.java98
-rw-r--r--nio/src/main/java/java/nio/ReadOnlyFloatArrayBuffer.java96
-rw-r--r--nio/src/main/java/java/nio/ReadOnlyHeapByteBuffer.java138
-rw-r--r--nio/src/main/java/java/nio/ReadOnlyIntArrayBuffer.java96
-rw-r--r--nio/src/main/java/java/nio/ReadOnlyLongArrayBuffer.java96
-rw-r--r--nio/src/main/java/java/nio/ReadOnlyShortArrayBuffer.java96
-rw-r--r--nio/src/main/java/java/nio/ReadWriteCharArrayBuffer.java121
-rw-r--r--nio/src/main/java/java/nio/ReadWriteDirectByteBuffer.java316
-rw-r--r--nio/src/main/java/java/nio/ReadWriteDoubleArrayBuffer.java125
-rw-r--r--nio/src/main/java/java/nio/ReadWriteFloatArrayBuffer.java125
-rw-r--r--nio/src/main/java/java/nio/ReadWriteHeapByteBuffer.java204
-rw-r--r--nio/src/main/java/java/nio/ReadWriteIntArrayBuffer.java122
-rw-r--r--nio/src/main/java/java/nio/ReadWriteLongArrayBuffer.java122
-rw-r--r--nio/src/main/java/java/nio/ReadWriteShortArrayBuffer.java124
-rw-r--r--nio/src/main/java/java/nio/ShortArrayBuffer.java88
-rw-r--r--nio/src/main/java/java/nio/ShortBuffer.java584
-rw-r--r--nio/src/main/java/java/nio/ShortToByteBufferAdapter.java216
-rw-r--r--nio/src/main/java/java/nio/channels/AlreadyConnectedException.java34
-rw-r--r--nio/src/main/java/java/nio/channels/AsynchronousCloseException.java35
-rw-r--r--nio/src/main/java/java/nio/channels/ByteChannel.java30
-rw-r--r--nio/src/main/java/java/nio/channels/CancelledKeyException.java38
-rw-r--r--nio/src/main/java/java/nio/channels/Channel.java67
-rw-r--r--nio/src/main/java/java/nio/channels/Channels.java569
-rw-r--r--nio/src/main/java/java/nio/channels/ClosedByInterruptException.java39
-rw-r--r--nio/src/main/java/java/nio/channels/ClosedChannelException.java38
-rw-r--r--nio/src/main/java/java/nio/channels/ClosedSelectorException.java37
-rw-r--r--nio/src/main/java/java/nio/channels/ConnectionPendingException.java37
-rw-r--r--nio/src/main/java/java/nio/channels/DatagramChannel.java456
-rw-r--r--nio/src/main/java/java/nio/channels/FileChannel.java680
-rw-r--r--nio/src/main/java/java/nio/channels/FileLock.java209
-rw-r--r--nio/src/main/java/java/nio/channels/FileLockInterruptionException.java39
-rw-r--r--nio/src/main/java/java/nio/channels/GatheringByteChannel.java104
-rw-r--r--nio/src/main/java/java/nio/channels/IllegalBlockingModeException.java35
-rw-r--r--nio/src/main/java/java/nio/channels/IllegalSelectorException.java37
-rw-r--r--nio/src/main/java/java/nio/channels/InterruptibleChannel.java58
-rw-r--r--nio/src/main/java/java/nio/channels/NoConnectionPendingException.java36
-rw-r--r--nio/src/main/java/java/nio/channels/NonReadableChannelException.java34
-rw-r--r--nio/src/main/java/java/nio/channels/NonWritableChannelException.java34
-rw-r--r--nio/src/main/java/java/nio/channels/NotYetBoundException.java36
-rw-r--r--nio/src/main/java/java/nio/channels/NotYetConnectedException.java37
-rw-r--r--nio/src/main/java/java/nio/channels/OverlappingFileLockException.java35
-rw-r--r--nio/src/main/java/java/nio/channels/Pipe.java118
-rw-r--r--nio/src/main/java/java/nio/channels/ReadableByteChannel.java67
-rw-r--r--nio/src/main/java/java/nio/channels/ScatteringByteChannel.java104
-rw-r--r--nio/src/main/java/java/nio/channels/SelectableChannel.java153
-rw-r--r--nio/src/main/java/java/nio/channels/SelectionKey.java189
-rw-r--r--nio/src/main/java/java/nio/channels/Selector.java148
-rw-r--r--nio/src/main/java/java/nio/channels/ServerSocketChannel.java119
-rw-r--r--nio/src/main/java/java/nio/channels/SocketChannel.java484
-rw-r--r--nio/src/main/java/java/nio/channels/UnresolvedAddressException.java36
-rw-r--r--nio/src/main/java/java/nio/channels/UnsupportedAddressTypeException.java35
-rw-r--r--nio/src/main/java/java/nio/channels/WritableByteChannel.java68
-rw-r--r--nio/src/main/java/java/nio/channels/package.html9
-rw-r--r--nio/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java180
-rw-r--r--nio/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java238
-rw-r--r--nio/src/main/java/java/nio/channels/spi/AbstractSelectionKey.java60
-rw-r--r--nio/src/main/java/java/nio/channels/spi/AbstractSelector.java169
-rw-r--r--nio/src/main/java/java/nio/channels/spi/SelectorProvider.java259
-rw-r--r--nio/src/main/java/java/nio/channels/spi/package.html7
-rw-r--r--nio/src/main/java/java/nio/package.html15
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/AddressUtil.java86
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/FileChannelFactory.java56
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/Util.java162
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java910
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/DirectBuffer.java36
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/FileChannelImpl.java656
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/FileLockImpl.java73
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java238
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/LockManager.java80
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/MappedByteBufferFactory.java60
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/PipeImpl.java194
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/ReadOnlyFileChannel.java110
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/ReadWriteFileChannel.java55
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/SelectionKeyImpl.java94
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/SelectorImpl.java404
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java82
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java320
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java1047
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/WriteOnlyFileChannel.java115
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/nls/Messages.java124
-rw-r--r--nio/src/main/java/org/apache/harmony/nio/internal/nls/messages.properties28
-rw-r--r--nio/src/main/native/org_apache_harmony_nio_AddressUtil.cpp73
-rw-r--r--nio/src/main/native/sub.mk16
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/AbstractBufferTest.java306
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/AllTests.java102
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java42
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferTest.java324
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java45
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteBufferTest.java2306
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteOrderTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java1253
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectByteBufferTest.java58
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectCharBufferTest.java61
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectDoubleBufferTest.java60
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectFloatBufferTest.java61
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectIntBufferTest.java61
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectLongBufferTest.java62
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectShortBufferTest.java61
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java741
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateDirectByteBufferTest.java31
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateHeapByteBufferTest.java32
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateWrappedByteBufferTest.java32
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java749
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapByteBufferTest.java60
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapCharBufferTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapDoubleBufferTest.java42
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapFloatBufferTest.java42
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapIntBufferTest.java42
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapLongBufferTest.java42
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapShortBufferTest.java42
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/IntBufferTest.java738
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java41
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/LongBufferTest.java745
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java41
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyCharBufferTest.java209
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDirectByteBufferTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDoubleBufferTest.java160
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyFloatBufferTest.java161
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapByteBufferTest.java43
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapCharBufferTest.java35
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapDoubleBufferTest.java34
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapFloatBufferTest.java32
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapIntBufferTest.java32
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapLongBufferTest.java32
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapShortBufferTest.java32
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyIntBufferTest.java161
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyLongBufferTest.java161
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyShortBufferTest.java161
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedByteBufferTest.java45
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedCharBufferTest1.java34
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedDoubleBufferTest.java32
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedFloatBufferTest.java32
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedIntBufferTest.java32
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedLongBufferTest.java32
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedShortBufferTest.java32
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ShortBufferTest.java725
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceDirectByteBufferTest.java32
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceHeapByteBufferTest.java33
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceWrappedByteBufferTest.java33
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedByteBufferTest.java97
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest1.java84
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest2.java129
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedDoubleBufferTest.java87
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedFloatBufferTest.java87
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedIntBufferTest.java87
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedLongBufferTest.java87
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedShortBufferTest.java87
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AllTests.java67
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ChannelsTest.java683
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java2643
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelLockingTest.java196
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java3271
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java45
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java193
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java45
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MapModeTest.java52
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockDatagramChannel.java81
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockServerSocketChannel.java46
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockSocketChannel.java75
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java45
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java45
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/PipeTest.java57
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectableChannelTest.java89
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectionKeyTest.java321
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java544
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ServerSocketChannelTest.java575
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SinkChannelTest.java537
-rwxr-xr-xnio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java3118
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SourceChannelTest.java532
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java44
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java45
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractInterruptibleChannelTest.java136
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java304
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectionKeyTest.java76
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectorTest.java160
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AllTests.java37
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/MockAbstractSelector.java89
-rw-r--r--nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/SelectorProviderTest.java115
-rw-r--r--nio/src/test/java/tests/nio/AllTests.java40
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.golden.serbin0 -> 1283 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.golden.serbin0 -> 1369 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.golden.serbin0 -> 1403 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.golden.serbin0 -> 1420 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.golden.serbin0 -> 1427 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.golden.serbin0 -> 1441 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.golden.serbin0 -> 1424 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.golden.serbin0 -> 1500 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.golden.serbin0 -> 1374 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.golden.serbin0 -> 1430 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.golden.serbin0 -> 1439 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.golden.serbin0 -> 1395 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.golden.serbin0 -> 1743 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.golden.serbin0 -> 1734 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.golden.serbin0 -> 1445 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.golden.serbin0 -> 1442 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.golden.serbin0 -> 1442 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.golden.serbin0 -> 1719 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.golden.serbin0 -> 1731 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.golden.serbin0 -> 1743 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.golden.serbin0 -> 1740 bytes
-rw-r--r--nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.golden.serbin0 -> 1755 bytes
247 files changed, 47353 insertions, 0 deletions
diff --git a/nio/MODULE_LICENSE_APACHE2 b/nio/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/nio/MODULE_LICENSE_APACHE2
diff --git a/nio/src/main/java/java/nio/BaseByteBuffer.java b/nio/src/main/java/java/nio/BaseByteBuffer.java
new file mode 100644
index 0000000..009bcb7
--- /dev/null
+++ b/nio/src/main/java/java/nio/BaseByteBuffer.java
@@ -0,0 +1,70 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+
+/**
+ * Serves as the root of other byte buffer impl classes, implements common
+ * methods that can be shared by child classes.
+ *
+ */
+abstract class BaseByteBuffer extends ByteBuffer {
+
+ protected BaseByteBuffer(int capacity) {
+ super(capacity);
+ }
+
+ public final CharBuffer asCharBuffer() {
+ return CharToByteBufferAdapter.wrap(this);
+ }
+
+ public final DoubleBuffer asDoubleBuffer() {
+ return DoubleToByteBufferAdapter.wrap(this);
+ }
+
+ public final FloatBuffer asFloatBuffer() {
+ return FloatToByteBufferAdapter.wrap(this);
+ }
+
+ public final IntBuffer asIntBuffer() {
+ return IntToByteBufferAdapter.wrap(this);
+ }
+
+ public final LongBuffer asLongBuffer() {
+ return LongToByteBufferAdapter.wrap(this);
+ }
+
+ public final ShortBuffer asShortBuffer() {
+ return ShortToByteBufferAdapter.wrap(this);
+ }
+
+ public final char getChar() {
+ return (char) getShort();
+ }
+
+ public final char getChar(int index) {
+ return (char) getShort(index);
+ }
+
+ public final ByteBuffer putChar(char value) {
+ return putShort((short) value);
+ }
+
+ public final ByteBuffer putChar(int index, char value) {
+ return putShort(index, (short) value);
+ }
+}
diff --git a/nio/src/main/java/java/nio/Buffer.java b/nio/src/main/java/java/nio/Buffer.java
new file mode 100644
index 0000000..200246c
--- /dev/null
+++ b/nio/src/main/java/java/nio/Buffer.java
@@ -0,0 +1,322 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+
+/**
+ * A buffer is a list of elements of a specific primitive type.
+ * <p>
+ * A buffer can be described by following properties:
+ * <ul>
+ * <li>Capacity, is the number of elements a buffer can hold. Capacity is no
+ * less than zero and never changes.</li>
+ * <li>Position, is a cursor of this buffer. Elements are read or write at the
+ * position if you do not specify an index explicitly. Position is no less than
+ * zero and no greater than the limit.</li>
+ * <li>Limit controls the scope of accessible elements. You can only read or
+ * write elements from index zero to <code>limit - 1</code>. Accessing
+ * elements out of the scope will cause exception. Limit is no less than zero
+ * and no greater than capacity.</li>
+ * <li>Mark, is used to remember the current position, so that you can reset
+ * the position later. Mark is no less than zero and no greater than position.</li>
+ * <li>A buffer can be readonly or read-write. Trying to modify the elements of
+ * a readonly buffer will cause <code>ReadOnlyBufferException</code>, while
+ * changing the position, limit and mark of a readonly buffer is OK.</li>
+ * <li>A buffer can be direct or indirect. A direct buffer will try its best to
+ * take advantage of native memory APIs and it may not stay in java heap, thus
+ * not affected by GC.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Buffers are not thread-safe. If concurrent access to a buffer instance is
+ * required, then the callers are responsible to take care of the
+ * synchronization issues.
+ * </p>
+ *
+ */
+public abstract class Buffer {
+
+ /**
+ * <code>UNSET_MARK</code> means the mark has not been set.
+ */
+ final static int UNSET_MARK = -1;
+
+ /**
+ * The capacity of this buffer, which never change.
+ */
+ final int capacity;
+
+ /**
+ * <code>limit - 1</code> is the last element that can be read or write.
+ * Limit must be no less than zero and no greater than <code>capacity</code>.
+ */
+ int limit;
+
+ /**
+ * Mark is the position will be set when <code>reset()</code> is called.
+ * Mark is not set by default. Mark is always no less than zero and no
+ * greater than <code>position</code>.
+ */
+ int mark = UNSET_MARK;
+
+ /**
+ * The current position of this buffer. Position is always no less than zero
+ * and no greater than <code>limit</code>.
+ */
+ int position = 0;
+
+ // BEGIN android-added
+ /**
+ * The log base 2 of the element size of this buffer. Each typed subclass
+ * (ByteBuffer, CharBuffer, etc.) is responsible for initializing this
+ * value. The value is used by native code to avoid the need for costly
+ * 'instanceof' tests.
+ *
+ */
+ int _elementSizeShift;
+
+ /**
+ * Returns the array associated with this buffer, or null if none exists.
+ * Each typed subclass (ByteBuffer, CharBuffer, etc.) overrides this method
+ * to call its array() method with appropriate checks.
+ *
+ * @return a primitive array or null
+ */
+ Object _array() {
+ return null;
+ }
+
+ /**
+ * Returns the offset into the backing array, if one exists, otherwise 0.
+ * Each typed subclass (ByteBuffer, CharBuffer, etc.) overrides this method
+ * to call its arrayOffset() method with appropriate checks.
+ *
+ * @return the array offset, or 0
+ */
+ int _arrayOffset() {
+ return 0;
+ }
+ // END android-added
+
+ /**
+ * Construct a buffer with the specified capacity.
+ *
+ * @param capacity
+ * The capacity of this buffer
+ */
+ Buffer(int capacity) {
+ super();
+ if (capacity < 0) {
+ throw new IllegalArgumentException();
+ }
+ this.capacity = this.limit = capacity;
+ }
+
+ /**
+ * Returns the capacity of this buffer.
+ *
+ * @return The number of elements that are contained in this buffer.
+ */
+ public final int capacity() {
+ return capacity;
+ }
+
+ /**
+ * Clears this buffer.
+ * <p>
+ * While the content of this buffer is not changed the following internal
+ * changes take place : the current position is reset back to the start of the buffer,
+ * the value of the buffer limit is made equal to the capacity and mark is unset.
+ * </p>
+ *
+ * @return This buffer
+ */
+ public final Buffer clear() {
+ position = 0;
+ mark = UNSET_MARK;
+ limit = capacity;
+ return this;
+ }
+
+ /**
+ * Flips this buffer.
+ * <p>
+ * The limit is set to the current position, then the position is set to
+ * zero, and the mark is cleared.
+ * </p>
+ * <p>
+ * The content of this buffer is not changed.
+ * </p>
+ *
+ * @return This buffer
+ */
+ public final Buffer flip() {
+ limit = position;
+ position = 0;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ /**
+ * Returns true if there are remaining element(s) in this buffer.
+ * <p>
+ * Or more precisely, returns <code>position &lt; limit</code>.
+ * </p>
+ *
+ * @return True if there are remaining element(s) in this buffer.
+ */
+ public final boolean hasRemaining() {
+ return position < limit;
+ }
+
+ /**
+ * Returns whether this buffer is readonly or not.
+ *
+ * @return Whether this buffer is readonly or not.
+ */
+ public abstract boolean isReadOnly();
+
+ /**
+ * Returns the limit of this buffer.
+ *
+ * @return The limit of this buffer.
+ */
+ public final int limit() {
+ return limit;
+ }
+
+ /**
+ * Sets the limit of this buffer.
+ * <p>
+ * If the current position in the buffer is in excess of
+ * <code>newLimit</code> then, on returning from this call, it will have
+ * been adjusted to be equivalent to <code>newLimit</code>. If the mark
+ * is set and is greater than the new limit, then it is cleared.
+ * </p>
+ *
+ * @param newLimit
+ * The new limit, must be no less than zero and no greater than
+ * capacity
+ * @return This buffer
+ * @exception IllegalArgumentException
+ * If <code>newLimit</code> is invalid.
+ */
+ public final Buffer limit(int newLimit) {
+ if (newLimit < 0 || newLimit > capacity) {
+ throw new IllegalArgumentException();
+ }
+
+ limit = newLimit;
+ if (position > newLimit) {
+ position = newLimit;
+ }
+ if ((mark != UNSET_MARK) && (mark > newLimit)) {
+ mark = UNSET_MARK;
+ }
+ return this;
+ }
+
+ /**
+ * Mark the current position, so that the position may return to this point
+ * later by calling <code>reset()</code>.
+ *
+ * @return This buffer
+ */
+ public final Buffer mark() {
+ mark = position;
+ return this;
+ }
+
+ /**
+ * Returns the position of this buffer.
+ *
+ * @return The value of this buffer's current position.
+ */
+ public final int position() {
+ return position;
+ }
+
+ /**
+ * Sets the position of this buffer.
+ * <p>
+ * If the mark is set and is greater than the new position, then it is
+ * cleared.
+ * </p>
+ *
+ * @param newPosition
+ * The new position, must be no less than zero and no greater
+ * than limit
+ * @return This buffer
+ * @exception IllegalArgumentException
+ * If <code>newPosition</code> is invalid
+ */
+ public final Buffer position(int newPosition) {
+ if (newPosition < 0 || newPosition > limit) {
+ throw new IllegalArgumentException();
+ }
+
+ position = newPosition;
+ if ((mark != UNSET_MARK) && (mark > position)) {
+ mark = UNSET_MARK;
+ }
+ return this;
+ }
+
+ /**
+ * Returns the number of remaining elements in this buffer.
+ * <p>
+ * Or more precisely, returns <code>limit - position</code>.
+ * </p>
+ *
+ * @return The number of remaining elements in this buffer.
+ */
+ public final int remaining() {
+ return limit - position;
+ }
+
+ /**
+ * Reset the position of this buffer to the <code>mark</code>.
+ *
+ * @return This buffer
+ * @exception InvalidMarkException
+ * If the mark is not set
+ */
+ public final Buffer reset() {
+ if (mark == UNSET_MARK) {
+ throw new InvalidMarkException();
+ }
+ position = mark;
+ return this;
+ }
+
+ /**
+ * Rewinds this buffer.
+ * <p>
+ * The position is set to zero, and the mark is cleared.
+ * </p>
+ * <p>
+ * The content of this buffer is not changed.
+ * </p>
+ *
+ * @return This buffer
+ */
+ public final Buffer rewind() {
+ position = 0;
+ mark = UNSET_MARK;
+ return this;
+ }
+}
diff --git a/nio/src/main/java/java/nio/BufferFactory.java b/nio/src/main/java/java/nio/BufferFactory.java
new file mode 100644
index 0000000..acb2400
--- /dev/null
+++ b/nio/src/main/java/java/nio/BufferFactory.java
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+
+/**
+ * Provide factory service of buffer classes.
+ * <p>
+ * Since all buffer impl classes are package private (except DirectByteBuffer),
+ * this factory is the only entrance to access buffer functions from outside of
+ * the impl package.
+ * </p>
+ *
+ */
+final class BufferFactory {
+
+ /**
+ * Returns a new byte buffer based on the specified byte array.
+ *
+ * @param array
+ * The byte array
+ * @return A new byte buffer based on the specified byte array.
+ */
+ public static ByteBuffer newByteBuffer(byte array[]) {
+ return new ReadWriteHeapByteBuffer(array);
+ }
+
+ /**
+ * Returns a new array based byte buffer with the specified capacity.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return A new array based byte buffer with the specified capacity.
+ */
+ public static ByteBuffer newByteBuffer(int capacity) {
+ return new ReadWriteHeapByteBuffer(capacity);
+ }
+
+ /**
+ * Returns a new char buffer based on the specified char array.
+ *
+ * @param array
+ * The char array
+ * @return A new char buffer based on the specified char array.
+ */
+ public static CharBuffer newCharBuffer(char array[]) {
+ return new ReadWriteCharArrayBuffer(array);
+ }
+
+ /**
+ * Returns a new readonly char buffer based on the specified char sequence.
+ *
+ * @param chseq
+ * The char sequence
+ * @return A new readonly char buffer based on the specified char sequence.
+ */
+ public static CharBuffer newCharBuffer(CharSequence chseq) {
+ return new CharSequenceAdapter(chseq);
+ }
+
+ /**
+ * Returns a new array based char buffer with the specified capacity.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return A new array based char buffer with the specified capacity.
+ */
+ public static CharBuffer newCharBuffer(int capacity) {
+ return new ReadWriteCharArrayBuffer(capacity);
+ }
+
+ /**
+ * Returns a new direct byte buffer with the specified capacity.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return A new direct byte buffer with the specified capacity.
+ */
+ public static ByteBuffer newDirectByteBuffer(int capacity) {
+ return new ReadWriteDirectByteBuffer(capacity);
+ }
+
+ /**
+ * Returns a new double buffer based on the specified double array.
+ *
+ * @param array
+ * The double array
+ * @return A new double buffer based on the specified double array.
+ */
+ public static DoubleBuffer newDoubleBuffer(double array[]) {
+ return new ReadWriteDoubleArrayBuffer(array);
+ }
+
+ /**
+ * Returns a new array based double buffer with the specified capacity.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return A new array based double buffer with the specified capacity.
+ */
+ public static DoubleBuffer newDoubleBuffer(int capacity) {
+ return new ReadWriteDoubleArrayBuffer(capacity);
+ }
+
+ /**
+ * Returns a new float buffer based on the specified float array.
+ *
+ * @param array
+ * The float array
+ * @return A new float buffer based on the specified float array.
+ */
+ public static FloatBuffer newFloatBuffer(float array[]) {
+ return new ReadWriteFloatArrayBuffer(array);
+ }
+
+ /**
+ * Returns a new array based float buffer with the specified capacity.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return A new array based float buffer with the specified capacity.
+ */
+ public static FloatBuffer newFloatBuffer(int capacity) {
+ return new ReadWriteFloatArrayBuffer(capacity);
+ }
+
+ /**
+ * Returns a new array based int buffer with the specified capacity.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return A new array based int buffer with the specified capacity.
+ */
+ public static IntBuffer newIntBuffer(int capacity) {
+ return new ReadWriteIntArrayBuffer(capacity);
+ }
+
+ /**
+ * Returns a new int buffer based on the specified int array.
+ *
+ * @param array
+ * The int array
+ * @return A new int buffer based on the specified int array.
+ */
+ public static IntBuffer newIntBuffer(int array[]) {
+ return new ReadWriteIntArrayBuffer(array);
+ }
+
+ /**
+ * Returns a new array based long buffer with the specified capacity.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return A new array based long buffer with the specified capacity.
+ */
+ public static LongBuffer newLongBuffer(int capacity) {
+ return new ReadWriteLongArrayBuffer(capacity);
+ }
+
+ /**
+ * Returns a new long buffer based on the specified long array.
+ *
+ * @param array
+ * The long array
+ * @return A new long buffer based on the specified long array.
+ */
+ public static LongBuffer newLongBuffer(long array[]) {
+ return new ReadWriteLongArrayBuffer(array);
+ }
+
+ /**
+ * Returns a new array based short buffer with the specified capacity.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return A new array based short buffer with the specified capacity.
+ */
+ public static ShortBuffer newShortBuffer(int capacity) {
+ return new ReadWriteShortArrayBuffer(capacity);
+ }
+
+ /**
+ * Returns a new short buffer based on the specified short array.
+ *
+ * @param array
+ * The short array
+ * @return A new short buffer based on the specified short array.
+ */
+ public static ShortBuffer newShortBuffer(short array[]) {
+ return new ReadWriteShortArrayBuffer(array);
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/BufferOverflowException.java b/nio/src/main/java/java/nio/BufferOverflowException.java
new file mode 100644
index 0000000..9dc6330
--- /dev/null
+++ b/nio/src/main/java/java/nio/BufferOverflowException.java
@@ -0,0 +1,36 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+
+/**
+ * A <code>BufferOverflowException</code> is thrown when you try to write
+ * elements to a buffer, but there is not enough remaining space in the
+ * buffer.
+ *
+ */
+public class BufferOverflowException extends RuntimeException {
+
+ private static final long serialVersionUID = -5484897634319144535L;
+
+ /**
+ * Constructs a <code>BufferOverflowException</code>.
+ */
+ public BufferOverflowException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/BufferUnderflowException.java b/nio/src/main/java/java/nio/BufferUnderflowException.java
new file mode 100644
index 0000000..fe56555
--- /dev/null
+++ b/nio/src/main/java/java/nio/BufferUnderflowException.java
@@ -0,0 +1,36 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+
+/**
+ * A <code>BufferUnderflowException</code> is thrown when you try to read
+ * elements from a buffer, but there is not enough remaining elements in the
+ * buffer.
+ *
+ */
+public class BufferUnderflowException extends RuntimeException {
+
+ private static final long serialVersionUID = -1713313658691622206L;
+
+ /**
+ * Constructs a <code>BufferUnderflowException</code>.
+ */
+ public BufferUnderflowException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/ByteBuffer.java b/nio/src/main/java/java/nio/ByteBuffer.java
new file mode 100644
index 0000000..7a14ad9
--- /dev/null
+++ b/nio/src/main/java/java/nio/ByteBuffer.java
@@ -0,0 +1,1121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+
+import org.apache.harmony.luni.platform.Endianness;
+
+/**
+ * A buffer of <code>byte</code>s.
+ * <p>
+ * A byte buffer can be created in either of the following ways:
+ * <ul>
+ * <li>{@link #allocate(int) Allocate} a new byte array and create a buffer
+ * based on it;</li>
+ * <li>{@link #allocateDirect(int) Allocate} a memory block and create a direct
+ * buffer based on it;</li>
+ * <li>{@link #wrap(byte[]) Wrap} an existing byte array to create a new
+ * buffer.</li>
+ * </ul>
+ * </p>
+ *
+ */
+public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer> {
+
+ /**
+ * Creates a byte buffer based on a new allocated byte array.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return The created byte buffer
+ * @throws IllegalArgumentException
+ * If <code>capacity</code> is less than zero
+ */
+ public static ByteBuffer allocate(int capacity) {
+ if (capacity < 0) {
+ throw new IllegalArgumentException();
+ }
+ return BufferFactory.newByteBuffer(capacity);
+ }
+
+ /**
+ * Creates a direct byte buffer based on a new allocated memory block.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return The created byte buffer
+ * @throws IllegalArgumentException
+ * If <code>capacity</code> is less than zero
+ */
+ public static ByteBuffer allocateDirect(int capacity) {
+ if (capacity < 0) {
+ throw new IllegalArgumentException();
+ }
+ return BufferFactory.newDirectByteBuffer(capacity);
+ }
+
+ /**
+ * Creates a new byte buffer by wrapping the given byte array.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>wrap(array, 0, array.length)</code>.</p>
+ *
+ * @param array The byte array which the new buffer will be based on
+ * @return The created byte buffer
+ */
+ public static ByteBuffer wrap(byte[] array) {
+ return BufferFactory.newByteBuffer(array);
+ }
+
+ /**
+ * Creates new a byte buffer by wrapping the given byte array.
+ * <p>
+ * The new buffer's position will be <code>start</code>, limit will be
+ * <code>start + len</code>, capacity will be the length of the array.
+ * </p>
+ *
+ * @param array
+ * The byte array which the new buffer will be based on
+ * @param start
+ * The start index, must be no less than zero and no greater than
+ * <code>array.length</code>
+ * @param len
+ * The length, must be no less than zero and no greater than
+ * <code>array.length - start</code>
+ * @return The created byte buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>start</code> or <code>len</code> is
+ * invalid
+ */
+ public static ByteBuffer wrap(byte[] array, int start, int len) {
+ int length = array.length;
+ if ((start < 0) || (len < 0) || ((long) start + (long) len > length)) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ ByteBuffer buf = BufferFactory.newByteBuffer(array);
+ buf.position = start;
+ buf.limit = start + len;
+
+ return buf;
+ }
+
+ /**
+ * The byte order of this buffer, default is <code>BIG_ENDIAN</code>.
+ */
+ Endianness order = Endianness.BIG_ENDIAN;
+
+ /**
+ * Constructs a <code>ByteBuffer</code> with given capacity.
+ *
+ * @param capacity The capacity of the buffer
+ */
+ ByteBuffer(int capacity) {
+ super(capacity);
+ // BEGIN android-added
+ _elementSizeShift = 0;
+ // END android-added
+ }
+
+ /**
+ * Returns the byte array which this buffer is based on, if there's one.
+ *
+ * @return The byte array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on a readonly array
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final byte[] array() {
+ return protectedArray();
+ }
+
+ /**
+ * Returns the offset of the byte array which this buffer is based on, if
+ * there's one.
+ * <p>
+ * The offset is the index of the array corresponds to the zero position of
+ * the buffer.
+ * </p>
+ *
+ * @return The offset of the byte array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on a readonly array
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final int arrayOffset() {
+ return protectedArrayOffset();
+ }
+
+ // BEGIN android-added
+ @Override Object _array() {
+ if (hasArray()) {
+ return array();
+ }
+ return null;
+ }
+
+ @Override int _arrayOffset() {
+ if (hasArray()) {
+ return arrayOffset();
+ }
+ return 0;
+ }
+ // END android-added
+
+ /**
+ * Returns a char buffer which is based on the remaining content of
+ * this byte buffer.
+ * <p>
+ * The new buffer's position is zero, its limit and capacity is
+ * the number of remaining bytes divided by two, and its mark is not set.
+ * The new buffer's readonly property and byte order are same as this
+ * buffer. The new buffer is direct, if this byte buffer is direct.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * either buffer's change of content will be visible to the other.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A char buffer which is based on the content of
+ * this byte buffer.
+ */
+ public abstract CharBuffer asCharBuffer();
+
+ /**
+ * Returns a double buffer which is based on the remaining content of
+ * this byte buffer.
+ * <p>
+ * The new buffer's position is zero, its limit and capacity is
+ * the number of remaining bytes divided by two, and its mark is not set.
+ * The new buffer's readonly property and byte order are same as this
+ * buffer. The new buffer is direct, if this byte buffer is direct.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * either buffer's change of content will be visible to the other.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A double buffer which is based on the content of
+ * this byte buffer.
+ */
+ public abstract DoubleBuffer asDoubleBuffer();
+
+ /**
+ * Returns a float buffer which is based on the remaining content of
+ * this byte buffer.
+ * <p>
+ * The new buffer's position is zero, its limit and capacity is
+ * the number of remaining bytes divided by two, and its mark is not set.
+ * The new buffer's readonly property and byte order are same as this
+ * buffer. The new buffer is direct, if this byte buffer is direct.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * either buffer's change of content will be visible to the other.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A float buffer which is based on the content of
+ * this byte buffer.
+ */
+ public abstract FloatBuffer asFloatBuffer();
+
+ /**
+ * Returns a int buffer which is based on the remaining content of
+ * this byte buffer.
+ * <p>
+ * The new buffer's position is zero, its limit and capacity is
+ * the number of remaining bytes divided by two, and its mark is not set.
+ * The new buffer's readonly property and byte order are same as this
+ * buffer. The new buffer is direct, if this byte buffer is direct.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * either buffer's change of content will be visible to the other.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A int buffer which is based on the content of
+ * this byte buffer.
+ */
+ public abstract IntBuffer asIntBuffer();
+
+ /**
+ * Returns a long buffer which is based on the remaining content of
+ * this byte buffer.
+ * <p>
+ * The new buffer's position is zero, its limit and capacity is
+ * the number of remaining bytes divided by two, and its mark is not set.
+ * The new buffer's readonly property and byte order are same as this
+ * buffer. The new buffer is direct, if this byte buffer is direct.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * either buffer's change of content will be visible to the other.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A long buffer which is based on the content of
+ * this byte buffer.
+ */
+ public abstract LongBuffer asLongBuffer();
+
+ /**
+ * Returns a readonly buffer that shares content with this buffer.
+ * <p>
+ * The returned buffer is guaranteed to be a new instance, even this
+ * buffer is readonly itself. The new buffer's position, limit, capacity
+ * and mark are the same as this buffer.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * this buffer's change of content will be visible to the new buffer.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A readonly version of this buffer.
+ */
+ public abstract ByteBuffer asReadOnlyBuffer();
+
+ /**
+ * Returns a short buffer which is based on the remaining content of
+ * this byte buffer.
+ * <p>
+ * The new buffer's position is zero, its limit and capacity is
+ * the number of remaining bytes divided by two, and its mark is not set.
+ * The new buffer's readonly property and byte order are same as this
+ * buffer. The new buffer is direct, if this byte buffer is direct.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * either buffer's change of content will be visible to the other.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A short buffer which is based on the content of
+ * this byte buffer.
+ */
+ public abstract ShortBuffer asShortBuffer();
+
+ /**
+ * Compacts this byte buffer.
+ * <p>
+ * The remaining <code>byte</code>s will be moved to the head of the
+ * buffer, staring from position zero. Then the position is set to
+ * <code>remaining()</code>; the limit is set to capacity; the mark is
+ * cleared.
+ * </p>
+ *
+ * @return This buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer compact();
+
+ /**
+ * Compare the remaining <code>byte</code>s of this buffer to another
+ * byte buffer's remaining <code>byte</code>s.
+ *
+ * @param otherBuffer
+ * Another byte buffer
+ * @return a negative value if this is less than <code>other</code>; 0 if
+ * this equals to <code>other</code>; a positive value if this is
+ * greater than <code>other</code>
+ * @exception ClassCastException
+ * If <code>other</code> is not a byte buffer
+ */
+ public int compareTo(ByteBuffer otherBuffer) {
+ int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
+ : otherBuffer.remaining();
+ int thisPos = position;
+ int otherPos = otherBuffer.position;
+ byte thisByte, otherByte;
+ while (compareRemaining > 0) {
+ thisByte = get(thisPos);
+ otherByte = otherBuffer.get(otherPos);
+ if (thisByte != otherByte) {
+ return thisByte < otherByte ? -1 : 1;
+ }
+ thisPos++;
+ otherPos++;
+ compareRemaining--;
+ }
+ return remaining() - otherBuffer.remaining();
+ }
+
+ /**
+ * Returns a duplicated buffer that shares content with this buffer.
+ * <p>
+ * The duplicated buffer's position, limit, capacity and mark are the
+ * same as this buffer. The duplicated buffer's readonly property and
+ * byte order are same as this buffer too.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * either buffer's change of content will be visible to the other.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A duplicated buffer that shares content with this buffer.
+ */
+ public abstract ByteBuffer duplicate();
+
+ /**
+ * Tests whether this byte buffer equals to another object.
+ * <p>
+ * If <code>other</code> is not a byte buffer, then false is returned.</p>
+ * <p>
+ * Two byte buffers are equals if, and only if, their remaining
+ * <code>byte</code>s are exactly the same. Position, limit, capacity and
+ * mark are not considered.</p>
+ *
+ * @param other the object to compare against
+ * @return Whether this byte buffer equals to another object.
+ */
+ public boolean equals(Object other) {
+ if (!(other instanceof ByteBuffer)) {
+ return false;
+ }
+ ByteBuffer otherBuffer = (ByteBuffer) other;
+
+ if (remaining() != otherBuffer.remaining()) {
+ return false;
+ }
+
+ int myPosition = position;
+ int otherPosition = otherBuffer.position;
+ boolean equalSoFar = true;
+ while (equalSoFar && (myPosition < limit)) {
+ equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++);
+ }
+
+ return equalSoFar;
+ }
+
+ /**
+ * Returns the byte at the current position and increase the position by 1.
+ *
+ * @return The byte at the current position.
+ * @exception BufferUnderflowException
+ * If the position is equal or greater than limit
+ */
+ public abstract byte get();
+
+ /**
+ * Reads <code>byte</code>s from the current position into the specified
+ * byte array and increase the position by the number of <code>byte</code>s
+ * read.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>get(dest, 0, dest.length)</code>.
+ * </p>
+ *
+ * @param dest
+ * The destination byte array
+ * @return This buffer
+ * @exception BufferUnderflowException
+ * if <code>dest.length</code> is greater than
+ * <code>remaining()</code>
+ */
+ public ByteBuffer get(byte[] dest) {
+ return get(dest, 0, dest.length);
+ }
+
+ /**
+ * Reads <code>byte</code>s from the current position into the specified
+ * byte array, starting from the specified offset, and increase the position
+ * by the number of <code>byte</code>s read.
+ *
+ * @param dest
+ * The target byte array
+ * @param off
+ * The offset of the byte array, must be no less than zero and no
+ * greater than <code>dest.length</code>
+ * @param len
+ * The number of <code>byte</code>s to read, must be no less
+ * than zero and no greater than <code>dest.length - off</code>
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception BufferUnderflowException
+ * If <code>len</code> is greater than
+ * <code>remaining()</code>
+ */
+ public ByteBuffer get(byte[] dest, int off, int len) {
+ int length = dest.length;
+ if ((off < 0 ) || (len < 0) || ((long)off + (long)len > length)) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ dest[i] = get();
+ }
+ return this;
+ }
+
+ /**
+ * Returns a byte at the specified index, and the position is not changed.
+ *
+ * @param index The index, must be no less than zero and less than limit
+ * @return A byte at the specified index.
+ * @exception IndexOutOfBoundsException If index is invalid
+ */
+ public abstract byte get(int index);
+
+ /**
+ * Returns the char at the current position and increase the position by 2.
+ * <p>
+ * The 2 bytes start from the current position are composed into a char
+ * according to current byte order and returned. The position increases by
+ * 2.
+ * </p>
+ *
+ * @return The char at the current position.
+ * @exception BufferUnderflowException
+ * If the position is greater than <code>limit - 2</code>
+ */
+ public abstract char getChar();
+
+ /**
+ * Returns the char at the specified index.
+ * <p>
+ * The 2 bytes start from the specified index are composed into a char
+ * according to current byte order and returned. The position is not
+ * changed.
+ * </p>
+ *
+ * @param index
+ * The index, must be no less than zero and equal or less than
+ * <code>limit - 2</code>
+ * @return The char at the specified index.
+ * @exception IndexOutOfBoundsException
+ * If <code>index</code> is invalid
+ */
+ public abstract char getChar(int index);
+
+ /**
+ * Returns the double at the current position and increase the position by
+ * 8.
+ * <p>
+ * The 8 bytes start from the current position are composed into a double
+ * according to current byte order and returned. The position increases by
+ * 8.
+ * </p>
+ *
+ * @return The double at the current position.
+ * @exception BufferUnderflowException
+ * If the position is greater than <code>limit - 8</code>
+ */
+ public abstract double getDouble();
+
+ /**
+ * Returns the double at the specified index.
+ * <p>
+ * The 8 bytes start from the specified index are composed into a double
+ * according to current byte order and returned. The position is not
+ * changed.
+ * </p>
+ *
+ * @param index
+ * The index, must be no less than zero and equal or less than
+ * <code>limit - 8</code>
+ * @return The double at the specified index.
+ * @exception IndexOutOfBoundsException
+ * If <code>index</code> is invalid
+ */
+ public abstract double getDouble(int index);
+
+ /**
+ * Returns the float at the current position and increase the position by 4.
+ * <p>
+ * The 4 bytes start from the current position are composed into a float
+ * according to current byte order and returned. The position increases by
+ * 4.
+ * </p>
+ *
+ * @return The float at the current position.
+ * @exception BufferUnderflowException
+ * If the position is greater than <code>limit - 4</code>
+ */
+ public abstract float getFloat();
+
+ /**
+ * Returns the float at the specified index.
+ * <p>
+ * The 4 bytes start from the specified index are composed into a float
+ * according to current byte order and returned. The position is not
+ * changed.
+ * </p>
+ *
+ * @param index
+ * The index, must be no less than zero and equal or less than
+ * <code>limit - 4</code>
+ * @return The float at the specified index.
+ * @exception IndexOutOfBoundsException
+ * If <code>index</code> is invalid
+ */
+ public abstract float getFloat(int index);
+
+ /**
+ * Returns the int at the current position and increase the position by 4.
+ * <p>
+ * The 4 bytes start from the current position are composed into a int
+ * according to current byte order and returned.
+ * The position increases by 4.</p>
+ *
+ * @return The int at the current position.
+ * @exception BufferUnderflowException If the position is greater than <code>limit - 4</code>
+ */
+ public abstract int getInt();
+
+ /**
+ * Returns the int at the specified index.
+ * <p>
+ * The 4 bytes start from the specified index are composed into a int
+ * according to current byte order and returned. The position is not
+ * changed.
+ * </p>
+ *
+ * @param index
+ * The index, must be no less than zero and equal or less than
+ * <code>limit - 4</code>
+ * @return The int at the specified index.
+ * @exception IndexOutOfBoundsException
+ * If <code>index</code> is invalid
+ */
+ public abstract int getInt(int index);
+
+ /**
+ * Returns the long at the current position and increase the position by 8.
+ * <p>
+ * The 8 bytes start from the current position are composed into a long
+ * according to current byte order and returned. The position increases by
+ * 8.
+ * </p>
+ *
+ * @return The long at the current position.
+ * @exception BufferUnderflowException
+ * If the position is greater than <code>limit - 8</code>
+ */
+ public abstract long getLong();
+
+ /**
+ * Returns the long at the specified index.
+ * <p>
+ * The 8 bytes start from the specified index are composed into a long
+ * according to current byte order and returned. The position is not
+ * changed.
+ * </p>
+ *
+ * @param index
+ * The index, must be no less than zero and equal or less than
+ * <code>limit - 8</code>
+ * @return The long at the specified index.
+ * @exception IndexOutOfBoundsException
+ * If <code>index</code> is invalid
+ */
+ public abstract long getLong(int index);
+
+ /**
+ * Returns the short at the current position and increase the position by 2.
+ * <p>
+ * The 2 bytes start from the current position are composed into a short
+ * according to current byte order and returned.
+ * The position increases by 2.</p>
+ *
+ * @return The short at the current position.
+ * @exception BufferUnderflowException If the position is greater than <code>limit - 2</code>
+ */
+ public abstract short getShort();
+
+ /**
+ * Returns the short at the specified index.
+ * <p>
+ * The 2 bytes start from the specified index are composed into a short
+ * according to current byte order and returned. The position is not
+ * changed.
+ * </p>
+ *
+ * @param index
+ * The index, must be no less than zero and equal or less than
+ * <code>limit - 2</code>
+ * @return The short at the specified index.
+ * @exception IndexOutOfBoundsException
+ * If <code>index</code> is invalid
+ */
+ public abstract short getShort(int index);
+
+ /**
+ * Returns whether this buffer is based on a byte array and is read/write.
+ * <p>
+ * If this buffer is readonly, then false is returned.</p>
+ *
+ * @return Whether this buffer is based on a byte array and is read/write.
+ */
+ public final boolean hasArray() {
+ return protectedHasArray();
+ }
+
+ /**
+ * Hash code is calculated from the remaining <code>byte</code>s.
+ * <p>
+ * Position, limit, capacity and mark don't affect the hash code.</p>
+ *
+ * @return The hash code calculated from the remaining <code>byte</code>s.
+ */
+ public int hashCode() {
+ int myPosition = position;
+ int hash = 0;
+ while (myPosition < limit) {
+ hash = hash + get(myPosition++);
+ }
+ return hash;
+ }
+
+ /**
+ * Returns true if this buffer is direct.
+ * <p>
+ * A byte buffer is direct, if it is based on a byte buffer and the byte
+ * buffer is direct.
+ * </p>
+ *
+ * @return True if this buffer is direct.
+ */
+ public abstract boolean isDirect();
+
+ /**
+ * Returns the byte order used by this buffer when converting
+ * <code>byte</code>s from/to other primitive types.
+ * <p>
+ * The default byte order of byte buffer is always BIG_ENDIAN.</p>
+ *
+ * @return The byte order used by this buffer when converting
+ * <code>byte</code>s from/to other primitive types.
+ */
+ public final ByteOrder order() {
+ return order == Endianness.BIG_ENDIAN ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN;
+ }
+
+ /**
+ * Sets the byte order of this buffer.
+ *
+ * @param byteOrder
+ * The byte order to set. If <code>null</code> then the order
+ * will be {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}.
+ * @return This buffer
+ * @see ByteOrder
+ */
+ public final ByteBuffer order(ByteOrder byteOrder) {
+ return orderImpl(byteOrder);
+ }
+
+ ByteBuffer orderImpl(ByteOrder byteOrder) {
+ order = byteOrder == ByteOrder.BIG_ENDIAN ? Endianness.BIG_ENDIAN
+ : Endianness.LITTLE_ENDIAN;
+ return this;
+ }
+
+ /**
+ * Child class implements this method to realize <code>array()</code>.
+ *
+ * @return see <code>array()</code>
+ */
+ abstract byte[] protectedArray();
+
+ /**
+ * Child class implements this method to realize <code>arrayOffset()</code>.
+ *
+ * @return see <code>arrayOffset()</code>
+ */
+ abstract int protectedArrayOffset();
+
+ /**
+ * Child class implements this method to realize <code>hasArray()</code>.
+ *
+ * @return see <code>hasArray()</code>
+ */
+ abstract boolean protectedHasArray();
+
+ /**
+ * Writes the given byte to the current position and increase the position
+ * by 1.
+ *
+ * @param b
+ * The byte to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If position is equal or greater than limit
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer put(byte b);
+
+ /**
+ * Writes <code>byte</code>s in the given byte array to the current
+ * position and increase the position by the number of <code>byte</code>s
+ * written.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>put(src, 0, src.length)</code>.
+ * </p>
+ *
+ * @param src
+ * The source byte array
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>src.length</code>
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public final ByteBuffer put(byte[] src) {
+ return put(src, 0, src.length);
+ }
+
+ /**
+ * Writes <code>byte</code>s in the given byte array, starting from the
+ * specified offset, to the current position and increase the position by
+ * the number of <code>byte</code>s written.
+ *
+ * @param src
+ * The source byte array
+ * @param off
+ * The offset of byte array, must be no less than zero and no
+ * greater than <code>src.length</code>
+ * @param len
+ * The number of <code>byte</code>s to write, must be no less
+ * than zero and no greater than <code>src.length - off</code>
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>len</code>
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public ByteBuffer put(byte[] src, int off, int len) {
+ int length = src.length;
+ if ((off < 0 ) || (len < 0) || ((long)off + (long)len > length)) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ put(src[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Writes all the remaining <code>byte</code>s of the <code>src</code>
+ * byte buffer to this buffer's current position, and increase both buffers'
+ * position by the number of <code>byte</code>s copied.
+ *
+ * @param src
+ * The source byte buffer
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>src.remaining()</code> is greater than this
+ * buffer's <code>remaining()</code>
+ * @exception IllegalArgumentException
+ * If <code>src</code> is this buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public ByteBuffer put(ByteBuffer src) {
+ if (src == this) {
+ throw new IllegalArgumentException();
+ }
+ if (src.remaining() > remaining()) {
+ throw new BufferOverflowException();
+ }
+ byte[] contents = new byte[src.remaining()];
+ src.get(contents);
+ put(contents);
+ return this;
+ }
+
+ /**
+ * Write a byte to the specified index of this buffer and the position is
+ * not changed.
+ *
+ * @param index
+ * The index, must be no less than zero and less than the limit
+ * @param b
+ * The byte to write
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If <code>index</code> is invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer put(int index, byte b);
+
+ /**
+ * Writes the given char to the current position and increase the position
+ * by 2.
+ * <p>
+ * The char is converted to bytes using the current byte order.
+ * </p>
+ *
+ * @param value
+ * The char to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If position is greater than <code>limit - 2</code>
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer putChar(char value);
+
+ /**
+ * Write a char to the specified index of this buffer.
+ * <p>
+ * The char is converted to bytes using the current byte order. The position
+ * is not changed.
+ * </p>
+ *
+ * @param index
+ * The index, must be no less than zero and equal or less than
+ * <code>limit - 2</code>
+ * @param value
+ * The char to write
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If <code>index</code> is invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer putChar(int index, char value);
+
+ /**
+ * Writes the given double to the current position and increase the position
+ * by 8.
+ * <p>
+ * The double is converted to bytes using the current byte order.
+ * </p>
+ *
+ * @param value
+ * The double to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If position is greater than <code>limit - 8</code>
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer putDouble(double value);
+
+ /**
+ * Write a double to the specified index of this buffer.
+ * <p>
+ * The double is converted to bytes using the current byte order. The
+ * position is not changed.
+ * </p>
+ *
+ * @param index
+ * The index, must be no less than zero and equal or less than
+ * <code>limit - 8</code>
+ * @param value
+ * The double to write
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If <code>index</code> is invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer putDouble(int index, double value);
+
+ /**
+ * Writes the given float to the current position and increase the position
+ * by 4.
+ * <p>
+ * The float is converted to bytes using the current byte order.
+ * </p>
+ *
+ * @param value
+ * The float to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If position is greater than <code>limit - 4</code>
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer putFloat(float value);
+
+ /**
+ * Write a float to the specified index of this buffer.
+ * <p>
+ * The float is converted to bytes using the current byte order. The
+ * position is not changed.
+ * </p>
+ *
+ * @param index
+ * The index, must be no less than zero and equal or less than
+ * <code>limit - 4</code>
+ * @param value
+ * The float to write
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If <code>index</code> is invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer putFloat(int index, float value);
+
+ /**
+ * Writes the given int to the current position and increase the position by
+ * 4.
+ * <p>
+ * The int is converted to bytes using the current byte order.
+ * </p>
+ *
+ * @param value
+ * The int to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If position is greater than <code>limit - 4</code>
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer putInt(int value);
+
+ /**
+ * Write a int to the specified index of this buffer.
+ * <p>
+ * The int is converted to bytes using the current byte order. The position
+ * is not changed.
+ * </p>
+ *
+ * @param index
+ * The index, must be no less than zero and equal or less than
+ * <code>limit - 4</code>
+ * @param value
+ * The int to write
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If <code>index</code> is invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer putInt(int index, int value);
+
+ /**
+ * Writes the given long to the current position and increase the position
+ * by 8.
+ * <p>
+ * The long is converted to bytes using the current byte order.
+ * </p>
+ *
+ * @param value
+ * The long to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If position is greater than <code>limit - 8</code>
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer putLong(long value);
+
+ /**
+ * Write a long to the specified index of this buffer.
+ * <p>
+ * The long is converted to bytes using the current byte order. The position
+ * is not changed.
+ * </p>
+ *
+ * @param index
+ * The index, must be no less than zero and equal or less than
+ * <code>limit - 8</code>
+ * @param value
+ * The long to write
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If <code>index</code> is invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer putLong(int index, long value);
+
+ /**
+ * Writes the given short to the current position and increase the position
+ * by 2.
+ * <p>
+ * The short is converted to bytes using the current byte order.
+ * </p>
+ *
+ * @param value
+ * The short to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If position is greater than <code>limit - 2</code>
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer putShort(short value);
+
+ /**
+ * Write a short to the specified index of this buffer.
+ * <p>
+ * The short is converted to bytes using the current byte order. The
+ * position is not changed.
+ * </p>
+ *
+ * @param index
+ * The index, must be no less than zero and equal or less than
+ * <code>limit - 2</code>
+ * @param value
+ * The short to write
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If <code>index</code> is invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ByteBuffer putShort(int index, short value);
+
+ /**
+ * Returns a sliced buffer that shares content with this buffer.
+ * <p>
+ * The sliced buffer's capacity will be this buffer's
+ * <code>remaining()</code>, and its zero position will correspond to
+ * this buffer's current position. The new buffer's position will be
+ * 0, limit will be its capacity, and its mark is unset. The new buffer's
+ * readonly property and byte order are same as this buffer.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * either buffer's change of content will be visible to the other.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A sliced buffer that shares content with this buffer.
+ */
+ public abstract ByteBuffer slice();
+
+ /**
+ * Returns a string represents the state of this byte buffer.
+ *
+ * @return A string represents the state of this byte buffer.
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append(getClass().getName());
+ buf.append(", status: capacity="); //$NON-NLS-1$
+ buf.append(capacity());
+ buf.append(" position="); //$NON-NLS-1$
+ buf.append(position());
+ buf.append(" limit="); //$NON-NLS-1$
+ buf.append(limit());
+ return buf.toString();
+ }
+}
diff --git a/nio/src/main/java/java/nio/ByteOrder.java b/nio/src/main/java/java/nio/ByteOrder.java
new file mode 100644
index 0000000..4ae6a96
--- /dev/null
+++ b/nio/src/main/java/java/nio/ByteOrder.java
@@ -0,0 +1,73 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+
+import org.apache.harmony.luni.platform.Platform;
+
+/**
+ * Holds byte order constants.
+ *
+ */
+public final class ByteOrder {
+
+ /**
+ * This constant represents big endian.
+ */
+ public static final ByteOrder BIG_ENDIAN = new ByteOrder("BIG_ENDIAN"); //$NON-NLS-1$
+
+ /**
+ * This constant represents little endian.
+ */
+ public static final ByteOrder LITTLE_ENDIAN = new ByteOrder("LITTLE_ENDIAN"); //$NON-NLS-1$
+
+ private static final ByteOrder NATIVE_ORDER;
+
+ static {
+ if (Platform.getMemorySystem().isLittleEndian()) {
+ NATIVE_ORDER = LITTLE_ENDIAN;
+ } else {
+ NATIVE_ORDER = BIG_ENDIAN;
+ }
+ }
+
+ /**
+ * Returns the current platform byte order.
+ *
+ * @return the byte order object, which is either identical to LITTLE_ENDIAN
+ * or BIG_ENDIAN.
+ */
+ public static ByteOrder nativeOrder() {
+ return NATIVE_ORDER;
+ }
+
+ private final String name;
+
+ private ByteOrder(String name) {
+ super();
+ this.name = name;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ return name;
+ }
+}
diff --git a/nio/src/main/java/java/nio/CharArrayBuffer.java b/nio/src/main/java/java/nio/CharArrayBuffer.java
new file mode 100644
index 0000000..516aada
--- /dev/null
+++ b/nio/src/main/java/java/nio/CharArrayBuffer.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * CharArrayBuffer, ReadWriteCharArrayBuffer and ReadOnlyCharArrayBuffer compose
+ * the implementation of array based char buffers.
+ * <p>
+ * CharArrayBuffer implements all the shared readonly methods and is extended by
+ * the other two classes.
+ * </p>
+ * <p>
+ * All methods are marked final for runtime performance.
+ * </p>
+ *
+ */
+abstract class CharArrayBuffer extends CharBuffer {
+
+ protected final char[] backingArray;
+
+ protected final int offset;
+
+ CharArrayBuffer(char[] array) {
+ this(array.length, array, 0);
+ }
+
+ CharArrayBuffer(int capacity) {
+ this(capacity, new char[capacity], 0);
+ }
+
+ CharArrayBuffer(int capacity, char[] backingArray, int offset) {
+ super(capacity);
+ this.backingArray = backingArray;
+ this.offset = offset;
+ }
+
+ public final char get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return backingArray[offset + position++];
+ }
+
+ public final char get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return backingArray[offset + index];
+ }
+
+ public final CharBuffer get(char[] dest, int off, int len) {
+ int length = dest.length;
+ if ((off < 0 ) || (len < 0) || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ System.arraycopy(backingArray, offset+position, dest, off, len);
+ position += len;
+ return this;
+ }
+
+ public final boolean isDirect() {
+ return false;
+ }
+
+ public final ByteOrder order() {
+ return ByteOrder.nativeOrder();
+ }
+
+ public final CharSequence subSequence(int start, int end) {
+ if (start < 0 || end < start || end > remaining()) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ CharBuffer result = duplicate();
+ result.limit(position + end);
+ result.position(position + start);
+ return result;
+ }
+
+ public final String toString() {
+ return String.copyValueOf(backingArray, offset + position, remaining());
+ }
+}
diff --git a/nio/src/main/java/java/nio/CharBuffer.java b/nio/src/main/java/java/nio/CharBuffer.java
new file mode 100644
index 0000000..2c12e8e
--- /dev/null
+++ b/nio/src/main/java/java/nio/CharBuffer.java
@@ -0,0 +1,810 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+import java.io.IOException;
+
+/**
+ * A buffer of <code>char</code>s.
+ * <p>
+ * A char buffer can be created in either of the following ways:
+ * <ul>
+ * <li>{@link #allocate(int) Allocate} a new char array and create a buffer
+ * based on it;</li>
+ * <li>{@link #wrap(char[]) Wrap} an existing char array to create a new
+ * buffer;</li>
+ * <li>{@link #wrap(CharSequence) Wrap} an existing char sequence to create a
+ * new buffer;</li>
+ * <li>Use {@link java.nio.ByteBuffer#asCharBuffer() ByteBuffer.asCharBuffer}
+ * to create a char buffer based on a byte buffer.</li>
+ * </ul>
+ * </p>
+ *
+ */
+public abstract class CharBuffer extends Buffer implements Comparable<CharBuffer>,
+ CharSequence, Appendable, Readable {
+
+ /**
+ * Creates a char buffer based on a new allocated char array.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return The created char buffer
+ * @throws IllegalArgumentException
+ * If <code>capacity</code> is less than zero
+ */
+ public static CharBuffer allocate(int capacity) {
+ if (capacity < 0) {
+ throw new IllegalArgumentException();
+ }
+ return BufferFactory.newCharBuffer(capacity);
+ }
+
+ /**
+ * Creates a new char buffer by wrapping the given char array.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>wrap(array, 0, array.length)</code>.
+ * </p>
+ *
+ * @param array
+ * The char array which the new buffer will be based on
+ * @return The created char buffer
+ */
+ public static CharBuffer wrap(char[] array) {
+ return wrap(array, 0, array.length);
+ }
+
+ /**
+ * Creates new a char buffer by wrapping the given char array.
+ * <p>
+ * The new buffer's position will be <code>start</code>, limit will be
+ * <code>start + len</code>, capacity will be the length of the array.
+ * </p>
+ *
+ * @param array
+ * The char array which the new buffer will be based on
+ * @param start
+ * The start index, must be no less than zero and no greater than
+ * <code>array.length</code>
+ * @param len
+ * The length, must be no less than zero and no greater than
+ * <code>array.length - start</code>
+ * @return The created char buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>start</code> or <code>len</code> is
+ * invalid
+ */
+ public static CharBuffer wrap(char[] array, int start, int len) {
+ int length = array.length;
+ if ((start < 0) || (len < 0)
+ || (long) start + (long) len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ CharBuffer buf = BufferFactory.newCharBuffer(array);
+ buf.position = start;
+ buf.limit = start + len;
+
+ return buf;
+ }
+
+ /**
+ * Creates a new char buffer by wrapping the given char sequence.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>wrap(chseq, 0, chseq.length())</code>.
+ * </p>
+ *
+ * @param chseq
+ * The char sequence which the new buffer will be based on
+ * @return The created char buffer
+ */
+ public static CharBuffer wrap(CharSequence chseq) {
+ return BufferFactory.newCharBuffer(chseq);
+ }
+
+ /**
+ * Creates a new char buffer by wrapping the given char sequence.
+ * <p>
+ * The new buffer's position will be <code>start</code>, limit will be
+ * <code>end</code>, capacity will be the length of the char sequence.
+ * The new buffer is readonly.
+ * </p>
+ *
+ * @param chseq
+ * The char sequence which the new buffer will be based on
+ * @param start
+ * The start index, must be no less than zero and no greater than
+ * <code>chseq.length()</code>
+ * @param end
+ * The end index, must be no less than <code>start</code> and
+ * no greater than <code>chseq.length()</code>
+ * @return The created char buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>start</code> or <code>end</code> is
+ * invalid
+ */
+ public static CharBuffer wrap(CharSequence chseq, int start, int end) {
+ if (chseq == null) {
+ throw new NullPointerException();
+ }
+ if (start < 0 || end < start || end > chseq.length()) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ CharBuffer result = BufferFactory.newCharBuffer(chseq);
+ result.position = start;
+ result.limit = end;
+ return result;
+ }
+
+ /**
+ * Constructs a <code>CharBuffer</code> with given capacity.
+ *
+ * @param capacity
+ * The capacity of the buffer
+ */
+ CharBuffer(int capacity) {
+ super(capacity);
+ // BEGIN android-added
+ _elementSizeShift = 1;
+ // END android-added
+ }
+
+ /**
+ * Returns the char array which this buffer is based on, if there's one.
+ *
+ * @return The char array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on an array, but it is readonly
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final char[] array() {
+ return protectedArray();
+ }
+
+ /**
+ * Returns the offset of the char array which this buffer is based on, if
+ * there's one.
+ * <p>
+ * The offset is the index of the array corresponds to the zero position of
+ * the buffer.
+ * </p>
+ *
+ * @return The offset of the char array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on an array, but it is readonly
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final int arrayOffset() {
+ return protectedArrayOffset();
+ }
+
+ // BEGIN android-added
+ @Override Object _array() {
+ if (hasArray()) {
+ return array();
+ }
+ return null;
+ }
+
+ @Override int _arrayOffset() {
+ if (hasArray()) {
+ return arrayOffset();
+ }
+ return 0;
+ }
+ // END android-added
+
+ /**
+ * Returns a readonly buffer that shares content with this buffer.
+ * <p>
+ * The returned buffer is guaranteed to be a new instance, even this buffer
+ * is readonly itself. The new buffer's position, limit, capacity and mark
+ * are the same as this buffer.
+ * </p>
+ * <p>
+ * The new buffer shares content with this buffer, which means this buffer's
+ * change of content will be visible to the new buffer. The two buffer's
+ * position, limit and mark are independent.
+ * </p>
+ *
+ * @return A readonly version of this buffer.
+ */
+ public abstract CharBuffer asReadOnlyBuffer();
+
+ /**
+ * Returns the character located at the specified index in the buffer. The
+ * index value is referenced from the current buffer position.
+ *
+ * @param index
+ * The index referenced from the current buffer position. It must
+ * not be less than zero but less than the value obtained from a
+ * call to <code>remaining()</code>
+ * @return the character located at the specified index (referenced from the
+ * current position) in the buffer.
+ * @exception IndexOutOfBoundsException
+ * If the index is invalid
+ */
+ public final char charAt(int index) {
+ if (index < 0 || index >= remaining()) {
+ throw new IndexOutOfBoundsException();
+ }
+ return get(position + index);
+ }
+
+ /**
+ * Compacts this char buffer.
+ * <p>
+ * The remaining <code>char</code>s will be moved to the head of the
+ * buffer, staring from position zero. Then the position is set to
+ * <code>remaining()</code>; the limit is set to capacity; the mark is
+ * cleared.
+ * </p>
+ *
+ * @return This buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract CharBuffer compact();
+
+ /**
+ * Compare the remaining <code>char</code>s of this buffer to another
+ * char buffer's remaining <code>char</code>s.
+ *
+ * @param otherBuffer
+ * Another char buffer
+ * @return a negative value if this is less than <code>other</code>; 0 if
+ * this equals to <code>other</code>; a positive value if this is
+ * greater than <code>other</code>
+ * @exception ClassCastException
+ * If <code>other</code> is not a char buffer
+ */
+ public int compareTo(CharBuffer otherBuffer) {
+ int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
+ : otherBuffer.remaining();
+ int thisPos = position;
+ int otherPos = otherBuffer.position;
+ char thisByte, otherByte;
+ while (compareRemaining > 0) {
+ thisByte = get(thisPos);
+ otherByte = otherBuffer.get(otherPos);
+ if (thisByte != otherByte) {
+ return thisByte < otherByte ? -1 : 1;
+ }
+ thisPos++;
+ otherPos++;
+ compareRemaining--;
+ }
+ return remaining() - otherBuffer.remaining();
+ }
+
+ /**
+ * Returns a duplicated buffer that shares content with this buffer.
+ * <p>
+ * The duplicated buffer's position, limit, capacity and mark are the same
+ * as this buffer. The duplicated buffer's readonly property and byte order
+ * are same as this buffer too.
+ * </p>
+ * <p>
+ * The new buffer shares content with this buffer, which means either
+ * buffer's change of content will be visible to the other. The two buffer's
+ * position, limit and mark are independent.
+ * </p>
+ *
+ * @return A duplicated buffer that shares content with this buffer.
+ */
+ public abstract CharBuffer duplicate();
+
+ /**
+ * Tests whether this char buffer equals to another object.
+ * <p>
+ * If <code>other</code> is not a char buffer, then false is returned.
+ * </p>
+ * <p>
+ * Two char buffers are equals if, and only if, their remaining
+ * <code>char</code>s are exactly the same. Position, limit, capacity and
+ * mark are not considered.
+ * </p>
+ *
+ * @param other
+ * the object to be compared against
+ * @return Whether this char buffer equals to another object.
+ */
+ public boolean equals(Object other) {
+ if (!(other instanceof CharBuffer)) {
+ return false;
+ }
+ CharBuffer otherBuffer = (CharBuffer) other;
+
+ if (remaining() != otherBuffer.remaining()) {
+ return false;
+ }
+
+ int myPosition = position;
+ int otherPosition = otherBuffer.position;
+ boolean equalSoFar = true;
+ while (equalSoFar && (myPosition < limit)) {
+ equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++);
+ }
+
+ return equalSoFar;
+ }
+
+ /**
+ * Returns the char at the current position and increase the position by 1.
+ *
+ * @return The char at the current position.
+ * @exception BufferUnderflowException
+ * If the position is equal or greater than limit
+ */
+ public abstract char get();
+
+ /**
+ * Reads <code>char</code>s from the current position into the specified
+ * char array and increase the position by the number of <code>char</code>s
+ * read.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>get(dest, 0, dest.length)</code>.
+ * </p>
+ *
+ * @param dest
+ * The destination char array
+ * @return This buffer
+ * @exception BufferUnderflowException
+ * if <code>dest.length</code> is greater than
+ * <code>remaining()</code>
+ */
+ public CharBuffer get(char[] dest) {
+ return get(dest, 0, dest.length);
+ }
+
+ /**
+ * Reads <code>char</code>s from the current position into the specified
+ * char array, starting from the specified offset, and increase the position
+ * by the number of <code>char</code>s read.
+ *
+ * @param dest
+ * The target char array
+ * @param off
+ * The offset of the char array, must be no less than zero and no
+ * greater than <code>dest.length</code>
+ * @param len
+ * The number of <code>char</code>s to read, must be no less
+ * than zero and no greater than <code>dest.length - off</code>
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception BufferUnderflowException
+ * If <code>len</code> is greater than
+ * <code>remaining()</code>
+ */
+ public CharBuffer get(char[] dest, int off, int len) {
+ int length = dest.length;
+ if ((off < 0 ) || (len < 0) || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ dest[i] = get();
+ }
+ return this;
+ }
+
+ /**
+ * Returns a char at the specified index, and the position is not changed.
+ *
+ * @param index
+ * The index, must be no less than zero and less than limit
+ * @return A char at the specified index.
+ * @exception IndexOutOfBoundsException
+ * If index is invalid
+ */
+ public abstract char get(int index);
+
+ /**
+ * Returns whether this buffer is based on a char array and is read/write.
+ * <p>
+ * If this buffer is readonly, then false is returned.
+ * </p>
+ *
+ * @return Whether this buffer is based on a char array and is read/write.
+ */
+ public final boolean hasArray() {
+ return protectedHasArray();
+ }
+
+ /**
+ * Hash code is calculated from the remaining <code>char</code>s.
+ * <p>
+ * Position, limit, capacity and mark don't affect the hash code.
+ * </p>
+ *
+ * @return The hash code calculated from the remaining <code>char</code>s.
+ */
+ public int hashCode() {
+ int myPosition = position;
+ int hash = 0;
+ while (myPosition < limit) {
+ hash = hash + get(myPosition++);
+ }
+ return hash;
+ }
+
+ /**
+ * Returns true if this buffer is direct.
+ * <p>
+ * A direct buffer will try its best to take advantage of native memory APIs
+ * and it may not stay in java heap, thus not affected by GC.
+ * </p>
+ * <p>
+ * A char buffer is direct, if it is based on a byte buffer and the byte
+ * buffer is direct.
+ * </p>
+ *
+ * @return True if this buffer is direct.
+ */
+ public abstract boolean isDirect();
+
+ /**
+ * Returns the number of remaining <code>char</code>s.
+ *
+ * @return The number of remaining <code>char</code>s.
+ */
+ public final int length() {
+ return remaining();
+ }
+
+ /**
+ * Returns the byte order used by this buffer when converting
+ * <code>char</code>s from/to <code>byte</code>s.
+ * <p>
+ * If this buffer is not based on a byte buffer, then always return the
+ * platform's native byte order.
+ * </p>
+ *
+ * @return The byte order used by this buffer when converting
+ * <code>char</code>s from/to <code>byte</code>s.
+ */
+ public abstract ByteOrder order();
+
+ /**
+ * Child class implements this method to realize <code>array()</code>.
+ *
+ * @return see <code>array()</code>
+ */
+ abstract char[] protectedArray();
+
+ /**
+ * Child class implements this method to realize <code>arrayOffset()</code>.
+ *
+ * @return see <code>arrayOffset()</code>
+ */
+ abstract int protectedArrayOffset();
+
+ /**
+ * Child class implements this method to realize <code>hasArray()</code>.
+ *
+ * @return see <code>hasArray()</code>
+ */
+ abstract boolean protectedHasArray();
+
+ /**
+ * Writes the given char to the current position and increase the position
+ * by 1.
+ *
+ * @param c
+ * The char to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If position is equal or greater than limit
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract CharBuffer put(char c);
+
+ /**
+ * Writes <code>char</code>s in the given char array to the current
+ * position and increase the position by the number of <code>char</code>s
+ * written.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>put(src, 0, src.length)</code>.
+ * </p>
+ *
+ * @param src
+ * The source char array
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>src.length</code>
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public final CharBuffer put(char[] src) {
+ return put(src, 0, src.length);
+ }
+
+ /**
+ * Writes <code>char</code>s in the given char array, starting from the
+ * specified offset, to the current position and increase the position by
+ * the number of <code>char</code>s written.
+ *
+ * @param src
+ * The source char array
+ * @param off
+ * The offset of char array, must be no less than zero and no
+ * greater than <code>src.length</code>
+ * @param len
+ * The number of <code>char</code>s to write, must be no less
+ * than zero and no greater than <code>src.length - off</code>
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>len</code>
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public CharBuffer put(char[] src, int off, int len) {
+ int length = src.length;
+ if ((off < 0 ) || (len < 0) || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ put(src[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Writes all the remaining <code>char</code>s of the <code>src</code>
+ * char buffer to this buffer's current position, and increase both buffers'
+ * position by the number of <code>char</code>s copied.
+ *
+ * @param src
+ * The source char buffer
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>src.remaining()</code> is greater than this
+ * buffer's <code>remaining()</code>
+ * @exception IllegalArgumentException
+ * If <code>src</code> is this buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public CharBuffer put(CharBuffer src) {
+ if (src == this) {
+ throw new IllegalArgumentException();
+ }
+ if (src.remaining() > remaining()) {
+ throw new BufferOverflowException();
+ }
+
+ char[] contents = new char[src.remaining()];
+ src.get(contents);
+ put(contents);
+ return this;
+ }
+
+ /**
+ * Write a char to the specified index of this buffer and the position is
+ * not changed.
+ *
+ * @param index
+ * The index, must be no less than zero and less than the limit
+ * @param c
+ * The char to write
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If index is invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract CharBuffer put(int index, char c);
+
+ /**
+ * Write all <code>char</code>s of the give string to the current
+ * position of this buffer, and increase the position by the length of
+ * string.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>put(str, 0, str.length())</code>.
+ * </p>
+ *
+ * @param str
+ * The string to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than the length of
+ * string
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public final CharBuffer put(String str) {
+ return put(str, 0, str.length());
+ }
+
+ /**
+ * Write <code>char</code>s of the given string to the current position
+ * of this buffer, and increase the position by the number of
+ * <code>char</code>s written.
+ *
+ * @param str
+ * The string to write
+ * @param start
+ * The first char to write, must be no less than zero and no
+ * greater than <code>str.length()</code>
+ * @param end
+ * The last char to write (excluding), must be less than
+ * <code>start</code> and no greater than
+ * <code>str.length()</code>
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining</code> is less than
+ * <code>end - start</code>
+ * @exception IndexOutOfBoundsException
+ * If either <code>start</code> or <code>end</code> is
+ * invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public CharBuffer put(String str, int start, int end) {
+ int length = str.length();
+ if (start < 0 || end < start || end > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (end - start > remaining()) {
+ throw new BufferOverflowException();
+ }
+ for (int i = start; i < end; i++) {
+ put(str.charAt(i));
+ }
+ return this;
+ }
+
+ /**
+ * Returns a sliced buffer that shares content with this buffer.
+ * <p>
+ * The sliced buffer's capacity will be this buffer's
+ * <code>remaining()</code>, and its zero position will correspond to
+ * this buffer's current position. The new buffer's position will be 0,
+ * limit will be its capacity, and its mark is unset. The new buffer's
+ * readonly property and byte order are same as this buffer.
+ * </p>
+ * <p>
+ * The new buffer shares content with this buffer, which means either
+ * buffer's change of content will be visible to the other. The two buffer's
+ * position, limit and mark are independent.
+ * </p>
+ *
+ * @return A sliced buffer that shares content with this buffer.
+ */
+ public abstract CharBuffer slice();
+
+ /**
+ * Returns a new char buffer represents a sub-sequence of this buffer's
+ * current remaining content.
+ * <p>
+ * The new buffer's position will be <code>position() + start</code>,
+ * limit will be <code>position() + end</code>, capacity will be same as
+ * this buffer. The new buffer's readonly property and byte order are same
+ * as this buffer.
+ * </p>
+ * <p>
+ * The new buffer shares content with this buffer, which means either
+ * buffer's change of content will be visible to the other. The two buffer's
+ * position, limit and mark are independent.
+ * </p>
+ *
+ * @param start
+ * The start index of the sub-sequence, referenced from the
+ * current buffer position. Must not be less than zero and not
+ * greater than the value obtained from a call to
+ * <code>remaining()</code>.
+ * @param end
+ * The end index of the sub-sequence, referenced from the current
+ * buffer position. Must not be less than <code>start</code>
+ * and not be greater than the value obtained from a call to
+ * <code>remaining()</code>
+ * @return A new char buffer represents a sub-sequence of this buffer's
+ * current remaining content.
+ * @exception IndexOutOfBoundsException
+ * If either <code>start</code> or <code>end</code> is
+ * invalid
+ */
+ public abstract CharSequence subSequence(int start, int end);
+
+ /**
+ * Returns a string represents the current remaining <code>char</code>s
+ * of this buffer.
+ *
+ * @return A string represents the current remaining <code>char</code>s
+ * of this buffer.
+ */
+ public String toString() {
+ StringBuffer strbuf = new StringBuffer();
+ for (int i = position; i < limit; i++) {
+ strbuf.append(get(i));
+ }
+ return strbuf.toString();
+ }
+
+ /**
+ * @see Appendable#append(char)
+ */
+ public CharBuffer append(char c){
+ return put(c);
+ }
+
+ /**
+ * @see Appendable#append(CharSequence)
+ */
+ public CharBuffer append(CharSequence csq){
+ if (csq != null) {
+ return put(csq.toString());
+ }
+ return put("null"); //$NON-NLS-1$
+ }
+
+ /**
+ * @see Appendable#append(CharSequence, int, int)
+ */
+ public CharBuffer append(CharSequence csq, int start, int end){
+ if (csq == null) {
+ csq = "null"; //$NON-NLS-1$
+ }
+ CharSequence cs = csq.subSequence(start, end);
+ if (cs.length() > 0) {
+ return put(cs.toString());
+ }
+ return this;
+ }
+
+ /**
+ * @see Readable#read(CharBuffer)
+ */
+ public int read(CharBuffer target) throws IOException {
+ if(target == this){
+ throw new IllegalArgumentException();
+ }
+ if (remaining() == 0) {
+ return target.remaining()==0?0:-1;
+ }
+ int result = Math.min(target.remaining(), remaining());
+ char[] chars = new char[result];
+ get(chars);
+ target.put(chars);
+ return result;
+ }
+}
diff --git a/nio/src/main/java/java/nio/CharSequenceAdapter.java b/nio/src/main/java/java/nio/CharSequenceAdapter.java
new file mode 100644
index 0000000..32edc18
--- /dev/null
+++ b/nio/src/main/java/java/nio/CharSequenceAdapter.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * This class wraps a char sequence to be a char buffer.
+ * <p>
+ * Implementation notice:
+ * <ul>
+ * <li>Char sequence based buffer is always readonly.</li>
+ * </ul>
+ * </p>
+ *
+ */
+final class CharSequenceAdapter extends CharBuffer {
+
+ static CharSequenceAdapter copy(CharSequenceAdapter other) {
+ CharSequenceAdapter buf = new CharSequenceAdapter(other.sequence);
+ buf.limit = other.limit;
+ buf.position = other.position;
+ buf.mark = other.mark;
+ return buf;
+ }
+
+ final CharSequence sequence;
+
+ CharSequenceAdapter(CharSequence chseq) {
+ super(chseq.length());
+ sequence = chseq;
+ }
+
+ public CharBuffer asReadOnlyBuffer() {
+ return duplicate();
+ }
+
+ public CharBuffer compact() {
+ throw new ReadOnlyBufferException();
+ }
+
+ public CharBuffer duplicate() {
+ return copy(this);
+ }
+
+ public char get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return sequence.charAt(position++);
+ }
+
+ public char get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return sequence.charAt(index);
+ }
+
+ public final CharBuffer get(char[] dest, int off, int len) {
+ int length = dest.length;
+ if ((off < 0 ) || (len < 0) || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ int newPosition = position + len;
+ sequence.toString().getChars(position, newPosition, dest, off);
+ position = newPosition;
+ return this;
+ }
+
+ public boolean isDirect() {
+ return false;
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ public ByteOrder order() {
+ return ByteOrder.nativeOrder();
+ }
+
+ protected char[] protectedArray() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public CharBuffer put(char c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public CharBuffer put(int index, char c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public final CharBuffer put(char[] src, int off, int len) {
+ if ((off < 0 ) || (len < 0) || (long)off + (long)len > src.length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+
+ throw new ReadOnlyBufferException();
+ }
+
+ public CharBuffer put(String src, int start, int end) {
+ if ((start < 0 ) || (end < 0) || (long)start + (long)end > src.length()) {
+ throw new IndexOutOfBoundsException();
+ }
+ throw new ReadOnlyBufferException();
+ }
+
+ public CharBuffer slice() {
+ return new CharSequenceAdapter(sequence.subSequence(position, limit));
+ }
+
+ public CharSequence subSequence(int start, int end) {
+ if (end < start || start < 0 || end > remaining()) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ CharSequenceAdapter result = copy(this);
+ result.position = position + start;
+ result.limit = position + end;
+ return result;
+ }
+}
diff --git a/nio/src/main/java/java/nio/CharToByteBufferAdapter.java b/nio/src/main/java/java/nio/CharToByteBufferAdapter.java
new file mode 100644
index 0000000..14a48ff
--- /dev/null
+++ b/nio/src/main/java/java/nio/CharToByteBufferAdapter.java
@@ -0,0 +1,214 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+// BEGIN android-added
+// Copied from newer version of harmony
+import org.apache.harmony.nio.internal.DirectBuffer;
+import org.apache.harmony.luni.platform.PlatformAddress;
+// END android-added
+
+/**
+ * This class wraps a byte buffer to be a char buffer.
+ * <p>
+ * Implementation notice:
+ * <ul>
+ * <li>After a byte buffer instance is wrapped, it becomes privately owned by
+ * the adapter. It must NOT be accessed outside the adapter any more.</li>
+ * <li>The byte buffer's position and limit are NOT linked with the adapter.
+ * The adapter extends Buffer, thus has its own position and limit.</li>
+ * </ul>
+ * </p>
+ *
+ */
+// BEGIN android-changed
+// Copied from newer version of harmony
+final class CharToByteBufferAdapter extends CharBuffer implements DirectBuffer {
+// END android-changed
+
+ static CharBuffer wrap(ByteBuffer byteBuffer) {
+ return new CharToByteBufferAdapter(byteBuffer.slice());
+ }
+
+ private final ByteBuffer byteBuffer;
+
+ CharToByteBufferAdapter(ByteBuffer byteBuffer) {
+ super((byteBuffer.capacity() >> 1));
+ this.byteBuffer = byteBuffer;
+ this.byteBuffer.clear();
+ }
+
+ // BEGIN android-added
+ // Copied from newer version of harmony
+ public int getByteCapacity() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getByteCapacity();
+ } else {
+ assert false : byteBuffer;
+ return -1;
+ }
+ }
+
+ public PlatformAddress getEffectiveAddress() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getEffectiveAddress();
+ } else {
+ assert false : byteBuffer;
+ return null;
+ }
+ }
+
+ public PlatformAddress getBaseAddress() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getBaseAddress();
+ } else {
+ assert false : byteBuffer;
+ return null;
+ }
+ }
+
+ public boolean isAddressValid() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).isAddressValid();
+ } else {
+ assert false : byteBuffer;
+ return false;
+ }
+ }
+
+ public void addressValidityCheck() {
+ if (byteBuffer instanceof DirectBuffer) {
+ ((DirectBuffer)byteBuffer).addressValidityCheck();
+ } else {
+ assert false : byteBuffer;
+ }
+ }
+
+ public void free() {
+ if (byteBuffer instanceof DirectBuffer) {
+ ((DirectBuffer)byteBuffer).free();
+ } else {
+ assert false : byteBuffer;
+ }
+ }
+ // END android-added
+
+ public CharBuffer asReadOnlyBuffer() {
+ CharToByteBufferAdapter buf = new CharToByteBufferAdapter(byteBuffer
+ .asReadOnlyBuffer());
+ buf.limit = limit;
+ buf.position = position;
+ buf.mark = mark;
+ return buf;
+ }
+
+ public CharBuffer compact() {
+ if (byteBuffer.isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+ byteBuffer.limit(limit << 1);
+ byteBuffer.position(position << 1);
+ byteBuffer.compact();
+ byteBuffer.clear();
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public CharBuffer duplicate() {
+ CharToByteBufferAdapter buf = new CharToByteBufferAdapter(byteBuffer
+ .duplicate());
+ buf.limit = limit;
+ buf.position = position;
+ buf.mark = mark;
+ return buf;
+ }
+
+ public char get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return byteBuffer.getChar(position++ << 1);
+ }
+
+ public char get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return byteBuffer.getChar(index << 1);
+ }
+
+ public boolean isDirect() {
+ return byteBuffer.isDirect();
+ }
+
+ public boolean isReadOnly() {
+ return byteBuffer.isReadOnly();
+ }
+
+ public ByteOrder order() {
+ return byteBuffer.order();
+ }
+
+ protected char[] protectedArray() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public CharBuffer put(char c) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ byteBuffer.putChar(position++ << 1, c);
+ return this;
+ }
+
+ public CharBuffer put(int index, char c) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ byteBuffer.putChar(index << 1, c);
+ return this;
+ }
+
+ public CharBuffer slice() {
+ byteBuffer.limit(limit << 1);
+ byteBuffer.position(position << 1);
+ CharBuffer result = new CharToByteBufferAdapter(byteBuffer.slice());
+ byteBuffer.clear();
+ return result;
+ }
+
+ public CharSequence subSequence(int start, int end) {
+ if (start < 0 || end < start || end > remaining()) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ CharBuffer result = duplicate();
+ result.limit(position + end);
+ result.position(position + start);
+ return result;
+ }
+}
diff --git a/nio/src/main/java/java/nio/DirectByteBuffer.java b/nio/src/main/java/java/nio/DirectByteBuffer.java
new file mode 100644
index 0000000..46529a5
--- /dev/null
+++ b/nio/src/main/java/java/nio/DirectByteBuffer.java
@@ -0,0 +1,289 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+import org.apache.harmony.luni.platform.PlatformAddress;
+import org.apache.harmony.luni.platform.PlatformAddressFactory;
+import org.apache.harmony.nio.internal.DirectBuffer;
+import org.apache.harmony.nio.internal.nls.Messages;
+
+
+/**
+ * DirectByteBuffer, ReadWriteDirectByteBuffer and ReadOnlyDirectByteBuffer
+ * compose the implementation of platform memory based byte buffers.
+ * <p>
+ * DirectByteBuffer implements all the shared readonly methods and is extended
+ * by the other two classes.
+ * </p>
+ * <p>
+ * All methods are marked final for runtime performance.
+ * </p>
+ *
+ */
+abstract class DirectByteBuffer extends BaseByteBuffer implements DirectBuffer {
+
+ // This class will help us track whether the address is valid or not.
+ static final class SafeAddress {
+ protected volatile boolean isValid = true;
+
+ protected final PlatformAddress address;
+
+ protected SafeAddress(PlatformAddress address) {
+ super();
+ this.address = address;
+ }
+ }
+
+ // This is a wrapped reference to the base address of the buffer memory.
+ protected final SafeAddress safeAddress;
+
+ // This is the offset from the base address at which this buffer logically
+ // starts.
+ protected final int offset;
+
+ /*
+ * Constructs a new direct byte buffer of the given capacity on newly
+ * allocated OS memory. The memory will have been zeroed. When the
+ * instance is discarded the OS memory will be freed if it has not
+ * already been done so by an explicit call to #free(). Callers are
+ * encouraged to explicitly free the memory where possible.
+ */
+ DirectByteBuffer(int capacity) {
+ this(new SafeAddress(PlatformAddressFactory.alloc(capacity, (byte)0)), capacity, 0);
+ safeAddress.address.autoFree();
+ }
+
+ DirectByteBuffer(SafeAddress address, int capacity, int offset) {
+ super(capacity);
+
+ // BEGIN android-added
+ PlatformAddress baseAddress = address.address;
+ long baseSize = baseAddress.getSize();
+
+ if ((baseSize >= 0) && ((offset + capacity) > baseSize)) {
+ throw new IllegalArgumentException("slice out of range");
+ }
+ // END android-added
+
+ this.safeAddress = address;
+ this.offset = offset;
+ }
+
+ /*
+ * Override ByteBuffer.get(byte[], int, int) to improve performance.
+ *
+ * (non-Javadoc)
+ * @see java.nio.ByteBuffer#get(byte[], int, int)
+ */
+ public final ByteBuffer get(byte[] dest, int off, int len) {
+ int length = dest.length;
+ if ((off < 0 ) || (len < 0) || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ getBaseAddress().getByteArray(offset+position, dest, off, len);
+ position += len;
+ return this;
+ }
+
+ public final byte get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return getBaseAddress().getByte(offset + position++);
+ }
+
+ public final byte get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return getBaseAddress().getByte(offset + index);
+ }
+
+ public final double getDouble() {
+ int newPosition = position + 8;
+ if (newPosition > limit) {
+ throw new BufferUnderflowException();
+ }
+ double result = getBaseAddress().getDouble(offset + position, order);
+ position = newPosition;
+ return result;
+ }
+
+ public final double getDouble(int index) {
+ if (index < 0 || (long)index + 8 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return getBaseAddress().getDouble(offset + index, order);
+ }
+
+ public final float getFloat() {
+ int newPosition = position + 4;
+ if (newPosition > limit) {
+ throw new BufferUnderflowException();
+ }
+ float result = getBaseAddress().getFloat(offset + position, order);
+ position = newPosition;
+ return result;
+ }
+
+ public final float getFloat(int index) {
+ if (index < 0 || (long)index + 4 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return getBaseAddress().getFloat(offset + index, order);
+ }
+
+ public final int getInt() {
+ int newPosition = position + 4;
+ if (newPosition > limit) {
+ throw new BufferUnderflowException();
+ }
+ int result = getBaseAddress().getInt(offset + position, order);
+ position = newPosition;
+ return result;
+ }
+
+ public final int getInt(int index) {
+ if (index < 0 || (long)index + 4 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return getBaseAddress().getInt(offset + index, order);
+ }
+
+ public final long getLong() {
+ int newPosition = position + 8;
+ if (newPosition > limit) {
+ throw new BufferUnderflowException();
+ }
+ long result = getBaseAddress().getLong(offset + position, order);
+ position = newPosition;
+ return result;
+ }
+
+ public final long getLong(int index) {
+ if (index < 0 || (long)index + 8 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return getBaseAddress().getLong(offset + index, order);
+ }
+
+ public final short getShort() {
+ int newPosition = position + 2;
+ if (newPosition > limit) {
+ throw new BufferUnderflowException();
+ }
+ short result = getBaseAddress().getShort(offset + position, order);
+ position = newPosition;
+ return result;
+ }
+
+ public final short getShort(int index) {
+ if (index < 0 || (long)index + 2 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return getBaseAddress().getShort(offset + index, order);
+ }
+
+ public final boolean isDirect() {
+ return true;
+ }
+
+ public final boolean isAddressValid() {
+ return safeAddress.isValid;
+ }
+
+ public final void addressValidityCheck() {
+ if (!isAddressValid()) {
+ // nio.08=Cannot use the direct byte buffer after it has been explicitly freed.
+ throw new IllegalStateException(
+ Messages.getString("nio.08")); //$NON-NLS-1$
+ }
+ }
+
+ private void markAddressInvalid() {
+ safeAddress.isValid = false;
+ }
+
+ /*
+ * Returns the base address of the buffer (i.e. before offset).
+ */
+ public final PlatformAddress getBaseAddress() {
+ addressValidityCheck();
+ return safeAddress.address;
+ }
+
+ /**
+ * Returns the platform address of the start of this buffer instance.
+ * <em>You must not attempt to free the returned address!!</em> It may not
+ * be an address that was explicitly malloc'ed (i.e. if this buffer is the
+ * result of a split); and it may be memory shared by multiple buffers.
+ * <p>
+ * If you can guarantee that you want to free the underlying memory call the
+ * #free() method on this instance -- generally applications will rely on
+ * the garbage collector to autofree this memory.
+ * </p>
+ *
+ * @return the effective address of the start of the buffer.
+ * @throws IllegalStateException
+ * if this buffer address is known to have been freed
+ * previously.
+ */
+ public final PlatformAddress getEffectiveAddress() {
+ return getBaseAddress().offsetBytes(offset);
+ }
+
+ /**
+ * Explicitly free the memory used by this direct byte buffer. If the memory
+ * has already been freed then this is a no-op. Once the memory has been
+ * freed then operations requiring access to the memory will throw an
+ * <code>IllegalStateException</code>.
+ * <p>
+ * Note this is is possible that the memory is freed by code that reaches
+ * into the address and explicitly frees it 'beneith' us -- this is bad
+ * form.
+ * </p>
+ */
+ public final void free() {
+ if (isAddressValid()) {
+ markAddressInvalid();
+ safeAddress.address.free();
+ }
+ }
+
+ final protected byte[] protectedArray() {
+ throw new UnsupportedOperationException();
+ }
+
+ final protected int protectedArrayOffset() {
+ throw new UnsupportedOperationException();
+ }
+
+ final protected boolean protectedHasArray() {
+ return false;
+ }
+
+ // BEGIN android-added
+ // copied from newer version of harmony
+ public final int getByteCapacity() {
+ return capacity;
+ }
+ // END android-added
+}
diff --git a/nio/src/main/java/java/nio/DirectByteBuffers.java b/nio/src/main/java/java/nio/DirectByteBuffers.java
new file mode 100644
index 0000000..03a0df7
--- /dev/null
+++ b/nio/src/main/java/java/nio/DirectByteBuffers.java
@@ -0,0 +1,84 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+import org.apache.harmony.luni.platform.PlatformAddress;
+
+/**
+ * Helper class for operations on direct ByteBuffer
+ *
+ * @see java.nio.ByteBuffer
+ */
+class DirectByteBuffers {
+
+ /**
+ * Explicitly frees the memory used by the given direct byte buffer.
+ * <p>
+ * If the memory is known to already have been freed then this is a no-op.
+ * Once the memory has been freed then operations requiring access to the
+ * memory will throw an <code>IllegalStateException</code>.
+ * </p>
+ * <p>
+ * Note this is is possible that the memory is freed by code that reaches
+ * into the address and explicitly frees it 'beneith' us -- this is bad
+ * form.
+ * </p>
+ *
+ * @param directBuffer
+ * the direct byte buffer memory to free
+ * @throws IllegalArgumentException
+ * if the buffer is <code>null</code> or is not a
+ * <em>direct</em> byte buffer.
+ */
+ public static void free(ByteBuffer directBuffer) {
+ if ((directBuffer == null) || (!directBuffer.isDirect())) {
+ throw new IllegalArgumentException();
+ }
+ DirectByteBuffer buf = (DirectByteBuffer) directBuffer;
+ buf.free();
+ }
+
+ /**
+ * Returns the platform address of the start of this buffer instance.
+ * <em>You must not attempt to free the returned address!!</em> It may not
+ * be an address that was explicitly malloc'ed (i.e. if this buffer is the
+ * result of a split); and it may be memory shared by multiple buffers.
+ * <p>
+ * If you can guarantee that you want to free the underlying memory call the
+ * #free() method on this instance -- generally applications will rely on
+ * the garbage collector to autofree this memory.
+ * </p>
+ *
+ * @param directBuffer
+ * the direct byte buffer
+ * @return the effective address of the start of the buffer.
+ * @throws IllegalStateException
+ * if this buffer address is known to have been freed
+ * previously.
+ */
+ public static PlatformAddress getEffectiveAddress(ByteBuffer directBuffer) {
+ return toDirectBuffer(directBuffer).getEffectiveAddress();
+ }
+
+ private static DirectByteBuffer toDirectBuffer(ByteBuffer directBuffer) {
+ if ((directBuffer == null) || (!directBuffer.isDirect())) {
+ throw new IllegalArgumentException();
+ }
+ return (DirectByteBuffer) directBuffer;
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/DoubleArrayBuffer.java b/nio/src/main/java/java/nio/DoubleArrayBuffer.java
new file mode 100644
index 0000000..ad488ea
--- /dev/null
+++ b/nio/src/main/java/java/nio/DoubleArrayBuffer.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * DoubleArrayBuffer, ReadWriteDoubleArrayBuffer and ReadOnlyDoubleArrayBuffer
+ * compose the implementation of array based double buffers.
+ * <p>
+ * DoubleArrayBuffer implements all the shared readonly methods and is extended
+ * by the other two classes.
+ * </p>
+ * <p>
+ * All methods are marked final for runtime performance.
+ * </p>
+ *
+ */
+abstract class DoubleArrayBuffer extends DoubleBuffer {
+
+ protected final double[] backingArray;
+
+ protected final int offset;
+
+ DoubleArrayBuffer(double[] array) {
+ this(array.length, array, 0);
+ }
+
+ DoubleArrayBuffer(int capacity) {
+ this(capacity, new double[capacity], 0);
+ }
+
+ DoubleArrayBuffer(int capacity, double[] backingArray, int offset) {
+ super(capacity);
+ this.backingArray = backingArray;
+ this.offset = offset;
+ }
+
+ public final double get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return backingArray[offset + position++];
+ }
+
+ public final double get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return backingArray[offset + index];
+ }
+
+ public final DoubleBuffer get(double[] dest, int off, int len) {
+ int length = dest.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ System.arraycopy(backingArray, offset + position, dest,
+ off, len);
+ position += len;
+ return this;
+ }
+
+ public final boolean isDirect() {
+ return false;
+ }
+
+ public final ByteOrder order() {
+ return ByteOrder.nativeOrder();
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/DoubleBuffer.java b/nio/src/main/java/java/nio/DoubleBuffer.java
new file mode 100644
index 0000000..f08188c
--- /dev/null
+++ b/nio/src/main/java/java/nio/DoubleBuffer.java
@@ -0,0 +1,565 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * A buffer of <code>double</code>s.
+ * <p>
+ * A double buffer can be created in either of the following ways:
+ * <ul>
+ * <li>{@link #allocate(int) Allocate} a new double array and create a buffer
+ * based on it;</li>
+ * <li>{@link #wrap(double[]) Wrap} an existing double array to create a new
+ * buffer;</li>
+ * <li>Use
+ * {@link java.nio.ByteBuffer#asDoubleBuffer() ByteBuffer.asDoubleBuffer} to
+ * create a double buffer based on a byte buffer.</li>
+ * </ul>
+ * </p>
+ */
+public abstract class DoubleBuffer extends Buffer implements Comparable<DoubleBuffer> {
+
+ /**
+ * Creates a double buffer based on a new allocated double array.
+ *
+ * @param capacity The capacity of the new buffer
+ * @return The created double buffer
+ * @throws IllegalArgumentException If <code>capacity</code> is less than zero
+ */
+ public static DoubleBuffer allocate(int capacity) {
+ if (capacity < 0) {
+ throw new IllegalArgumentException();
+ }
+ return BufferFactory.newDoubleBuffer(capacity);
+ }
+
+ /**
+ * Creates a new double buffer by wrapping the given double array.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>wrap(array, 0, array.length)</code>.</p>
+ *
+ * @param array The double array which the new buffer will be based on
+ * @return The created double buffer
+ */
+ public static DoubleBuffer wrap(double[] array) {
+ return wrap(array, 0, array.length);
+ }
+
+ /**
+ * Creates new a double buffer by wrapping the given double array.
+ * <p>
+ * The new buffer's position will be <code>start</code>, limit will be
+ * <code>start + len</code>, capacity will be the length of the array.
+ * </p>
+ *
+ * @param array
+ * The double array which the new buffer will be based on
+ * @param start
+ * The start index, must be no less than zero and no greater than
+ * <code>array.length</code>
+ * @param len
+ * The length, must be no less than zero and no greater than
+ * <code>array.length - start</code>
+ * @return The created double buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>start</code> or <code>len</code> is
+ * invalid
+ */
+ public static DoubleBuffer wrap(double[] array, int start, int len) {
+ int length = array.length;
+ if (start < 0 || len < 0 || (long)start + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ DoubleBuffer buf = BufferFactory.newDoubleBuffer(array);
+ buf.position = start;
+ buf.limit = start + len;
+
+ return buf;
+ }
+
+ /**
+ * Constructs a <code>DoubleBuffer</code> with given capacity.
+ *
+ * @param capacity The capacity of the buffer
+ */
+ DoubleBuffer(int capacity) {
+ super(capacity);
+ // BEGIN android-added
+ _elementSizeShift = 3;
+ // END android-added
+ }
+
+ /**
+ * Returns the double array which this buffer is based on, if there's one.
+ *
+ * @return The double array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on an array, but it is readonly
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final double[] array() {
+ return protectedArray();
+ }
+
+ /**
+ * Returns the offset of the double array which this buffer is based on, if
+ * there's one.
+ * <p>
+ * The offset is the index of the array corresponds to the zero position of
+ * the buffer.
+ * </p>
+ *
+ * @return The offset of the double array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on an array, but it is readonly
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final int arrayOffset() {
+ return protectedArrayOffset();
+ }
+
+ // BEGIN android-added
+ @Override Object _array() {
+ if (hasArray()) {
+ return array();
+ }
+ return null;
+ }
+
+ @Override int _arrayOffset() {
+ if (hasArray()) {
+ return arrayOffset();
+ }
+ return 0;
+ }
+ // END android-added
+
+ /**
+ * Returns a readonly buffer that shares content with this buffer.
+ * <p>
+ * The returned buffer is guaranteed to be a new instance, even this
+ * buffer is readonly itself. The new buffer's position, limit, capacity
+ * and mark are the same as this buffer.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * this buffer's change of content will be visible to the new buffer.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A readonly version of this buffer.
+ */
+ public abstract DoubleBuffer asReadOnlyBuffer();
+
+ /**
+ * Compacts this double buffer.
+ * <p>
+ * The remaining <code>double</code>s will be moved to the head of the
+ * buffer, staring from position zero. Then the position is set to
+ * <code>remaining()</code>; the limit is set to capacity; the mark is
+ * cleared.
+ * </p>
+ *
+ * @return This buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract DoubleBuffer compact();
+
+ /**
+ * Compare the remaining <code>double</code>s of this buffer to another
+ * double buffer's remaining <code>double</code>s.
+ *
+ * @param otherBuffer
+ * Another double buffer
+ * @return a negative value if this is less than <code>other</code>; 0 if
+ * this equals to <code>other</code>; a positive value if this is
+ * greater than <code>other</code>
+ * @exception ClassCastException
+ * If <code>other</code> is not a double buffer
+ */
+ public int compareTo(DoubleBuffer otherBuffer) {
+ int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
+ : otherBuffer.remaining();
+ int thisPos = position;
+ int otherPos = otherBuffer.position;
+ double thisByte, otherByte;
+ while (compareRemaining > 0) {
+ thisByte = get(thisPos);
+ otherByte = otherBuffer.get(otherPos);
+ if (thisByte != otherByte) {
+ return thisByte < otherByte ? -1 : 1;
+ }
+ thisPos++;
+ otherPos++;
+ compareRemaining--;
+ }
+ return remaining() - otherBuffer.remaining();
+ }
+
+ /**
+ * Returns a duplicated buffer that shares content with this buffer.
+ * <p>
+ * The duplicated buffer's position, limit, capacity and mark are the
+ * same as this buffer. The duplicated buffer's readonly property and
+ * byte order are same as this buffer too.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * either buffer's change of content will be visible to the other.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A duplicated buffer that shares content with this buffer.
+ */
+ public abstract DoubleBuffer duplicate();
+
+ /**
+ * Tests whether this double buffer equals to another object.
+ * <p>
+ * If <code>other</code> is not a double buffer, then false is returned.</p>
+ * <p>
+ * Two double buffers are equals if, and only if, their remaining
+ * <code>double</code>s are exactly the same. Position, limit, capacity and
+ * mark are not considered.</p>
+ *
+ * @param other the object to be compared against
+ * @return Whether this double buffer equals to another object.
+ */
+ public boolean equals(Object other) {
+ if (!(other instanceof DoubleBuffer)) {
+ return false;
+ }
+ DoubleBuffer otherBuffer = (DoubleBuffer) other;
+
+ if (remaining() != otherBuffer.remaining()) {
+ return false;
+ }
+
+ int myPosition = position;
+ int otherPosition = otherBuffer.position;
+ boolean equalSoFar = true;
+ while (equalSoFar && (myPosition < limit)) {
+ equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++);
+ }
+
+ return equalSoFar;
+ }
+
+ /**
+ * Returns the double at the current position and increase the position by 1.
+ *
+ * @return The double at the current position.
+ * @exception BufferUnderflowException If the position is equal or greater than limit
+ */
+ public abstract double get();
+
+ /**
+ * Reads <code>double</code>s from the current position into the
+ * specified double array and increase the position by the number of
+ * <code>double</code>s read.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>get(dest, 0, dest.length)</code>.
+ * </p>
+ *
+ * @param dest
+ * The destination double array
+ * @return This buffer
+ * @exception BufferUnderflowException
+ * if <code>dest.length</code> is greater than
+ * <code>remaining()</code>
+ */
+ public DoubleBuffer get(double[] dest) {
+ return get(dest, 0, dest.length);
+ }
+
+ /**
+ * Reads <code>double</code>s from the current position into the
+ * specified double array, starting from the specified offset, and increase
+ * the position by the number of <code>double</code>s read.
+ *
+ * @param dest
+ * The target double array
+ * @param off
+ * The offset of the double array, must be no less than zero and
+ * no greater than <code>dest.length</code>
+ * @param len
+ * The number of <code>double</code>s to read, must be no less
+ * than zero and no greater than <code>dest.length - off</code>
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception BufferUnderflowException
+ * If <code>len</code> is greater than
+ * <code>remaining()</code>
+ */
+ public DoubleBuffer get(double[] dest, int off, int len) {
+ int length = dest.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ dest[i] = get();
+ }
+ return this;
+ }
+
+ /**
+ * Returns a double at the specified index, and the position is not changed.
+ *
+ * @param index The index, must be no less than zero and less than limit
+ * @return A double at the specified index.
+ * @exception IndexOutOfBoundsException If index is invalid
+ */
+ public abstract double get(int index);
+
+ /**
+ * Returns whether this buffer is based on a double array and is read/write.
+ * <p>
+ * If this buffer is readonly, then false is returned.</p>
+ *
+ * @return Whether this buffer is based on a double array and is read/write.
+ */
+ public final boolean hasArray() {
+ return protectedHasArray();
+ }
+
+ /**
+ * Hash code is calculated from the remaining <code>double</code>s.
+ * <p>
+ * Position, limit, capacity and mark don't affect the hash code.</p>
+ *
+ * @return The hash code calculated from the remaining <code>double</code>s.
+ */
+ public int hashCode() {
+ int myPosition = position;
+ int hash = 0;
+ long l;
+ while (myPosition < limit) {
+ l = Double.doubleToLongBits(get(myPosition++));
+ hash = hash + ((int) l) ^ ((int) (l >> 32));
+ }
+ return hash;
+ }
+
+ /**
+ * Returns true if this buffer is direct.
+ * <p>
+ * A direct buffer will try its best to take advantage of native memory
+ * APIs and it may not stay in java heap, thus not affected by GC.</p>
+ * <p>
+ * A double buffer is direct, if it is based on a byte buffer and the byte
+ * buffer is direct.</p>
+ *
+ * @return True if this buffer is direct.
+ */
+ public abstract boolean isDirect();
+
+ /**
+ * Returns the byte order used by this buffer when converting
+ * <code>double</code>s from/to <code>byte</code>s.
+ * <p>
+ * If this buffer is not based on a byte buffer, then always return the
+ * platform's native byte order.</p>
+ *
+ * @return The byte order used by this buffer when converting
+ * <code>double</code>s from/to <code>byte</code>s.
+ */
+ public abstract ByteOrder order();
+
+ /**
+ * Child class implements this method to realize <code>array()</code>.
+ *
+ * @return see <code>array()</code>
+ */
+ abstract double[] protectedArray();
+
+ /**
+ * Child class implements this method to realize <code>arrayOffset()</code>.
+ *
+ * @return see <code>arrayOffset()</code>
+ */
+ abstract int protectedArrayOffset();
+
+ /**
+ * Child class implements this method to realize <code>hasArray()</code>.
+ *
+ * @return see <code>hasArray()</code>
+ */
+ abstract boolean protectedHasArray();
+
+ /**
+ * Writes the given double to the current position and increase the position
+ * by 1.
+ *
+ * @param d
+ * The double to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If position is equal or greater than limit
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract DoubleBuffer put(double d);
+
+ /**
+ * Writes <code>double</code>s in the given double array to the current
+ * position and increase the position by the number of <code>double</code>s
+ * written.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>put(src, 0, src.length)</code>.
+ * </p>
+ *
+ * @param src
+ * The source double array
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>src.length</code>
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public final DoubleBuffer put(double[] src) {
+ return put(src, 0, src.length);
+ }
+
+ /**
+ * Writes <code>double</code>s in the given double array, starting from
+ * the specified offset, to the current position and increase the position
+ * by the number of <code>double</code>s written.
+ *
+ * @param src
+ * The source double array
+ * @param off
+ * The offset of double array, must be no less than zero and no
+ * greater than <code>src.length</code>
+ * @param len
+ * The number of <code>double</code>s to write, must be no
+ * less than zero and no greater than
+ * <code>src.length - off</code>
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>len</code>
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public DoubleBuffer put(double[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ put(src[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Writes all the remaining <code>double</code>s of the <code>src</code>
+ * double buffer to this buffer's current position, and increase both
+ * buffers' position by the number of <code>double</code>s copied.
+ *
+ * @param src
+ * The source double buffer
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>src.remaining()</code> is greater than this
+ * buffer's <code>remaining()</code>
+ * @exception IllegalArgumentException
+ * If <code>src</code> is this buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public DoubleBuffer put(DoubleBuffer src) {
+ if (src == this) {
+ throw new IllegalArgumentException();
+ }
+ if (src.remaining() > remaining()) {
+ throw new BufferOverflowException();
+ }
+ double[] doubles = new double[src.remaining()];
+ src.get(doubles);
+ put(doubles);
+ return this;
+ }
+
+ /**
+ * Write a double to the specified index of this buffer and the position is
+ * not changed.
+ *
+ * @param index
+ * The index, must be no less than zero and less than the limit
+ * @param d
+ * The double to write
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If index is invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract DoubleBuffer put(int index, double d);
+
+ /**
+ * Returns a sliced buffer that shares content with this buffer.
+ * <p>
+ * The sliced buffer's capacity will be this buffer's
+ * <code>remaining()</code>, and its zero position will correspond to
+ * this buffer's current position. The new buffer's position will be
+ * 0, limit will be its capacity, and its mark is unset. The new buffer's
+ * readonly property and byte order are same as this buffer.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * either buffer's change of content will be visible to the other.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A sliced buffer that shares content with this buffer.
+ */
+ public abstract DoubleBuffer slice();
+
+ /**
+ * Returns a string represents the state of this double buffer.
+ *
+ * @return A string represents the state of this double buffer.
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append(getClass().getName());
+ buf.append(", status: capacity="); //$NON-NLS-1$
+ buf.append(capacity());
+ buf.append(" position="); //$NON-NLS-1$
+ buf.append(position());
+ buf.append(" limit="); //$NON-NLS-1$
+ buf.append(limit());
+ return buf.toString();
+ }
+}
diff --git a/nio/src/main/java/java/nio/DoubleToByteBufferAdapter.java b/nio/src/main/java/java/nio/DoubleToByteBufferAdapter.java
new file mode 100644
index 0000000..336488b
--- /dev/null
+++ b/nio/src/main/java/java/nio/DoubleToByteBufferAdapter.java
@@ -0,0 +1,204 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+// BEGIN android-added
+// Copied from newer version of harmony
+import org.apache.harmony.nio.internal.DirectBuffer;
+import org.apache.harmony.luni.platform.PlatformAddress;
+// END android-added
+
+/**
+ * This class wraps a byte buffer to be a double buffer.
+ * <p>
+ * Implementation notice:
+ * <ul>
+ * <li>After a byte buffer instance is wrapped, it becomes privately owned by
+ * the adapter. It must NOT be accessed outside the adapter any more.</li>
+ * <li>The byte buffer's position and limit are NOT linked with the adapter.
+ * The adapter extends Buffer, thus has its own position and limit.</li>
+ * </ul>
+ * </p>
+ *
+ */
+// BEGIN android-changed
+// Copied from newer version of harmony
+final class DoubleToByteBufferAdapter extends DoubleBuffer implements DirectBuffer {
+// END android-changed
+
+ static DoubleBuffer wrap(ByteBuffer byteBuffer) {
+ return new DoubleToByteBufferAdapter(byteBuffer.slice());
+ }
+
+ private final ByteBuffer byteBuffer;
+
+ DoubleToByteBufferAdapter(ByteBuffer byteBuffer) {
+ super((byteBuffer.capacity() >> 3));
+ this.byteBuffer = byteBuffer;
+ this.byteBuffer.clear();
+ }
+
+ // BEGIN android-added
+ // Copied from newer version of harmony
+ public int getByteCapacity() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getByteCapacity();
+ } else {
+ assert false : byteBuffer;
+ return -1;
+ }
+ }
+
+ public PlatformAddress getEffectiveAddress() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getEffectiveAddress();
+ } else {
+ assert false : byteBuffer;
+ return null;
+ }
+ }
+
+ public PlatformAddress getBaseAddress() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getBaseAddress();
+ } else {
+ assert false : byteBuffer;
+ return null;
+ }
+ }
+
+ public boolean isAddressValid() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).isAddressValid();
+ } else {
+ assert false : byteBuffer;
+ return false;
+ }
+ }
+
+ public void addressValidityCheck() {
+ if (byteBuffer instanceof DirectBuffer) {
+ ((DirectBuffer)byteBuffer).addressValidityCheck();
+ } else {
+ assert false : byteBuffer;
+ }
+ }
+
+ public void free() {
+ if (byteBuffer instanceof DirectBuffer) {
+ ((DirectBuffer)byteBuffer).free();
+ } else {
+ assert false : byteBuffer;
+ }
+ }
+ // END android-added
+
+ public DoubleBuffer asReadOnlyBuffer() {
+ DoubleToByteBufferAdapter buf = new DoubleToByteBufferAdapter(
+ byteBuffer.asReadOnlyBuffer());
+ buf.limit = limit;
+ buf.position = position;
+ buf.mark = mark;
+ return buf;
+ }
+
+ public DoubleBuffer compact() {
+ if (byteBuffer.isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+ byteBuffer.limit(limit << 3);
+ byteBuffer.position(position << 3);
+ byteBuffer.compact();
+ byteBuffer.clear();
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public DoubleBuffer duplicate() {
+ DoubleToByteBufferAdapter buf = new DoubleToByteBufferAdapter(
+ byteBuffer.duplicate());
+ buf.limit = limit;
+ buf.position = position;
+ buf.mark = mark;
+ return buf;
+ }
+
+ public double get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return byteBuffer.getDouble(position++ << 3);
+ }
+
+ public double get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return byteBuffer.getDouble(index << 3);
+ }
+
+ public boolean isDirect() {
+ return byteBuffer.isDirect();
+ }
+
+ public boolean isReadOnly() {
+ return byteBuffer.isReadOnly();
+ }
+
+ public ByteOrder order() {
+ return byteBuffer.order();
+ }
+
+ protected double[] protectedArray() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public DoubleBuffer put(double c) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ byteBuffer.putDouble(position++ << 3, c);
+ return this;
+ }
+
+ public DoubleBuffer put(int index, double c) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ byteBuffer.putDouble(index << 3, c);
+ return this;
+ }
+
+ public DoubleBuffer slice() {
+ byteBuffer.limit(limit << 3);
+ byteBuffer.position(position << 3);
+ DoubleBuffer result = new DoubleToByteBufferAdapter(byteBuffer.slice());
+ byteBuffer.clear();
+ return result;
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/FloatArrayBuffer.java b/nio/src/main/java/java/nio/FloatArrayBuffer.java
new file mode 100644
index 0000000..bb07e97
--- /dev/null
+++ b/nio/src/main/java/java/nio/FloatArrayBuffer.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * FloatArrayBuffer, ReadWriteFloatArrayBuffer and ReadOnlyFloatArrayBuffer
+ * compose the implementation of array based float buffers.
+ * <p>
+ * FloatArrayBuffer implements all the shared readonly methods and is extended
+ * by the other two classes.
+ * </p>
+ * <p>
+ * All methods are marked final for runtime performance.
+ * </p>
+ *
+ */
+abstract class FloatArrayBuffer extends FloatBuffer {
+
+ protected final float[] backingArray;
+
+ protected final int offset;
+
+ FloatArrayBuffer(float[] array) {
+ this(array.length, array, 0);
+ }
+
+ FloatArrayBuffer(int capacity) {
+ this(capacity, new float[capacity], 0);
+ }
+
+ FloatArrayBuffer(int capacity, float[] backingArray, int offset) {
+ super(capacity);
+ this.backingArray = backingArray;
+ this.offset = offset;
+ }
+
+ public final float get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return backingArray[offset + position++];
+ }
+
+ public final float get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return backingArray[offset + index];
+ }
+
+ public final FloatBuffer get(float[] dest, int off, int len) {
+ int length = dest.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ System.arraycopy(backingArray, offset+position, dest, off, len);
+ position += len;
+ return this;
+ }
+
+ public final boolean isDirect() {
+ return false;
+ }
+
+ public final ByteOrder order() {
+ return ByteOrder.nativeOrder();
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/FloatBuffer.java b/nio/src/main/java/java/nio/FloatBuffer.java
new file mode 100644
index 0000000..c695d13
--- /dev/null
+++ b/nio/src/main/java/java/nio/FloatBuffer.java
@@ -0,0 +1,564 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * A buffer of <code>float</code>s.
+ * <p>
+ * A float buffer can be created in either of the following ways:
+ * <ul>
+ * <li>{@link #allocate(int) Allocate} a new float array and create a buffer
+ * based on it;</li>
+ * <li>{@link #wrap(float[]) Wrap} an existing float array to create a new
+ * buffer;</li>
+ * <li>Use {@link java.nio.ByteBuffer#asFloatBuffer() ByteBuffer.asFloatBuffer}
+ * to create a float buffer based on a byte buffer.</li>
+ * </ul>
+ * </p>
+ *
+ */
+public abstract class FloatBuffer extends Buffer implements Comparable<FloatBuffer> {
+
+ /**
+ * Creates a float buffer based on a new allocated float array.
+ *
+ * @param capacity The capacity of the new buffer
+ * @return The created float buffer
+ * @throws IllegalArgumentException If <code>capacity</code> is less than zero
+ */
+ public static FloatBuffer allocate(int capacity) {
+ if (capacity < 0) {
+ throw new IllegalArgumentException();
+ }
+ return BufferFactory.newFloatBuffer(capacity);
+ }
+
+ /**
+ * Creates a new float buffer by wrapping the given float array.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>wrap(array, 0, array.length)</code>.</p>
+ *
+ * @param array The float array which the new buffer will be based on
+ * @return The created float buffer
+ */
+ public static FloatBuffer wrap(float[] array) {
+ return wrap(array, 0, array.length);
+ }
+
+ /**
+ * Creates new a float buffer by wrapping the given float array.
+ * <p>
+ * The new buffer's position will be <code>start</code>, limit will be
+ * <code>start + len</code>, capacity will be the length of the array.
+ * </p>
+ *
+ * @param array
+ * The float array which the new buffer will be based on
+ * @param start
+ * The start index, must be no less than zero and no greater than
+ * <code>array.length</code>
+ * @param len
+ * The length, must be no less than zero and no greater than
+ * <code>array.length - start</code>
+ * @return The created float buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>start</code> or <code>len</code> is
+ * invalid
+ */
+ public static FloatBuffer wrap(float[] array, int start, int len) {
+ if (array == null) {
+ throw new NullPointerException();
+ }
+ if (start < 0 || len < 0 || (long)start + (long)len > array.length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ FloatBuffer buf = BufferFactory.newFloatBuffer(array);
+ buf.position = start;
+ buf.limit = start + len;
+
+ return buf;
+ }
+
+ /**
+ * Constructs a <code>FloatBuffer</code> with given capacity.
+ *
+ * @param capacity The capacity of the buffer
+ */
+ FloatBuffer(int capacity) {
+ super(capacity);
+ // BEGIN android-added
+ _elementSizeShift = 2;
+ // END android-added
+ }
+
+ /**
+ * Returns the float array which this buffer is based on, if there's one.
+ *
+ * @return The float array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on an array, but it is readonly
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final float[] array() {
+ return protectedArray();
+ }
+
+ /**
+ * Returns the offset of the float array which this buffer is based on, if
+ * there's one.
+ * <p>
+ * The offset is the index of the array corresponds to the zero position of
+ * the buffer.
+ * </p>
+ *
+ * @return The offset of the float array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on an array, but it is readonly
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final int arrayOffset() {
+ return protectedArrayOffset();
+ }
+
+ // BEGIN android-added
+ @Override Object _array() {
+ if (hasArray()) {
+ return array();
+ }
+ return null;
+ }
+
+ @Override int _arrayOffset() {
+ if (hasArray()) {
+ return arrayOffset();
+ }
+ return 0;
+ }
+ // END android-added
+
+ /**
+ * Returns a readonly buffer that shares content with this buffer.
+ * <p>
+ * The returned buffer is guaranteed to be a new instance, even this
+ * buffer is readonly itself. The new buffer's position, limit, capacity
+ * and mark are the same as this buffer.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * this buffer's change of content will be visible to the new buffer.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A readonly version of this buffer.
+ */
+ public abstract FloatBuffer asReadOnlyBuffer();
+
+ /**
+ * Compacts this float buffer.
+ * <p>
+ * The remaining <code>float</code>s will be moved to the head of the
+ * buffer, staring from position zero. Then the position is set to
+ * <code>remaining()</code>; the limit is set to capacity; the mark is
+ * cleared.
+ * </p>
+ *
+ * @return This buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract FloatBuffer compact();
+
+ /**
+ * Compare the remaining <code>float</code>s of this buffer to another
+ * float buffer's remaining <code>float</code>s.
+ *
+ * @param otherBuffer
+ * Another float buffer
+ * @return a negative value if this is less than <code>other</code>; 0 if
+ * this equals to <code>other</code>; a positive value if this is
+ * greater than <code>other</code>
+ * @exception ClassCastException
+ * If <code>other</code> is not a float buffer
+ */
+ public int compareTo(FloatBuffer otherBuffer) {
+ int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
+ : otherBuffer.remaining();
+ int thisPos = position;
+ int otherPos = otherBuffer.position;
+ float thisByte, otherByte;
+ while (compareRemaining > 0) {
+ thisByte = get(thisPos);
+ otherByte = otherBuffer.get(otherPos);
+ if (thisByte != otherByte) {
+ return thisByte < otherByte ? -1 : 1;
+ }
+ thisPos++;
+ otherPos++;
+ compareRemaining--;
+ }
+ return remaining() - otherBuffer.remaining();
+ }
+
+ /**
+ * Returns a duplicated buffer that shares content with this buffer.
+ * <p>
+ * The duplicated buffer's position, limit, capacity and mark are the
+ * same as this buffer. The duplicated buffer's readonly property and
+ * byte order are same as this buffer too.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * either buffer's change of content will be visible to the other.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A duplicated buffer that shares content with this buffer.
+ */
+ public abstract FloatBuffer duplicate();
+
+ /**
+ * Tests whether this float buffer equals to another object.
+ * <p>
+ * If <code>other</code> is not a float buffer, then false is returned.</p>
+ * <p>
+ * Two float buffers are equals if, and only if, their remaining
+ * <code>float</code>s are exactly the same. Position, limit, capacity and
+ * mark are not considered.</p>
+ *
+ * @param other the object to be compared against
+ * @return Whether this float buffer equals to another object.
+ */
+ public boolean equals(Object other) {
+ if (!(other instanceof FloatBuffer)) {
+ return false;
+ }
+ FloatBuffer otherBuffer = (FloatBuffer) other;
+
+ if (remaining() != otherBuffer.remaining()) {
+ return false;
+ }
+
+ int myPosition = position;
+ int otherPosition = otherBuffer.position;
+ boolean equalSoFar = true;
+ while (equalSoFar && (myPosition < limit)) {
+ equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++);
+ }
+
+ return equalSoFar;
+ }
+
+ /**
+ * Returns the float at the current position and increase the position by 1.
+ *
+ * @return The float at the current position.
+ * @exception BufferUnderflowException If the position is equal or greater than limit
+ */
+ public abstract float get();
+
+ /**
+ * Reads <code>float</code>s from the current position into the specified
+ * float array and increase the position by the number of <code>float</code>s
+ * read.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>get(dest, 0, dest.length)</code>.
+ * </p>
+ *
+ * @param dest
+ * The destination float array
+ * @return This buffer
+ * @exception BufferUnderflowException
+ * if <code>dest.length</code> is greater than
+ * <code>remaining()</code>
+ */
+ public FloatBuffer get(float[] dest) {
+ return get(dest, 0, dest.length);
+ }
+
+ /**
+ * Reads <code>float</code>s from the current position into the specified
+ * float array, starting from the specified offset, and increase the
+ * position by the number of <code>float</code>s read.
+ *
+ * @param dest
+ * The target float array
+ * @param off
+ * The offset of the float array, must be no less than zero and
+ * no greater than <code>dest.length</code>
+ * @param len
+ * The number of <code>float</code>s to read, must be no less
+ * than zero and no greater than <code>dest.length - off</code>
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception BufferUnderflowException
+ * If <code>len</code> is greater than
+ * <code>remaining()</code>
+ */
+ public FloatBuffer get(float[] dest, int off, int len) {
+ int length = dest.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ dest[i] = get();
+ }
+ return this;
+ }
+
+ /**
+ * Returns a float at the specified index, and the position is not changed.
+ *
+ * @param index The index, must be no less than zero and less than limit
+ * @return A float at the specified index.
+ * @exception IndexOutOfBoundsException If index is invalid
+ */
+ public abstract float get(int index);
+
+ /**
+ * Returns whether this buffer is based on a float array and is read/write.
+ * <p>
+ * If this buffer is readonly, then false is returned.</p>
+ *
+ * @return Whether this buffer is based on a float array and is read/write.
+ */
+ public final boolean hasArray() {
+ return protectedHasArray();
+ }
+
+ /**
+ * Hash code is calculated from the remaining <code>float</code>s.
+ * <p>
+ * Position, limit, capacity and mark don't affect the hash code.</p>
+ *
+ * @return The hash code calculated from the remaining <code>float</code>s.
+ */
+ public int hashCode() {
+ int myPosition = position;
+ int hash = 0;
+ while (myPosition < limit) {
+ hash = hash + Float.floatToIntBits(get(myPosition++));
+ }
+ return hash;
+ }
+
+ /**
+ * Returns true if this buffer is direct.
+ * <p>
+ * A direct buffer will try its best to take advantage of native memory
+ * APIs and it may not stay in java heap, thus not affected by GC.</p>
+ * <p>
+ * A float buffer is direct, if it is based on a byte buffer and the byte
+ * buffer is direct.</p>
+ *
+ * @return True if this buffer is direct.
+ */
+ public abstract boolean isDirect();
+
+ /**
+ * Returns the byte order used by this buffer when converting
+ * <code>float</code>s from/to <code>byte</code>s.
+ * <p>
+ * If this buffer is not based on a byte buffer, then always return the
+ * platform's native byte order.</p>
+ *
+ * @return The byte order used by this buffer when converting
+ * <code>float</code>s from/to <code>byte</code>s.
+ */
+ public abstract ByteOrder order();
+
+ /**
+ * Child class implements this method to realize <code>array()</code>.
+ *
+ * @return see <code>array()</code>
+ */
+ abstract float[] protectedArray();
+
+ /**
+ * Child class implements this method to realize <code>arrayOffset()</code>.
+ *
+ * @return see <code>arrayOffset()</code>
+ */
+ abstract int protectedArrayOffset();
+
+ /**
+ * Child class implements this method to realize <code>hasArray()</code>.
+ *
+ * @return see <code>hasArray()</code>
+ */
+ abstract boolean protectedHasArray();
+
+ /**
+ * Writes the given float to the current position and increase the position
+ * by 1.
+ *
+ * @param f
+ * The float to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If position is equal or greater than limit
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract FloatBuffer put(float f);
+
+ /**
+ * Writes <code>float</code>s in the given float array to the current
+ * position and increase the position by the number of <code>float</code>s
+ * written.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>put(src, 0, src.length)</code>.
+ * </p>
+ *
+ * @param src
+ * The source float array
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>src.length</code>
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public final FloatBuffer put(float[] src) {
+ return put(src, 0, src.length);
+ }
+
+ /**
+ * Writes <code>float</code>s in the given float array, starting from the
+ * specified offset, to the current position and increase the position by
+ * the number of <code>float</code>s written.
+ *
+ * @param src
+ * The source float array
+ * @param off
+ * The offset of float array, must be no less than zero and no
+ * greater than <code>src.length</code>
+ * @param len
+ * The number of <code>float</code>s to write, must be no less
+ * than zero and no greater than <code>src.length - off</code>
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>len</code>
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public FloatBuffer put(float[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ put(src[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Writes all the remaining <code>float</code>s of the <code>src</code>
+ * float buffer to this buffer's current position, and increase both
+ * buffers' position by the number of <code>float</code>s copied.
+ *
+ * @param src
+ * The source float buffer
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>src.remaining()</code> is greater than this
+ * buffer's <code>remaining()</code>
+ * @exception IllegalArgumentException
+ * If <code>src</code> is this buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public FloatBuffer put(FloatBuffer src) {
+ if (src == this) {
+ throw new IllegalArgumentException();
+ }
+ if (src.remaining() > remaining()) {
+ throw new BufferOverflowException();
+ }
+ float[] contents = new float[src.remaining()];
+ src.get(contents);
+ put(contents);
+ return this;
+ }
+
+ /**
+ * Write a float to the specified index of this buffer and the position is
+ * not changed.
+ *
+ * @param index
+ * The index, must be no less than zero and less than the limit
+ * @param f
+ * The float to write
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If index is invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract FloatBuffer put(int index, float f);
+
+ /**
+ * Returns a sliced buffer that shares content with this buffer.
+ * <p>
+ * The sliced buffer's capacity will be this buffer's
+ * <code>remaining()</code>, and its zero position will correspond to
+ * this buffer's current position. The new buffer's position will be
+ * 0, limit will be its capacity, and its mark is unset. The new buffer's
+ * readonly property and byte order are same as this buffer.</p>
+ * <p>
+ * The new buffer shares content with this buffer, which means
+ * either buffer's change of content will be visible to the other.
+ * The two buffer's position, limit and mark are independent.</p>
+ *
+ * @return A sliced buffer that shares content with this buffer.
+ */
+ public abstract FloatBuffer slice();
+
+ /**
+ * Returns a string represents the state of this float buffer.
+ *
+ * @return A string represents the state of this float buffer.
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append(getClass().getName());
+ buf.append(", status: capacity="); //$NON-NLS-1$
+ buf.append(capacity());
+ buf.append(" position="); //$NON-NLS-1$
+ buf.append(position());
+ buf.append(" limit="); //$NON-NLS-1$
+ buf.append(limit());
+ return buf.toString();
+ }
+}
diff --git a/nio/src/main/java/java/nio/FloatToByteBufferAdapter.java b/nio/src/main/java/java/nio/FloatToByteBufferAdapter.java
new file mode 100644
index 0000000..97c0528
--- /dev/null
+++ b/nio/src/main/java/java/nio/FloatToByteBufferAdapter.java
@@ -0,0 +1,204 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+// BEGIN android-added
+// copied from newer version of harmony
+import org.apache.harmony.nio.internal.DirectBuffer;
+import org.apache.harmony.luni.platform.PlatformAddress;
+// END android-added
+
+/**
+ * This class wraps a byte buffer to be a float buffer.
+ * <p>
+ * Implementation notice:
+ * <ul>
+ * <li>After a byte buffer instance is wrapped, it becomes privately owned by
+ * the adapter. It must NOT be accessed outside the adapter any more.</li>
+ * <li>The byte buffer's position and limit are NOT linked with the adapter.
+ * The adapter extends Buffer, thus has its own position and limit.</li>
+ * </ul>
+ * </p>
+ *
+ */
+// BEGIN android-changed
+// copied from newer version of harmony
+final class FloatToByteBufferAdapter extends FloatBuffer implements DirectBuffer {
+// END android-changed
+
+ static FloatBuffer wrap(ByteBuffer byteBuffer) {
+ return new FloatToByteBufferAdapter(byteBuffer.slice());
+ }
+
+ private final ByteBuffer byteBuffer;
+
+ FloatToByteBufferAdapter(ByteBuffer byteBuffer) {
+ super((byteBuffer.capacity() >> 2));
+ this.byteBuffer = byteBuffer;
+ this.byteBuffer.clear();
+ }
+
+ // BEGIN android-added
+ // copied from newer version of harmony
+ public int getByteCapacity() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getByteCapacity();
+ } else {
+ assert false : byteBuffer;
+ return -1;
+ }
+ }
+
+ public PlatformAddress getEffectiveAddress() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getEffectiveAddress();
+ } else {
+ assert false : byteBuffer;
+ return null;
+ }
+ }
+
+ public PlatformAddress getBaseAddress() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getBaseAddress();
+ } else {
+ assert false : byteBuffer;
+ return null;
+ }
+ }
+
+ public boolean isAddressValid() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).isAddressValid();
+ } else {
+ assert false : byteBuffer;
+ return false;
+ }
+ }
+
+ public void addressValidityCheck() {
+ if (byteBuffer instanceof DirectBuffer) {
+ ((DirectBuffer)byteBuffer).addressValidityCheck();
+ } else {
+ assert false : byteBuffer;
+ }
+ }
+
+ public void free() {
+ if (byteBuffer instanceof DirectBuffer) {
+ ((DirectBuffer)byteBuffer).free();
+ } else {
+ assert false : byteBuffer;
+ }
+ }
+ // END android-added
+
+ public FloatBuffer asReadOnlyBuffer() {
+ FloatToByteBufferAdapter buf = new FloatToByteBufferAdapter(byteBuffer
+ .asReadOnlyBuffer());
+ buf.limit = limit;
+ buf.position = position;
+ buf.mark = mark;
+ return buf;
+ }
+
+ public FloatBuffer compact() {
+ if (byteBuffer.isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+ byteBuffer.limit(limit << 2);
+ byteBuffer.position(position << 2);
+ byteBuffer.compact();
+ byteBuffer.clear();
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public FloatBuffer duplicate() {
+ FloatToByteBufferAdapter buf = new FloatToByteBufferAdapter(byteBuffer
+ .duplicate());
+ buf.limit = limit;
+ buf.position = position;
+ buf.mark = mark;
+ return buf;
+ }
+
+ public float get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return byteBuffer.getFloat(position++ << 2);
+ }
+
+ public float get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return byteBuffer.getFloat(index << 2);
+ }
+
+ public boolean isDirect() {
+ return byteBuffer.isDirect();
+ }
+
+ public boolean isReadOnly() {
+ return byteBuffer.isReadOnly();
+ }
+
+ public ByteOrder order() {
+ return byteBuffer.order();
+ }
+
+ protected float[] protectedArray() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public FloatBuffer put(float c) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ byteBuffer.putFloat(position++ << 2, c);
+ return this;
+ }
+
+ public FloatBuffer put(int index, float c) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ byteBuffer.putFloat(index << 2, c);
+ return this;
+ }
+
+ public FloatBuffer slice() {
+ byteBuffer.limit(limit << 2);
+ byteBuffer.position(position << 2);
+ FloatBuffer result = new FloatToByteBufferAdapter(byteBuffer.slice());
+ byteBuffer.clear();
+ return result;
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/HeapByteBuffer.java b/nio/src/main/java/java/nio/HeapByteBuffer.java
new file mode 100644
index 0000000..49c4038
--- /dev/null
+++ b/nio/src/main/java/java/nio/HeapByteBuffer.java
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+import org.apache.harmony.luni.platform.Endianness;
+
+/**
+ * HeapByteBuffer, ReadWriteHeapByteBuffer and ReadOnlyHeapByteBuffer compose
+ * the implementation of array based byte buffers.
+ * <p>
+ * HeapByteBuffer implements all the shared readonly methods and is extended by
+ * the other two classes.
+ * </p>
+ * <p>
+ * All methods are marked final for runtime performance.
+ * </p>
+ *
+ */
+abstract class HeapByteBuffer extends BaseByteBuffer {
+
+ protected final byte[] backingArray;
+
+ protected final int offset;
+
+ HeapByteBuffer(byte[] backingArray) {
+ this(backingArray, backingArray.length, 0);
+ }
+
+ HeapByteBuffer(int capacity) {
+ this(new byte[capacity], capacity, 0);
+ }
+
+ HeapByteBuffer(byte[] backingArray, int capacity, int offset) {
+ super(capacity);
+ this.backingArray = backingArray;
+ this.offset = offset;
+
+ if (offset + capacity > backingArray.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+ /*
+ * Override ByteBuffer.get(byte[], int, int) to improve performance.
+ *
+ * (non-Javadoc)
+ *
+ * @see java.nio.ByteBuffer#get(byte[], int, int)
+ */
+ public final ByteBuffer get(byte[] dest, int off, int len) {
+ int length = dest.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ System.arraycopy(backingArray, offset + position, dest, off, len);
+ position += len;
+ return this;
+ }
+
+ public final byte get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return backingArray[offset + position++];
+ }
+
+ public final byte get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return backingArray[offset + index];
+ }
+
+ public final double getDouble() {
+ return Double.longBitsToDouble(getLong());
+ }
+
+ public final double getDouble(int index) {
+ return Double.longBitsToDouble(getLong(index));
+ }
+
+ public final float getFloat() {
+ return Float.intBitsToFloat(getInt());
+ }
+
+ public final float getFloat(int index) {
+ return Float.intBitsToFloat(getInt(index));
+ }
+
+ public final int getInt() {
+ int newPosition = position + 4;
+ if (newPosition > limit) {
+ throw new BufferUnderflowException();
+ }
+ int result = loadInt(position);
+ position = newPosition;
+ return result;
+ }
+
+ public final int getInt(int index) {
+ if (index < 0 || index + 4 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return loadInt(index);
+ }
+
+ public final long getLong() {
+ int newPosition = position + 8;
+ if (newPosition > limit) {
+ throw new BufferUnderflowException();
+ }
+ long result = loadLong(position);
+ position = newPosition;
+ return result;
+ }
+
+ public final long getLong(int index) {
+ if (index < 0 || index + 8 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return loadLong(index);
+ }
+
+ public final short getShort() {
+ int newPosition = position + 2;
+ if (newPosition > limit) {
+ throw new BufferUnderflowException();
+ }
+ short result = loadShort(position);
+ position = newPosition;
+ return result;
+ }
+
+ public final short getShort(int index) {
+ if (index < 0 || index + 2 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return loadShort(index);
+ }
+
+ public final boolean isDirect() {
+ return false;
+ }
+
+ protected final int loadInt(int index) {
+ int baseOffset = offset + index;
+ int bytes = 0;
+ if(order == Endianness.BIG_ENDIAN){
+ for (int i = 0; i < 4; i++) {
+ bytes = bytes << 8;
+ bytes = bytes | (backingArray[baseOffset + i] & 0xFF);
+ }
+ }else{
+ for (int i = 3; i >= 0; i--) {
+ bytes = bytes << 8;
+ bytes = bytes | (backingArray[baseOffset + i] & 0xFF);
+ }
+ }
+ return bytes;
+ }
+
+ protected final long loadLong(int index) {
+ int baseOffset = offset + index;
+ long bytes = 0;
+ if(order == Endianness.BIG_ENDIAN){
+ for (int i = 0; i < 8; i++) {
+ bytes = bytes << 8;
+ bytes = bytes | (backingArray[baseOffset + i] & 0xFF);
+ }
+ }else{
+ for (int i = 7; i >= 0; i--) {
+ bytes = bytes << 8;
+ bytes = bytes | (backingArray[baseOffset + i] & 0xFF);
+ }
+ }
+ return bytes;
+ }
+
+ protected final short loadShort(int index) {
+ int baseOffset = offset + index;
+ short bytes = 0;
+ if(order == Endianness.BIG_ENDIAN){
+ bytes = (short) (backingArray[baseOffset] << 8);
+ bytes |= (backingArray[baseOffset + 1] & 0xFF);
+ }else{
+ bytes = (short) (backingArray[baseOffset+1] << 8);
+ bytes |= (backingArray[baseOffset] & 0xFF);
+ }
+ return bytes;
+ }
+
+ protected final void store(int index, int value) {
+ int baseOffset = offset + index;
+ if (order == Endianness.BIG_ENDIAN) {
+ for (int i = 3; i >= 0; i--) {
+ backingArray[baseOffset + i] = (byte) (value & 0xFF);
+ value = value >> 8;
+ }
+ } else {
+ for (int i = 0; i <= 3; i++) {
+ backingArray[baseOffset + i] = (byte) (value & 0xFF);
+ value = value >> 8;
+ }
+ }
+ }
+
+ protected final void store(int index, long value) {
+ int baseOffset = offset + index;
+ if (order == Endianness.BIG_ENDIAN) {
+ for (int i = 7; i >= 0; i--) {
+ backingArray[baseOffset + i] = (byte) (value & 0xFF);
+ value = value >> 8;
+ }
+ } else {
+ for (int i = 0; i <= 7; i++) {
+ backingArray[baseOffset + i] = (byte) (value & 0xFF);
+ value = value >> 8;
+ }
+ }
+ }
+
+ protected final void store(int index, short value) {
+ int baseOffset = offset + index;
+ if (order == Endianness.BIG_ENDIAN) {
+ backingArray[baseOffset] = (byte) ((value >> 8) & 0xFF);
+ backingArray[baseOffset + 1] = (byte) (value & 0xFF);
+ } else {
+ backingArray[baseOffset+1] = (byte) ((value >> 8) & 0xFF);
+ backingArray[baseOffset] = (byte) (value & 0xFF);
+ }
+ }
+}
diff --git a/nio/src/main/java/java/nio/IntArrayBuffer.java b/nio/src/main/java/java/nio/IntArrayBuffer.java
new file mode 100644
index 0000000..d77268e
--- /dev/null
+++ b/nio/src/main/java/java/nio/IntArrayBuffer.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * IntArrayBuffer, ReadWriteIntArrayBuffer and ReadOnlyIntArrayBuffer compose
+ * the implementation of array based int buffers.
+ * <p>
+ * IntArrayBuffer implements all the shared readonly methods and is extended by
+ * the other two classes.
+ * </p>
+ * <p>
+ * All methods are marked final for runtime performance.
+ * </p>
+ *
+ */
+abstract class IntArrayBuffer extends IntBuffer {
+
+ protected final int[] backingArray;
+
+ protected final int offset;
+
+ IntArrayBuffer(int[] array) {
+ this(array.length, array, 0);
+ }
+
+ IntArrayBuffer(int capacity) {
+ this(capacity, new int[capacity], 0);
+ }
+
+ IntArrayBuffer(int capacity, int[] backingArray, int offset) {
+ super(capacity);
+ this.backingArray = backingArray;
+ this.offset = offset;
+ }
+
+ public final int get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return backingArray[offset + position++];
+ }
+
+ public final int get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return backingArray[offset + index];
+ }
+
+ public final IntBuffer get(int[] dest, int off, int len) {
+ int length = dest.length;
+ if (off < 0 || len < 0 || (long)len + (long)off > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ System.arraycopy(backingArray, offset+position, dest, off, len);
+ position += len;
+ return this;
+ }
+
+ public final boolean isDirect() {
+ return false;
+ }
+
+ public final ByteOrder order() {
+ return ByteOrder.nativeOrder();
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/IntBuffer.java b/nio/src/main/java/java/nio/IntBuffer.java
new file mode 100644
index 0000000..ba7ac18
--- /dev/null
+++ b/nio/src/main/java/java/nio/IntBuffer.java
@@ -0,0 +1,579 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * A buffer of <code>int</code>s.
+ * <p>
+ * A int buffer can be created in either of the following ways:
+ * <ul>
+ * <li>{@link #allocate(int) Allocate} a new int array and create a buffer
+ * based on it;</li>
+ * <li>{@link #wrap(int[]) Wrap} an existing int array to create a new buffer;</li>
+ * <li>Use {@link java.nio.ByteBuffer#asIntBuffer() ByteBuffer.asIntBuffer} to
+ * create a int buffer based on a byte buffer.</li>
+ * </ul>
+ * </p>
+ */
+public abstract class IntBuffer extends Buffer implements Comparable<IntBuffer> {
+
+ /**
+ * Creates a int buffer based on a new allocated int array.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return The created int buffer
+ * @throws IllegalArgumentException
+ * If <code>capacity</code> is less than zero
+ */
+ public static IntBuffer allocate(int capacity) {
+ if (capacity < 0) {
+ throw new IllegalArgumentException();
+ }
+ return BufferFactory.newIntBuffer(capacity);
+ }
+
+ /**
+ * Creates a new int buffer by wrapping the given int array.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>wrap(array, 0, array.length)</code>.
+ * </p>
+ *
+ * @param array
+ * The int array which the new buffer will be based on
+ * @return The created int buffer
+ */
+ public static IntBuffer wrap(int[] array) {
+ return wrap(array, 0, array.length);
+ }
+
+ /**
+ * Creates new a int buffer by wrapping the given int array.
+ * <p>
+ * The new buffer's position will be <code>start</code>, limit will be
+ * <code>start + len</code>, capacity will be the length of the array.
+ * </p>
+ *
+ * @param array
+ * The int array which the new buffer will be based on
+ * @param start
+ * The start index, must be no less than zero and no greater than
+ * <code>array.length</code>
+ * @param len
+ * The length, must be no less than zero and no greater than
+ * <code>array.length - start</code>
+ * @return The created int buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>start</code> or <code>len</code> is
+ * invalid
+ */
+ public static IntBuffer wrap(int[] array, int start, int len) {
+ if (array == null) {
+ throw new NullPointerException();
+ }
+ if (start < 0 || len < 0 || (long)len + (long)start > array.length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ IntBuffer buf = BufferFactory.newIntBuffer(array);
+ buf.position = start;
+ buf.limit = start + len;
+
+ return buf;
+ }
+
+ /**
+ * Constructs a <code>IntBuffer</code> with given capacity.
+ *
+ * @param capacity
+ * The capacity of the buffer
+ */
+ IntBuffer(int capacity) {
+ super(capacity);
+ // BEGIN android-added
+ _elementSizeShift = 2;
+ // END android-added
+ }
+
+ /**
+ * Returns the int array which this buffer is based on, if there's one.
+ *
+ * @return The int array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on an array, but it is readonly
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final int[] array() {
+ return protectedArray();
+ }
+
+ /**
+ * Returns the offset of the int array which this buffer is based on, if
+ * there's one.
+ * <p>
+ * The offset is the index of the array corresponds to the zero position of
+ * the buffer.
+ * </p>
+ *
+ * @return The offset of the int array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on an array, but it is readonly
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final int arrayOffset() {
+ return protectedArrayOffset();
+ }
+
+ // BEGIN android-added
+ @Override Object _array() {
+ if (hasArray()) {
+ return array();
+ }
+ return null;
+ }
+
+ @Override int _arrayOffset() {
+ if (hasArray()) {
+ return arrayOffset();
+ }
+ return 0;
+ }
+ // END android-added
+
+ /**
+ * Returns a readonly buffer that shares content with this buffer.
+ * <p>
+ * The returned buffer is guaranteed to be a new instance, even this buffer
+ * is readonly itself. The new buffer's position, limit, capacity and mark
+ * are the same as this buffer.
+ * </p>
+ * <p>
+ * The new buffer shares content with this buffer, which means this buffer's
+ * change of content will be visible to the new buffer. The two buffer's
+ * position, limit and mark are independent.
+ * </p>
+ *
+ * @return A readonly version of this buffer.
+ */
+ public abstract IntBuffer asReadOnlyBuffer();
+
+ /**
+ * Compacts this int buffer.
+ * <p>
+ * The remaining <code>int</code>s will be moved to the head of the
+ * buffer, staring from position zero. Then the position is set to
+ * <code>remaining()</code>; the limit is set to capacity; the mark is
+ * cleared.
+ * </p>
+ *
+ * @return This buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract IntBuffer compact();
+
+ /**
+ * Compare the remaining <code>int</code>s of this buffer to another int
+ * buffer's remaining <code>int</code>s.
+ *
+ * @param otherBuffer
+ * Another int buffer
+ * @return a negative value if this is less than <code>other</code>; 0 if
+ * this equals to <code>other</code>; a positive value if this is
+ * greater than <code>other</code>
+ * @exception ClassCastException
+ * If <code>other</code> is not a int buffer
+ */
+ public int compareTo(IntBuffer otherBuffer) {
+ int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
+ : otherBuffer.remaining();
+ int thisPos = position;
+ int otherPos = otherBuffer.position;
+ int thisByte, otherByte;
+ while (compareRemaining > 0) {
+ thisByte = get(thisPos);
+ otherByte = otherBuffer.get(otherPos);
+ if (thisByte != otherByte) {
+ return thisByte < otherByte ? -1 : 1;
+ }
+ thisPos++;
+ otherPos++;
+ compareRemaining--;
+ }
+ return remaining() - otherBuffer.remaining();
+ }
+
+ /**
+ * Returns a duplicated buffer that shares content with this buffer.
+ * <p>
+ * The duplicated buffer's position, limit, capacity and mark are the same
+ * as this buffer. The duplicated buffer's readonly property and byte order
+ * are same as this buffer too.
+ * </p>
+ * <p>
+ * The new buffer shares content with this buffer, which means either
+ * buffer's change of content will be visible to the other. The two buffer's
+ * position, limit and mark are independent.
+ * </p>
+ *
+ * @return A duplicated buffer that shares content with this buffer.
+ */
+ public abstract IntBuffer duplicate();
+
+ /**
+ * Tests whether this int buffer equals to another object.
+ * <p>
+ * If <code>other</code> is not a int buffer, then false is returned.
+ * </p>
+ * <p>
+ * Two int buffers are equals if, and only if, their remaining
+ * <code>int</code>s are exactly the same. Position, limit, capacity and
+ * mark are not considered.
+ * </p>
+ *
+ * @param other
+ * the object to be compared against
+ * @return Whether this int buffer equals to another object.
+ */
+ public boolean equals(Object other) {
+ if (!(other instanceof IntBuffer)) {
+ return false;
+ }
+ IntBuffer otherBuffer = (IntBuffer) other;
+
+ if (remaining() != otherBuffer.remaining()) {
+ return false;
+ }
+
+ int myPosition = position;
+ int otherPosition = otherBuffer.position;
+ boolean equalSoFar = true;
+ while (equalSoFar && (myPosition < limit)) {
+ equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++);
+ }
+
+ return equalSoFar;
+ }
+
+ /**
+ * Returns the int at the current position and increase the position by 1.
+ *
+ * @return The int at the current position.
+ * @exception BufferUnderflowException
+ * If the position is equal or greater than limit
+ */
+ public abstract int get();
+
+ /**
+ * Reads <code>int</code>s from the current position into the specified
+ * int array and increase the position by the number of <code>int</code>s
+ * read.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>get(dest, 0, dest.length)</code>.
+ * </p>
+ *
+ * @param dest
+ * The destination int array
+ * @return This buffer
+ * @exception BufferUnderflowException
+ * if <code>dest.length</code> is greater than
+ * <code>remaining()</code>
+ */
+ public IntBuffer get(int[] dest) {
+ return get(dest, 0, dest.length);
+ }
+
+ /**
+ * Reads <code>int</code>s from the current position into the specified
+ * int array, starting from the specified offset, and increase the position
+ * by the number of <code>int</code>s read.
+ *
+ * @param dest
+ * The target int array
+ * @param off
+ * The offset of the int array, must be no less than zero and no
+ * greater than <code>dest.length</code>
+ * @param len
+ * The number of <code>int</code>s to read, must be no less
+ * than zero and no greater than <code>dest.length - off</code>
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception BufferUnderflowException
+ * If <code>len</code> is greater than
+ * <code>remaining()</code>
+ */
+ public IntBuffer get(int[] dest, int off, int len) {
+ int length = dest.length;
+ if (off < 0 || len < 0 || (long)len + (long)off > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ dest[i] = get();
+ }
+ return this;
+ }
+
+ /**
+ * Returns a int at the specified index, and the position is not changed.
+ *
+ * @param index
+ * The index, must be no less than zero and less than limit
+ * @return A int at the specified index.
+ * @exception IndexOutOfBoundsException
+ * If index is invalid
+ */
+ public abstract int get(int index);
+
+ /**
+ * Returns whether this buffer is based on a int array and is read/write.
+ * <p>
+ * If this buffer is readonly, then false is returned.
+ * </p>
+ *
+ * @return Whether this buffer is based on a int array and is read/write.
+ */
+ public final boolean hasArray() {
+ return protectedHasArray();
+ }
+
+ /**
+ * Hash code is calculated from the remaining <code>int</code>s.
+ * <p>
+ * Position, limit, capacity and mark don't affect the hash code.
+ * </p>
+ *
+ * @return The hash code calculated from the remaining <code>int</code>s.
+ */
+ public int hashCode() {
+ int myPosition = position;
+ int hash = 0;
+ while (myPosition < limit) {
+ hash = hash + get(myPosition++);
+ }
+ return hash;
+ }
+
+ /**
+ * Returns true if this buffer is direct.
+ * <p>
+ * A int buffer is direct, if it is based on a byte buffer and the byte
+ * buffer is direct.
+ * </p>
+ *
+ * @return True if this buffer is direct.
+ */
+ public abstract boolean isDirect();
+
+ /**
+ * Returns the byte order used by this buffer when converting
+ * <code>int</code>s from/to <code>byte</code>s.
+ * <p>
+ * If this buffer is not based on a byte buffer, then always return the
+ * platform's native byte order.
+ * </p>
+ *
+ * @return The byte order used by this buffer when converting
+ * <code>int</code>s from/to <code>byte</code>s.
+ */
+ public abstract ByteOrder order();
+
+ /**
+ * Child class implements this method to realize <code>array()</code>.
+ *
+ * @return see <code>array()</code>
+ */
+ abstract int[] protectedArray();
+
+ /**
+ * Child class implements this method to realize <code>arrayOffset()</code>.
+ *
+ * @return see <code>arrayOffset()</code>
+ */
+ abstract int protectedArrayOffset();
+
+ /**
+ * Child class implements this method to realize <code>hasArray()</code>.
+ *
+ * @return see <code>hasArray()</code>
+ */
+ abstract boolean protectedHasArray();
+
+ /**
+ * Writes the given int to the current position and increase the position by
+ * 1.
+ *
+ * @param i
+ * The int to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If position is equal or greater than limit
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract IntBuffer put(int i);
+
+ /**
+ * Writes <code>int</code>s in the given int array to the current
+ * position and increase the position by the number of <code>int</code>s
+ * written.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>put(src, 0, src.length)</code>.
+ * </p>
+ *
+ * @param src
+ * The source int array
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>src.length</code>
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public final IntBuffer put(int[] src) {
+ return put(src, 0, src.length);
+ }
+
+ /**
+ * Writes <code>int</code>s in the given int array, starting from the
+ * specified offset, to the current position and increase the position by
+ * the number of <code>int</code>s written.
+ *
+ * @param src
+ * The source int array
+ * @param off
+ * The offset of int array, must be no less than zero and no
+ * greater than <code>src.length</code>
+ * @param len
+ * The number of <code>int</code>s to write, must be no less
+ * than zero and no greater than <code>src.length - off</code>
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>len</code>
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public IntBuffer put(int[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)len + (long)off > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ put(src[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Writes all the remaining <code>int</code>s of the <code>src</code>
+ * int buffer to this buffer's current position, and increase both buffers'
+ * position by the number of <code>int</code>s copied.
+ *
+ * @param src
+ * The source int buffer
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>src.remaining()</code> is greater than this
+ * buffer's <code>remaining()</code>
+ * @exception IllegalArgumentException
+ * If <code>src</code> is this buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public IntBuffer put(IntBuffer src) {
+ if (src == this) {
+ throw new IllegalArgumentException();
+ }
+ if (src.remaining() > remaining()) {
+ throw new BufferOverflowException();
+ }
+ int[] contents = new int[src.remaining()];
+ src.get(contents);
+ put(contents);
+ return this;
+ }
+
+ /**
+ * Write a int to the specified index of this buffer and the position is not
+ * changed.
+ *
+ * @param index
+ * The index, must be no less than zero and less than the limit
+ * @param i
+ * The int to write
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If index is invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract IntBuffer put(int index, int i);
+
+ /**
+ * Returns a sliced buffer that shares content with this buffer.
+ * <p>
+ * The sliced buffer's capacity will be this buffer's
+ * <code>remaining()</code>, and its zero position will correspond to
+ * this buffer's current position. The new buffer's position will be 0,
+ * limit will be its capacity, and its mark is unset. The new buffer's
+ * readonly property and byte order are same as this buffer.
+ * </p>
+ * <p>
+ * The new buffer shares content with this buffer, which means either
+ * buffer's change of content will be visible to the other. The two buffer's
+ * position, limit and mark are independent.
+ * </p>
+ *
+ * @return A sliced buffer that shares content with this buffer.
+ */
+ public abstract IntBuffer slice();
+
+ /**
+ * Returns a string represents the state of this int buffer.
+ *
+ * @return A string represents the state of this int buffer.
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append(getClass().getName());
+ buf.append(", status: capacity="); //$NON-NLS-1$
+ buf.append(capacity());
+ buf.append(" position="); //$NON-NLS-1$
+ buf.append(position());
+ buf.append(" limit="); //$NON-NLS-1$
+ buf.append(limit());
+ return buf.toString();
+ }
+}
diff --git a/nio/src/main/java/java/nio/IntToByteBufferAdapter.java b/nio/src/main/java/java/nio/IntToByteBufferAdapter.java
new file mode 100644
index 0000000..b5e1118
--- /dev/null
+++ b/nio/src/main/java/java/nio/IntToByteBufferAdapter.java
@@ -0,0 +1,216 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+// BEGIN android-added
+// copied from newer version of harmony
+import org.apache.harmony.nio.internal.DirectBuffer;
+import org.apache.harmony.luni.platform.PlatformAddress;
+// END android-added
+
+/**
+ * This class wraps a byte buffer to be a int buffer.
+ * <p>
+ * Implementation notice:
+ * <ul>
+ * <li>After a byte buffer instance is wrapped, it becomes privately owned by
+ * the adapter. It must NOT be accessed outside the adapter any more.</li>
+ * <li>The byte buffer's position and limit are NOT linked with the adapter.
+ * The adapter extends Buffer, thus has its own position and limit.</li>
+ * </ul>
+ * </p>
+ *
+ */
+// BEGIN android-changed
+// copied from newer version of harmony
+final class IntToByteBufferAdapter extends IntBuffer implements DirectBuffer {
+// END android-changed
+
+ static IntBuffer wrap(ByteBuffer byteBuffer) {
+ return new IntToByteBufferAdapter(byteBuffer.slice());
+ }
+
+ private final ByteBuffer byteBuffer;
+
+ IntToByteBufferAdapter(ByteBuffer byteBuffer) {
+ super((byteBuffer.capacity() >> 2));
+ this.byteBuffer = byteBuffer;
+ this.byteBuffer.clear();
+ }
+
+ // BEGIN android-added
+ // copied from newer version of harmony
+ public int getByteCapacity() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getByteCapacity();
+ } else {
+ assert false : byteBuffer;
+ return -1;
+ }
+ }
+
+ public PlatformAddress getEffectiveAddress() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getEffectiveAddress();
+ } else {
+ assert false : byteBuffer;
+ return null;
+ }
+ }
+
+ public PlatformAddress getBaseAddress() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getBaseAddress();
+ } else {
+ assert false : byteBuffer;
+ return null;
+ }
+ }
+
+ public boolean isAddressValid() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).isAddressValid();
+ } else {
+ assert false : byteBuffer;
+ return false;
+ }
+ }
+
+ public void addressValidityCheck() {
+ if (byteBuffer instanceof DirectBuffer) {
+ ((DirectBuffer)byteBuffer).addressValidityCheck();
+ } else {
+ assert false : byteBuffer;
+ }
+ }
+
+ public void free() {
+ if (byteBuffer instanceof DirectBuffer) {
+ ((DirectBuffer)byteBuffer).free();
+ } else {
+ assert false : byteBuffer;
+ }
+ }
+ // END android-added
+
+ public IntBuffer asReadOnlyBuffer() {
+ IntToByteBufferAdapter buf = new IntToByteBufferAdapter(byteBuffer
+ .asReadOnlyBuffer());
+ buf.limit = limit;
+ buf.position = position;
+ buf.mark = mark;
+ return buf;
+ }
+
+ public IntBuffer compact() {
+ if (byteBuffer.isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+ byteBuffer.limit(limit << 2);
+ byteBuffer.position(position << 2);
+ byteBuffer.compact();
+ byteBuffer.clear();
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public IntBuffer duplicate() {
+ IntToByteBufferAdapter buf = new IntToByteBufferAdapter(byteBuffer
+ .duplicate());
+ buf.limit = limit;
+ buf.position = position;
+ buf.mark = mark;
+ return buf;
+ }
+
+ public int get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return byteBuffer.getInt(position++ << 2);
+ }
+
+ public int get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return byteBuffer.getInt(index << 2);
+ }
+
+ public boolean isDirect() {
+ return byteBuffer.isDirect();
+ }
+
+ public boolean isReadOnly() {
+ return byteBuffer.isReadOnly();
+ }
+
+ public ByteOrder order() {
+ return byteBuffer.order();
+ }
+
+ protected int[] protectedArray() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public IntBuffer put(int c) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ byteBuffer.putInt(position++ << 2, c);
+ return this;
+ }
+
+ public IntBuffer put(int index, int c) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ byteBuffer.putInt(index << 2, c);
+ return this;
+ }
+
+ // BEGIN android-added
+ public IntBuffer put(int[] i, int off, int len) {
+ if (byteBuffer instanceof ReadWriteDirectByteBuffer) {
+ ((ReadWriteDirectByteBuffer) byteBuffer).put(i, off, len);
+ this.position += len;
+ return this;
+ } else {
+ return super.put(i, off, len);
+ }
+ }
+ // END android-added
+
+ public IntBuffer slice() {
+ byteBuffer.limit(limit << 2);
+ byteBuffer.position(position << 2);
+ IntBuffer result = new IntToByteBufferAdapter(byteBuffer.slice());
+ byteBuffer.clear();
+ return result;
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/InvalidMarkException.java b/nio/src/main/java/java/nio/InvalidMarkException.java
new file mode 100644
index 0000000..1860576
--- /dev/null
+++ b/nio/src/main/java/java/nio/InvalidMarkException.java
@@ -0,0 +1,35 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+
+/**
+ * A <code>InvalidMarkException</code> is thrown when <code>reset()</code>
+ * is called on a buffer, but there is no mark set previously.
+ *
+ */
+public class InvalidMarkException extends IllegalStateException {
+
+ private static final long serialVersionUID = 1698329710438510774L;
+
+ /**
+ * Constructs an <code>InvalidMarkException</code>.
+ */
+ public InvalidMarkException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/LongArrayBuffer.java b/nio/src/main/java/java/nio/LongArrayBuffer.java
new file mode 100644
index 0000000..efd259c
--- /dev/null
+++ b/nio/src/main/java/java/nio/LongArrayBuffer.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * LongArrayBuffer, ReadWriteLongArrayBuffer and ReadOnlyLongArrayBuffer compose
+ * the implementation of array based long buffers.
+ * <p>
+ * LongArrayBuffer implements all the shared readonly methods and is extended by
+ * the other two classes.
+ * </p>
+ * <p>
+ * All methods are marked final for runtime performance.
+ * </p>
+ *
+ */
+abstract class LongArrayBuffer extends LongBuffer {
+
+ protected final long[] backingArray;
+
+ protected final int offset;
+
+ LongArrayBuffer(long[] array) {
+ this(array.length, array, 0);
+ }
+
+ LongArrayBuffer(int capacity) {
+ this(capacity, new long[capacity], 0);
+ }
+
+ LongArrayBuffer(int capacity, long[] backingArray, int offset) {
+ super(capacity);
+ this.backingArray = backingArray;
+ this.offset = offset;
+ }
+
+ public final long get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return backingArray[offset + position++];
+ }
+
+ public final long get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return backingArray[offset + index];
+ }
+
+ public final LongBuffer get(long[] dest, int off, int len) {
+ int length = dest.length;
+ if (off < 0 || len < 0 || (long)len + (long)off > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ System.arraycopy(backingArray, offset+position, dest, off, len);
+ position += len;
+ return this;
+ }
+
+ public final boolean isDirect() {
+ return false;
+ }
+
+ public final ByteOrder order() {
+ return ByteOrder.nativeOrder();
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/LongBuffer.java b/nio/src/main/java/java/nio/LongBuffer.java
new file mode 100644
index 0000000..a44f56a
--- /dev/null
+++ b/nio/src/main/java/java/nio/LongBuffer.java
@@ -0,0 +1,587 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * A buffer of <code>long</code>s.
+ * <p>
+ * A long buffer can be created in either of the following ways:
+ * <ul>
+ * <li>{@link #allocate(int) Allocate} a new long array and create a buffer
+ * based on it;</li>
+ * <li>{@link #wrap(long[]) Wrap} an existing long array to create a new
+ * buffer;</li>
+ * <li>Use {@link java.nio.ByteBuffer#asLongBuffer() ByteBuffer.asLongBuffer}
+ * to create a long buffer based on a byte buffer.</li>
+ * </ul>
+ * </p>
+ */
+public abstract class LongBuffer extends Buffer implements Comparable<LongBuffer> {
+
+ /**
+ * Creates a long buffer based on a new allocated long array.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return The created long buffer
+ * @throws IllegalArgumentException
+ * If <code>capacity</code> is less than zero
+ */
+ public static LongBuffer allocate(int capacity) {
+ if (capacity < 0) {
+ throw new IllegalArgumentException();
+ }
+ return BufferFactory.newLongBuffer(capacity);
+ }
+
+ /**
+ * Creates a new long buffer by wrapping the given long array.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>wrap(array, 0, array.length)</code>.
+ * </p>
+ *
+ * @param array
+ * The long array which the new buffer will be based on
+ * @return The created long buffer
+ */
+ public static LongBuffer wrap(long[] array) {
+ return wrap(array, 0, array.length);
+ }
+
+ /**
+ * Creates new a long buffer by wrapping the given long array.
+ * <p>
+ * The new buffer's position will be <code>start</code>, limit will be
+ * <code>start + len</code>, capacity will be the length of the array.
+ * </p>
+ *
+ * @param array
+ * The long array which the new buffer will be based on
+ * @param start
+ * The start index, must be no less than zero and no greater than
+ * <code>array.length</code>
+ * @param len
+ * The length, must be no less than zero and no greater than
+ * <code>array.length - start</code>
+ * @return The created long buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>start</code> or <code>len</code> is
+ * invalid
+ */
+ public static LongBuffer wrap(long[] array, int start, int len) {
+ if (array == null) {
+ throw new NullPointerException();
+ }
+ if (start < 0 || len < 0 || (long)len + (long)start > array.length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ LongBuffer buf = BufferFactory.newLongBuffer(array);
+ buf.position = start;
+ buf.limit = start + len;
+
+ return buf;
+ }
+
+ /**
+ * Constructs a <code>LongBuffer</code> with given capacity.
+ *
+ * @param capacity
+ * The capacity of the buffer
+ */
+ LongBuffer(int capacity) {
+ super(capacity);
+ // BEGIN android-added
+ _elementSizeShift = 3;
+ // END android-added
+ }
+
+ /**
+ * Returns the long array which this buffer is based on, if there's one.
+ *
+ * @return The long array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on an array, but it is readonly
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final long[] array() {
+ return protectedArray();
+ }
+
+ /**
+ * Returns the offset of the long array which this buffer is based on, if
+ * there's one.
+ * <p>
+ * The offset is the index of the array corresponds to the zero position of
+ * the buffer.
+ * </p>
+ *
+ * @return The offset of the long array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on an array, but it is readonly
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final int arrayOffset() {
+ return protectedArrayOffset();
+ }
+
+ // BEGIN android-added
+ @Override Object _array() {
+ if (hasArray()) {
+ return array();
+ }
+ return null;
+ }
+
+ @Override int _arrayOffset() {
+ if (hasArray()) {
+ return arrayOffset();
+ }
+ return 0;
+ }
+ // END android-added
+
+ /**
+ * Returns a readonly buffer that shares content with this buffer.
+ * <p>
+ * The returned buffer is guaranteed to be a new instance, even this buffer
+ * is readonly itself. The new buffer's position, limit, capacity and mark
+ * are the same as this buffer.
+ * </p>
+ * <p>
+ * The new buffer shares content with this buffer, which means this buffer's
+ * change of content will be visible to the new buffer. The two buffer's
+ * position, limit and mark are independent.
+ * </p>
+ *
+ * @return A readonly version of this buffer.
+ */
+ public abstract LongBuffer asReadOnlyBuffer();
+
+ /**
+ * Compacts this long buffer.
+ * <p>
+ * The remaining <code>long</code>s will be moved to the head of the
+ * buffer, staring from position zero. Then the position is set to
+ * <code>remaining()</code>; the limit is set to capacity; the mark is
+ * cleared.
+ * </p>
+ *
+ * @return This buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract LongBuffer compact();
+
+ /**
+ * Compare the remaining <code>long</code>s of this buffer to another
+ * long buffer's remaining <code>long</code>s.
+ *
+ * @param otherBuffer
+ * Another long buffer
+ * @return a negative value if this is less than <code>other</code>; 0 if
+ * this equals to <code>other</code>; a positive value if this is
+ * greater than <code>other</code>
+ * @exception ClassCastException
+ * If <code>other</code> is not a long buffer
+ */
+ public int compareTo(LongBuffer otherBuffer) {
+ int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
+ : otherBuffer.remaining();
+ int thisPos = position;
+ int otherPos = otherBuffer.position;
+ long thisByte, otherByte;
+ while (compareRemaining > 0) {
+ thisByte = get(thisPos);
+ otherByte = otherBuffer.get(otherPos);
+ if (thisByte != otherByte) {
+ return thisByte < otherByte ? -1 : 1;
+ }
+ thisPos++;
+ otherPos++;
+ compareRemaining--;
+ }
+ return remaining() - otherBuffer.remaining();
+ }
+
+ /**
+ * Returns a duplicated buffer that shares content with this buffer.
+ * <p>
+ * The duplicated buffer's position, limit, capacity and mark are the same
+ * as this buffer. The duplicated buffer's readonly property and byte order
+ * are same as this buffer too.
+ * </p>
+ * <p>
+ * The new buffer shares content with this buffer, which means either
+ * buffer's change of content will be visible to the other. The two buffer's
+ * position, limit and mark are independent.
+ * </p>
+ *
+ * @return A duplicated buffer that shares content with this buffer.
+ */
+ public abstract LongBuffer duplicate();
+
+ /**
+ * Tests whether this long buffer equals to another object.
+ * <p>
+ * If <code>other</code> is not a long buffer, then false is returned.
+ * </p>
+ * <p>
+ * Two long buffers are equals if, and only if, their remaining
+ * <code>long</code>s are exactly the same. Position, limit, capacity and
+ * mark are not considered.
+ * </p>
+ *
+ * @param other
+ * the object to be compared against
+ * @return Whether this long buffer equals to another object.
+ */
+ public boolean equals(Object other) {
+ if (!(other instanceof LongBuffer)) {
+ return false;
+ }
+ LongBuffer otherBuffer = (LongBuffer) other;
+
+ if (remaining() != otherBuffer.remaining()) {
+ return false;
+ }
+
+ int myPosition = position;
+ int otherPosition = otherBuffer.position;
+ boolean equalSoFar = true;
+ while (equalSoFar && (myPosition < limit)) {
+ equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++);
+ }
+
+ return equalSoFar;
+ }
+
+ /**
+ * Returns the long at the current position and increase the position by 1.
+ *
+ * @return The long at the current position.
+ * @exception BufferUnderflowException
+ * If the position is equal or greater than limit
+ */
+ public abstract long get();
+
+ /**
+ * Reads <code>long</code>s from the current position into the specified
+ * long array and increase the position by the number of <code>long</code>s
+ * read.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>get(dest, 0, dest.length)</code>.
+ * </p>
+ *
+ * @param dest
+ * The destination long array
+ * @return This buffer
+ * @exception BufferUnderflowException
+ * if <code>dest.length</code> is greater than
+ * <code>remaining()</code>
+ */
+ public LongBuffer get(long[] dest) {
+ return get(dest, 0, dest.length);
+ }
+
+ /**
+ * Reads <code>long</code>s from the current position into the specified
+ * long array, starting from the specified offset, and increase the position
+ * by the number of <code>long</code>s read.
+ *
+ * @param dest
+ * The target long array
+ * @param off
+ * The offset of the long array, must be no less than zero and no
+ * greater than <code>dest.length</code>
+ * @param len
+ * The number of <code>long</code>s to read, must be no less
+ * than zero and no greater than <code>dest.length - off</code>
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception BufferUnderflowException
+ * If <code>len</code> is greater than
+ * <code>remaining()</code>
+ */
+ public LongBuffer get(long[] dest, int off, int len) {
+ int length = dest.length;
+ if (off < 0 || len < 0 || (long)len + (long)off > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ dest[i] = get();
+ }
+ return this;
+ }
+
+ /**
+ * Returns a long at the specified index, and the position is not changed.
+ *
+ * @param index
+ * The index, must be no less than zero and less than limit
+ * @return A long at the specified index.
+ * @exception IndexOutOfBoundsException
+ * If index is invalid
+ */
+ public abstract long get(int index);
+
+ /**
+ * Returns whether this buffer is based on a long array and is read/write.
+ * <p>
+ * If this buffer is readonly, then false is returned.
+ * </p>
+ *
+ * @return Whether this buffer is based on a long array and is read/write.
+ */
+ public final boolean hasArray() {
+ return protectedHasArray();
+ }
+
+ /**
+ * Hash code is calculated from the remaining <code>long</code>s.
+ * <p>
+ * Position, limit, capacity and mark don't affect the hash code.
+ * </p>
+ *
+ * @return The hash code calculated from the remaining <code>long</code>s.
+ */
+ public int hashCode() {
+ int myPosition = position;
+ int hash = 0;
+ long l;
+ while (myPosition < limit) {
+ l = get(myPosition++);
+ hash = hash + ((int) l) ^ ((int) (l >> 32));
+ }
+ return hash;
+ }
+
+ /**
+ * Returns true if this buffer is direct.
+ * <p>
+ * A direct buffer will try its best to take advantage of native memory APIs
+ * and it may not stay in java heap, thus not affected by GC.
+ * </p>
+ * <p>
+ * A long buffer is direct, if it is based on a byte buffer and the byte
+ * buffer is direct.
+ * </p>
+ *
+ * @return True if this buffer is direct.
+ */
+ public abstract boolean isDirect();
+
+ /**
+ * Returns the byte order used by this buffer when converting
+ * <code>long</code>s from/to <code>byte</code>s.
+ * <p>
+ * If this buffer is not based on a byte buffer, then always return the
+ * platform's native byte order.
+ * </p>
+ *
+ * @return The byte order used by this buffer when converting
+ * <code>long</code>s from/to <code>byte</code>s.
+ */
+ public abstract ByteOrder order();
+
+ /**
+ * Child class implements this method to realize <code>array()</code>.
+ *
+ * @return see <code>array()</code>
+ */
+ abstract long[] protectedArray();
+
+ /**
+ * Child class implements this method to realize <code>arrayOffset()</code>.
+ *
+ * @return see <code>arrayOffset()</code>
+ */
+ abstract int protectedArrayOffset();
+
+ /**
+ * Child class implements this method to realize <code>hasArray()</code>.
+ *
+ * @return see <code>hasArray()</code>
+ */
+ abstract boolean protectedHasArray();
+
+ /**
+ * Writes the given long to the current position and increase the position
+ * by 1.
+ *
+ * @param l
+ * The long to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If position is equal or greater than limit
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract LongBuffer put(long l);
+
+ /**
+ * Writes <code>long</code>s in the given long array to the current
+ * position and increase the position by the number of <code>long</code>s
+ * written.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>put(src, 0, src.length)</code>.
+ * </p>
+ *
+ * @param src
+ * The source long array
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>src.length</code>
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public final LongBuffer put(long[] src) {
+ return put(src, 0, src.length);
+ }
+
+ /**
+ * Writes <code>long</code>s in the given long array, starting from the
+ * specified offset, to the current position and increase the position by
+ * the number of <code>long</code>s written.
+ *
+ * @param src
+ * The source long array
+ * @param off
+ * The offset of long array, must be no less than zero and no
+ * greater than <code>src.length</code>
+ * @param len
+ * The number of <code>long</code>s to write, must be no less
+ * than zero and no greater than <code>src.length - off</code>
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>len</code>
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public LongBuffer put(long[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)len + (long)off > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ put(src[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Writes all the remaining <code>long</code>s of the <code>src</code>
+ * long buffer to this buffer's current position, and increase both buffers'
+ * position by the number of <code>long</code>s copied.
+ *
+ * @param src
+ * The source long buffer
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>src.remaining()</code> is greater than this
+ * buffer's <code>remaining()</code>
+ * @exception IllegalArgumentException
+ * If <code>src</code> is this buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public LongBuffer put(LongBuffer src) {
+ if (src == this) {
+ throw new IllegalArgumentException();
+ }
+ if (src.remaining() > remaining()) {
+ throw new BufferOverflowException();
+ }
+ long[] contents = new long[src.remaining()];
+ src.get(contents);
+ put(contents);
+ return this;
+ }
+
+ /**
+ * Write a long to the specified index of this buffer and the position is
+ * not changed.
+ *
+ * @param index
+ * The index, must be no less than zero and less than the limit
+ * @param l
+ * The long to write
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If index is invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract LongBuffer put(int index, long l);
+
+ /**
+ * Returns a sliced buffer that shares content with this buffer.
+ * <p>
+ * The sliced buffer's capacity will be this buffer's
+ * <code>remaining()</code>, and its zero position will correspond to
+ * this buffer's current position. The new buffer's position will be 0,
+ * limit will be its capacity, and its mark is unset. The new buffer's
+ * readonly property and byte order are same as this buffer.
+ * </p>
+ * <p>
+ * The new buffer shares content with this buffer, which means either
+ * buffer's change of content will be visible to the other. The two buffer's
+ * position, limit and mark are independent.
+ * </p>
+ *
+ * @return A sliced buffer that shares content with this buffer.
+ */
+ public abstract LongBuffer slice();
+
+ /**
+ * Returns a string represents the state of this long buffer.
+ *
+ * @return A string represents the state of this long buffer.
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append(getClass().getName());
+ buf.append(", status: capacity="); //$NON-NLS-1$
+ buf.append(capacity());
+ buf.append(" position="); //$NON-NLS-1$
+ buf.append(position());
+ buf.append(" limit="); //$NON-NLS-1$
+ buf.append(limit());
+ return buf.toString();
+ }
+}
diff --git a/nio/src/main/java/java/nio/LongToByteBufferAdapter.java b/nio/src/main/java/java/nio/LongToByteBufferAdapter.java
new file mode 100644
index 0000000..0bd3ce4
--- /dev/null
+++ b/nio/src/main/java/java/nio/LongToByteBufferAdapter.java
@@ -0,0 +1,204 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+// BEGIN android-added
+// copied from newer version of harmony
+import org.apache.harmony.nio.internal.DirectBuffer;
+import org.apache.harmony.luni.platform.PlatformAddress;
+// END android-added
+
+/**
+ * This class wraps a byte buffer to be a long buffer.
+ * <p>
+ * Implementation notice:
+ * <ul>
+ * <li>After a byte buffer instance is wrapped, it becomes privately owned by
+ * the adapter. It must NOT be accessed outside the adapter any more.</li>
+ * <li>The byte buffer's position and limit are NOT linked with the adapter.
+ * The adapter extends Buffer, thus has its own position and limit.</li>
+ * </ul>
+ * </p>
+ *
+ */
+// BEGIN android-changed
+// copied from newer version of harmony
+final class LongToByteBufferAdapter extends LongBuffer implements DirectBuffer {
+// END android-changed
+
+ static LongBuffer wrap(ByteBuffer byteBuffer) {
+ return new LongToByteBufferAdapter(byteBuffer.slice());
+ }
+
+ private final ByteBuffer byteBuffer;
+
+ LongToByteBufferAdapter(ByteBuffer byteBuffer) {
+ super((byteBuffer.capacity() >> 3));
+ this.byteBuffer = byteBuffer;
+ this.byteBuffer.clear();
+ }
+
+ // BEGIN android-added
+ // copied from newer version of harmony
+ public int getByteCapacity() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getByteCapacity();
+ } else {
+ assert false : byteBuffer;
+ return -1;
+ }
+ }
+
+ public PlatformAddress getEffectiveAddress() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getEffectiveAddress();
+ } else {
+ assert false : byteBuffer;
+ return null;
+ }
+ }
+
+ public PlatformAddress getBaseAddress() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getBaseAddress();
+ } else {
+ assert false : byteBuffer;
+ return null;
+ }
+ }
+
+ public boolean isAddressValid() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).isAddressValid();
+ } else {
+ assert false : byteBuffer;
+ return false;
+ }
+ }
+
+ public void addressValidityCheck() {
+ if (byteBuffer instanceof DirectBuffer) {
+ ((DirectBuffer)byteBuffer).addressValidityCheck();
+ } else {
+ assert false : byteBuffer;
+ }
+ }
+
+ public void free() {
+ if (byteBuffer instanceof DirectBuffer) {
+ ((DirectBuffer)byteBuffer).free();
+ } else {
+ assert false : byteBuffer;
+ }
+ }
+ // END android-added
+
+ public LongBuffer asReadOnlyBuffer() {
+ LongToByteBufferAdapter buf = new LongToByteBufferAdapter(byteBuffer
+ .asReadOnlyBuffer());
+ buf.limit = limit;
+ buf.position = position;
+ buf.mark = mark;
+ return buf;
+ }
+
+ public LongBuffer compact() {
+ if (byteBuffer.isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+ byteBuffer.limit(limit << 3);
+ byteBuffer.position(position << 3);
+ byteBuffer.compact();
+ byteBuffer.clear();
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public LongBuffer duplicate() {
+ LongToByteBufferAdapter buf = new LongToByteBufferAdapter(byteBuffer
+ .duplicate());
+ buf.limit = limit;
+ buf.position = position;
+ buf.mark = mark;
+ return buf;
+ }
+
+ public long get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return byteBuffer.getLong(position++ << 3);
+ }
+
+ public long get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return byteBuffer.getLong(index << 3);
+ }
+
+ public boolean isDirect() {
+ return byteBuffer.isDirect();
+ }
+
+ public boolean isReadOnly() {
+ return byteBuffer.isReadOnly();
+ }
+
+ public ByteOrder order() {
+ return byteBuffer.order();
+ }
+
+ protected long[] protectedArray() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public LongBuffer put(long c) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ byteBuffer.putLong(position++ << 3, c);
+ return this;
+ }
+
+ public LongBuffer put(int index, long c) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ byteBuffer.putLong(index << 3, c);
+ return this;
+ }
+
+ public LongBuffer slice() {
+ byteBuffer.limit(limit << 3);
+ byteBuffer.position(position << 3);
+ LongBuffer result = new LongToByteBufferAdapter(byteBuffer.slice());
+ byteBuffer.clear();
+ return result;
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/MappedByteBuffer.java b/nio/src/main/java/java/nio/MappedByteBuffer.java
new file mode 100644
index 0000000..5c11eae
--- /dev/null
+++ b/nio/src/main/java/java/nio/MappedByteBuffer.java
@@ -0,0 +1,107 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+import org.apache.harmony.luni.platform.IMemorySystem;
+import org.apache.harmony.luni.platform.MappedPlatformAddress;
+import org.apache.harmony.luni.platform.PlatformAddress;
+import org.apache.harmony.nio.internal.DirectBuffer;
+
+
+/**
+ * <code>MappedByteBuffer</code> is a special kind of direct byte buffer,
+ * which maps a region of file to memory.
+ * <p>
+ * <code>MappedByteBuffer</code> can be created by calling
+ * {@link java.nio.channels.FileChannel#map(java.nio.channels.FileChannel.MapMode, long, long) FileChannel.map}.
+ * Once created, the mapping between the byte buffer and the file region remains
+ * valid until the byte buffer is garbage collected.
+ * </p>
+ * <p>
+ * All or part of a <code>MappedByteBuffer</code>'s content may change or
+ * become inaccessible at any time, since the mapped file region can be modified
+ * by another thread or process at any time. If this happens, the behavior of
+ * the <code>MappedByteBuffer</code> is undefined.
+ * </p>
+ *
+ */
+public abstract class MappedByteBuffer extends ByteBuffer {
+
+ final DirectByteBuffer wrapped;
+
+ private int mapMode;
+
+ MappedByteBuffer(ByteBuffer directBuffer) {
+ super(directBuffer.capacity);
+ if (!directBuffer.isDirect()) {
+ throw new IllegalArgumentException();
+ }
+ this.wrapped = (DirectByteBuffer) directBuffer;
+
+ }
+
+ MappedByteBuffer(PlatformAddress addr, int capa, int offset, int mode) {
+ super(capa);
+ mapMode = mode;
+ switch (mapMode) {
+ case IMemorySystem.MMAP_READ_ONLY:
+ wrapped = new ReadOnlyDirectByteBuffer(addr, capa, offset);
+ break;
+ case IMemorySystem.MMAP_READ_WRITE:
+ case IMemorySystem.MMAP_WRITE_COPY:
+ wrapped = new ReadWriteDirectByteBuffer(addr, capa, offset);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ addr.autoFree();
+ }
+
+ /**
+ * Returns true if this buffer's content is loaded.
+ *
+ * @return True if this buffer's content is loaded.
+ */
+ public final boolean isLoaded() {
+ return ((MappedPlatformAddress)((DirectBuffer) wrapped).getBaseAddress()).mmapIsLoaded();
+ }
+
+ /**
+ * Loads this buffer's content into memory.
+ *
+ * @return This buffer
+ */
+ public final MappedByteBuffer load() {
+ ((MappedPlatformAddress)((DirectBuffer) wrapped).getBaseAddress()).mmapLoad();
+ return this;
+ }
+
+ /**
+ * Writes all changes of the buffer to the mapped file.
+ *
+ * All changes must be written by invoking this method if the mapped file
+ * exists on the local device, otherwise the action can not be specified.
+ *
+ * @return This buffer
+ */
+ public final MappedByteBuffer force() {
+ if (mapMode == IMemorySystem.MMAP_READ_WRITE) {
+ ((MappedPlatformAddress)((DirectBuffer) wrapped).getBaseAddress()).mmapFlush();
+ }
+ return this;
+ }
+}
diff --git a/nio/src/main/java/java/nio/MappedByteBufferAdapter.java b/nio/src/main/java/java/nio/MappedByteBufferAdapter.java
new file mode 100644
index 0000000..5533df9
--- /dev/null
+++ b/nio/src/main/java/java/nio/MappedByteBufferAdapter.java
@@ -0,0 +1,368 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+import org.apache.harmony.luni.platform.PlatformAddress;
+import org.apache.harmony.nio.internal.DirectBuffer;
+
+
+class MappedByteBufferAdapter extends MappedByteBuffer implements DirectBuffer {
+
+ private static final int CHAR_SIZE = 2;
+
+ private static final int SHORT_SIZE = 2;
+
+ private static final int INTEGER_SIZE = 4;
+
+ private static final int LONG_SIZE = 8;
+
+ private static final int FLOAT_SIZE = 4;
+
+ private static final int DOUBLE_SIZE = 8;
+
+ public MappedByteBufferAdapter(ByteBuffer buffer) {
+ super(buffer);
+ }
+
+ public MappedByteBufferAdapter(PlatformAddress addr, int capa, int offset,
+ int mode) {
+ super(addr, capa, offset, mode);
+ }
+
+ public CharBuffer asCharBuffer() {
+ return this.wrapped.asCharBuffer();
+ }
+
+ public DoubleBuffer asDoubleBuffer() {
+ return this.wrapped.asDoubleBuffer();
+ }
+
+ public FloatBuffer asFloatBuffer() {
+ return this.wrapped.asFloatBuffer();
+ }
+
+ public IntBuffer asIntBuffer() {
+ return this.wrapped.asIntBuffer();
+ }
+
+ public LongBuffer asLongBuffer() {
+ return this.wrapped.asLongBuffer();
+ }
+
+ public ByteBuffer asReadOnlyBuffer() {
+ MappedByteBufferAdapter buf = new MappedByteBufferAdapter(this.wrapped
+ .asReadOnlyBuffer());
+ buf.limit = this.limit;
+ buf.position = this.position;
+ buf.mark = this.mark;
+ return buf;
+ }
+
+ public ShortBuffer asShortBuffer() {
+ return this.wrapped.asShortBuffer();
+ }
+
+ public ByteBuffer compact() {
+ if (this.wrapped.isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+ this.wrapped.limit(this.limit);
+ this.wrapped.position(this.position);
+ this.wrapped.compact();
+ this.wrapped.clear();
+ this.position = this.limit - this.position;
+ this.limit = this.capacity;
+ this.mark = UNSET_MARK;
+ return this;
+ }
+
+ public ByteBuffer duplicate() {
+ MappedByteBufferAdapter buf = new MappedByteBufferAdapter(this.wrapped
+ .duplicate());
+ buf.limit = this.limit;
+ buf.position = this.position;
+ buf.mark = this.mark;
+ return buf;
+ }
+
+ public byte get() {
+ if (this.position == this.limit) {
+ throw new BufferUnderflowException();
+ }
+ return this.wrapped.get(this.position++);
+ }
+
+ public byte get(int index) {
+ return this.wrapped.get(index);
+ }
+
+ public char getChar() {
+ int newPosition = this.position + CHAR_SIZE;
+ if (newPosition > this.limit) {
+ throw new BufferUnderflowException();
+ }
+ char result = this.wrapped.getChar(this.position);
+ this.position = newPosition;
+ return result;
+ }
+
+ public char getChar(int index) {
+ return this.wrapped.getChar(index);
+ }
+
+ public double getDouble() {
+ int newPosition = this.position + DOUBLE_SIZE;
+ if (newPosition > this.limit) {
+ throw new BufferUnderflowException();
+ }
+ double result = this.wrapped.getDouble(this.position);
+ this.position = newPosition;
+ return result;
+ }
+
+ public double getDouble(int index) {
+ return this.wrapped.getDouble(index);
+ }
+
+ public PlatformAddress getEffectiveAddress() {
+ return ((DirectBuffer) this.wrapped).getEffectiveAddress();
+ }
+
+ public float getFloat() {
+ int newPosition = this.position + FLOAT_SIZE;
+ if (newPosition > this.limit) {
+ throw new BufferUnderflowException();
+ }
+ float result = this.wrapped.getFloat(this.position);
+ this.position = newPosition;
+ return result;
+ }
+
+ public float getFloat(int index) {
+ return this.wrapped.getFloat(index);
+ }
+
+ public int getInt() {
+ int newPosition = this.position + INTEGER_SIZE;
+ if (newPosition > this.limit) {
+ throw new BufferUnderflowException();
+ }
+ int result = this.wrapped.getInt(this.position);
+ this.position = newPosition;
+ return result;
+ }
+
+ public int getInt(int index) {
+ return this.wrapped.getInt(index);
+ }
+
+ public long getLong() {
+ int newPosition = this.position + LONG_SIZE;
+ if (newPosition > this.limit) {
+ throw new BufferUnderflowException();
+ }
+ long result = this.wrapped.getLong(this.position);
+ this.position = newPosition;
+ return result;
+ }
+
+ public long getLong(int index) {
+ return this.wrapped.getLong(index);
+ }
+
+ public short getShort() {
+ int newPosition = this.position + SHORT_SIZE;
+ if (newPosition > this.limit) {
+ throw new BufferUnderflowException();
+ }
+ short result = this.wrapped.getShort(this.position);
+ this.position = newPosition;
+ return result;
+ }
+
+ public short getShort(int index) {
+ return this.wrapped.getShort(index);
+ }
+
+ public boolean isDirect() {
+ return true;
+ }
+
+ public boolean isReadOnly() {
+ return this.wrapped.isReadOnly();
+ }
+
+ ByteBuffer orderImpl(ByteOrder byteOrder) {
+ super.orderImpl(byteOrder);
+ return this.wrapped.order(byteOrder);
+ }
+
+ public ByteBuffer put(byte b) {
+ if (this.position == this.limit) {
+ throw new BufferOverflowException();
+ }
+ this.wrapped.put(this.position++, b);
+ return this;
+ }
+
+ public ByteBuffer put(byte[] src, int off, int len) {
+ this.wrapped.position(this.position);
+ this.wrapped.put(src, off, len);
+ this.position += len;
+ return this;
+ }
+
+ public ByteBuffer put(int index, byte b) {
+ this.wrapped.put(index, b);
+ return this;
+ }
+
+ public ByteBuffer putChar(char value) {
+ int newPosition = this.position + CHAR_SIZE;
+ if (newPosition > this.limit) {
+ throw new BufferOverflowException();
+ }
+ this.wrapped.putChar(this.position, value);
+ this.position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer putChar(int index, char value) {
+ this.wrapped.putChar(index, value);
+ return this;
+ }
+
+ public ByteBuffer putDouble(double value) {
+ int newPosition = this.position + DOUBLE_SIZE;
+ if (newPosition > this.limit) {
+ throw new BufferOverflowException();
+ }
+ this.wrapped.putDouble(this.position, value);
+ this.position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer putDouble(int index, double value) {
+ this.wrapped.putDouble(index, value);
+ return this;
+ }
+
+ public ByteBuffer putFloat(float value) {
+ int newPosition = this.position + FLOAT_SIZE;
+ if (newPosition > this.limit) {
+ throw new BufferOverflowException();
+ }
+ this.wrapped.putFloat(this.position, value);
+ this.position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer putFloat(int index, float value) {
+ this.wrapped.putFloat(index, value);
+ return this;
+ }
+
+ public ByteBuffer putInt(int index, int value) {
+ this.wrapped.putInt(index, value);
+ return this;
+ }
+
+ public ByteBuffer putInt(int value) {
+ int newPosition = this.position + INTEGER_SIZE;
+ if (newPosition > this.limit) {
+ throw new BufferOverflowException();
+ }
+ this.wrapped.putInt(this.position, value);
+ this.position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer putLong(int index, long value) {
+ this.wrapped.putLong(index, value);
+ return this;
+ }
+
+ public ByteBuffer putLong(long value) {
+ int newPosition = this.position + LONG_SIZE;
+ if (newPosition > this.limit) {
+ throw new BufferOverflowException();
+ }
+ this.wrapped.putLong(this.position, value);
+ this.position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer putShort(int index, short value) {
+ this.wrapped.putShort(index, value);
+ return this;
+ }
+
+ public ByteBuffer putShort(short value) {
+ int newPosition = this.position + SHORT_SIZE;
+ if (newPosition > this.limit) {
+ throw new BufferOverflowException();
+ }
+ this.wrapped.putShort(this.position, value);
+ this.position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer slice() {
+ this.wrapped.limit(this.limit);
+ this.wrapped.position(this.position);
+ MappedByteBufferAdapter result = new MappedByteBufferAdapter(
+ this.wrapped.slice());
+ this.wrapped.clear();
+ return result;
+ }
+
+ byte[] protectedArray() {
+ return this.wrapped.protectedArray();
+ }
+
+ int protectedArrayOffset() {
+ return this.wrapped.protectedArrayOffset();
+ }
+
+ boolean protectedHasArray() {
+ return this.wrapped.protectedHasArray();
+ }
+
+ public PlatformAddress getBaseAddress() {
+ return this.wrapped.getBaseAddress();
+ }
+
+ public boolean isAddressValid() {
+ return this.wrapped.isAddressValid();
+ }
+
+ public void addressValidityCheck() {
+ this.wrapped.addressValidityCheck();
+ }
+
+ public void free() {
+ this.wrapped.free();
+ }
+
+ // BEGIN android-added
+ // copied from newer version of harmony
+ public int getByteCapacity() {
+ return wrapped.getByteCapacity();
+ }
+ // END android-added
+}
diff --git a/nio/src/main/java/java/nio/NIOAccess.java b/nio/src/main/java/java/nio/NIOAccess.java
new file mode 100644
index 0000000..979ee19
--- /dev/null
+++ b/nio/src/main/java/java/nio/NIOAccess.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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;
+
+import org.apache.harmony.luni.platform.PlatformAddress;
+import org.apache.harmony.nio.internal.DirectBuffer;
+
+/**
+ * A class allowing native code to access the underlying data of
+ * an NIO Buffer, breaking encapsulation in the name of efficiency.
+ */
+class NIOAccess {
+
+ /**
+ * Returns the underlying native pointer to the data of the given
+ * Buffer starting at the Buffer's current position, or 0 if the
+ * Buffer is not backed by native heap storage. Note that this is
+ * different than what the Harmony implementation calls a "base
+ * address."
+ *
+ * @param Buffer b the Buffer to be queried
+ * @return the native pointer to the Buffer's data at its current
+ * position, or 0 if there is none
+ */
+ static long getBasePointer(Buffer b) {
+ if (b instanceof DirectBuffer) {
+ PlatformAddress address = ((DirectBuffer) b).getEffectiveAddress();
+ if (address == null) {
+ return 0L;
+ }
+ return address.toInt() + (b.position() << b._elementSizeShift);
+ }
+ return 0L;
+ }
+
+ /**
+ * Returns the number of bytes remaining in the given Buffer. That is,
+ * this scales <code>remaining()</code> by the byte-size of elements
+ * of this Buffer.
+ *
+ * @param Buffer b the Buffer to be queried
+ * @return the number of remaining bytes
+ */
+ static int getRemainingBytes(Buffer b) {
+ return (b.limit - b.position) << b._elementSizeShift;
+ }
+
+ /**
+ * Returns the underlying Java array containing the data of the
+ * given Buffer, or null if the Buffer is not backed by a Java array.
+ *
+ * @param Buffer b the Buffer to be queried
+ * @return the Java array containing the Buffer's data, or null if
+ * there is none
+ */
+ static Object getBaseArray(Buffer b) {
+ return b._array();
+ }
+
+ /**
+ * Returns the offset in bytes from the start of the underlying
+ * Java array object containing the data of the given Buffer to
+ * the actual start of the data. This method is only meaningful if
+ * getBaseArray() returns non-null.
+ *
+ * @param Buffer b the Buffer to be queried
+ * @return the data offset in bytes to the start of this Buffer's data
+ */
+ static int getBaseArrayOffset(Buffer b) {
+ return b._arrayOffset() << b._elementSizeShift;
+ }
+}
+
diff --git a/nio/src/main/java/java/nio/ReadOnlyBufferException.java b/nio/src/main/java/java/nio/ReadOnlyBufferException.java
new file mode 100644
index 0000000..990d8ec
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadOnlyBufferException.java
@@ -0,0 +1,35 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+
+/**
+ * A <code>ReadOnlyBufferException</code> is thrown when some write operation
+ * is called on a readonly buffer.
+ *
+ */
+public class ReadOnlyBufferException extends UnsupportedOperationException {
+
+ private static final long serialVersionUID = -1210063976496234090L;
+
+ /**
+ * Constructs a <code>ReadOnlyBufferException</code>.
+ */
+ public ReadOnlyBufferException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/ReadOnlyCharArrayBuffer.java b/nio/src/main/java/java/nio/ReadOnlyCharArrayBuffer.java
new file mode 100644
index 0000000..461ea4f
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadOnlyCharArrayBuffer.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * CharArrayBuffer, ReadWriteCharArrayBuffer and ReadOnlyCharArrayBuffer compose
+ * the implementation of array based char buffers.
+ * <p>
+ * ReadOnlyCharArrayBuffer extends CharArrayBuffer with all the write methods
+ * throwing read only exception.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadOnlyCharArrayBuffer extends CharArrayBuffer {
+
+ static ReadOnlyCharArrayBuffer copy(CharArrayBuffer other, int markOfOther) {
+ ReadOnlyCharArrayBuffer buf = new ReadOnlyCharArrayBuffer(other
+ .capacity(), other.backingArray, other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ return buf;
+ }
+
+ ReadOnlyCharArrayBuffer(int capacity, char[] backingArray, int arrayOffset) {
+ super(capacity, backingArray, arrayOffset);
+ }
+
+ public CharBuffer asReadOnlyBuffer() {
+ return duplicate();
+ }
+
+ public CharBuffer compact() {
+ throw new ReadOnlyBufferException();
+ }
+
+ public CharBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ protected char[] protectedArray() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public CharBuffer put(char c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public CharBuffer put(int index, char c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public final CharBuffer put(char[] src, int off, int len) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public final CharBuffer put(CharBuffer src) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public CharBuffer put(String src, int start, int end) {
+ if ((start < 0 ) || (end < 0) || (long)start + (long)end > src.length()) {
+ throw new IndexOutOfBoundsException();
+ }
+ throw new ReadOnlyBufferException();
+ }
+
+ public CharBuffer slice() {
+ return new ReadOnlyCharArrayBuffer(remaining(), backingArray, offset
+ + position);
+ }
+}
diff --git a/nio/src/main/java/java/nio/ReadOnlyDirectByteBuffer.java b/nio/src/main/java/java/nio/ReadOnlyDirectByteBuffer.java
new file mode 100644
index 0000000..bc0e1cc
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadOnlyDirectByteBuffer.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+import org.apache.harmony.luni.platform.PlatformAddress;
+
+/**
+ * DirectByteBuffer, ReadWriteDirectByteBuffer and ReadOnlyDirectByteBuffer
+ * compose the implementation of platform memory based byte buffers.
+ * <p>
+ * ReadOnlyDirectByteBuffer extends DirectByteBuffer with all the write methods
+ * throwing read only exception.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadOnlyDirectByteBuffer extends DirectByteBuffer {
+
+ static ReadOnlyDirectByteBuffer copy(DirectByteBuffer other, int markOfOther) {
+ ReadOnlyDirectByteBuffer buf = new ReadOnlyDirectByteBuffer(
+ other.safeAddress, other.capacity(), other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ buf.order(other.order());
+ return buf;
+ }
+
+ protected ReadOnlyDirectByteBuffer(SafeAddress address, int capacity,
+ int offset) {
+ super(address, capacity, offset);
+ }
+
+ protected ReadOnlyDirectByteBuffer(PlatformAddress address, int capacity,
+ int offset) {
+ super(new SafeAddress(address), capacity, offset);
+ }
+
+ public ByteBuffer asReadOnlyBuffer() {
+ return copy(this, mark);
+ }
+
+ public ByteBuffer compact() {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ public ByteBuffer put(byte value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer put(int index, byte value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer put(byte[] src, int off, int len) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putDouble(double value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putDouble(int index, double value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putFloat(float value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putFloat(int index, float value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putInt(int value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putInt(int index, int value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putLong(int index, long value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putLong(long value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putShort(int index, short value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putShort(short value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer put(ByteBuffer buf) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer slice() {
+ ReadOnlyDirectByteBuffer buf = new ReadOnlyDirectByteBuffer(
+ safeAddress, remaining(), offset + position);
+ buf.order = order;
+ return buf;
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ReadOnlyDoubleArrayBuffer.java b/nio/src/main/java/java/nio/ReadOnlyDoubleArrayBuffer.java
new file mode 100644
index 0000000..4f0b5d2
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadOnlyDoubleArrayBuffer.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * DoubleArrayBuffer, ReadWriteDoubleArrayBuffer and ReadOnlyDoubleArrayBuffer
+ * compose the implementation of array based double buffers.
+ * <p>
+ * ReadOnlyDoubleArrayBuffer extends DoubleArrayBuffer with all the write
+ * methods throwing read only exception.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadOnlyDoubleArrayBuffer extends DoubleArrayBuffer {
+
+ static ReadOnlyDoubleArrayBuffer copy(DoubleArrayBuffer other,
+ int markOfOther) {
+ ReadOnlyDoubleArrayBuffer buf = new ReadOnlyDoubleArrayBuffer(other
+ .capacity(), other.backingArray, other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ return buf;
+ }
+
+ ReadOnlyDoubleArrayBuffer(int capacity, double[] backingArray,
+ int arrayOffset) {
+ super(capacity, backingArray, arrayOffset);
+ }
+
+ public DoubleBuffer asReadOnlyBuffer() {
+ return duplicate();
+ }
+
+ public DoubleBuffer compact() {
+ throw new ReadOnlyBufferException();
+ }
+
+ public DoubleBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ protected double[] protectedArray() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public DoubleBuffer put(double c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public DoubleBuffer put(int index, double c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public final DoubleBuffer put(double[] src, int off, int len) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public final DoubleBuffer put(DoubleBuffer buf) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public DoubleBuffer slice() {
+ return new ReadOnlyDoubleArrayBuffer(remaining(), backingArray, offset
+ + position);
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ReadOnlyFloatArrayBuffer.java b/nio/src/main/java/java/nio/ReadOnlyFloatArrayBuffer.java
new file mode 100644
index 0000000..7559ffa
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadOnlyFloatArrayBuffer.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * FloatArrayBuffer, ReadWriteFloatArrayBuffer and ReadOnlyFloatArrayBuffer
+ * compose the implementation of array based float buffers.
+ * <p>
+ * ReadOnlyFloatArrayBuffer extends FloatArrayBuffer with all the write methods
+ * throwing read only exception.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadOnlyFloatArrayBuffer extends FloatArrayBuffer {
+
+ static ReadOnlyFloatArrayBuffer copy(FloatArrayBuffer other, int markOfOther) {
+ ReadOnlyFloatArrayBuffer buf = new ReadOnlyFloatArrayBuffer(other
+ .capacity(), other.backingArray, other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ return buf;
+ }
+
+ ReadOnlyFloatArrayBuffer(int capacity, float[] backingArray, int arrayOffset) {
+ super(capacity, backingArray, arrayOffset);
+ }
+
+ public FloatBuffer asReadOnlyBuffer() {
+ return duplicate();
+ }
+
+ public FloatBuffer compact() {
+ throw new ReadOnlyBufferException();
+ }
+
+ public FloatBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ protected float[] protectedArray() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public FloatBuffer put(float c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public FloatBuffer put(int index, float c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public FloatBuffer put(FloatBuffer buf) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public final FloatBuffer put(float[] src, int off, int len) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public FloatBuffer slice() {
+ return new ReadOnlyFloatArrayBuffer(remaining(), backingArray, offset
+ + position);
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ReadOnlyHeapByteBuffer.java b/nio/src/main/java/java/nio/ReadOnlyHeapByteBuffer.java
new file mode 100644
index 0000000..857ecff
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadOnlyHeapByteBuffer.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * HeapByteBuffer, ReadWriteHeapByteBuffer and ReadOnlyHeapByteBuffer compose
+ * the implementation of array based byte buffers.
+ * <p>
+ * ReadOnlyHeapByteBuffer extends HeapByteBuffer with all the write methods
+ * throwing read only exception.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadOnlyHeapByteBuffer extends HeapByteBuffer {
+
+ static ReadOnlyHeapByteBuffer copy(HeapByteBuffer other, int markOfOther) {
+ ReadOnlyHeapByteBuffer buf = new ReadOnlyHeapByteBuffer(
+ other.backingArray, other.capacity(), other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ buf.order(other.order());
+ return buf;
+ }
+
+ ReadOnlyHeapByteBuffer(byte[] backingArray, int capacity, int arrayOffset) {
+ super(backingArray, capacity, arrayOffset);
+ }
+
+ public ByteBuffer asReadOnlyBuffer() {
+ return copy(this, mark);
+ }
+
+ public ByteBuffer compact() {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ protected byte[] protectedArray() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public ByteBuffer put(byte b) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer put(int index, byte b) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer put(byte[] src, int off, int len) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putDouble(double value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putDouble(int index, double value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putFloat(float value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putFloat(int index, float value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putInt(int value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putInt(int index, int value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putLong(int index, long value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putLong(long value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putShort(int index, short value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer putShort(short value) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer put(ByteBuffer buf) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ByteBuffer slice() {
+ ReadOnlyHeapByteBuffer slice = new ReadOnlyHeapByteBuffer(backingArray,
+ remaining(), offset + position);
+ slice.order = order;
+ return slice;
+ }
+}
diff --git a/nio/src/main/java/java/nio/ReadOnlyIntArrayBuffer.java b/nio/src/main/java/java/nio/ReadOnlyIntArrayBuffer.java
new file mode 100644
index 0000000..ba9380e
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadOnlyIntArrayBuffer.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * IntArrayBuffer, ReadWriteIntArrayBuffer and ReadOnlyIntArrayBuffer compose
+ * the implementation of array based int buffers.
+ * <p>
+ * ReadOnlyIntArrayBuffer extends IntArrayBuffer with all the write methods
+ * throwing read only exception.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadOnlyIntArrayBuffer extends IntArrayBuffer {
+
+ static ReadOnlyIntArrayBuffer copy(IntArrayBuffer other, int markOfOther) {
+ ReadOnlyIntArrayBuffer buf = new ReadOnlyIntArrayBuffer(other
+ .capacity(), other.backingArray, other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ return buf;
+ }
+
+ ReadOnlyIntArrayBuffer(int capacity, int[] backingArray, int arrayOffset) {
+ super(capacity, backingArray, arrayOffset);
+ }
+
+ public IntBuffer asReadOnlyBuffer() {
+ return duplicate();
+ }
+
+ public IntBuffer compact() {
+ throw new ReadOnlyBufferException();
+ }
+
+ public IntBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ protected int[] protectedArray() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public IntBuffer put(int c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public IntBuffer put(int index, int c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public IntBuffer put(IntBuffer buf) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public final IntBuffer put(int[] src, int off, int len) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public IntBuffer slice() {
+ return new ReadOnlyIntArrayBuffer(remaining(), backingArray, offset
+ + position);
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ReadOnlyLongArrayBuffer.java b/nio/src/main/java/java/nio/ReadOnlyLongArrayBuffer.java
new file mode 100644
index 0000000..76c1a4a
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadOnlyLongArrayBuffer.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * LongArrayBuffer, ReadWriteLongArrayBuffer and ReadOnlyLongArrayBuffer compose
+ * the implementation of array based long buffers.
+ * <p>
+ * ReadOnlyLongArrayBuffer extends LongArrayBuffer with all the write methods
+ * throwing read only exception.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadOnlyLongArrayBuffer extends LongArrayBuffer {
+
+ static ReadOnlyLongArrayBuffer copy(LongArrayBuffer other, int markOfOther) {
+ ReadOnlyLongArrayBuffer buf = new ReadOnlyLongArrayBuffer(other
+ .capacity(), other.backingArray, other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ return buf;
+ }
+
+ ReadOnlyLongArrayBuffer(int capacity, long[] backingArray, int arrayOffset) {
+ super(capacity, backingArray, arrayOffset);
+ }
+
+ public LongBuffer asReadOnlyBuffer() {
+ return duplicate();
+ }
+
+ public LongBuffer compact() {
+ throw new ReadOnlyBufferException();
+ }
+
+ public LongBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ protected long[] protectedArray() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public LongBuffer put(long c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public LongBuffer put(int index, long c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public LongBuffer put(LongBuffer buf) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public final LongBuffer put(long[] src, int off, int len) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public LongBuffer slice() {
+ return new ReadOnlyLongArrayBuffer(remaining(), backingArray, offset
+ + position);
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ReadOnlyShortArrayBuffer.java b/nio/src/main/java/java/nio/ReadOnlyShortArrayBuffer.java
new file mode 100644
index 0000000..1a3bfd3
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadOnlyShortArrayBuffer.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * ShortArrayBuffer, ReadWriteShortArrayBuffer and ReadOnlyShortArrayBuffer
+ * compose the implementation of array based short buffers.
+ * <p>
+ * ReadOnlyShortArrayBuffer extends ShortArrayBuffer with all the write methods
+ * throwing read only exception.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadOnlyShortArrayBuffer extends ShortArrayBuffer {
+
+ static ReadOnlyShortArrayBuffer copy(ShortArrayBuffer other, int markOfOther) {
+ ReadOnlyShortArrayBuffer buf = new ReadOnlyShortArrayBuffer(other
+ .capacity(), other.backingArray, other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ return buf;
+ }
+
+ ReadOnlyShortArrayBuffer(int capacity, short[] backingArray, int arrayOffset) {
+ super(capacity, backingArray, arrayOffset);
+ }
+
+ public ShortBuffer asReadOnlyBuffer() {
+ return duplicate();
+ }
+
+ public ShortBuffer compact() {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ShortBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ protected short[] protectedArray() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new ReadOnlyBufferException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public ShortBuffer put(ShortBuffer buf) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ShortBuffer put(short c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ShortBuffer put(int index, short c) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public final ShortBuffer put(short[] src, int off, int len) {
+ throw new ReadOnlyBufferException();
+ }
+
+ public ShortBuffer slice() {
+ return new ReadOnlyShortArrayBuffer(remaining(), backingArray, offset
+ + position);
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ReadWriteCharArrayBuffer.java b/nio/src/main/java/java/nio/ReadWriteCharArrayBuffer.java
new file mode 100644
index 0000000..08f79b2
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadWriteCharArrayBuffer.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * CharArrayBuffer, ReadWriteCharArrayBuffer and ReadOnlyCharArrayBuffer compose
+ * the implementation of array based char buffers.
+ * <p>
+ * ReadWriteCharArrayBuffer extends CharArrayBuffer with all the write methods.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadWriteCharArrayBuffer extends CharArrayBuffer {
+
+ static ReadWriteCharArrayBuffer copy(CharArrayBuffer other, int markOfOther) {
+ ReadWriteCharArrayBuffer buf = new ReadWriteCharArrayBuffer(other
+ .capacity(), other.backingArray, other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ return buf;
+ }
+
+ ReadWriteCharArrayBuffer(char[] array) {
+ super(array);
+ }
+
+ ReadWriteCharArrayBuffer(int capacity) {
+ super(capacity);
+ }
+
+ ReadWriteCharArrayBuffer(int capacity, char[] backingArray, int arrayOffset) {
+ super(capacity, backingArray, arrayOffset);
+ }
+
+ public CharBuffer asReadOnlyBuffer() {
+ return ReadOnlyCharArrayBuffer.copy(this, mark);
+ }
+
+ public CharBuffer compact() {
+ System.arraycopy(backingArray, position + offset, backingArray, offset,
+ remaining());
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public CharBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ protected char[] protectedArray() {
+ return backingArray;
+ }
+
+ protected int protectedArrayOffset() {
+ return offset;
+ }
+
+ protected boolean protectedHasArray() {
+ return true;
+ }
+
+ public CharBuffer put(char c) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ backingArray[offset + position++] = c;
+ return this;
+ }
+
+ public CharBuffer put(int index, char c) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ backingArray[offset + index] = c;
+ return this;
+ }
+
+ public CharBuffer put(char[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)len + (long)off > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ System.arraycopy(src, off, backingArray, offset+position, len);
+ position += len;
+ return this;
+ }
+
+ public CharBuffer slice() {
+ return new ReadWriteCharArrayBuffer(remaining(), backingArray, offset
+ + position);
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ReadWriteDirectByteBuffer.java b/nio/src/main/java/java/nio/ReadWriteDirectByteBuffer.java
new file mode 100644
index 0000000..74655b8
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadWriteDirectByteBuffer.java
@@ -0,0 +1,316 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+import org.apache.harmony.luni.platform.PlatformAddress;
+// BEGIN android-added
+import org.apache.harmony.luni.platform.PlatformAddressFactory;
+// END android-added
+
+/**
+ * DirectByteBuffer, ReadWriteDirectByteBuffer and ReadOnlyDirectByteBuffer
+ * compose the implementation of platform memory based byte buffers.
+ * <p>
+ * ReadWriteDirectByteBuffer extends DirectByteBuffer with all the write
+ * methods.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadWriteDirectByteBuffer extends DirectByteBuffer {
+
+ static ReadWriteDirectByteBuffer copy(DirectByteBuffer other,
+ int markOfOther) {
+ ReadWriteDirectByteBuffer buf = new ReadWriteDirectByteBuffer(
+ other.safeAddress, other.capacity(), other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ buf.order(other.order());
+ return buf;
+ }
+
+ ReadWriteDirectByteBuffer(int capacity) {
+ super(capacity);
+ }
+
+ // BEGIN android-added
+ ReadWriteDirectByteBuffer(int pointer, int capacity) {
+ this(PlatformAddressFactory.on(pointer, capacity),capacity,0);
+ }
+ // END android-added
+
+ ReadWriteDirectByteBuffer(SafeAddress address, int capacity, int offset) {
+ super(address, capacity, offset);
+ }
+
+ ReadWriteDirectByteBuffer(PlatformAddress address, int aCapacity,
+ int anOffset) {
+ super(new SafeAddress(address), aCapacity, anOffset);
+ }
+
+ // BEGIN android-added
+ int getAddress() {
+ return this.safeAddress.address.toInt();
+ }
+ // END android-added
+
+ public ByteBuffer asReadOnlyBuffer() {
+ return ReadOnlyDirectByteBuffer.copy(this, mark);
+ }
+
+ public ByteBuffer compact() {
+ PlatformAddress effectiveAddress = getEffectiveAddress();
+ effectiveAddress.offsetBytes(position).moveTo(effectiveAddress,
+ remaining());
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public ByteBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ public ByteBuffer put(byte value) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ getBaseAddress().setByte(offset + position++, value);
+ return this;
+ }
+
+ public ByteBuffer put(int index, byte value) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ getBaseAddress().setByte(offset + index, value);
+ return this;
+ }
+
+ /*
+ * Override ByteBuffer.put(byte[], int, int) to improve performance.
+ *
+ * (non-Javadoc)
+ *
+ * @see java.nio.ByteBuffer#put(byte[], int, int)
+ */
+ public ByteBuffer put(byte[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ if (isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+ getBaseAddress().setByteArray(offset + position, src, off,
+ len);
+ position += len;
+ return this;
+ }
+
+ // BEGIN android-added
+ /**
+ * Writes <code>short</code>s in the given short array, starting from the
+ * specified offset, to the current position and increase the position by
+ * the number of <code>short</code>s written.
+ *
+ * @param src
+ * The source short array
+ * @param off
+ * The offset of short array, must be no less than zero and no
+ * greater than <code>src.length</code>
+ * @param len
+ * The number of <code>short</code>s to write, must be no less
+ * than zero and no greater than <code>src.length - off</code>
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>len</code>
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ ByteBuffer put(short[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len << 1 > remaining()) {
+ throw new BufferOverflowException();
+ }
+ if (isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+ boolean swap = order() != ByteOrder.nativeOrder();
+ getBaseAddress().setShortArray(offset + position, src, off, len, swap);
+ position += len << 1;
+ return this;
+ }
+
+ /**
+ * Writes <code>int</code>s in the given int array, starting from the
+ * specified offset, to the current position and increase the position by
+ * the number of <code>int</code>s written.
+ *
+ * @param src
+ * The source int array
+ * @param off
+ * The offset of int array, must be no less than zero and no
+ * greater than <code>src.length</code>
+ * @param len
+ * The number of <code>int</code>s to write, must be no less
+ * than zero and no greater than <code>src.length - off</code>
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>len</code>
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ ByteBuffer put(int[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len << 2 > remaining()) {
+ throw new BufferOverflowException();
+ }
+ if (isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+ boolean swap = order() != ByteOrder.nativeOrder();
+ getBaseAddress().setIntArray(offset + position, src, off, len, swap);
+ position += len << 2;
+ return this;
+ }
+ // END android-added
+
+ public ByteBuffer putDouble(double value) {
+ int newPosition = position + 8;
+ if (newPosition > limit) {
+ throw new BufferOverflowException();
+ }
+ getBaseAddress().setDouble(offset + position, value, order);
+ position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer putDouble(int index, double value) {
+ if (index < 0 || (long)index + 8 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ getBaseAddress().setDouble(offset + index, value, order);
+ return this;
+ }
+
+ public ByteBuffer putFloat(float value) {
+ int newPosition = position + 4;
+ if (newPosition > limit) {
+ throw new BufferOverflowException();
+ }
+ getBaseAddress().setFloat(offset + position, value, order);
+ position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer putFloat(int index, float value) {
+ if (index < 0 || (long)index + 4 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ getBaseAddress().setFloat(offset + index, value, order);
+ return this;
+ }
+
+ public ByteBuffer putInt(int value) {
+ int newPosition = position + 4;
+ if (newPosition > limit) {
+ throw new BufferOverflowException();
+ }
+ getBaseAddress().setInt(offset + position, value, order);
+ position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer putInt(int index, int value) {
+ if (index < 0 || (long)index + 4 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ getBaseAddress().setInt(offset + index, value, order);
+ return this;
+ }
+
+ public ByteBuffer putLong(long value) {
+ int newPosition = position + 8;
+ if (newPosition > limit) {
+ throw new BufferOverflowException();
+ }
+ getBaseAddress().setLong(offset + position, value, order);
+ position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer putLong(int index, long value) {
+ if (index < 0 || (long)index + 8 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ getBaseAddress().setLong(offset + index, value, order);
+ return this;
+ }
+
+ public ByteBuffer putShort(short value) {
+ int newPosition = position + 2;
+ if (newPosition > limit) {
+ throw new BufferOverflowException();
+ }
+ getBaseAddress().setShort(offset + position, value, order);
+ position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer putShort(int index, short value) {
+ if (index < 0 || (long)index + 2 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ getBaseAddress().setShort(offset + index, value, order);
+ return this;
+ }
+
+ public ByteBuffer slice() {
+ ReadWriteDirectByteBuffer buf = new ReadWriteDirectByteBuffer(
+ safeAddress, remaining(), offset + position);
+ buf.order = order;
+ return buf;
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ReadWriteDoubleArrayBuffer.java b/nio/src/main/java/java/nio/ReadWriteDoubleArrayBuffer.java
new file mode 100644
index 0000000..2933178
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadWriteDoubleArrayBuffer.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * DoubleArrayBuffer, ReadWriteDoubleArrayBuffer and ReadOnlyDoubleArrayBuffer
+ * compose the implementation of array based double buffers.
+ * <p>
+ * ReadWriteDoubleArrayBuffer extends DoubleArrayBuffer with all the write
+ * methods.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadWriteDoubleArrayBuffer extends DoubleArrayBuffer {
+
+ static ReadWriteDoubleArrayBuffer copy(DoubleArrayBuffer other,
+ int markOfOther) {
+ ReadWriteDoubleArrayBuffer buf = new ReadWriteDoubleArrayBuffer(other
+ .capacity(), other.backingArray, other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ return buf;
+ }
+
+ ReadWriteDoubleArrayBuffer(double[] array) {
+ super(array);
+ }
+
+ ReadWriteDoubleArrayBuffer(int capacity) {
+ super(capacity);
+ }
+
+ ReadWriteDoubleArrayBuffer(int capacity, double[] backingArray,
+ int arrayOffset) {
+ super(capacity, backingArray, arrayOffset);
+ }
+
+ public DoubleBuffer asReadOnlyBuffer() {
+ return ReadOnlyDoubleArrayBuffer.copy(this, mark);
+ }
+
+ public DoubleBuffer compact() {
+ System.arraycopy(backingArray, position + offset, backingArray, offset,
+ remaining());
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public DoubleBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ protected double[] protectedArray() {
+ return backingArray;
+ }
+
+ protected int protectedArrayOffset() {
+ return offset;
+ }
+
+ protected boolean protectedHasArray() {
+ return true;
+ }
+
+ public DoubleBuffer put(double c) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ backingArray[offset + position++] = c;
+ return this;
+ }
+
+ public DoubleBuffer put(int index, double c) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ backingArray[offset + index] = c;
+ return this;
+ }
+
+ public DoubleBuffer put(double[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ System.arraycopy(src, off, backingArray, offset
+ + position, len);
+ position += len;
+ return this;
+ }
+
+ public DoubleBuffer slice() {
+ return new ReadWriteDoubleArrayBuffer(remaining(), backingArray, offset
+ + position);
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ReadWriteFloatArrayBuffer.java b/nio/src/main/java/java/nio/ReadWriteFloatArrayBuffer.java
new file mode 100644
index 0000000..49b0b11
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadWriteFloatArrayBuffer.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * FloatArrayBuffer, ReadWriteFloatArrayBuffer and ReadOnlyFloatArrayBuffer
+ * compose the implementation of array based float buffers.
+ * <p>
+ * ReadWriteFloatArrayBuffer extends FloatArrayBuffer with all the write
+ * methods.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadWriteFloatArrayBuffer extends FloatArrayBuffer {
+
+ static ReadWriteFloatArrayBuffer copy(FloatArrayBuffer other,
+ int markOfOther) {
+ ReadWriteFloatArrayBuffer buf = new ReadWriteFloatArrayBuffer(other
+ .capacity(), other.backingArray, other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ return buf;
+ }
+
+ ReadWriteFloatArrayBuffer(float[] array) {
+ super(array);
+ }
+
+ ReadWriteFloatArrayBuffer(int capacity) {
+ super(capacity);
+ }
+
+ ReadWriteFloatArrayBuffer(int capacity, float[] backingArray,
+ int arrayOffset) {
+ super(capacity, backingArray, arrayOffset);
+ }
+
+ public FloatBuffer asReadOnlyBuffer() {
+ return ReadOnlyFloatArrayBuffer.copy(this, mark);
+ }
+
+ public FloatBuffer compact() {
+ System.arraycopy(backingArray, position + offset, backingArray, offset,
+ remaining());
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public FloatBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ protected float[] protectedArray() {
+ return backingArray;
+ }
+
+ protected int protectedArrayOffset() {
+ return offset;
+ }
+
+ protected boolean protectedHasArray() {
+ return true;
+ }
+
+ public FloatBuffer put(float c) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ backingArray[offset + position++] = c;
+ return this;
+ }
+
+ public FloatBuffer put(int index, float c) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ backingArray[offset + index] = c;
+ return this;
+ }
+
+ public FloatBuffer put(float[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ System.arraycopy(src, off, backingArray, offset
+ + position, len);
+ position += len;
+ return this;
+ }
+
+ public FloatBuffer slice() {
+ return new ReadWriteFloatArrayBuffer(remaining(), backingArray, offset
+ + position);
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ReadWriteHeapByteBuffer.java b/nio/src/main/java/java/nio/ReadWriteHeapByteBuffer.java
new file mode 100644
index 0000000..af74054
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadWriteHeapByteBuffer.java
@@ -0,0 +1,204 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+
+
+/**
+ * HeapByteBuffer, ReadWriteHeapByteBuffer and ReadOnlyHeapByteBuffer compose
+ * the implementation of array based byte buffers.
+ * <p>
+ * ReadWriteHeapByteBuffer extends HeapByteBuffer with all the write methods.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadWriteHeapByteBuffer extends HeapByteBuffer {
+
+ static ReadWriteHeapByteBuffer copy(HeapByteBuffer other, int markOfOther) {
+ ReadWriteHeapByteBuffer buf = new ReadWriteHeapByteBuffer(
+ other.backingArray, other.capacity(), other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ buf.order(other.order());
+ return buf;
+ }
+
+ ReadWriteHeapByteBuffer(byte[] backingArray) {
+ super(backingArray);
+ }
+
+ ReadWriteHeapByteBuffer(int capacity) {
+ super(capacity);
+ }
+
+ ReadWriteHeapByteBuffer(byte[] backingArray, int capacity, int arrayOffset) {
+ super(backingArray, capacity, arrayOffset);
+ }
+
+ public ByteBuffer asReadOnlyBuffer() {
+ return ReadOnlyHeapByteBuffer.copy(this, mark);
+ }
+
+ public ByteBuffer compact() {
+ System.arraycopy(backingArray, position + offset, backingArray, offset,
+ remaining());
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public ByteBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ protected byte[] protectedArray() {
+ return backingArray;
+ }
+
+ protected int protectedArrayOffset() {
+ return offset;
+ }
+
+ protected boolean protectedHasArray() {
+ return true;
+ }
+
+ public ByteBuffer put(byte b) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ backingArray[offset + position++] = b;
+ return this;
+ }
+
+ public ByteBuffer put(int index, byte b) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ backingArray[offset + index] = b;
+ return this;
+ }
+
+ /*
+ * Override ByteBuffer.put(byte[], int, int) to improve performance.
+ *
+ * (non-Javadoc)
+ *
+ * @see java.nio.ByteBuffer#put(byte[], int, int)
+ */
+ public ByteBuffer put(byte[] src, int off, int len) {
+ if (off < 0 || len < 0 || (long)off + (long)len > src.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ if (isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+ System.arraycopy(src, off, backingArray, offset
+ + position, len);
+ position += len;
+ return this;
+ }
+
+ public ByteBuffer putDouble(double value) {
+ return putLong(Double.doubleToRawLongBits(value));
+ }
+
+ public ByteBuffer putDouble(int index, double value) {
+ return putLong(index, Double.doubleToRawLongBits(value));
+ }
+
+ public ByteBuffer putFloat(float value) {
+ return putInt(Float.floatToIntBits(value));
+ }
+
+ public ByteBuffer putFloat(int index, float value) {
+ return putInt(index, Float.floatToIntBits(value));
+ }
+
+ public ByteBuffer putInt(int value) {
+ int newPosition = position + 4;
+ if (newPosition > limit) {
+ throw new BufferOverflowException();
+ }
+ store(position, value);
+ position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer putInt(int index, int value) {
+ if (index < 0 || (long)index + 4 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ store(index, value);
+ return this;
+ }
+
+ public ByteBuffer putLong(int index, long value) {
+ if (index < 0 || (long)index + 8 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ store(index, value);
+ return this;
+ }
+
+ public ByteBuffer putLong(long value) {
+ int newPosition = position + 8;
+ if (newPosition > limit) {
+ throw new BufferOverflowException();
+ }
+ store(position, value);
+ position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer putShort(int index, short value) {
+ if (index < 0 || (long)index + 2 > limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ store(index, value);
+ return this;
+ }
+
+ public ByteBuffer putShort(short value) {
+ int newPosition = position + 2;
+ if (newPosition > limit) {
+ throw new BufferOverflowException();
+ }
+ store(position, value);
+ position = newPosition;
+ return this;
+ }
+
+ public ByteBuffer slice() {
+ ReadWriteHeapByteBuffer slice = new ReadWriteHeapByteBuffer(
+ backingArray, remaining(), offset + position);
+ slice.order = order;
+ return slice;
+ }
+}
diff --git a/nio/src/main/java/java/nio/ReadWriteIntArrayBuffer.java b/nio/src/main/java/java/nio/ReadWriteIntArrayBuffer.java
new file mode 100644
index 0000000..005e45b
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadWriteIntArrayBuffer.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * IntArrayBuffer, ReadWriteIntArrayBuffer and ReadOnlyIntArrayBuffer compose
+ * the implementation of array based int buffers.
+ * <p>
+ * ReadWriteIntArrayBuffer extends IntArrayBuffer with all the write methods.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadWriteIntArrayBuffer extends IntArrayBuffer {
+
+ static ReadWriteIntArrayBuffer copy(IntArrayBuffer other, int markOfOther) {
+ ReadWriteIntArrayBuffer buf = new ReadWriteIntArrayBuffer(other
+ .capacity(), other.backingArray, other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ return buf;
+ }
+
+ ReadWriteIntArrayBuffer(int[] array) {
+ super(array);
+ }
+
+ ReadWriteIntArrayBuffer(int capacity) {
+ super(capacity);
+ }
+
+ ReadWriteIntArrayBuffer(int capacity, int[] backingArray, int arrayOffset) {
+ super(capacity, backingArray, arrayOffset);
+ }
+
+ public IntBuffer asReadOnlyBuffer() {
+ return ReadOnlyIntArrayBuffer.copy(this, mark);
+ }
+
+ public IntBuffer compact() {
+ System.arraycopy(backingArray, position + offset, backingArray, offset,
+ remaining());
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public IntBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ protected int[] protectedArray() {
+ return backingArray;
+ }
+
+ protected int protectedArrayOffset() {
+ return offset;
+ }
+
+ protected boolean protectedHasArray() {
+ return true;
+ }
+
+ public IntBuffer put(int c) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ backingArray[offset + position++] = c;
+ return this;
+ }
+
+ public IntBuffer put(int index, int c) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ backingArray[offset + index] = c;
+ return this;
+ }
+
+ public IntBuffer put(int[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ System.arraycopy(src, off, backingArray, offset
+ + position, len);
+ position += len;
+ return this;
+ }
+
+ public IntBuffer slice() {
+ return new ReadWriteIntArrayBuffer(remaining(), backingArray, offset
+ + position);
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ReadWriteLongArrayBuffer.java b/nio/src/main/java/java/nio/ReadWriteLongArrayBuffer.java
new file mode 100644
index 0000000..ff2c588
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadWriteLongArrayBuffer.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * LongArrayBuffer, ReadWriteLongArrayBuffer and ReadOnlyLongArrayBuffer compose
+ * the implementation of array based long buffers.
+ * <p>
+ * ReadWriteLongArrayBuffer extends LongArrayBuffer with all the write methods.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadWriteLongArrayBuffer extends LongArrayBuffer {
+
+ static ReadWriteLongArrayBuffer copy(LongArrayBuffer other, int markOfOther) {
+ ReadWriteLongArrayBuffer buf = new ReadWriteLongArrayBuffer(other
+ .capacity(), other.backingArray, other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ return buf;
+ }
+
+ ReadWriteLongArrayBuffer(long[] array) {
+ super(array);
+ }
+
+ ReadWriteLongArrayBuffer(int capacity) {
+ super(capacity);
+ }
+
+ ReadWriteLongArrayBuffer(int capacity, long[] backingArray, int arrayOffset) {
+ super(capacity, backingArray, arrayOffset);
+ }
+
+ public LongBuffer asReadOnlyBuffer() {
+ return ReadOnlyLongArrayBuffer.copy(this, mark);
+ }
+
+ public LongBuffer compact() {
+ System.arraycopy(backingArray, position + offset, backingArray, offset,
+ remaining());
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public LongBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ protected long[] protectedArray() {
+ return backingArray;
+ }
+
+ protected int protectedArrayOffset() {
+ return offset;
+ }
+
+ protected boolean protectedHasArray() {
+ return true;
+ }
+
+ public LongBuffer put(long c) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ backingArray[offset + position++] = c;
+ return this;
+ }
+
+ public LongBuffer put(int index, long c) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ backingArray[offset + index] = c;
+ return this;
+ }
+
+ public LongBuffer put(long[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ System.arraycopy(src, off, backingArray, offset
+ + position, len);
+ position += len;
+ return this;
+ }
+
+ public LongBuffer slice() {
+ return new ReadWriteLongArrayBuffer(remaining(), backingArray, offset
+ + position);
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ReadWriteShortArrayBuffer.java b/nio/src/main/java/java/nio/ReadWriteShortArrayBuffer.java
new file mode 100644
index 0000000..193bdb3
--- /dev/null
+++ b/nio/src/main/java/java/nio/ReadWriteShortArrayBuffer.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * ShortArrayBuffer, ReadWriteShortArrayBuffer and ReadOnlyShortArrayBuffer
+ * compose the implementation of array based short buffers.
+ * <p>
+ * ReadWriteShortArrayBuffer extends ShortArrayBuffer with all the write
+ * methods.
+ * </p>
+ * <p>
+ * This class is marked final for runtime performance.
+ * </p>
+ *
+ */
+final class ReadWriteShortArrayBuffer extends ShortArrayBuffer {
+
+ static ReadWriteShortArrayBuffer copy(ShortArrayBuffer other,
+ int markOfOther) {
+ ReadWriteShortArrayBuffer buf = new ReadWriteShortArrayBuffer(other
+ .capacity(), other.backingArray, other.offset);
+ buf.limit = other.limit();
+ buf.position = other.position();
+ buf.mark = markOfOther;
+ return buf;
+ }
+
+ ReadWriteShortArrayBuffer(short[] array) {
+ super(array);
+ }
+
+ ReadWriteShortArrayBuffer(int capacity) {
+ super(capacity);
+ }
+
+ ReadWriteShortArrayBuffer(int capacity, short[] backingArray,
+ int arrayOffset) {
+ super(capacity, backingArray, arrayOffset);
+ }
+
+ public ShortBuffer asReadOnlyBuffer() {
+ return ReadOnlyShortArrayBuffer.copy(this, mark);
+ }
+
+ public ShortBuffer compact() {
+ System.arraycopy(backingArray, position + offset, backingArray, offset,
+ remaining());
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public ShortBuffer duplicate() {
+ return copy(this, mark);
+ }
+
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ protected short[] protectedArray() {
+ return backingArray;
+ }
+
+ protected int protectedArrayOffset() {
+ return offset;
+ }
+
+ protected boolean protectedHasArray() {
+ return true;
+ }
+
+ public ShortBuffer put(short c) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ backingArray[offset + position++] = c;
+ return this;
+ }
+
+ public ShortBuffer put(int index, short c) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ backingArray[offset + index] = c;
+ return this;
+ }
+
+ public ShortBuffer put(short[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ System.arraycopy(src, off, backingArray, offset+position, len);
+ position += len;
+ return this;
+ }
+
+ public ShortBuffer slice() {
+ return new ReadWriteShortArrayBuffer(remaining(), backingArray, offset
+ + position);
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ShortArrayBuffer.java b/nio/src/main/java/java/nio/ShortArrayBuffer.java
new file mode 100644
index 0000000..54f8adb
--- /dev/null
+++ b/nio/src/main/java/java/nio/ShortArrayBuffer.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * ShortArrayBuffer, ReadWriteShortArrayBuffer and ReadOnlyShortArrayBuffer
+ * compose the implementation of array based short buffers.
+ * <p>
+ * ShortArrayBuffer implements all the shared readonly methods and is extended
+ * by the other two classes.
+ * </p>
+ * <p>
+ * All methods are marked final for runtime performance.
+ * </p>
+ *
+ */
+abstract class ShortArrayBuffer extends ShortBuffer {
+
+ protected final short[] backingArray;
+
+ protected final int offset;
+
+ ShortArrayBuffer(short[] array) {
+ this(array.length, array, 0);
+ }
+
+ ShortArrayBuffer(int capacity) {
+ this(capacity, new short[capacity], 0);
+ }
+
+ ShortArrayBuffer(int capacity, short[] backingArray, int offset) {
+ super(capacity);
+ this.backingArray = backingArray;
+ this.offset = offset;
+ }
+
+ public final short get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return backingArray[offset + position++];
+ }
+
+ public final short get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return backingArray[offset + index];
+ }
+
+ public final ShortBuffer get(short[] dest, int off, int len) {
+ int length = dest.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ System.arraycopy(backingArray, offset + position, dest,
+ off, len);
+ position += len;
+ return this;
+ }
+
+ public final boolean isDirect() {
+ return false;
+ }
+
+ public final ByteOrder order() {
+ return ByteOrder.nativeOrder();
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/ShortBuffer.java b/nio/src/main/java/java/nio/ShortBuffer.java
new file mode 100644
index 0000000..58c2462
--- /dev/null
+++ b/nio/src/main/java/java/nio/ShortBuffer.java
@@ -0,0 +1,584 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+/**
+ * A buffer of <code>short</code>s.
+ * <p>
+ * A short buffer can be created in either of the following ways:
+ * <ul>
+ * <li>{@link #allocate(int) Allocate} a new short array and create a buffer
+ * based on it;</li>
+ * <li>{@link #wrap(short[]) Wrap} an existing short array to create a new
+ * buffer;</li>
+ * <li>Use {@link java.nio.ByteBuffer#asShortBuffer() ByteBuffer.asShortBuffer}
+ * to create a short buffer based on a byte buffer.</li>
+ * </ul>
+ * </p>
+ */
+public abstract class ShortBuffer extends Buffer implements Comparable<ShortBuffer> {
+
+ /**
+ * Creates a short buffer based on a new allocated short array.
+ *
+ * @param capacity
+ * The capacity of the new buffer
+ * @return The created short buffer
+ * @throws IllegalArgumentException
+ * If <code>capacity</code> is less than zero
+ */
+ public static ShortBuffer allocate(int capacity) {
+ if (capacity < 0) {
+ throw new IllegalArgumentException();
+ }
+ return BufferFactory.newShortBuffer(capacity);
+ }
+
+ /**
+ * Creates a new short buffer by wrapping the given short array.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>wrap(array, 0, array.length)</code>.
+ * </p>
+ *
+ * @param array
+ * The short array which the new buffer will be based on
+ * @return The created short buffer
+ */
+ public static ShortBuffer wrap(short[] array) {
+ return wrap(array, 0, array.length);
+ }
+
+ /**
+ * Creates new a short buffer by wrapping the given short array.
+ * <p>
+ * The new buffer's position will be <code>start</code>, limit will be
+ * <code>start + len</code>, capacity will be the length of the array.
+ * </p>
+ *
+ * @param array
+ * The short array which the new buffer will be based on
+ * @param start
+ * The start index, must be no less than zero and no greater than
+ * <code>array.length</code>
+ * @param len
+ * The length, must be no less than zero and no greater than
+ * <code>array.length - start</code>
+ * @return The created short buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>start</code> or <code>len</code> is
+ * invalid
+ */
+ public static ShortBuffer wrap(short[] array, int start, int len) {
+ if (array == null) {
+ throw new NullPointerException();
+ }
+ if (start< 0 || len < 0 || (long)start + (long)len > array.length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ ShortBuffer buf = BufferFactory.newShortBuffer(array);
+ buf.position = start;
+ buf.limit = start + len;
+
+ return buf;
+ }
+
+ /**
+ * Constructs a <code>ShortBuffer</code> with given capacity.
+ *
+ * @param capacity
+ * The capacity of the buffer
+ */
+ ShortBuffer(int capacity) {
+ super(capacity);
+ // BEGIN android-added
+ _elementSizeShift = 1;
+ // END android-added
+ }
+
+ /**
+ * Returns the short array which this buffer is based on, if there's one.
+ *
+ * @return The short array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on an array, but it is readonly
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final short[] array() {
+ return protectedArray();
+ }
+
+ /**
+ * Returns the offset of the short array which this buffer is based on, if
+ * there's one.
+ * <p>
+ * The offset is the index of the array corresponds to the zero position of
+ * the buffer.
+ * </p>
+ *
+ * @return The offset of the short array which this buffer is based on
+ * @exception ReadOnlyBufferException
+ * If this buffer is based on an array, but it is readonly
+ * @exception UnsupportedOperationException
+ * If this buffer is not based on an array
+ */
+ public final int arrayOffset() {
+ return protectedArrayOffset();
+ }
+
+ // BEGIN android-added
+ @Override Object _array() {
+ if (hasArray()) {
+ return array();
+ }
+ return null;
+ }
+
+ @Override int _arrayOffset() {
+ if (hasArray()) {
+ return arrayOffset();
+ }
+ return 0;
+ }
+ // END android-added
+
+ /**
+ * Returns a readonly buffer that shares content with this buffer.
+ * <p>
+ * The returned buffer is guaranteed to be a new instance, even this buffer
+ * is readonly itself. The new buffer's position, limit, capacity and mark
+ * are the same as this buffer.
+ * </p>
+ * <p>
+ * The new buffer shares content with this buffer, which means this buffer's
+ * change of content will be visible to the new buffer. The two buffer's
+ * position, limit and mark are independent.
+ * </p>
+ *
+ * @return A readonly version of this buffer.
+ */
+ public abstract ShortBuffer asReadOnlyBuffer();
+
+ /**
+ * Compacts this short buffer.
+ * <p>
+ * The remaining <code>short</code>s will be moved to the head of the
+ * buffer, staring from position zero. Then the position is set to
+ * <code>remaining()</code>; the limit is set to capacity; the mark is
+ * cleared.
+ * </p>
+ *
+ * @return This buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ShortBuffer compact();
+
+ /**
+ * Compare the remaining <code>short</code>s of this buffer to another
+ * short buffer's remaining <code>short</code>s.
+ *
+ * @param otherBuffer
+ * Another short buffer
+ * @return a negative value if this is less than <code>other</code>; 0 if
+ * this equals to <code>other</code>; a positive value if this is
+ * greater than <code>other</code>
+ * @exception ClassCastException
+ * If <code>other</code> is not a short buffer
+ */
+ public int compareTo(ShortBuffer otherBuffer) {
+ int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
+ : otherBuffer.remaining();
+ int thisPos = position;
+ int otherPos = otherBuffer.position;
+ short thisByte, otherByte;
+ while (compareRemaining > 0) {
+ thisByte = get(thisPos);
+ otherByte = otherBuffer.get(otherPos);
+ if (thisByte != otherByte) {
+ return thisByte < otherByte ? -1 : 1;
+ }
+ thisPos++;
+ otherPos++;
+ compareRemaining--;
+ }
+ return remaining() - otherBuffer.remaining();
+ }
+
+ /**
+ * Returns a duplicated buffer that shares content with this buffer.
+ * <p>
+ * The duplicated buffer's position, limit, capacity and mark are the same
+ * as this buffer. The duplicated buffer's readonly property and byte order
+ * are same as this buffer too.
+ * </p>
+ * <p>
+ * The new buffer shares content with this buffer, which means either
+ * buffer's change of content will be visible to the other. The two buffer's
+ * position, limit and mark are independent.
+ * </p>
+ *
+ * @return A duplicated buffer that shares content with this buffer.
+ */
+ public abstract ShortBuffer duplicate();
+
+ /**
+ * Tests whether this short buffer equals to another object.
+ * <p>
+ * If <code>other</code> is not a short buffer, then false is returned.
+ * </p>
+ * <p>
+ * Two short buffers are equals if, and only if, their remaining
+ * <code>short</code>s are exactly the same. Position, limit, capacity
+ * and mark are not considered.
+ * </p>
+ *
+ * @param other
+ * the object to be compared against
+ * @return Whether this short buffer equals to another object.
+ */
+ public boolean equals(Object other) {
+ if (!(other instanceof ShortBuffer)) {
+ return false;
+ }
+ ShortBuffer otherBuffer = (ShortBuffer) other;
+
+ if (remaining() != otherBuffer.remaining()) {
+ return false;
+ }
+
+ int myPosition = position;
+ int otherPosition = otherBuffer.position;
+ boolean equalSoFar = true;
+ while (equalSoFar && (myPosition < limit)) {
+ equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++);
+ }
+
+ return equalSoFar;
+ }
+
+ /**
+ * Returns the short at the current position and increase the position by 1.
+ *
+ * @return The short at the current position.
+ * @exception BufferUnderflowException
+ * If the position is equal or greater than limit
+ */
+ public abstract short get();
+
+ /**
+ * Reads <code>short</code>s from the current position into the specified
+ * short array and increase the position by the number of <code>short</code>s
+ * read.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>get(dest, 0, dest.length)</code>.
+ * </p>
+ *
+ * @param dest
+ * The destination short array
+ * @return This buffer
+ * @exception BufferUnderflowException
+ * if <code>dest.length</code> is greater than
+ * <code>remaining()</code>
+ */
+ public ShortBuffer get(short[] dest) {
+ return get(dest, 0, dest.length);
+ }
+
+ /**
+ * Reads <code>short</code>s from the current position into the specified
+ * short array, starting from the specified offset, and increase the
+ * position by the number of <code>short</code>s read.
+ *
+ * @param dest
+ * The target short array
+ * @param off
+ * The offset of the short array, must be no less than zero and
+ * no greater than <code>dest.length</code>
+ * @param len
+ * The number of <code>short</code>s to read, must be no less
+ * than zero and no greater than <code>dest.length - off</code>
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception BufferUnderflowException
+ * If <code>len</code> is greater than
+ * <code>remaining()</code>
+ */
+ public ShortBuffer get(short[] dest, int off, int len) {
+ int length = dest.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (len > remaining()) {
+ throw new BufferUnderflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ dest[i] = get();
+ }
+ return this;
+ }
+
+ /**
+ * Returns a short at the specified index, and the position is not changed.
+ *
+ * @param index
+ * The index, must be no less than zero and less than limit
+ * @return A short at the specified index.
+ * @exception IndexOutOfBoundsException
+ * If index is invalid
+ */
+ public abstract short get(int index);
+
+ /**
+ * Returns whether this buffer is based on a short array and is read/write.
+ * <p>
+ * If this buffer is readonly, then false is returned.
+ * </p>
+ *
+ * @return Whether this buffer is based on a short array and is read/write.
+ */
+ public final boolean hasArray() {
+ return protectedHasArray();
+ }
+
+ /**
+ * Hash code is calculated from the remaining <code>short</code>s.
+ * <p>
+ * Position, limit, capacity and mark don't affect the hash code.
+ * </p>
+ *
+ * @return The hash code calculated from the remaining <code>short</code>s.
+ */
+ public int hashCode() {
+ int myPosition = position;
+ int hash = 0;
+ while (myPosition < limit) {
+ hash = hash + get(myPosition++);
+ }
+ return hash;
+ }
+
+ /**
+ * Returns true if this buffer is direct.
+ * <p>
+ * A direct buffer will try its best to take advantage of native memory APIs
+ * and it may not stay in java heap, thus not affected by GC.
+ * </p>
+ * <p>
+ * A short buffer is direct, if it is based on a byte buffer and the byte
+ * buffer is direct.
+ * </p>
+ *
+ * @return True if this buffer is direct.
+ */
+ public abstract boolean isDirect();
+
+ /**
+ * Returns the byte order used by this buffer when converting
+ * <code>short</code>s from/to <code>byte</code>s.
+ * <p>
+ * If this buffer is not based on a byte buffer, then always return the
+ * platform's native byte order.
+ * </p>
+ *
+ * @return The byte order used by this buffer when converting
+ * <code>short</code>s from/to <code>byte</code>s.
+ */
+ public abstract ByteOrder order();
+
+ /**
+ * Child class implements this method to realize <code>array()</code>.
+ *
+ * @return see <code>array()</code>
+ */
+ abstract short[] protectedArray();
+
+ /**
+ * Child class implements this method to realize <code>arrayOffset()</code>.
+ *
+ * @return see <code>arrayOffset()</code>
+ */
+ abstract int protectedArrayOffset();
+
+ /**
+ * Child class implements this method to realize <code>hasArray()</code>.
+ *
+ * @return see <code>hasArray()</code>
+ */
+ abstract boolean protectedHasArray();
+
+ /**
+ * Writes the given short to the current position and increase the position
+ * by 1.
+ *
+ * @param s
+ * The short to write
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If position is equal or greater than limit
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ShortBuffer put(short s);
+
+ /**
+ * Writes <code>short</code>s in the given short array to the current
+ * position and increase the position by the number of <code>short</code>s
+ * written.
+ * <p>
+ * Calling this method has the same effect as
+ * <code>put(src, 0, src.length)</code>.
+ * </p>
+ *
+ * @param src
+ * The source short array
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>src.length</code>
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public final ShortBuffer put(short[] src) {
+ return put(src, 0, src.length);
+ }
+
+ /**
+ * Writes <code>short</code>s in the given short array, starting from the
+ * specified offset, to the current position and increase the position by
+ * the number of <code>short</code>s written.
+ *
+ * @param src
+ * The source short array
+ * @param off
+ * The offset of short array, must be no less than zero and no
+ * greater than <code>src.length</code>
+ * @param len
+ * The number of <code>short</code>s to write, must be no less
+ * than zero and no greater than <code>src.length - off</code>
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>remaining()</code> is less than
+ * <code>len</code>
+ * @exception IndexOutOfBoundsException
+ * If either <code>off</code> or <code>len</code> is
+ * invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public ShortBuffer put(short[] src, int off, int len) {
+ int length = src.length;
+ if (off < 0 || len < 0 || (long)off + (long)len > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len > remaining()) {
+ throw new BufferOverflowException();
+ }
+ for (int i = off; i < off + len; i++) {
+ put(src[i]);
+ }
+ return this;
+ }
+
+ /**
+ * Writes all the remaining <code>short</code>s of the <code>src</code>
+ * short buffer to this buffer's current position, and increase both
+ * buffers' position by the number of <code>short</code>s copied.
+ *
+ * @param src
+ * The source short buffer
+ * @return This buffer
+ * @exception BufferOverflowException
+ * If <code>src.remaining()</code> is greater than this
+ * buffer's <code>remaining()</code>
+ * @exception IllegalArgumentException
+ * If <code>src</code> is this buffer
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public ShortBuffer put(ShortBuffer src) {
+ if (src == this) {
+ throw new IllegalArgumentException();
+ }
+ if (src.remaining() > remaining()) {
+ throw new BufferOverflowException();
+ }
+ short[] contents = new short[src.remaining()];
+ src.get(contents);
+ put(contents);
+ return this;
+ }
+
+ /**
+ * Write a short to the specified index of this buffer and the position is
+ * not changed.
+ *
+ * @param index
+ * The index, must be no less than zero and less than the limit
+ * @param s
+ * The short to write
+ * @return This buffer
+ * @exception IndexOutOfBoundsException
+ * If index is invalid
+ * @exception ReadOnlyBufferException
+ * If no changes may be made to the contents of this buffer
+ */
+ public abstract ShortBuffer put(int index, short s);
+
+ /**
+ * Returns a sliced buffer that shares content with this buffer.
+ * <p>
+ * The sliced buffer's capacity will be this buffer's
+ * <code>remaining()</code>, and its zero position will correspond to
+ * this buffer's current position. The new buffer's position will be 0,
+ * limit will be its capacity, and its mark is unset. The new buffer's
+ * readonly property and byte order are same as this buffer.
+ * </p>
+ * <p>
+ * The new buffer shares content with this buffer, which means either
+ * buffer's change of content will be visible to the other. The two buffer's
+ * position, limit and mark are independent.
+ * </p>
+ *
+ * @return A sliced buffer that shares content with this buffer.
+ */
+ public abstract ShortBuffer slice();
+
+ /**
+ * Returns a string represents the state of this short buffer.
+ *
+ * @return A string represents the state of this short buffer.
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append(getClass().getName());
+ buf.append(", status: capacity="); //$NON-NLS-1$
+ buf.append(capacity());
+ buf.append(" position="); //$NON-NLS-1$
+ buf.append(position());
+ buf.append(" limit="); //$NON-NLS-1$
+ buf.append(limit());
+ return buf.toString();
+ }
+}
diff --git a/nio/src/main/java/java/nio/ShortToByteBufferAdapter.java b/nio/src/main/java/java/nio/ShortToByteBufferAdapter.java
new file mode 100644
index 0000000..a3c3e38
--- /dev/null
+++ b/nio/src/main/java/java/nio/ShortToByteBufferAdapter.java
@@ -0,0 +1,216 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio;
+
+// BEGIN android-added
+// Copied from newer version of harmony
+import org.apache.harmony.nio.internal.DirectBuffer;
+import org.apache.harmony.luni.platform.PlatformAddress;
+// END android-added
+
+/**
+ * This class wraps a byte buffer to be a short buffer.
+ * <p>
+ * Implementation notice:
+ * <ul>
+ * <li>After a byte buffer instance is wrapped, it becomes privately owned by
+ * the adapter. It must NOT be accessed outside the adapter any more.</li>
+ * <li>The byte buffer's position and limit are NOT linked with the adapter.
+ * The adapter extends Buffer, thus has its own position and limit.</li>
+ * </ul>
+ * </p>
+ *
+ */
+// BEGIN android-changed
+// Copied from newer version of harmony
+final class ShortToByteBufferAdapter extends ShortBuffer implements DirectBuffer {
+// END android-changed
+
+ static ShortBuffer wrap(ByteBuffer byteBuffer) {
+ return new ShortToByteBufferAdapter(byteBuffer.slice());
+ }
+
+ private final ByteBuffer byteBuffer;
+
+ ShortToByteBufferAdapter(ByteBuffer byteBuffer) {
+ super((byteBuffer.capacity() >> 1));
+ this.byteBuffer = byteBuffer;
+ this.byteBuffer.clear();
+ }
+
+// BEGIN android-added
+// Copied from newer version of harmony
+ public int getByteCapacity() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getByteCapacity();
+ } else {
+ assert false : byteBuffer;
+ return -1;
+ }
+ }
+
+ public PlatformAddress getEffectiveAddress() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getEffectiveAddress();
+ } else {
+ assert false : byteBuffer;
+ return null;
+ }
+ }
+
+ public PlatformAddress getBaseAddress() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).getBaseAddress();
+ } else {
+ assert false : byteBuffer;
+ return null;
+ }
+ }
+
+ public boolean isAddressValid() {
+ if (byteBuffer instanceof DirectBuffer) {
+ return ((DirectBuffer)byteBuffer).isAddressValid();
+ } else {
+ assert false : byteBuffer;
+ return false;
+ }
+ }
+
+ public void addressValidityCheck() {
+ if (byteBuffer instanceof DirectBuffer) {
+ ((DirectBuffer)byteBuffer).addressValidityCheck();
+ } else {
+ assert false : byteBuffer;
+ }
+ }
+
+ public void free() {
+ if (byteBuffer instanceof DirectBuffer) {
+ ((DirectBuffer)byteBuffer).free();
+ } else {
+ assert false : byteBuffer;
+ }
+ }
+ // END android-added
+
+ public ShortBuffer asReadOnlyBuffer() {
+ ShortToByteBufferAdapter buf = new ShortToByteBufferAdapter(byteBuffer
+ .asReadOnlyBuffer());
+ buf.limit = limit;
+ buf.position = position;
+ buf.mark = mark;
+ return buf;
+ }
+
+ public ShortBuffer compact() {
+ if (byteBuffer.isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+ byteBuffer.limit(limit << 1);
+ byteBuffer.position(position << 1);
+ byteBuffer.compact();
+ byteBuffer.clear();
+ position = limit - position;
+ limit = capacity;
+ mark = UNSET_MARK;
+ return this;
+ }
+
+ public ShortBuffer duplicate() {
+ ShortToByteBufferAdapter buf = new ShortToByteBufferAdapter(byteBuffer
+ .duplicate());
+ buf.limit = limit;
+ buf.position = position;
+ buf.mark = mark;
+ return buf;
+ }
+
+ public short get() {
+ if (position == limit) {
+ throw new BufferUnderflowException();
+ }
+ return byteBuffer.getShort(position++ << 1);
+ }
+
+ public short get(int index) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ return byteBuffer.getShort(index << 1);
+ }
+
+ public boolean isDirect() {
+ return byteBuffer.isDirect();
+ }
+
+ public boolean isReadOnly() {
+ return byteBuffer.isReadOnly();
+ }
+
+ public ByteOrder order() {
+ return byteBuffer.order();
+ }
+
+ protected short[] protectedArray() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected int protectedArrayOffset() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected boolean protectedHasArray() {
+ return false;
+ }
+
+ public ShortBuffer put(short c) {
+ if (position == limit) {
+ throw new BufferOverflowException();
+ }
+ byteBuffer.putShort(position++ << 1, c);
+ return this;
+ }
+
+ public ShortBuffer put(int index, short c) {
+ if (index < 0 || index >= limit) {
+ throw new IndexOutOfBoundsException();
+ }
+ byteBuffer.putShort(index << 1, c);
+ return this;
+ }
+
+ // BEGIN android-added
+ public ShortBuffer put(short[] s, int off, int len) {
+ if (byteBuffer instanceof ReadWriteDirectByteBuffer) {
+ ((ReadWriteDirectByteBuffer) byteBuffer).put(s, off, len);
+ this.position += len;
+ return this;
+ } else {
+ return super.put(s, off, len);
+ }
+ }
+ // END android-added
+
+ public ShortBuffer slice() {
+ byteBuffer.limit(limit << 1);
+ byteBuffer.position(position << 1);
+ ShortBuffer result = new ShortToByteBufferAdapter(byteBuffer.slice());
+ byteBuffer.clear();
+ return result;
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/channels/AlreadyConnectedException.java b/nio/src/main/java/java/nio/channels/AlreadyConnectedException.java
new file mode 100644
index 0000000..a092dc9
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/AlreadyConnectedException.java
@@ -0,0 +1,34 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown when an attempt is made to connect a SocketChannel that is already connected.
+ *
+ */
+public class AlreadyConnectedException extends IllegalStateException {
+
+ private static final long serialVersionUID = -7331895245053773357L;
+
+ /**
+ * Default constructor.
+ */
+ public AlreadyConnectedException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/AsynchronousCloseException.java b/nio/src/main/java/java/nio/channels/AsynchronousCloseException.java
new file mode 100644
index 0000000..2c07ba0
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/AsynchronousCloseException.java
@@ -0,0 +1,35 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown when the underlying channel for an IO operation is closed by another thread.
+ *
+ */
+public class AsynchronousCloseException extends ClosedChannelException {
+
+ private static final long serialVersionUID = 6891178312432313966L;
+
+ /**
+ * Default constructor
+ */
+ public AsynchronousCloseException() {
+ super();
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/channels/ByteChannel.java b/nio/src/main/java/java/nio/channels/ByteChannel.java
new file mode 100644
index 0000000..0c262c0
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/ByteChannel.java
@@ -0,0 +1,30 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * A ByteChannel is both readable and writable.
+ * <p>
+ * The methods for the byte channel are precisely those defined by readable and
+ * writable byte channels.
+ * </p>
+ *
+ */
+public interface ByteChannel extends ReadableByteChannel, WritableByteChannel {
+ // No methods defined.
+}
diff --git a/nio/src/main/java/java/nio/channels/CancelledKeyException.java b/nio/src/main/java/java/nio/channels/CancelledKeyException.java
new file mode 100644
index 0000000..c448fd8
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/CancelledKeyException.java
@@ -0,0 +1,38 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown when an invalid selection key is used.
+ *
+ */
+public class CancelledKeyException extends IllegalStateException {
+
+ /**
+ * Version ID for serialization.
+ */
+ private static final long serialVersionUID = -8438032138028814268L;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public CancelledKeyException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/Channel.java b/nio/src/main/java/java/nio/channels/Channel.java
new file mode 100644
index 0000000..da9e715
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/Channel.java
@@ -0,0 +1,67 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+import java.io.Closeable;
+import java.io.IOException;
+
+/**
+ * A channel is a conduit to IO services covering such items as files, sockets,
+ * hardware devices, IO ports, or some software component.
+ * <p>
+ * Channels are open upon creation, and can be explicitly closed. Once a channel
+ * is closed it cannot be re-opened, and attempts to perform IO operations on
+ * the closed channel result in a <code>ClosedChannelException
+ * </code>.
+ * </p>
+ * <p>
+ * Particular implementations or sub-interfaces of Channel dictate whether they
+ * are thread-safe or not.
+ * </p>
+ *
+ */
+public interface Channel extends Closeable {
+
+ /**
+ * Returns whether this channel is open or not.
+ *
+ * @return true if the channel is open, otherwise returns false.
+ */
+ public boolean isOpen();
+
+ /**
+ * Closes an open channel.
+ *
+ * If the channel is already closed this method has no effect. If there is a
+ * problem with closing the channel then the method throws an IOException
+ * and the exception contains reasons for the failure.
+ * <p>
+ * If an attempt is made to perform an operation on a closed channel then a
+ * <code>ClosedChannelException</code> will be thrown on that attempt.
+ * </p>
+ * <p>
+ * If multiple threads attempts to simultaneously close a channel, then only
+ * one thread will run the closure code, and others will be blocked until the
+ * first returns.
+ * </p>
+ *
+ * @throws IOException
+ * if a problem occurs closing the channel.
+ */
+ public void close() throws IOException;
+}
diff --git a/nio/src/main/java/java/nio/channels/Channels.java b/nio/src/main/java/java/nio/channels/Channels.java
new file mode 100644
index 0000000..10a301c
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/Channels.java
@@ -0,0 +1,569 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.spi.AbstractInterruptibleChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import org.apache.harmony.nio.internal.IOUtil;
+
+/**
+ * This class provides several utilities to get I/O streams from channels.
+ *
+ */
+public final class Channels {
+
+ // -------------------------------------------------------------------
+ // Constructor
+ // -------------------------------------------------------------------
+ /*
+ * Not intended to be instantiated.
+ */
+ private Channels() {
+ super();
+ }
+
+ // -------------------------------------------------------------------
+ // Public Methods
+ // -------------------------------------------------------------------
+
+ /**
+ * Returns an input stream on the given channel
+ *
+ * @param channel
+ * The channel to be wrapped in an InputStream.
+ * @return an InputStream that takes bytes from the given byte channel.
+ */
+ public static InputStream newInputStream(ReadableByteChannel channel) {
+ return new ReadableByteChannelInputStream(channel);
+ }
+
+ /**
+ * Returns an output stream on the given channel
+ *
+ * @param channel
+ * the channel to be wrapped in an OutputStream.
+ * @return an OutputStream that puts bytes onto the given byte channel.
+ */
+ public static OutputStream newOutputStream(WritableByteChannel channel) {
+ return new WritableByteChannelOutputStream(channel);
+ }
+
+ /**
+ * Returns a channel on the given input stream
+ *
+ * @param inputStream
+ * the stream to be wrapped in a byte channel.
+ * @return a byte channel that reads bytes from the input stream.
+ */
+ public static ReadableByteChannel newChannel(InputStream inputStream) {
+ return new ReadableByteChannelImpl(inputStream);
+ }
+
+ /**
+ * Returns a channel on the given output stream
+ *
+ * @param outputStream
+ * the stream to be wrapped in a byte channel.
+ * @return a byte channel that writes bytes to the output stream.
+ */
+ public static WritableByteChannel newChannel(OutputStream outputStream) {
+ return new WritableByteChannelImpl(outputStream);
+ }
+
+ /**
+ * Returns a reader that decodes bytes from a channel.
+ *
+ * @param channel
+ * Channel to be read.
+ * @param decoder
+ * Charset decoder to be used.
+ * @param minBufferCapacity
+ * The minimum size of byte buffer, -1 means to use default size.
+ * @return The reader.
+ */
+ public static Reader newReader(ReadableByteChannel channel,
+ CharsetDecoder decoder, int minBufferCapacity) {
+ return new ByteChannelReader(
+ new ReaderInputStream(channel), decoder,
+ minBufferCapacity);
+ }
+
+ /**
+ * Returns a reader that decodes bytes from a channel.
+ *
+ * @param channel
+ * Channel to be read.
+ * @param charsetName
+ * Name of charset.
+ * @return The reader.
+ */
+ public static Reader newReader(ReadableByteChannel channel,
+ String charsetName) {
+ return newReader(channel, Charset.forName(charsetName).newDecoder(), -1);
+ }
+
+ /**
+ * Returns a writer that encodes characters by encoder and output bytes to a
+ * channel.
+ *
+ * @param channel
+ * Channel to be written.
+ * @param encoder
+ * Charset decoder to be used.
+ * @param minBufferCapacity
+ * The minimum size of byte buffer, -1 means to use default size.
+ * @return The writer.
+ */
+ public static Writer newWriter(WritableByteChannel channel,
+ CharsetEncoder encoder, int minBufferCapacity) {
+ return new ByteChannelWriter(new WritableByteChannelOutputStream(
+ channel), encoder, minBufferCapacity);
+ }
+
+ /**
+ * Returns a writer that encodes characters by encoder and output bytes to a
+ * channel.
+ *
+ * @param channel
+ * Channel to be written.
+ * @param charsetName
+ * Name of charset.
+ * @return The writer.
+ */
+ public static Writer newWriter(WritableByteChannel channel,
+ String charsetName) {
+ return newWriter(channel, Charset.forName(charsetName).newEncoder(), -1);
+ }
+
+ // -------------------------------------------------------------------
+ // share routine
+ // -------------------------------------------------------------------
+ /*
+ * wrap a byte array to a ByteBuffer
+ */
+ static ByteBuffer wrapByteBuffer(byte[] bytes, int offset, int length) {
+ ByteBuffer buffer = ByteBuffer.wrap(bytes);
+ int newLimit = offset + length <= buffer.capacity() ? offset + length
+ : buffer.capacity();
+ buffer.limit(newLimit);
+ buffer.position(offset);
+ return buffer;
+ }
+
+ // -------------------------------------------------------------------
+ // Wrapper classes
+ // -------------------------------------------------------------------
+
+ private static class ChannelInputStream extends InputStream {
+
+ protected ReadableByteChannel channel;
+
+ public ChannelInputStream(ReadableByteChannel aChannel) {
+ super();
+ channel = aChannel;
+ }
+
+ /*
+ * @see java.io.InputStream#read()
+ */
+ @Override
+ public synchronized int read() throws IOException {
+ byte[] oneByte = new byte[1];
+ int n = read(oneByte);
+ if (n == 1) {
+ // reads a single byte 0-255
+ return oneByte[0] & 0xff;
+ }
+ return -1;
+ }
+
+ /*
+ * @see java.io.InputStream#close()
+ */
+ @Override
+ public synchronized void close() throws IOException {
+ channel.close();
+ }
+ }
+
+ /*
+ * Wrapper class used for newInputStream(ReadableByteChannel channel)
+ */
+ private static class ReadableByteChannelInputStream extends
+ ChannelInputStream {
+
+ /*
+ * @param someChannel
+ */
+ public ReadableByteChannelInputStream(ReadableByteChannel aChannel) {
+ super(aChannel);
+ }
+
+ /*
+ * @see java.io.InputStream#read(byte[], int, int)
+ */
+ @Override
+ public synchronized int read(byte[] target, int offset, int length)
+ throws IOException {
+ // avoid int overflow, check null target
+ if (length + offset > target.length || length < 0 || offset < 0) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ if (0 == length) {
+ return 0;
+ }
+ if (channel instanceof SelectableChannel) {
+ if (!((SelectableChannel) channel).isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ }
+ ByteBuffer buffer = ByteBuffer.wrap(target, offset, length);
+ return channel.read(buffer);
+ }
+ }
+
+ /*
+ * Wrapper class used for newReader(ReadableByteChannel channel,
+ * CharsetDecoder decoder, int minBufferCapacity)
+ */
+ private static class ReaderInputStream extends ChannelInputStream {
+
+ /*
+ * @param someChannel
+ */
+ public ReaderInputStream(ReadableByteChannel aChannel) {
+ super(aChannel);
+ }
+
+ /*
+ * @see java.io.InputStream#read(byte[], int, int)
+ */
+ @Override
+ public synchronized int read(byte[] target, int offset, int length)
+ throws IOException {
+ // avoid int overflow, check null target
+ if (length + offset > target.length || length < 0 || offset < 0) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ if (0 == length) {
+ return 0;
+ }
+ ByteBuffer buffer = ByteBuffer.wrap(target, offset, length);
+ return channel.read(buffer);
+ }
+ }
+
+ /*
+ * Wrapper class used for newOutputStream(WritableByteChannel channel)
+ */
+ private static class WritableByteChannelOutputStream extends OutputStream {
+
+ private WritableByteChannel channel;
+
+ /*
+ * @param someChannel
+ */
+ public WritableByteChannelOutputStream(WritableByteChannel aChannel) {
+ super();
+ channel = aChannel;
+ }
+
+ /*
+ * @see java.io.OutputStream#write(int)
+ */
+ public synchronized void write(int oneByte) throws IOException {
+ byte[] wrappedByte = new byte[1];
+ wrappedByte[0] = (byte) oneByte;
+ write(wrappedByte);
+ }
+
+ /*
+ * @see java.io.OutputStream#write(byte[], int, int)
+ */
+ public synchronized void write(byte[] source, int offset, int length)
+ throws IOException {
+ // avoid int overflow, check null source
+ if (length + offset > source.length || length < 0 || offset < 0) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ if (0 == length) {
+ return;
+ }
+ if (channel instanceof SelectableChannel) {
+ if (!((SelectableChannel) channel).isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ }
+ ByteBuffer buffer = ByteBuffer.wrap(source, offset, length);
+ channel.write(buffer);
+ }
+
+ /*
+ * @see java.io.OutputStream#close()
+ */
+ public synchronized void close() throws IOException {
+ channel.close();
+ }
+ }
+
+ /*
+ * Wrapper class used for newChannel(InputStream inputStream)
+ */
+ private static class ReadableByteChannelImpl extends
+ AbstractInterruptibleChannel implements ReadableByteChannel {
+ private InputStream inputStream;
+
+ ReadableByteChannelImpl(InputStream aInputStream) {
+ super();
+ inputStream = aInputStream;
+ }
+
+ /*
+ * @see java.nio.channels.ReadableByteChannel#read(java.nio.ByteBuffer)
+ */
+ public synchronized int read(ByteBuffer target) throws IOException {
+ if (!isOpen()) {
+ throw new ClosedChannelException();
+ }
+ int bytesRemain = target.remaining();
+ byte[] bytes = new byte[bytesRemain];
+ int readCount = 0;
+ try {
+ begin();
+ readCount = inputStream.read(bytes);
+ } finally {
+ end(readCount >= 0);
+ }
+ if (readCount > 0) {
+ target.put(bytes, 0, readCount);
+ }
+ return readCount;
+ }
+
+ /*
+ * @see java.nio.channels.spi.AbstractInterruptibleChannel#implCloseChannel()
+ */
+ protected void implCloseChannel() throws IOException {
+ inputStream.close();
+ }
+ }
+
+ /*
+ * Wrapper class used for newChannel(OutputStream outputStream)
+ */
+ private static class WritableByteChannelImpl extends
+ AbstractInterruptibleChannel implements WritableByteChannel {
+ private OutputStream outputStream;
+
+ WritableByteChannelImpl(OutputStream aOutputStream) {
+ super();
+ outputStream = aOutputStream;
+ }
+
+ /*
+ * @see java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer)
+ */
+ public synchronized int write(ByteBuffer source) throws IOException {
+ if (!isOpen()) {
+ throw new ClosedChannelException();
+ }
+ int bytesRemain = source.remaining();
+ if (bytesRemain == 0) {
+ return 0;
+ }
+ byte[] buf = new byte[bytesRemain];
+ source.get(buf);
+ try {
+ begin();
+ outputStream.write(buf, 0, bytesRemain);
+ } finally {
+ end(bytesRemain >= 0);
+ }
+ return bytesRemain;
+ }
+
+ /*
+ * @see java.nio.channels.spi.AbstractInterruptibleChannel#implCloseChannel()
+ */
+ protected void implCloseChannel() throws IOException {
+ outputStream.close();
+ }
+ }
+
+ /*
+ * Wrapper class used for newReader(ReadableByteChannel channel,
+ * CharsetDecoder decoder, int minBufferCapacity)
+ */
+ private static class ByteChannelReader extends Reader {
+
+ private InputStream inputStream;
+
+ private static final int BUFFER_SIZE = 8192;
+
+ CharsetDecoder decoder;
+
+ ByteBuffer bytes;
+
+ CharBuffer chars;
+
+ /*
+ * @param inputStream @param dec @param minBufferCapacity
+ */
+ public ByteChannelReader(InputStream aInputStream,
+ CharsetDecoder aDecoder, int minBufferCapacity) {
+ super(aInputStream);
+ aDecoder.reset();
+ inputStream = aInputStream;
+ int bufferSize = Math.max(minBufferCapacity, BUFFER_SIZE);
+ bytes = ByteBuffer.allocate(bufferSize);
+ chars = CharBuffer.allocate(bufferSize);
+ decoder = aDecoder;
+ chars.limit(0);
+ }
+
+ /*
+ * @see java.io.Reader#close()
+ */
+ public void close() throws IOException {
+ synchronized (lock) {
+ decoder = null;
+ if (inputStream != null) {
+ inputStream.close();
+ inputStream = null;
+ }
+ }
+ }
+
+ /*
+ * @see java.io.Reader#ready()
+ */
+ public boolean ready() {
+ synchronized (lock) {
+ if (null == inputStream) {
+ return false;
+ }
+ try {
+ return chars.limit() > chars.position()
+ || inputStream.available() > 0;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+ }
+
+ /*
+ * @see java.io.Reader#read()
+ */
+ public int read() throws IOException {
+ return IOUtil.readInputStreamReader(inputStream,
+ bytes, chars, decoder, lock);
+ }
+
+ /*
+ * @see java.io.Reader#read(char[], int, int)
+ */
+ public int read(char[] buf, int offset, int length) throws IOException {
+ return IOUtil.readInputStreamReader(buf, offset,
+ length, inputStream, bytes, chars, decoder, lock);
+ }
+ }
+
+ /*
+ * Wrapper class used for newWriter(WritableByteChannel channel,
+ * CharsetEncoder encoder, int minBufferCapacity)
+ */
+ private static class ByteChannelWriter extends Writer {
+
+ private static final int BUFFER_SIZE = 8192;
+
+ private OutputStream outputStream;
+
+ private CharsetEncoder encoder;
+
+ private ByteBuffer byteBuf;
+
+ /*
+ * @param outputStream @param enc @param minBufferCap
+ */
+ public ByteChannelWriter(OutputStream aOutputStream,
+ CharsetEncoder aEncoder, int minBufferCap) {
+ super(aOutputStream);
+ aEncoder.charset();
+ outputStream = aOutputStream;
+ byteBuf = ByteBuffer.allocate(Math.max(minBufferCap, BUFFER_SIZE));
+ encoder = aEncoder;
+ }
+
+ /*
+ * @see java.io.Writer#close()
+ */
+ public void close() throws IOException {
+ synchronized (lock) {
+ if (encoder != null) {
+ flush();
+ outputStream.flush();
+ outputStream.close();
+ encoder = null;
+ byteBuf = null;
+ }
+ }
+ }
+
+ /*
+ * @see java.io.Writer#flush()
+ */
+ public void flush() throws IOException {
+ IOUtil.flushOutputStreamWriter(outputStream,
+ byteBuf, encoder, lock);
+ }
+
+ /*
+ * @see java.io.Writer#write(char[], int, int)
+ */
+ public void write(char[] buf, int offset, int count) throws IOException {
+ IOUtil.writeOutputStreamWriter(buf, offset, count,
+ outputStream, byteBuf, encoder, lock);
+ }
+
+ /*
+ * @see java.io.Writer#write(int)
+ */
+ public void write(int oneChar) throws IOException {
+ IOUtil.writeOutputStreamWriter(oneChar,
+ outputStream, byteBuf, encoder, lock);
+ }
+
+ /*
+ * @see java.io.Writer#write(java.lang.String, int, int)
+ */
+ public void write(String str, int offset, int count) throws IOException {
+ IOUtil.writeOutputStreamWriter(str, offset, count,
+ outputStream, byteBuf, encoder, lock);
+ }
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/channels/ClosedByInterruptException.java b/nio/src/main/java/java/nio/channels/ClosedByInterruptException.java
new file mode 100644
index 0000000..5c4aa0b
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/ClosedByInterruptException.java
@@ -0,0 +1,39 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown when a thread is interrupted in a blocking IO operation.
+ * <p>
+ * When the thread is interrupted by a call to <code>interrupt()</code>
+ * it will close the channel, set the interrupt status of the thread to true,
+ * and throw a <code>ClosedByInterruptException</code>.
+ *
+ */
+public class ClosedByInterruptException extends AsynchronousCloseException {
+
+ private static final long serialVersionUID = -4488191543534286750L;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public ClosedByInterruptException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/ClosedChannelException.java b/nio/src/main/java/java/nio/channels/ClosedChannelException.java
new file mode 100644
index 0000000..a2ab1c3
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/ClosedChannelException.java
@@ -0,0 +1,38 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+import java.io.IOException;
+
+/**
+ * This exception is thrown when a channel is closed for the type of operation
+ * attempted.
+ *
+ */
+public class ClosedChannelException extends IOException {
+
+ private static final long serialVersionUID = 882777185433553857L;
+
+ /**
+ * Default constructor.
+ */
+ public ClosedChannelException() {
+ super();
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/channels/ClosedSelectorException.java b/nio/src/main/java/java/nio/channels/ClosedSelectorException.java
new file mode 100644
index 0000000..62dca07
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/ClosedSelectorException.java
@@ -0,0 +1,37 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown when an a selector is closed and an IO operation is attempted.
+ *
+ */
+public class ClosedSelectorException extends IllegalStateException {
+
+ private static final long serialVersionUID = 6466297122317847835L;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public ClosedSelectorException() {
+ super();
+ }
+}
+
+
diff --git a/nio/src/main/java/java/nio/channels/ConnectionPendingException.java b/nio/src/main/java/java/nio/channels/ConnectionPendingException.java
new file mode 100644
index 0000000..cf6fd25
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/ConnectionPendingException.java
@@ -0,0 +1,37 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown when an attempt is made to connect a SocketChannel that has a
+ * non-blocking connection already underway.
+ *
+ */
+public class ConnectionPendingException extends IllegalStateException {
+
+ private static final long serialVersionUID = 2008393366501760879L;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public ConnectionPendingException() {
+ super();
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/channels/DatagramChannel.java b/nio/src/main/java/java/nio/channels/DatagramChannel.java
new file mode 100644
index 0000000..d5c99e2
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/DatagramChannel.java
@@ -0,0 +1,456 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 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;
+
+import org.apache.harmony.luni.platform.Platform;
+
+/**
+ * A DatagramChannel is a selectable channel for part abstraction of datagram
+ * socket. The <code>socket</code> method of this class can return the related
+ * <code>DatagramSocket</code> instance, which can handle the socket.
+ * <p>
+ * A datagram channel is open but not connected when created by
+ * <code>open</code> 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
+ * <code>read</code> or <code>write</code>, a connected channel is
+ * required.
+ * </p>
+ * <p>
+ * Datagram channels are thread-safe, no more than one thread can read or write
+ * at given time.
+ * </p>
+ *
+ */
+public abstract class DatagramChannel extends AbstractSelectableChannel
+ implements ByteChannel, ScatteringByteChannel, GatheringByteChannel {
+
+ static {
+ Platform.getNetworkSystem().oneTimeInitialization(true);
+ }
+
+ /**
+ * Constructor for this class.
+ *
+ * @param selectorProvider
+ * A instance of SelectorProvider
+ */
+ protected DatagramChannel(SelectorProvider selectorProvider) {
+ super(selectorProvider);
+ }
+
+ /**
+ * Create a open and not-connected datagram channel.
+ * <p>
+ * This channel is got by <code>openDatagramChannel</code> method of the
+ * default <code>SelectorProvider </code> instance.
+ * </p>
+ *
+ * @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 (
+ * <code>SelectionKey.OP_READ</code> | <code>SelectionKey.OP_WRITE</code> ).
+ *
+ * @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 <code>DatagramSocket</code>.
+ *
+ * @return The related DatagramSocket instance.
+ */
+ public abstract DatagramSocket socket();
+
+ /**
+ * Answer whether this channel's socket is connected or not.
+ *
+ * @return <code>true</code> for this channel's socket is connected;
+ * <code>false</code> 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.
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * This method just execute the same security checks as the connect method
+ * of the <code>DatagramSocket</code> class.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @return This channel.
+ * @throws IOException
+ * Some other IO error occurred.
+ */
+ public abstract DatagramChannel disconnect() throws IOException;
+
+ /**
+ * Get a datagram from this channel.
+ * <p>
+ * 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 <code>null</code> 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.
+ * </p>
+ * <p>
+ * This method can be called at any moment, and will block if there is
+ * another thread started a read operation on the channel.
+ * </p>
+ * <p>
+ * This method just execute the same security checks as the receive method
+ * of the <code>DatagramSocket</code> class.
+ * </p>
+ *
+ * @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 datagram 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.
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * This method can be called at any moment, and will block if there is
+ * another thread started a read operation on the channel.
+ * </p>
+ * <p>
+ * This method just execute the same security checks as the send method of
+ * the <code>DatagramSocket</code> class.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * 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 <code>ReadableByteChannel</code> interface.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * 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 <code>ScatteringByteChannel</code> interface.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * 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 <code>ScatteringByteChannel</code> interface.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * 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
+ * <code>WritableByteChannel</code> interface.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * 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
+ * <code>GatheringByteChannel</code> 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.
+ * <p>
+ * 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
+ * <code>GatheringByteChannel</code> 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);
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/FileChannel.java b/nio/src/main/java/java/nio/channels/FileChannel.java
new file mode 100644
index 0000000..18bf9e2
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/FileChannel.java
@@ -0,0 +1,680 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.spi.AbstractInterruptibleChannel;
+
+/**
+ * An abstract channel type for interaction with a platform file.
+ * <p>
+ * A FileChannel defines the methods for reading, writing, memory mapping, and
+ * manipulating the logical state of a platform file. This type does not have a
+ * method for opening files, since this behaviour has been delegated to the
+ * <code>FileInputStream</code>, <code>FileOutputStream</code>, and
+ * <code>RandomAccessFile</code> types.
+ * </p>
+ * <p>
+ * FileChannels created from a FileInputStream, or a RandomAccessFile created in
+ * mode "r", are read-only. FileChannels created from a FileOutputStream are
+ * write-only. FileChannels created from a RandomAccessFile created in mode "rw"
+ * are read/write. FileChannels created from a RandomAccessFile that was opened
+ * in append-mode will also be in append-mode -- meaning that each write will be
+ * proceeded by a seek to the end of file. Some platforms will seek and write
+ * atomically, others will not.
+ * </p>
+ * <p>
+ * FileChannels has a virtual pointer into the file which is referred to as a
+ * file <em>position</em>. The position can be manipulated by repositioning
+ * it within the file, and its current position can be queried.
+ * </p>
+ * <p>
+ * FileChannels also have an associated <em>size</em>. The size of the file
+ * is the number of bytes that it currently contains. The size can be
+ * manipulated by adding more bytes to the end of the file (which increases the
+ * size) or truncating the file (which decreases the size). The current size can
+ * also be queried.
+ * </p>
+ * <p>
+ * FileChannels have operations beyond the simple read, write, and close. They
+ * can also:
+ * <ul>
+ * <li>request that cached data be forced onto the disk</li>
+ * <li>lock ranges of bytes associated with the file</li>
+ * <li>transfer data directly to another channel in a manner that has the
+ * potential to be optimized by the platform</li>
+ * <li>memory-mapping files into NIO buffers to provide efficient manipulation
+ * of file data</li>
+ * <li>read and write to the file at absolute byte offsets in a fashion that
+ * does not modify the current position</li>
+ * </ul>
+ * </p>
+ * <p>
+ * FileChannels are thread-safe. Only one operation involving manipulation of
+ * the file position may be in-flight at once. Subsequent calls to such
+ * operations will block, and one of those blocked will be freed to continue
+ * when the first operation has completed. There is no ordered queue or fairness
+ * applied to the blocked threads.
+ * </p>
+ * <p>
+ * It is undefined whether operations that do not manipulate the file position
+ * will also block when there are any other operations in-flight.
+ * </p>
+ * <p>
+ * The logical view of the underlying file is consistent across all FileChannels
+ * and IO streams opened on the same file by the same JVM process. Therefore
+ * modifications performed via a channel will be visible to the stream, and vice
+ * versa; including modifications to the file position, content, size, etc.
+ * </p>
+ *
+ */
+public abstract class FileChannel extends AbstractInterruptibleChannel
+ implements GatheringByteChannel, ScatteringByteChannel, ByteChannel {
+
+ /**
+ * A type of file mapping modes.
+ *
+ */
+ public static class MapMode {
+ /**
+ * Private mapping mode (equivalent to copy on write).
+ */
+ public static final MapMode PRIVATE = new MapMode("PRIVATE"); //$NON-NLS-1$
+
+ /**
+ * Read-only mapping mode.
+ */
+ public static final MapMode READ_ONLY = new MapMode("READ_ONLY"); //$NON-NLS-1$
+
+ /**
+ * Read-write mapping mode.
+ */
+ public static final MapMode READ_WRITE = new MapMode("READ_WRITE"); //$NON-NLS-1$
+
+ // The string used to display the mapping mode.
+ private final String displayName;
+
+ /*
+ * Private constructor prevents others creating new modes.
+ */
+ private MapMode(String displayName) {
+ super();
+ this.displayName = displayName;
+ }
+
+ /**
+ * Returns a string version of the mapping mode useful for debugging
+ * etc.
+ *
+ * @return the mode string.
+ */
+ public String toString() {
+ return displayName;
+ }
+ }
+
+ /**
+ * Protected default constructor.
+ */
+ protected FileChannel() {
+ super();
+ }
+
+ /**
+ * Request that all updates to the channel are committed to the storage
+ * device.
+ * <p>
+ * When this method returns all modifications made to the platform file
+ * underlying this channel will be committed to a local storage device. If
+ * the file is not hosted locally, such as a networked file system, then
+ * applications cannot be certain that the modifications have been
+ * committed.
+ * </p>
+ * <p>
+ * There are no assurances given that changes made to the file using methods
+ * defined elsewhere will be committed. For example, changes made via a
+ * mapped byte buffer may not be committed.
+ * </p>
+ * <p>
+ * The <code>metadata</code> parameter indicated whether the update should
+ * include the file's metadata such as last modification time, last access
+ * time, etc. Note that passing <code>true</code> may invoke an underlying
+ * write to the operating system (if the platform is maintaining metadata
+ * such as last access time), even if the channel is opened read-only.
+ *
+ * @param metadata
+ * true if the file metadata should be flushed in addition to the
+ * file content, and false otherwise.
+ * @throws ClosedChannelException
+ * if the channel is already closed.
+ * @throws IOException
+ * some other problem occurred.
+ */
+ public abstract void force(boolean metadata) throws IOException;
+
+ /**
+ * Obtain an exclusive lock on this file.
+ * <p>
+ * This is a convenience method for acquiring a maximum length lock on a
+ * file. It is equivalent to:
+ *
+ * <pre>
+ * fileChannel.lock(0L, Long.MAX_VALUE, false)
+ * </pre>
+ *
+ * @return the lock object representing the locked file area.
+ * @throws ClosedChannelException
+ * the file channel is closed.
+ * @throws NonWritableChannelException
+ * this channel was not opened for writing.
+ * @throws OverlappingFileLockException
+ * Either a lock is already held that overlaps this lock
+ * request, or another thread is waiting to acquire a lock that
+ * will overlap with this request.
+ * @throws FileLockInterruptionException
+ * The calling thread was interrupted while waiting to acquire
+ * the lock.
+ * @throws AsynchronousCloseException
+ * The channel was closed while the calling thread was waiting
+ * to acquire the lock.
+ * @throws IOException
+ * some other problem occurred obtaining the requested lock.
+ */
+ public final FileLock lock() throws IOException {
+ return lock(0L, Long.MAX_VALUE, false);
+ }
+
+ /**
+ * Obtain a lock on a specified region of the file.
+ * <p>
+ * This is the blocking version of lock acquisition, see also the
+ * <code>tryLock()</code> methods.
+ * </p>
+ * <p>
+ * Attempts to acquire an overlapping lock region will fail. The attempt
+ * will fail if the overlapping lock has already been obtained, or if
+ * another thread is currently waiting to acquire the overlapping lock.
+ * </p>
+ * <p>
+ * If the request is not for an overlapping lock, the thread calling this
+ * method will block until the lock is obtained (likely by no contention or
+ * another process releasing a lock), or this thread being interrupted or
+ * the channel closed.
+ * </p>
+ * <p>
+ * If the lock is obtained successfully then the FileLock object returned
+ * represents the lock for subsequent operations on the locked region.
+ * </p>
+ * <p>
+ * If the thread is interrupted while waiting for the lock, the thread is
+ * set to the interrupted state, and throws a
+ * <code>FileLockInterruptionException</code>. If the channel is closed
+ * while the thread is waiting to obtain the lock then the thread throws a
+ * <code>AsynchronousCloseException</code>.
+ * </p>
+ * <p>
+ * There is no requirement for the position and size to be within the
+ * current start and length of the file.
+ * </p>
+ * <p>
+ * Some platforms do not support shared locks, and if a request is made for
+ * a shared lock on such a platform this method will attempt to acquire an
+ * exclusive lock instead. It is undefined whether the lock obtained is
+ * advisory or mandatory.
+ * </p>
+ *
+ * @param position
+ * the starting position for the lock region
+ * @param size
+ * the length of the lock, in bytes
+ * @param shared
+ * a flag indicating whether an attempt should be made to acquire
+ * a shared lock.
+ * @return the file lock object
+ * @throws IllegalArgumentException
+ * if the parameters are invalid.
+ * @throws ClosedChannelException
+ * if the channel is already closed.
+ * @throws OverlappingFileLockException
+ * if the requested region overlaps an existing lock or pending
+ * lock request.
+ * @throws NonReadableChannelException
+ * if the channel is not open in read-mode and shared is true.
+ * @throws NonWritableChannelException
+ * if the channel is not open in write mode and shared is false.
+ * @throws AsynchronousCloseException
+ * if the channel is closed by another thread while this method
+ * is in operation.
+ * @throws FileLockInterruptionException
+ * if the thread is interrupted while in the state of waiting
+ * on the desired file lock.
+ * @throws IOException
+ * if some other IO problem occurs.
+ */
+ public abstract FileLock lock(long position, long size, boolean shared)
+ throws IOException;
+
+ /**
+ * Maps the file into memory.There can be three modes:Read-only,Read/write
+ * and Private.
+ *
+ * After mapping, the memory and the file channel do not affect each other.
+ *
+ * Note : mapping a file into memory is usually expensive.
+ *
+ * @param mode
+ * one of three modes to map
+ * @param position
+ * the starting position of the file
+ * @param size
+ * the size to map
+ * @return the mapped byte buffer
+ *
+ * @throws NonReadableChannelException
+ * If the file is not opened for reading but the given mode is
+ * "READ_ONLY"
+ * @throws NonWritableChannelException
+ * If the file is not opened for writing but the mode is not
+ * "READ_ONLY"
+ * @throws IllegalArgumentException
+ * If the given parameters of position and size are not correct
+ * @throws IOException
+ * If any I/O error occurs
+ */
+ public abstract MappedByteBuffer map(FileChannel.MapMode mode,
+ long position, long size) throws IOException;
+
+ /**
+ * Returns the current value of the file position pointer.
+ *
+ * @return the current position as a positive integer number of bytes from
+ * the start of the file.
+ * @throws ClosedChannelException
+ * if the channel is already closed.
+ * @throws IOException
+ * if some other IO problem occurs.
+ */
+ public abstract long position() throws IOException;
+
+ /**
+ * Sets the file position pointer to a new value.
+ * <p>
+ * The argument is the number of bytes counted from the start of the file.
+ * The position cannot be set to a value that is negative. The new position
+ * can be set beyond the current file size. If set beyond the current file
+ * size, attempts to read will return end of file, and writes will succeed,
+ * but fill-in the bytes between the current end of file and the position
+ * with the required number of (unspecified) byte values.
+ *
+ * @param offset
+ * the new file position, in bytes.
+ * @return the receiver.
+ * @throws IllegalArgumentException
+ * if the new position is negative.
+ * @throws ClosedChannelException
+ * if the channel is already closed.
+ * @throws IOException
+ * if some other IO problem occurs.
+ */
+ public abstract FileChannel position(long offset) throws IOException;
+
+ /**
+ * Reads bytes from the channel into the given byte buffer.
+ * <p>
+ * The bytes are read starting at the current file position, and after some
+ * number of bytes are read (up to the remaining number of bytes in the
+ * buffer) the file position is increased by the number of bytes actually
+ * read.
+ *
+ * @see java.nio.channels.ReadableByteChannel#read(java.nio.ByteBuffer)
+ */
+ public abstract int read(ByteBuffer buffer) throws IOException;
+
+ /**
+ * Reads bytes from the file channel into the given buffer starting from the
+ * given file position.
+ * <p>
+ * The bytes are read starting at the given file position (up to the
+ * remaining number of bytes in the buffer). The number of bytes actually
+ * read is returned.
+ * </p>
+ * <p>
+ * If the position is beyond the current end of file, then no bytes are
+ * read.
+ * </p>
+ * <p>
+ * Note that file position is unmodified by this method.
+ * </p>
+ *
+ * @param buffer
+ * the buffer to receive the bytes
+ * @param position
+ * the (non-negative) position at which to read the bytes.
+ * @return the number of bytes actually read.
+ * @throws IllegalArgumentException
+ * if <code>position</code> is less than <code>-1</code>.
+ * @throws ClosedChannelException
+ * if the channel is already closed.
+ * @throws NonReadableChannelException
+ * if the channel was not opened in read-mode.
+ * @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 buffer, long position)
+ throws IOException;
+
+ /**
+ * Reads bytes from the channel into all the given byte buffers.
+ * <p>
+ * The bytes are read starting at the current file position, and after some
+ * number of bytes are read (up to the remaining number of bytes in all the
+ * buffers) the file position is increased by the number of bytes actually
+ * read.
+ * </p>
+ * <p>
+ * This method behaves exactly like:
+ *
+ * <pre>
+ * read(buffers, 0, buffers.length);
+ * </pre>
+ *
+ * </p>
+ *
+ * @see java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[])
+ */
+ public final long read(ByteBuffer[] buffers) throws IOException {
+ return read(buffers, 0, buffers.length);
+ }
+
+ /**
+ * Reads bytes from the file channel into a subset of the given byte
+ * buffers.
+ *
+ * @see java.nio.channels.ScatteringByteChannel#read(java.nio.ByteBuffer[],
+ * int, int)
+ */
+ public abstract long read(ByteBuffer[] buffers, int start, int number)
+ throws IOException;
+
+ /**
+ * Returns the size of the file underlying this channel, in bytes.
+ *
+ * @return the size of the file in bytes.
+ * @throws ClosedChannelException
+ * if the channel is closed.
+ * @throws IOException
+ * if a problem occurs getting the size of the file.
+ */
+ public abstract long size() throws IOException;
+
+ /**
+ * Transfers bytes into this channel's file from the given readable byte
+ * channel. It may be very efficient.
+ *
+ * By invoking this method, it will read form the source channel and write
+ * into the file channel.
+ *
+ * Note: no guarantee whether all bytes may be transferred. And it does not
+ * modify the position of the channel.
+ *
+ * @param src
+ * the source channel to read
+ * @param position
+ * the non-negative position to begin
+ * @param count
+ * the non-negative bytes to be transferred
+ * @return the number of bytes that are transferred.
+ *
+ * @throws IllegalArgumentException
+ * If the parameters are not correct
+ * @throws NonReadableChannelException
+ * If the source channel is not readable
+ * @throws NonWritableChannelException
+ * If this channel is not writable
+ * @throws ClosedChannelException
+ * If either channel has already been closed
+ * @throws AsynchronousCloseException
+ * If either channel is closed by other threads during this operation
+ * @throws ClosedByInterruptException
+ * If the thread is interrupted during this operation
+ * @throws IOException
+ * If any I/O error occurs
+ */
+ public abstract long transferFrom(ReadableByteChannel src, long position,
+ long count) throws IOException;
+
+ /**
+ * Transfers data from the file to the given channel. It may be very
+ * efficient.
+ *
+ * By invoking this method, it will read form the file and write into the
+ * writable channel.
+ *
+ * Note: no guarantee whether all bytes may be transfered.And it does not
+ * modify the position of the channel.
+ *
+ * @param position
+ * the non-negative position to begin
+ * @param count
+ * the non-negative bytes to be transferred
+ * @param target
+ * the target channel to write into
+ * @return the number of bytes that were transferred.
+ *
+ * @throws IllegalArgumentException
+ * If the parameters are not correct
+ * @throws NonReadableChannelException
+ * If this channel is not readable
+ * @throws NonWritableChannelException
+ * If the target channel is not writable
+ * @throws ClosedChannelException
+ * If either channel has already been closed
+ * @throws AsynchronousCloseException
+ * If either channel is closed by other threads during this
+ * operation
+ * @throws ClosedByInterruptException
+ * If the thread is interrupted during this operation
+ * @throws IOException
+ * If any I/O error occurs
+ */
+ public abstract long transferTo(long position, long count,
+ WritableByteChannel target) throws IOException;
+
+ /**
+ * Truncates the file underlying this channel to a given size.
+ * <p>
+ * Any bytes beyond the given size are removed from the file. If there are
+ * no bytes beyond the given size then the file contents are unmodified.
+ * </p>
+ * <p>
+ * If the file position is currently greater than the given size, then it is
+ * set to be the given size.
+ * </p>
+ *
+ * @param size
+ * the maximum size of the underlying file
+ * @throws IllegalArgumentException
+ * the requested size is negative.
+ * @throws ClosedChannelException
+ * the channel is closed.
+ * @throws NonWritableChannelException
+ * the channel cannot be written.
+ * @throws IOException
+ * some other IO problem occurred.
+ * @return this channel
+ */
+ public abstract FileChannel truncate(long size) throws IOException;
+
+ /**
+ * Attempts to acquire an exclusive lock on this file without blocking.
+ * <p>
+ * This is a convenience method for attempting to acquire a maximum length
+ * lock on the file. It is equivalent to:
+ *
+ * <pre>
+ * fileChannel.tryLock(0L, Long.MAX_VALUE, false)
+ * </pre>
+ *
+ * </p>
+ * <p>
+ * The method returns <code>null</code> if the acquisition would result in
+ * an overlapped lock with another OS process.
+ * </p>
+ *
+ * @return the file lock object, or <code>null</code> if the lock would
+ * overlap an existing exclusive lock in another OS process.
+ * @throws ClosedChannelException
+ * the file channel is closed.
+ * @throws OverlappingFileLockException
+ * Either a lock is already held that overlaps this lock
+ * request, or another thread is waiting to acquire a lock that
+ * will overlap with this request.
+ * @throws IOException
+ * if any I/O error occurs
+ */
+ public final FileLock tryLock() throws IOException {
+ return tryLock(0L, Long.MAX_VALUE, false);
+ }
+
+ /**
+ * Attempts to acquire an exclusive lock on this file without blocking.
+ * <p>
+ * The method returns <code>null</code> if the acquisition would result in
+ * an overlapped lock with another OS process.
+ * </p>
+ *
+ * @param position
+ * the starting position
+ * @param size
+ * the size of file to lock
+ * @param shared
+ * true if share
+ * @return the file lock object, or <code>null</code> if the lock would
+ * overlap an existing exclusive lock in another OS process.
+ *
+ * @throws IllegalArgumentException
+ * If any parameters are bad
+ * @throws ClosedChannelException
+ * the file channel is closed.
+ * @throws OverlappingFileLockException
+ * Either a lock is already held that overlaps this lock
+ * request, or another thread is waiting to acquire a lock that
+ * will overlap with this request.
+ * @throws IOException
+ * if any I/O error occurs
+ */
+ public abstract FileLock tryLock(long position, long size, boolean shared)
+ throws IOException;
+
+ /**
+ * Writes bytes from the given byte buffer into the file channel.
+ * <p>
+ * The bytes are written starting at the current file position, and after
+ * some number of bytes are written (up to the remaining number of bytes in
+ * the buffer) the file position is increased by the number of bytes
+ * actually written.
+ *
+ * @see java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer)
+ *
+ * @param src
+ * the source buffer to write
+ */
+ public abstract int write(ByteBuffer src) throws IOException;
+
+ /**
+ * Writes bytes from the given buffer to the file channel starting at the
+ * given file position.
+ * <p>
+ * The bytes are written starting at the given file position (up to the
+ * remaining number of bytes in the buffer). The number of bytes actually
+ * written is returned.
+ * </p>
+ * <p>
+ * If the position is beyond the current end of file, then the file is first
+ * extended up to the given position by the required number of unspecified
+ * byte values.
+ * </p>
+ * <p>
+ * Note that file position is unmodified by this method.
+ * </p>
+ *
+ * @param buffer
+ * the buffer containing the bytes to be written.
+ * @param position
+ * the (non-negative) position at which to write the bytes.
+ * @return the number of bytes actually written.
+ * @throws IllegalArgumentException
+ * if <code>position</code> is less than <code>-1</code>.
+ * @throws ClosedChannelException
+ * if the channel is already closed.
+ * @throws NonWritableChannelException
+ * if the channel was not opened in write-mode.
+ * @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 buffer, long position)
+ throws IOException;
+
+ /**
+ * Writes bytes from all the given byte buffers into the file channel.
+ * <p>
+ * The bytes are written starting at the current file position, and after
+ * some number of bytes are written (up to the remaining number of bytes in
+ * all the buffers) the file position is increased by the number of bytes
+ * actually written.
+ * <p>
+ * This method behaves exactly like:
+ *
+ * <pre>
+ * write(buffers, 0, buffers.length);
+ * </pre>
+ *
+ * </p>
+ *
+ * @see java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[])
+ */
+ public final long write(ByteBuffer[] buffers) throws IOException {
+ return write(buffers, 0, buffers.length);
+ }
+
+ /**
+ *
+ *
+ * @see java.nio.channels.GatheringByteChannel#write(java.nio.ByteBuffer[],
+ * int, int)
+ */
+ public abstract long write(ByteBuffer[] buffers, int offset, int length)
+ throws IOException;
+
+}
diff --git a/nio/src/main/java/java/nio/channels/FileLock.java b/nio/src/main/java/java/nio/channels/FileLock.java
new file mode 100644
index 0000000..46c94dd
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/FileLock.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+import java.io.IOException;
+
+// BEGIN android-note
+// - fixed bad htm in javadoc comments -joeo
+// END android-note
+
+/**
+ * A <code>FileLock</code> represents a locked region of a file.
+ * <p>
+ * Locks have certain properties that enable collaborating processes to avoid
+ * the lost update problem, or reading inconsistent data.
+ * </p>
+ * <p>
+ * logically, a file lock can be 'exclusive' or 'shared'. Multiple processes can
+ * hold shared locks on the same region of a file, but only a single process can
+ * hold an exclusive lock on a given region of a file and no other process can
+ * simultaneously hold a shared lock overlapping the exclusive lock. An
+ * application can determine whether a FileLock is shared or exclusive via the
+ * <code>isShared()</code> API.
+ * </p>
+ * <p>
+ * Locks held by a particular process cannot overlap one another. Applications
+ * can determine whether a proposed lock will overlap by using the
+ * <code>overlaps(long, long)</code>) API. Locks held in
+ * other processes may overlap locks held in this process.</p>
+ * <p>
+ * Locks are shared amongst all threads in the acquiring process, and are therefore unsuitable for
+ * intra-process synchronization.</p>
+ * <p>
+ * Once a lock is acquired it is immutable in all its state except <code>isValid()</code>. The lock
+ * will initially be valid, but may be rendered invalid by explicit removal of the lock, using <code>
+ * release()</code>, or implicitly by closing the channel or exiting the process (terminating the JVM).</p>
+ * <p>
+ * <em>Platform dependencies</em></p>
+ * <p>
+ * Locks are intended to be true platform operating system file locks, and therefore locks held by the
+ * JVM process will be visible to other OS processes.</p>
+ * <p>
+ * The characteristics of the underlying OS locks will show through in the Java implementation. For
+ * example, some platforms' locks are 'mandatory' -- meaning the operating system enforces the locks
+ * on processes that attempt to access locked regions of file; whereas other platforms' locks are
+ * only 'advisory' -- meaning that processes are required to collaborate on ensuring locks are acquired
+ * and there is a potential for processes not to play well. The only safe answer is to assume that
+ * the platform is adopting advisory locks an always acquire shared locks when reading a region of file.</p>
+ * <p>
+ * On some platforms the presence of a lock will prevent the file being memory mapped. On some platforms
+ * closing a channel on a given file handle will release all the locks held on that file -- even if there
+ * are other channels open on the same file (their locks will be released). The safe option here is to
+ * ensure that you only acquire locks on a single channel for a particular file, and that becomes the
+ * synchronization point.</p>
+ * <p>
+ * Further care should be exercised when locking files maintained on network file systems since they often
+ * have further limitations.</p>
+ *
+ */
+public abstract class FileLock {
+
+ // The underlying file channel.
+ private final FileChannel channel;
+
+ // The lock starting position.
+ private final long position;
+
+ // The lock length in bytes
+ private final long size;
+
+ // If true then shared, if false then exclusive
+ private final boolean shared;
+
+ /**
+ * Constructor for a new file lock instance for a given channel. The
+ * constructor enforces the starting position, stretch, and shared status of
+ * the lock.
+ *
+ * @param channel
+ * underlying file channel that holds the lock.
+ * @param position
+ * starting point for the lock.
+ * @param size
+ * length of lock in number of bytes.
+ * @param shared
+ * shared status of lock (true is shared, false is exclusive).
+ */
+ protected FileLock(FileChannel channel, long position, long size,
+ boolean shared) {
+ super();
+ if (position < 0 || size < 0 || position + size < 0) {
+ throw new IllegalArgumentException();
+ }
+ this.channel = channel;
+ this.position = position;
+ this.size = size;
+ this.shared = shared;
+ }
+
+ /**
+ * Returns the lock's FileChannel.
+ *
+ * @return the channel.
+ */
+ public final FileChannel channel() {
+ return channel;
+ }
+
+ /**
+ * Returns the lock's starting position in the file.
+ *
+ * @return the lock position.
+ */
+ public final long position() {
+ return position;
+ }
+
+ /**
+ * Returns the length of the file lock in bytes.
+ *
+ * @return the size of file lock in bytes.
+ */
+ public final long size() {
+ return size;
+ }
+
+ /**
+ * Returns true if the file lock is shared with other processes and false if
+ * it is not.
+ *
+ * @return true if the lock is a shared lock, and false if it is exclusive.
+ */
+ public final boolean isShared() {
+ return shared;
+ }
+
+ /**
+ * Returns true if the receiver's lock region overlapps the region described
+ * in the parameter list,and returns false otherwise.
+ *
+ * @param start
+ * the starting position for the comparative lock.
+ * @param length
+ * the length of the comparative lock.
+ * @return true if there is an overlap, and false otherwise.
+ */
+ public final boolean overlaps(long start, long length) {
+ final long end = position + size - 1;
+ final long newEnd = start + length - 1;
+ if (end < start || position > newEnd) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns whether the receiver is a valid file lock or not. The lock is
+ * valid unless the underlying channel has been closed or it has been
+ * explicitly released.
+ *
+ * @return true if the lock is valid, and false otherwise.
+ */
+ public abstract boolean isValid();
+
+ /**
+ * Releases this particular lock on the file. If the lock is invalid then
+ * this method has no effect. Once released the lock becomes invalid.
+ *
+ * @throws ClosedChannelException
+ * if the channel is already closed when an attempt to release
+ * the lock is made.
+ * @throws IOException
+ * some other IO exception occurred.
+ */
+ public abstract void release() throws IOException;
+
+ /**
+ * Returns a string that shows the details of the lock suitable for display
+ * to an end user.
+ *
+ * @return the display string.
+ */
+ public final String toString() {
+ StringBuffer buffer = new StringBuffer(64); // Guess length of string
+ buffer.append("FileLock: [position="); //$NON-NLS-1$
+ buffer.append(position);
+ buffer.append(", size="); //$NON-NLS-1$
+ buffer.append(size);
+ buffer.append(", shared="); //$NON-NLS-1$
+ buffer.append(Boolean.toString(shared));
+ buffer.append("]"); //$NON-NLS-1$
+ return buffer.toString();
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/FileLockInterruptionException.java b/nio/src/main/java/java/nio/channels/FileLockInterruptionException.java
new file mode 100644
index 0000000..44295f2
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/FileLockInterruptionException.java
@@ -0,0 +1,39 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+import java.io.IOException;
+
+/**
+ * Thrown when thread was interrupted while waiting to acquire a file lock.
+ * <p>
+ * Note that the thread will also be in the 'interrupted' state.
+ * </p>
+ *
+ */
+public class FileLockInterruptionException extends IOException {
+
+ private static final long serialVersionUID = 7104080643653532383L;
+
+ /**
+ * Default constructor.
+ */
+ public FileLockInterruptionException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/GatheringByteChannel.java b/nio/src/main/java/java/nio/channels/GatheringByteChannel.java
new file mode 100644
index 0000000..627aa3d
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/GatheringByteChannel.java
@@ -0,0 +1,104 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * The interface to channels that can write a set of buffers in a single
+ * operation.
+ * <p>
+ * The corresponding interface for reads is called
+ * <code>ScatteringByteChannel</code>.
+ *
+ */
+public interface GatheringByteChannel extends WritableByteChannel {
+
+ /**
+ * Writes bytes from all the given buffers to the channel.
+ * <p>
+ * This method is equivalent to:
+ *
+ * <pre>
+ * write(buffers, 0, buffers.length);
+ * </pre>
+ *
+ * </p>
+ *
+ * @param buffers
+ * the buffers containing bytes to be written.
+ * @return the number of bytes actually written.
+ * @throws ClosedChannelException
+ * if the channel is closed.
+ * @throws NonWritableChannelException
+ * if the channel is open, but not in a mode that permits
+ * writing.
+ * @throws ClosedByInterruptException
+ * if the thread is interrupted in its IO operation by another
+ * thread closing the channel.
+ * @throws AsynchronousCloseException
+ * if the write is interrupted by another thread sending an
+ * explicit interrupt.
+ * @throws IOException
+ * if some other type of exception occurs. Details are in the
+ * message.
+ */
+ public long write(ByteBuffer[] buffers) throws IOException;
+
+ /**
+ * Writes a subset of the given bytes from the buffers to the channel.
+ * <p>
+ * This method attempts to write all of the <code>remaining()</code> bytes
+ * from <code>length</code> byte buffers, in order, starting at
+ * <code>buffers[offset]</code>. The number of bytes actually written is
+ * returned.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @param buffers
+ * 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 IndexOutOfBoundsException
+ * if offset < 0 or > buffers.length; or length < 0 or >
+ * buffers.length - offset.
+ * @throws NonWritableChannelException
+ * if the channel was not opened for writing.
+ * @throws ClosedChannelException
+ * the channel is currently closed.
+ * @throws AsynchronousCloseException
+ * the channel was closed by another thread while the write was
+ * underway.
+ * @throws ClosedByInterruptException
+ * the thread was interrupted by another thread while the write
+ * was underway.
+ * @throws IOException
+ * if some other type of exception occurs. Details are in the
+ * message.
+ */
+ public long write(ByteBuffer[] buffers, int offset, int length)
+ throws IOException;
+}
diff --git a/nio/src/main/java/java/nio/channels/IllegalBlockingModeException.java b/nio/src/main/java/java/nio/channels/IllegalBlockingModeException.java
new file mode 100644
index 0000000..187c21f
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/IllegalBlockingModeException.java
@@ -0,0 +1,35 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown when when operation that requires a specific blocking mode is invoked
+ * on a channel that is in a different blocking mode.
+ *
+ */
+public class IllegalBlockingModeException extends IllegalStateException {
+
+ private static final long serialVersionUID = -3335774961855590474L;
+
+ /**
+ * Default constructor.
+ */
+ public IllegalBlockingModeException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/IllegalSelectorException.java b/nio/src/main/java/java/nio/channels/IllegalSelectorException.java
new file mode 100644
index 0000000..7a6235f
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/IllegalSelectorException.java
@@ -0,0 +1,37 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown when a call is made to register a channel on a selector that has been
+ * created by a different provider.
+ *
+ */
+public class IllegalSelectorException extends IllegalArgumentException {
+
+ private static final long serialVersionUID = -8406323347253320987L;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public IllegalSelectorException() {
+ super();
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/channels/InterruptibleChannel.java b/nio/src/main/java/java/nio/channels/InterruptibleChannel.java
new file mode 100644
index 0000000..c5e110d
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/InterruptibleChannel.java
@@ -0,0 +1,58 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+import java.io.IOException;
+
+/**
+ * Channels that implement this interface are both asynchronously closable and
+ * interruptible.
+ * <p>
+ * A channel that is asynchronously closable permits a thread blocked on an IO
+ * operation (the IO thread) to be released by another thread calling the
+ * channel's <code>close()</code> method. The IO thread will throw an
+ * <code>AsynchronousCloseException</code> and the channel will be closed.
+ * </p>
+ * <p>
+ * A channel that is interruptible permits a thread blocked on an IO operation
+ * (the IO thread) to be interrupted by another thread (by invoking
+ * <code>interrupt()</code> on the IO thread). When the IO thread is
+ * interrupted it will throw a <code>ClosedByInterruptException</code>
+ * exception, it will have its interrupted status set, and the channel will be
+ * closed. If the IO thread attempts to make an IO call with the interrupt
+ * status set the call will immediately fail with a
+ * <code>ClosedByInterruptException</code>.
+ *
+ */
+public interface InterruptibleChannel extends Channel {
+
+ /**
+ * Closes an InterruptibleChannel. This method is precisely the same as the
+ * super-interface <code>close()</code>.
+ * <p>
+ * Any threads that are blocked on IO operations on this channel will be
+ * interrupted with an <code>AsynchronousCloseException
+ * </code>.
+ * </p>
+ *
+ * @throws IOException
+ * if an IO problem occurs closing the channel.
+ */
+ public void close() throws IOException;
+
+}
diff --git a/nio/src/main/java/java/nio/channels/NoConnectionPendingException.java b/nio/src/main/java/java/nio/channels/NoConnectionPendingException.java
new file mode 100644
index 0000000..7e19797
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/NoConnectionPendingException.java
@@ -0,0 +1,36 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown if SocketChannel's finishConnect method is called before the
+ * SocketChannel's connect method completed without error.
+ *
+ */
+public class NoConnectionPendingException extends IllegalStateException {
+
+ private static final long serialVersionUID = -8296561183633134743L;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public NoConnectionPendingException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/NonReadableChannelException.java b/nio/src/main/java/java/nio/channels/NonReadableChannelException.java
new file mode 100644
index 0000000..6dc318e
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/NonReadableChannelException.java
@@ -0,0 +1,34 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown when attempting to read from a channel that is not open for reading.
+ *
+ */
+public class NonReadableChannelException extends IllegalStateException {
+
+ private static final long serialVersionUID = -3200915679294993514L;
+
+ /**
+ * Default constructor.
+ */
+ public NonReadableChannelException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/NonWritableChannelException.java b/nio/src/main/java/java/nio/channels/NonWritableChannelException.java
new file mode 100644
index 0000000..466f50a
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/NonWritableChannelException.java
@@ -0,0 +1,34 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown when attempting to write to a channel that is not open for writing.
+ *
+ */
+public class NonWritableChannelException extends IllegalStateException {
+
+ private static final long serialVersionUID = -7071230488279011621L;
+
+ /**
+ * Default constructor.
+ */
+ public NonWritableChannelException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/NotYetBoundException.java b/nio/src/main/java/java/nio/channels/NotYetBoundException.java
new file mode 100644
index 0000000..a41354a
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/NotYetBoundException.java
@@ -0,0 +1,36 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown if the server socket channel is not bound before an IO operation is
+ * made.
+ *
+ */
+public class NotYetBoundException extends IllegalStateException {
+
+ private static final long serialVersionUID = 4640999303950202242L;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public NotYetBoundException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/NotYetConnectedException.java b/nio/src/main/java/java/nio/channels/NotYetConnectedException.java
new file mode 100644
index 0000000..06e73e5
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/NotYetConnectedException.java
@@ -0,0 +1,37 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown if the socket channel is not connected before an IO operation is
+ * invoked.
+ *
+ */
+public class NotYetConnectedException extends IllegalStateException {
+
+ private static final long serialVersionUID = 4697316551909513464L;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public NotYetConnectedException() {
+ super();
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/channels/OverlappingFileLockException.java b/nio/src/main/java/java/nio/channels/OverlappingFileLockException.java
new file mode 100644
index 0000000..16a9645
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/OverlappingFileLockException.java
@@ -0,0 +1,35 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown when attempting to acquire a lock that overlaps an existing or pending
+ * lock held by this process.
+ *
+ */
+public class OverlappingFileLockException extends IllegalStateException {
+
+ private static final long serialVersionUID = 2047812138163068433L;
+
+ /**
+ * Default constructor.
+ */
+ public OverlappingFileLockException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/Pipe.java b/nio/src/main/java/java/nio/channels/Pipe.java
new file mode 100644
index 0000000..b0c44f4
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/Pipe.java
@@ -0,0 +1,118 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+import java.io.IOException;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+/**
+ * A pipe contains two channels. One is the writable sink channel and the other is
+ * readable source channel. When bytes are written into the writable channel they
+ * can be read from readable channel. The order of these bytes remains unchanged.
+ *
+ */
+public abstract class Pipe {
+
+ /**
+ * Writable sink channel for writing into.
+ */
+ public static abstract class SinkChannel extends AbstractSelectableChannel
+ implements WritableByteChannel, GatheringByteChannel {
+
+ /**
+ * The Constructor.
+ *
+ * @param provider
+ * the provider of the channel
+ */
+ protected SinkChannel(SelectorProvider provider) {
+ super(provider);
+ }
+
+ /**
+ * Indicates this channel supports only writing.
+ *
+ * @return a static value of OP_WRITE
+ */
+ public final int validOps() {
+ return SelectionKey.OP_WRITE;
+ }
+ }
+
+ /**
+ * Readable source channel for reading from.
+ */
+ public static abstract class SourceChannel extends
+ AbstractSelectableChannel implements ReadableByteChannel,
+ ScatteringByteChannel {
+
+ /**
+ * The Constructor.
+ *
+ * @param provider
+ * the provider of the channel
+ */
+ protected SourceChannel(SelectorProvider provider) {
+ super(provider);
+ }
+
+ /**
+ * Indicates this channel supports only reading.
+ *
+ * @return a static value of OP_READ
+ */
+ public final int validOps() {
+ return SelectionKey.OP_READ;
+ }
+
+ }
+
+ /**
+ * Initializes a pipe.
+ *
+ * @return a new instance of pipe
+ *
+ * @throws IOException
+ * if I/O error occurs
+ */
+ public static Pipe open() throws IOException {
+ return SelectorProvider.provider().openPipe();
+ }
+
+ /**
+ * The protected constructor.
+ */
+ protected Pipe() {
+ super();
+ }
+
+ /**
+ * Returns the sink channel of the pipe.
+ *
+ * @return a writable sink channel of the pipe
+ */
+ public abstract SinkChannel sink();
+
+ /**
+ * Returns the source channel of the pipe.
+ *
+ * @return a readable source channel of the pipe
+ */
+ public abstract SourceChannel source();
+
+}
diff --git a/nio/src/main/java/java/nio/channels/ReadableByteChannel.java b/nio/src/main/java/java/nio/channels/ReadableByteChannel.java
new file mode 100644
index 0000000..f34e702
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/ReadableByteChannel.java
@@ -0,0 +1,67 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * A ReadableByteChannel is a type of Channel that can read bytes.
+ * <p>
+ * Reads are synchronous on a ReadableByteChannel, that is, if a read is already
+ * in progress on the channel then subsequent reads will block until the first
+ * read completes. It is undefined whether non-read operations will block.
+ *
+ */
+public interface ReadableByteChannel extends Channel {
+
+ /**
+ * Reads bytes from the channel into the given buffer.
+ * <p>
+ * The maximum number of bytes that will be read is the
+ * <code>remaining()</code> number of bytes in the buffer when the method
+ * invoked. The bytes will be read into the buffer starting at the buffer's
+ * <code>position</code>.
+ * </p>
+ * <p>
+ * The call may block if other threads are also attempting to read on the
+ * same channel.
+ * </p>
+ * <p>
+ * Upon completion, the buffer's <code>position()</code> is updated to the
+ * end of the bytes that were read. The buffer's <code>limit()</code> is
+ * unmodified.
+ * </p>
+ *
+ * @param buffer
+ * the byte buffer to receive the bytes.
+ * @return the number of bytes actually read.
+ * @throws NonReadableChannelException
+ * if the channel was not opened for reading.
+ * @throws ClosedChannelException
+ * if the channel was already closed.
+ * @throws AsynchronousCloseException
+ * if another thread closes the channel during the read.
+ * @throws ClosedByInterruptException
+ * if another thread interrupt the calling thread during the
+ * read.
+ * @throws IOException
+ * another IO exception occurs, details are in the message.
+ */
+ public int read(ByteBuffer buffer) throws IOException;
+}
diff --git a/nio/src/main/java/java/nio/channels/ScatteringByteChannel.java b/nio/src/main/java/java/nio/channels/ScatteringByteChannel.java
new file mode 100644
index 0000000..41fb72f
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/ScatteringByteChannel.java
@@ -0,0 +1,104 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * The interface to channels that can read a set of buffers in a single
+ * operation.
+ * <p>
+ * The corresponding interface for writes is called
+ * <code>GatheringByteChannel</code>.
+ *
+ */
+public interface ScatteringByteChannel extends ReadableByteChannel {
+
+ /**
+ * Reads bytes from the channel into all the given buffers.
+ * <p>
+ * This method is equivalent to:
+ *
+ * <pre>
+ * read(buffers, 0, buffers.length);
+ * </pre>
+ *
+ * </p>
+ *
+ * @param buffers
+ * the array of byte buffers to receive the bytes being read.
+ * @return the number of bytes actually read.
+ * @throws ClosedChannelException
+ * if the channel is closed.
+ * @throws NonReadableChannelException
+ * if the channel is open, but not in a mode that permits
+ * reading.
+ * @throws ClosedByInterruptException
+ * if the thread is interrupted in its IO operation by another
+ * thread closing the channel.
+ * @throws AsynchronousCloseException
+ * if the read is interrupted by another thread sending an
+ * explicit interrupt.
+ * @throws IOException
+ * if some other type of exception occurs. Details are in the
+ * message.
+ */
+ public long read(ByteBuffer[] buffers) throws IOException;
+
+ /**
+ * Reads bytes from the channel into a subset of the given buffers.
+ * <p>
+ * This method attempts to read all of the <code>remaining()</code> bytes
+ * from <code>length</code> byte buffers, in order, starting at
+ * <code>buffers[offset]</code>. The number of bytes actually read is
+ * returned.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @param buffers
+ * 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.
+ * @return the number of bytes actually read.
+ * @throws IndexOutOfBoundsException
+ * if offset < 0 or > buffers.length; or length < 0 or >
+ * buffers.length - offset.
+ * @throws NonReadableChannelException
+ * if the channel was not opened for reading.
+ * @throws ClosedChannelException
+ * the channel is currently closed.
+ * @throws AsynchronousCloseException
+ * the channel was closed by another thread while the write was
+ * underway.
+ * @throws ClosedByInterruptException
+ * the thread was interrupted by another thread while the write
+ * was underway.
+ * @throws IOException
+ * if some other type of exception occurs. Details are in the
+ * message.
+ */
+ public long read(ByteBuffer[] buffers, int offset, int length)
+ throws IOException;
+
+}
diff --git a/nio/src/main/java/java/nio/channels/SelectableChannel.java b/nio/src/main/java/java/nio/channels/SelectableChannel.java
new file mode 100644
index 0000000..7707c29
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/SelectableChannel.java
@@ -0,0 +1,153 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+import java.io.IOException;
+import java.nio.channels.spi.AbstractInterruptibleChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+/**
+ * A channel that can be detected by a selector. The channel can be registered
+ * with some selectors, and when invoke select method of the selectors, the
+ * channel can be checked if it is readable, writable, connectable or
+ * acceptable according to its interesting operation.
+ *
+ */
+public abstract class SelectableChannel extends AbstractInterruptibleChannel
+ implements Channel {
+
+ /**
+ * Default constructor, can be overridden.
+ */
+ protected SelectableChannel() {
+ super();
+ }
+
+ /**
+ * Gets the blocking lock which synchronizes the configureBlocking and
+ * register methods.
+ *
+ * @return the blocking object as lock
+ */
+ public abstract Object blockingLock();
+
+ /**
+ * Sets blocking mode of the channel.
+ *
+ * @param block
+ * true as blocking, false as non-blocking
+ * @return this channel
+ * @throws ClosedChannelException
+ * If this channel has been closed
+ * @throws IllegalBlockingModeException
+ * If the channel has been registered
+ * @throws IOException
+ * if I/O error occurs
+ */
+ public abstract SelectableChannel configureBlocking(boolean block)
+ throws IOException;
+
+ /**
+ * Returns if channel is in blocking mode.
+ *
+ * @return true if channel is blocking
+ */
+ public abstract boolean isBlocking();
+
+ /**
+ * Returns if channel is registered.
+ *
+ * @return true if channel is registered
+ */
+ public abstract boolean isRegistered();
+
+ /**
+ * Gets the selection key for the channel with the given selector.
+ *
+ * @param sel
+ * the selector with which this channel may register
+ * @return the selection key for the channel according to the given selector
+ */
+ public abstract SelectionKey keyFor(Selector sel);
+
+ /**
+ * Gets the provider of the channel.
+ *
+ * @return the provider of the channel
+ */
+ public abstract SelectorProvider provider();
+
+ /**
+ * Registers with the given selector with a certain interesting operation.
+ *
+ * @param selector
+ * the selector with which this channel shall be registered
+ * @param operations
+ * the interesting operation
+ * @return the selection key indicates the channel
+ * @throws ClosedChannelException
+ * if the channel is closed
+ * @throws IllegalBlockingModeException
+ * If the channel is in blocking mode
+ * @throws IllegalSelectorException
+ * If this channel does not have the same provider as the
+ * given selector
+ * @throws CancelledKeyException
+ * If this channel is registered but its key has been cancelled
+ * @throws IllegalArgumentException
+ * If the operation given is unsupported by this channel
+ */
+ public final SelectionKey register(Selector selector, int operations)
+ throws ClosedChannelException {
+ return register(selector, operations, null);
+ }
+
+ /**
+ * Registers with the given selector with a certain interesting operation
+ * and an attached object.
+ *
+ * @param sel
+ * the selector with which this channel shall be registered
+ * @param ops
+ * the interesting operation
+ * @param att
+ * The attached object, which can be null
+ * @return the selection key indicates the channel
+ * @throws ClosedChannelException
+ * if the channel is closed
+ * @throws IllegalBlockingModeException
+ * If the channel is in blocking mode
+ * @throws IllegalSelectorException
+ * If this channel does not have the same provider with the
+ * given selector
+ * @throws CancelledKeyException
+ * If this channel is registered but its key has been cancelled
+ * @throws IllegalArgumentException
+ * If the operation given is unsupported by this channel
+ */
+ public abstract SelectionKey register(Selector sel, int ops, Object att)
+ throws ClosedChannelException;
+
+ /**
+ * Gets the possible interesting operation of the channel.
+ *
+ * @return the possible interesting operation of the channel
+ */
+ public abstract int validOps();
+
+}
diff --git a/nio/src/main/java/java/nio/channels/SelectionKey.java b/nio/src/main/java/java/nio/channels/SelectionKey.java
new file mode 100644
index 0000000..f52f99e
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/SelectionKey.java
@@ -0,0 +1,189 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+import java.nio.channels.Selector;
+
+/**
+ * A key that representing the relationship of a channel and the selector.
+ *
+ */
+public abstract class SelectionKey {
+
+ /**
+ * Interesting operation mask bit for socket-accept operations.
+ */
+ public static final int OP_ACCEPT = 16;
+
+ /**
+ * Interesting operation mask bit for socket-connect operations.
+ */
+ public static final int OP_CONNECT = 8;
+
+ /**
+ * Interesting operation mask bit for read operations.
+ */
+ public static final int OP_READ = 1;
+
+ /**
+ * Interesting operation mask bit for write operations.
+ */
+ public static final int OP_WRITE = 4;
+
+ private volatile Object attachment = null;
+
+ /**
+ * The constructor.
+ *
+ */
+ protected SelectionKey() {
+ super();
+ }
+
+ /**
+ * Attaches an object to the key.
+ *
+ * @param anObject
+ * the object to attach
+ * @return the last attached object
+ */
+ public final Object attach(Object anObject) {
+ Object oldAttachment = attachment;
+ attachment = anObject;
+ return oldAttachment;
+ }
+
+ /**
+ * Gets the attached object.
+ *
+ * @return the attached object or null if no object has been attached
+ */
+ public final Object attachment() {
+ return attachment;
+ }
+
+ /**
+ * Cancels this key.
+ *
+ */
+ public abstract void cancel();
+
+ /**
+ * Gets the channel of this key.
+ *
+ * @return the channel of this key
+ */
+ public abstract SelectableChannel channel();
+
+ /**
+ * Gets the interesting operation of this key.
+ *
+ * @return the interesting operation of this key
+ * @throws CancelledKeyException
+ * If the key has been cancelled already
+ */
+ public abstract int interestOps();
+
+ /**
+ * Sets the interesting operation for this key.
+ *
+ * @param operations
+ * the interesting operation to set
+ * @return this key
+ * @throws IllegalArgumentException
+ * if the given operation is not in the key's interesting
+ * operation set
+ * @throws CancelledKeyException
+ * If the key has been cancelled already
+ */
+ public abstract SelectionKey interestOps(int operations);
+
+ /**
+ * Tells whether the channel of this key is interested in accept operation
+ * and ready for acceptation.
+ *
+ * @return true if the channel is interested in accept operation and ready
+ * for acceptation
+ * @throws CancelledKeyException
+ * If the key has been cancelled already
+ */
+ public final boolean isAcceptable() {
+ return (readyOps() & OP_ACCEPT) == OP_ACCEPT;
+ }
+
+ /**
+ * Tells whether the channel of this key is interested in connect operation
+ * and ready for connection.
+ *
+ * @return true if the channel is interested in connect operation and ready
+ * for connection
+ * @throws CancelledKeyException
+ * If the key has been cancelled already
+ */
+ public final boolean isConnectable() {
+ return (readyOps() & OP_CONNECT) == OP_CONNECT;
+ }
+
+ /**
+ * Tells whether the channel of this key is interested in read operation and
+ * ready for reading.
+ *
+ * @return true if the channel is interested in read operation and ready for
+ * reading
+ * @throws CancelledKeyException
+ * If the key has been cancelled already
+ */
+ public final boolean isReadable() {
+ return (readyOps() & OP_READ) == OP_READ;
+ }
+
+ /**
+ * Tells whether the key is valid.
+ *
+ * @return true if the key has not been cancelled
+ */
+ public abstract boolean isValid();
+
+ /**
+ * Tells whether the channel of this key is interested in write operation
+ * and ready for writing.
+ *
+ * @return true if the channel is interested in write operation and ready
+ * for writing
+ * @throws CancelledKeyException
+ * If the key has been cancelled already
+ */
+ public final boolean isWritable() {
+ return (readyOps() & OP_WRITE) == OP_WRITE;
+ }
+
+ /**
+ * Gets the ready operation.
+ *
+ * @return the ready operation
+ * @throws CancelledKeyException
+ * If the key has been cancelled already
+ */
+ public abstract int readyOps();
+
+ /**
+ * Gets the related selector.
+ *
+ * @return the related selector
+ */
+ public abstract Selector selector();
+}
diff --git a/nio/src/main/java/java/nio/channels/Selector.java b/nio/src/main/java/java/nio/channels/Selector.java
new file mode 100644
index 0000000..91e4e01
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/Selector.java
@@ -0,0 +1,148 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+import java.io.IOException;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Set;
+
+/**
+ * A controller for selection of SelectableChannel objects.
+ *
+ * Selectable channels can be registered with a selector, and get SelectionKey
+ * as a linkage. The keys are also added to the selector's keyset. The
+ * SelectionKey can be cancelled so that the corresponding channel is no longer
+ * registered with the selector.
+ *
+ * By invoking the select operation, the keyset is checked and all keys that are
+ * cancelled since last select operation are moved to cancelledKey set. During
+ * the select operation, the channels registered with this selector are checked
+ * to see whether they are ready for operation according to their interesting
+ * operation.
+ *
+ */
+public abstract class Selector {
+
+ /**
+ * The factory method for selector.
+ *
+ * @return a new selector
+ * @throws IOException
+ * if I/O error occurs
+ */
+ public static Selector open() throws IOException {
+ return SelectorProvider.provider().openSelector();
+ }
+
+ /**
+ * The constructor.
+ */
+ protected Selector() {
+ super();
+ }
+
+ /**
+ * Closes this selector.
+ *
+ * @throws IOException
+ * if I/O error occurs
+ */
+ public abstract void close() throws IOException;
+
+ /**
+ * Tells whether this selector is open.
+ *
+ * @return true if this selector is not closed
+ */
+ public abstract boolean isOpen();
+
+ /**
+ * Gets the set of registered keys.
+ *
+ * @return the keyset of registered keys
+ */
+ public abstract Set<SelectionKey> keys();
+
+ /**
+ * Gets the provider of this selector.
+ *
+ * @return the provider of this selector
+ */
+ public abstract SelectorProvider provider();
+
+ /**
+ * Detects if any of the registered channels are ready for I/O operations
+ * according to their interesting operation. This operation will not return
+ * until some of the channels are ready or wakeup is invoked.
+ *
+ * @return the number of channels that are ready for operation
+ * @throws IOException
+ * if I/O error occurs
+ * @throws ClosedSelectorException
+ * If the selector is closed
+ */
+ public abstract int select() throws IOException;
+
+ /**
+ * Detects if any of the registered channels are ready for I/O operations
+ * according to their interesting operation.This operation will not return
+ * until some of the channels are ready or wakeup is invoked or timeout
+ * expired.
+ *
+ * @param timeout
+ * the timeout in millisecond
+ * @return the number of channels that are ready for operation
+ * @throws IOException
+ * if I/O error occurs
+ * @throws ClosedSelectorException
+ * If the selector is closed
+ * @throws IllegalArgumentException
+ * If the given timeout argument is less than zero
+ */
+ public abstract int select(long timeout) throws IOException;
+
+ /**
+ * Gets the keys whose channels are ready for operation.
+ *
+ * @return the keys whose channels are ready for operation
+ */
+ public abstract Set<SelectionKey> selectedKeys();
+
+ /**
+ * Detects if any of the registered channels are ready for I/O operations
+ * according to their interesting operation.This operation will not return
+ * immediately.
+ *
+ * @return the number of channels that are ready for operation
+ * @throws IOException
+ * if I/O error occur
+ * @throws ClosedSelectorException
+ * If the selector is closed
+ */
+ public abstract int selectNow() throws IOException;
+
+ /**
+ * Forces the blocked select operation to return immediately. If no select
+ * operation is blocked currently, the next select operation shall return
+ * immediately.
+ *
+ * @return this selector
+ * @throws ClosedSelectorException
+ * If the selector is closed
+ */
+ public abstract Selector wakeup();
+}
diff --git a/nio/src/main/java/java/nio/channels/ServerSocketChannel.java b/nio/src/main/java/java/nio/channels/ServerSocketChannel.java
new file mode 100644
index 0000000..ac37e7d
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/ServerSocketChannel.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 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 <code>ServerSocket</code> object, returned by calling
+ * socket method. ServerSocketChannels can not be constructed for a pre-existing
+ * server socket, nor can it be assigned a SocketImpl.
+ * <p>
+ * A Server-Socket channel is open but not bound when created by
+ * <code>open</code> method. (Calling <code>accept</code> before bound will cause a
+ * <code>NotYetBoundException</code>). It can be bound by calling the bind method
+ * of a related <code>ServerSocket</code> instance.</p>
+ */
+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.
+ * <p>
+ * This channel is got by calling <code>openServerSocketChannel</code>
+ * method of the default <code>SelectorProvider </code> instance.
+ * </p>
+ *
+ * @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 <code>SelectionKey.OP_ACCEPT</code>.
+ *
+ * @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 <code>ServerSocket</code>.
+ *
+ * @return The related ServerSocket instance.
+ */
+ public abstract ServerSocket socket();
+
+ /**
+ * Accepts a connection to this socket.
+ * <p>
+ * 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.
+ * </p>
+ *
+ * <p>
+ * This method just execute the same security checks as the accept method of
+ * the <code>ServerSocket</code> class.
+ * </p>
+ *
+ * @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;
+
+}
diff --git a/nio/src/main/java/java/nio/channels/SocketChannel.java b/nio/src/main/java/java/nio/channels/SocketChannel.java
new file mode 100644
index 0000000..812d811
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/SocketChannel.java
@@ -0,0 +1,484 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 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;
+
+import org.apache.harmony.luni.platform.Platform;
+
+/**
+ * A SocketChannel is a selectable channel for part abstraction of stream
+ * connecting socket. The <code>socket</code> method of this class can return
+ * the related <code>Socket</code> instance, which can handle the socket.
+ * <p>
+ * A socket channel is open but not connected when created by <code>open</code>
+ * method. After connected by calling the <code>connect</code> method, it will
+ * keep connected before closed. The connection is non-blocking that the
+ * <code>connect</code> method is for the initial connection and following
+ * <code>finishConnect</code> method is for the final steps of connection. The
+ * <code>isConnectionPending</code> method can tell the connection is blocked
+ * or not; the <code>isConnected</code> method can tell the socket is
+ * connected finally or not.
+ * </p>
+ * <p>
+ * The shut down operation can be independent and asynchronous for input and
+ * output. The <code>shutdownInput</code> 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 <code>shutdownOutput</code> method is
+ * for output, and can make the following write operation throwing a
+ * <code>ClosedChannelException</code>. If the output is shut down and
+ * another is pending in a write operation, an
+ * <code>AsynchronousCloseException</code> will thrown to the pending thread.
+ * </p>
+ * <p>
+ * Socket channels are thread-safe, no more than one thread can read or write at
+ * given time. The <code>connect</code> and <code>finishConnect</code>
+ * methods are concurrent each other, when they are processing, other read and
+ * write will block.
+ * </p>
+ */
+public abstract class SocketChannel extends AbstractSelectableChannel implements
+ ByteChannel, ScatteringByteChannel, GatheringByteChannel {
+
+ static {
+ Platform.getNetworkSystem().oneTimeInitialization(true);
+ }
+
+ /**
+ * Constructor for this class.
+ *
+ * @param selectorProvider
+ * A instance of SelectorProvider
+ */
+ protected SocketChannel(SelectorProvider selectorProvider) {
+ super(selectorProvider);
+ }
+
+ /**
+ * Create a open and not-connected socket channel.
+ * <p>
+ * This channel is got by <code>openSocketChannel</code> method of the
+ * default <code>SelectorProvider </code> instance.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * This method perform just as <code>open</code> method following by the
+ * <code>connect</code> method.
+ * </p>
+ *
+ * @param address
+ * The socket address to be connected.
+ * @return The new opened 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 (
+ * <code>SelectionKey.OP_CONNECT</code> |
+ * <code>SelectionKey.OP_READ</code> | <code>SelectionKey.OP_WRITE</code> ).
+ *
+ * @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 <code>Socket</code>.
+ *
+ * @return The related Socket instance.
+ */
+ public abstract Socket socket();
+
+ /**
+ * Answer whether this channel's socket is connected or not.
+ *
+ * @return <code>true</code> for this channel's socket is connected;
+ * <code>false</code> otherwise.
+ */
+ public abstract boolean isConnected();
+
+ /**
+ * Answer whether this channel's socket is in connecting or not.
+ *
+ * @return <code>true</code> for the connection is initiated but not
+ * finished; <code>false</code> otherwise.
+ */
+ public abstract boolean isConnectionPending();
+
+ /**
+ * Connect the socket to remote address.
+ * <p>
+ * 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 <code>true</code> if the connection is finished at once or
+ * return <code>false</code> and the connection must wait
+ * <code>finishConnect</code> to finished otherwise.
+ * </p>
+ * <p>
+ * This method can be called at any moment, and can block other read and
+ * write operations while connecting.
+ * </p>
+ * <p>
+ * This method just execute the same security checks as the connect method
+ * of the <code>Socket</code> class.
+ * </p>
+ *
+ * @param address
+ * The address to be connected.
+ * @return <code>true</code> if connection is finished,<code>false</code>
+ * 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.
+ * <p>
+ * 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
+ * <code>connect</code> method. It will throw related
+ * <code>IOException</code> if the connection failed.
+ * </p>
+ * <p>
+ * This method will return <code>true</code> if the connection is finished
+ * already, and return <code>false</code> if the channel is non-blocking
+ * and the connection is not finished yet.
+ * </p>
+ * <p>
+ * If the channel is in blocking mode, this method will suspend, and return
+ * <code>true</code> for connection finished or throw some exception
+ * otherwise. The channel will be closed if the connection failed and this
+ * method thrown some exception.
+ * </p>
+ * <p>
+ * This method can be called at any moment, and can block other read and
+ * write operations while connecting.
+ * </p>
+ *
+ * @return <code>true</code> if the connection is successfully finished,
+ * <code>false</code> 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.
+ * <p>
+ * The maximum number of bytes that will be read is the
+ * <code>remaining()</code> number of bytes in the buffer when the method
+ * invoked. The bytes will be read into the buffer starting at the buffer's
+ * <code>position</code>.
+ * </p>
+ * <p>
+ * The call may block if other threads are also attempting to read on the
+ * same channel.
+ * </p>
+ * <p>
+ * Upon completion, the buffer's <code>position()</code> is updated to the
+ * end of the bytes that were read. The buffer's <code>limit()</code> is
+ * unmodified.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * This method attempts to read all of the <code>remaining()</code> bytes
+ * from <code>length</code> byte buffers, in order, starting at
+ * <code>targets[offset]</code>. The number of bytes actually read is
+ * returned.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * This method is equivalent to:
+ *
+ * <pre>
+ * read(targets, 0, targets.length);
+ * </pre>
+ *
+ * @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.
+ * <p>
+ * The maximum number of bytes that will be written is the
+ * <code>remaining()</code> number of bytes in the buffer when the method
+ * invoked. The bytes will be written from the buffer starting at the
+ * buffer's <code>position</code>.
+ * </p>
+ * <p>
+ * The call may block if other threads are also attempting to write on the
+ * same channel.
+ * </p>
+ * <p>
+ * Upon completion, the buffer's <code>position()</code> is updated to the
+ * end of the bytes that were written. The buffer's <code>limit()</code>
+ * is unmodified.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * This method attempts to write all of the <code>remaining()</code> bytes
+ * from <code>length</code> byte buffers, in order, starting at
+ * <code>sources[offset]</code>. The number of bytes actually written is
+ * returned.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * This method is equivalent to:
+ *
+ * <pre>
+ * write(buffers, 0, buffers.length);
+ * </pre>
+ *
+ * </p>
+ *
+ * @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);
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/UnresolvedAddressException.java b/nio/src/main/java/java/nio/channels/UnresolvedAddressException.java
new file mode 100644
index 0000000..cd69a61
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/UnresolvedAddressException.java
@@ -0,0 +1,36 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown when trying to use an unresolved network address in a network
+ * operation.
+ *
+ */
+public class UnresolvedAddressException extends IllegalArgumentException {
+
+ private static final long serialVersionUID = 6136959093620794148L;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public UnresolvedAddressException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/UnsupportedAddressTypeException.java b/nio/src/main/java/java/nio/channels/UnsupportedAddressTypeException.java
new file mode 100644
index 0000000..29e6840
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/UnsupportedAddressTypeException.java
@@ -0,0 +1,35 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+/**
+ * Thrown when connecting or binding to an unsupported address type.
+ *
+ */
+public class UnsupportedAddressTypeException extends IllegalArgumentException {
+
+ private static final long serialVersionUID = -2964323842829700493L;
+
+ /**
+ * Default constructor.
+ *
+ */
+ public UnsupportedAddressTypeException() {
+ super();
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/WritableByteChannel.java b/nio/src/main/java/java/nio/channels/WritableByteChannel.java
new file mode 100644
index 0000000..ccfa558
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/WritableByteChannel.java
@@ -0,0 +1,68 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels;
+
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * A WritableByteChannel is a type of Channel that can write bytes.
+ * <p>
+ * Writes are synchronous on a WritableByteChannel, that is, if a write is
+ * already in progress on the channel then subsequent writes will block until
+ * the first write completes. It is undefined whether non-write operations will
+ * block.
+ *
+ */
+public interface WritableByteChannel extends Channel {
+
+ /**
+ * Writes bytes from the given buffer to the channel.
+ * <p>
+ * The maximum number of bytes that will be written is the
+ * <code>remaining()</code> number of bytes in the buffer when the method
+ * invoked. The bytes will be written from the buffer starting at the
+ * buffer's <code>position</code>.
+ * </p>
+ * <p>
+ * The call may block if other threads are also attempting to write on the
+ * same channel.
+ * </p>
+ * <p>
+ * Upon completion, the buffer's <code>position()</code> is updated to the
+ * end of the bytes that were written. The buffer's <code>limit()</code>
+ * is unmodified.
+ * </p>
+ *
+ * @param buffer
+ * the byte buffer containing the bytes to be written.
+ * @return the number of bytes actually written.
+ * @throws NonWritableChannelException
+ * if the channel was not opened for writing.
+ * @throws ClosedChannelException
+ * if the channel was already closed.
+ * @throws AsynchronousCloseException
+ * if another thread closes the channel during the write.
+ * @throws ClosedByInterruptException
+ * if another thread interrupt the calling thread during the
+ * write.
+ * @throws IOException
+ * another IO exception occurs, details are in the message.
+ */
+ public int write(ByteBuffer buffer) throws IOException;
+}
diff --git a/nio/src/main/java/java/nio/channels/package.html b/nio/src/main/java/java/nio/channels/package.html
new file mode 100644
index 0000000..454b671
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/package.html
@@ -0,0 +1,9 @@
+<html>
+ <body>
+ <p>
+ Channels provide a way to connect to sources of data such as
+ files, sockets or other structures that allow input and/or output of
+ data. The selector supports multiplexing of non-blocking channels.
+ </p>
+ </body>
+</html>
diff --git a/nio/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java b/nio/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java
new file mode 100644
index 0000000..bed6db8
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/spi/AbstractInterruptibleChannel.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels.spi;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.Channel;
+import java.nio.channels.ClosedByInterruptException;
+import java.nio.channels.InterruptibleChannel;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * This class roots the implementation of interruptible channels.
+ * <p>
+ * The basic usage pattern for an interruptible channel is to invoke
+ * <code>begin()</code> before any IO operations, then
+ * <code>end(boolean)</code> after completing the operation. The argument to
+ * the end method shows whether there has been any change to the java
+ * environment that is visible to the API user.
+ * </p>
+ *
+ */
+public abstract class AbstractInterruptibleChannel implements Channel,
+ InterruptibleChannel {
+
+ static Method setInterruptAction = null;
+
+ static {
+ try {
+ setInterruptAction = AccessController
+ .doPrivileged(new PrivilegedExceptionAction<Method>() {
+ public Method run() throws Exception {
+ return Thread.class.getDeclaredMethod(
+ "setInterruptAction", //$NON-NLS-1$
+ new Class[] { Runnable.class });
+
+ }
+ });
+ setInterruptAction.setAccessible(true);
+ } catch (Exception e) {
+ // FIXME: be accommodate before VM actually provides
+ // setInterruptAction method
+ // throw new Error(e);
+ }
+ }
+
+ private volatile boolean closed = false;
+
+ volatile boolean interrupted = false;
+
+ /**
+ * Default constructor.
+ */
+ protected AbstractInterruptibleChannel() {
+ super();
+ }
+
+ /**
+ * Returns whether the channel is open.
+ *
+ * @return true if the channel is open, and false if it is closed.
+ * @see java.nio.channels.Channel#isOpen()
+ */
+ public synchronized final boolean isOpen() {
+ return !closed;
+ }
+
+ /**
+ * Closes the channel.
+ * <p>
+ * If the channel is already closed then this method has no effect,
+ * otherwise it closes the receiver via the implCloseChannel method.
+ * </p>
+ *
+ * @see java.nio.channels.Channel#close()
+ */
+ public final void close() throws IOException {
+ if (!closed) {
+ synchronized (this) {
+ if (!closed) {
+ closed = true;
+ implCloseChannel();
+ }
+ }
+ }
+ }
+
+ /**
+ * Start an IO operation that is potentially blocking.
+ * <p>
+ * Once the operation is completed the application should invoke a
+ * corresponding <code>end(boolean)</code>.
+ */
+ protected final void begin() {
+ // FIXME: be accommodate before VM actually provides
+ // setInterruptAction method
+ if (setInterruptAction != null) {
+ try {
+ setInterruptAction.invoke(Thread.currentThread(),
+ new Object[] { new Runnable() {
+ public void run() {
+ try {
+ interrupted = true;
+ AbstractInterruptibleChannel.this.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ } });
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * End an IO operation that was previously started with <code>begin()</code>.
+ *
+ * @param success
+ * pass true if the operation succeeded and had a side effect on
+ * the Java system, or false if not.
+ * @throws AsynchronousCloseException
+ * the channel was closed while the IO operation was in
+ * progress.
+ * @throws java.nio.channels.ClosedByInterruptException
+ * the thread conducting the IO operation was interrupted.
+ */
+ protected final void end(boolean success) throws AsynchronousCloseException {
+ // FIXME: be accommodate before VM actually provides
+ // setInterruptAction method
+ if (setInterruptAction != null) {
+ try {
+ setInterruptAction.invoke(Thread.currentThread(),
+ new Object[] { null });
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ if (interrupted) {
+ interrupted = false;
+ throw new ClosedByInterruptException();
+ }
+ }
+ if (!success && closed) {
+ throw new AsynchronousCloseException();
+ }
+ }
+
+ /**
+ * Implements the close channel behavior.
+ * <p>
+ * Closes the channel with a guarantee that the channel is not currently
+ * closed via <code>close()</code> and that the method is thread-safe.
+ * </p>
+ * <p>
+ * any outstanding threads blocked on IO operations on this channel must be
+ * released with either a normal return code, or an
+ * <code>AsynchronousCloseException</code>.
+ *
+ * @throws IOException
+ * if a problem occurs closing the channel.
+ */
+ protected abstract void implCloseChannel() throws IOException;
+}
diff --git a/nio/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java b/nio/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java
new file mode 100644
index 0000000..97184a2
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/spi/AbstractSelectableChannel.java
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.CancelledKeyException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.IllegalSelectorException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Abstract class for selectable channels.
+ * <p>
+ * In this class, there are methods about registering/deregistering a channel,
+ * about channel closing. It realize the multi-thread safe.
+ * </p>
+ *
+ */
+public abstract class AbstractSelectableChannel extends SelectableChannel {
+
+ private final SelectorProvider provider;
+
+ /*
+ * The collection of key.
+ */
+ private List<SelectionKey> keyList = new ArrayList<SelectionKey>();
+
+ private class BlockingLock {
+ }
+
+ private final Object blockingLock = new BlockingLock();
+
+ 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 = keyList.get(i);
+ if (null != key && key.selector() == selector) {
+ return key;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Realize the register function.
+ * <p>
+ * 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
+ * <code>register</code> in <code>selector</code>, and add the relative
+ * key to the key set of the current channel.
+ * </p>
+ *
+ * @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();
+ }
+
+ synchronized (blockingLock) {
+ if (isBlocking) {
+ throw new IllegalBlockingModeException();
+ }
+ if (!selector.isOpen()) {
+ if (0 == interestSet) {
+ // throw ISE exactly to keep consistency
+ throw new IllegalSelectorException();
+ }
+ // throw NPE exactly to keep consistency
+ throw new NullPointerException();
+ }
+ if (0 == interestSet) {
+ // throw ISE exactly to keep consistency
+ throw new IllegalSelectorException();
+ }
+ 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 = keyList.get(i);
+ if (null != key) {
+ key.cancel();
+ }
+ }
+ }
+
+ /**
+ * Implement the closing function of the SelectableChannel.
+ *
+ * @throws IOException
+ * If some I/O exception occurred.
+ */
+ 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
+ * <code>true</code> for blocking mode; <code>false</code>
+ * 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
+ * <code>true</code> for blocking mode; <code>false</code>
+ * for non-blocking mode.
+ * @throws IOException
+ * If some I/O exception occurred.
+ */
+ 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);
+ }
+ }
+
+}
diff --git a/nio/src/main/java/java/nio/channels/spi/AbstractSelectionKey.java b/nio/src/main/java/java/nio/channels/spi/AbstractSelectionKey.java
new file mode 100644
index 0000000..bca1f87
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/spi/AbstractSelectionKey.java
@@ -0,0 +1,60 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels.spi;
+
+import java.nio.channels.SelectionKey;
+
+/**
+ * Abstract class for selection key.
+ * <p>
+ * The class takes charge of the validation and cancellation of key.
+ * </p>
+ *
+ */
+public abstract class AbstractSelectionKey extends SelectionKey {
+
+ /*
+ * package private for deregister method in AbstractSelector.
+ */
+ boolean isValid = true;
+
+ /**
+ * Constructor for this class.
+ */
+ protected AbstractSelectionKey() {
+ super();
+ }
+
+ /**
+ * @see java.nio.channels.SelectionKey#isValid()
+ */
+ public final boolean isValid() {
+ return isValid;
+ }
+
+ /**
+ * Cancels this key and adds it to the cancelled key set.
+ *
+ * @see java.nio.channels.SelectionKey#cancel()
+ */
+ public final void cancel() {
+ if (isValid) {
+ isValid = false;
+ ((AbstractSelector) selector()).cancel(this);
+ }
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/spi/AbstractSelector.java b/nio/src/main/java/java/nio/channels/spi/AbstractSelector.java
new file mode 100644
index 0000000..a744fb8
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/spi/AbstractSelector.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Abstract class for selectors.
+ * <p>
+ * This class realizes the interruption of selection by <code>begin</code> and
+ * <code>end</code>. It also holds the cancelled and the deletion of the key
+ * set.
+ * </p>
+ *
+ */
+public abstract class AbstractSelector extends Selector {
+ private volatile boolean isOpen = true;
+
+ private SelectorProvider provider = null;
+
+ /*
+ * Set of cancelled keys.
+ */
+ private Set<SelectionKey> cancelledKeysSet = new HashSet<SelectionKey>();
+
+ /**
+ * Constructor for this class.
+ *
+ * @param selectorProvider
+ * A instance of SelectorProvider
+ */
+ protected AbstractSelector(SelectorProvider selectorProvider) {
+ provider = selectorProvider;
+ }
+
+ /**
+ * Closes this channel.
+ *
+ * @see java.nio.channels.Selector#close()
+ */
+ public synchronized final void close() throws IOException {
+ if (isOpen) {
+ isOpen = false;
+ implCloseSelector();
+ }
+ }
+
+ /**
+ * Implements the closing of this channel.
+ *
+ * @throws IOException
+ * If some I/O exception occurs.
+ */
+ protected abstract void implCloseSelector() throws IOException;
+
+ /**
+ * @see java.nio.channels.Selector#isOpen()
+ */
+ public final boolean isOpen() {
+ return isOpen;
+ }
+
+ /**
+ * Returns the SelectorProvider of this channel.
+ *
+ * @see java.nio.channels.Selector#provider()
+ */
+ public final SelectorProvider provider() {
+ return provider;
+ }
+
+ /**
+ * Returns the cancelled key set of this channel.
+ *
+ * @return The cancelled key set.
+ */
+ protected final Set<SelectionKey> cancelledKeys() {
+ return cancelledKeysSet;
+ }
+
+ /**
+ * Registers a channel to this selector.
+ *
+ * @param channel
+ * The channel to be registered.
+ * @param operations
+ * The interest set.
+ * @param attachment
+ * The attachment of the key.
+ * @return The key related with the channel and the selector.
+ */
+ protected abstract SelectionKey register(AbstractSelectableChannel channel,
+ int operations, Object attachment);
+
+ /**
+ * Deletes the key from channel's key set.
+ *
+ * @param key
+ * The key.
+ */
+ protected final void deregister(AbstractSelectionKey key) {
+ ((AbstractSelectableChannel) key.channel()).deregister(key);
+ key.isValid = false;
+ }
+
+ /**
+ * This starts a potentially blocking I/O operation
+ */
+ protected final void begin() {
+ // FIXME: be accommodate before VM actually provides
+ // setInterruptAction method
+ if (AbstractInterruptibleChannel.setInterruptAction != null) {
+ try {
+ AbstractInterruptibleChannel.setInterruptAction.invoke(Thread
+ .currentThread(), new Object[] { new Runnable() {
+ public void run() {
+ AbstractSelector.this.wakeup();
+ }
+ } });
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * This ends a potentially blocking I/O operation
+ */
+ protected final void end() {
+ // FIXME: be accommodate before VM actually provides
+ // setInterruptAction method
+ if (AbstractInterruptibleChannel.setInterruptAction != null) {
+ try {
+ AbstractInterruptibleChannel.setInterruptAction.invoke(Thread
+ .currentThread(), new Object[] { null });
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /*
+ * package private method for AbstractSelectionKey.cancel()
+ */
+ void cancel(SelectionKey key) {
+ synchronized (cancelledKeysSet) {
+ cancelledKeysSet.add(key);
+ }
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java b/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java
new file mode 100644
index 0000000..92733c7
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/spi/SelectorProvider.java
@@ -0,0 +1,259 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package 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.luni.platform.Platform;
+import org.apache.harmony.nio.internal.SelectorProviderImpl;
+
+/**
+ * Provider for nio selector and selectable channel.
+ * <p>
+ * 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
+ * <code>DatagramChannel</code>, <code>Pipe</code>, <code>Selector</code> ,
+ * <code>ServerSocketChannel</code>, and <code>SocketChannel</code>. All
+ * the methods of this class are multi-thread safe.
+ * </p>
+ *
+ */
+public abstract class SelectorProvider extends Object {
+
+ private static final String SYMBOL_COMMENT = "#"; //$NON-NLS-1$
+
+ private static final String PROVIDER_IN_SYSTEM_PROPERTY = "java.nio.channels.spi.SelectorProvider"; //$NON-NLS-1$
+
+ 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;
+
+ /**
+ * 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.
+ * <p>
+ * <ul>
+ * <li> If the system property "java.nio.channels.spi.SelectorProvider" is
+ * set, the value of this property is the class name of the return provider.
+ * </li>
+ * <li>If there is a provider-configuration file named
+ * "java.nio.channels.spi.SelectorProvider" in META-INF/services of some jar
+ * file valid in the system class loader, the first class name is the return
+ * provider's class name. </li>
+ * <li> Otherwise, a system default provider will be returned. </li>
+ * </ul>
+ * </p>
+ *
+ * @return The provider.
+ */
+ synchronized public static SelectorProvider provider() {
+ if (null == provider) {
+ provider = loadProviderByProperty();
+ if (null == provider) {
+ provider = loadProviderByJar();
+ }
+ if (null == provider) {
+ provider = AccessController
+ .doPrivileged(new PrivilegedAction<SelectorProvider>() {
+ public SelectorProvider run() {
+ return new SelectorProviderImpl();
+ }
+ });
+ }
+ }
+ return provider;
+ }
+
+ /*
+ * load the provider in the jar file of class path.
+ */
+ static SelectorProvider loadProviderByJar() {
+ Enumeration<URL> enumeration = null;
+
+ ClassLoader classLoader = AccessController.doPrivileged(
+ new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return ClassLoader.getSystemClassLoader();
+ }
+ });
+ try {
+ enumeration = classLoader.getResources(PROVIDER_IN_JAR_RESOURCE);
+ } catch (IOException e) {
+ throw new Error(e);
+ }
+ 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 {
+ // BEGIN android-modified
+ br = new BufferedReader(
+ new InputStreamReader(
+ (enumeration.nextElement()).openStream()),
+ 8192);
+ // END android-modified
+ } catch (Exception e) {
+ continue;
+ }
+ try {
+ // only the first class is loaded ,as spec says, not the same as
+ // we do before.
+ while ((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()) {
+ return (SelectorProvider) classLoader.loadClass(
+ className).newInstance();
+ }
+ }
+ } catch (Exception e) {
+ throw new Error(e);
+ // BEGIN android-added
+ // copied from a newer version of harmony
+ } finally {
+ try {
+ br.close();
+ } catch (IOException ioe) {
+ // Ignore
+ }
+ // END android-added
+ }
+ }
+ return null;
+ }
+
+ /*
+ * load by system property.
+ */
+ static SelectorProvider loadProviderByProperty() {
+ return AccessController.doPrivileged(
+ new PrivilegedAction<SelectorProvider>() {
+ public SelectorProvider run() {
+ try {
+ final String className =
+ System.getProperty(PROVIDER_IN_SYSTEM_PROPERTY);
+ if (null != className) {
+ Class<?> spClass = ClassLoader
+ .getSystemClassLoader().loadClass(
+ className);
+ return (SelectorProvider)spClass.newInstance();
+ }
+ return null;
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+ });
+ }
+
+ /**
+ * Create a new open <code>DatagramChannel</code>.
+ *
+ * @return The channel.
+ * @throws IOException
+ * If some I/O exception occurred.
+ */
+ public abstract DatagramChannel openDatagramChannel() throws IOException;
+
+ /**
+ * Create a new <code>Pipe</code>.
+ *
+ * @return The pipe.
+ * @throws IOException
+ * If some I/O exception occurred.
+ */
+ public abstract Pipe openPipe() throws IOException;
+
+ /**
+ * Create a new selector.
+ *
+ * @return The selector.
+ * @throws IOException
+ * If some I/O exception occurred.
+ */
+ public abstract AbstractSelector openSelector() throws IOException;
+
+ /**
+ * Create a new open <code>ServerSocketChannel</code>.
+ *
+ * @return The channel.
+ * @throws IOException
+ * If some I/O exception occurred.
+ */
+ public abstract ServerSocketChannel openServerSocketChannel()
+ throws IOException;
+
+ /**
+ * Create a new open <code>SocketChannel</code>.
+ *
+ * @return The channel.
+ * @throws IOException
+ * If some I/O exception occurred.
+ */
+ 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 occurred.
+ * @throws SecurityException
+ * If there is a security manager, and it denies
+ * RuntimePermission("selectorProvider").
+ */
+ public Channel inheritedChannel() throws IOException {
+ if (null == inheritedChannel) {
+ inheritedChannel = Platform.getNetworkSystem().inheritedChannel();
+ }
+ return inheritedChannel;
+ }
+}
diff --git a/nio/src/main/java/java/nio/channels/spi/package.html b/nio/src/main/java/java/nio/channels/spi/package.html
new file mode 100644
index 0000000..e7b8a49
--- /dev/null
+++ b/nio/src/main/java/java/nio/channels/spi/package.html
@@ -0,0 +1,7 @@
+<html>
+ <body>
+ <p>
+ Service-provider classes for nio channels.
+ </p>
+ </body>
+</html>
diff --git a/nio/src/main/java/java/nio/package.html b/nio/src/main/java/java/nio/package.html
new file mode 100644
index 0000000..17d6ceb
--- /dev/null
+++ b/nio/src/main/java/java/nio/package.html
@@ -0,0 +1,15 @@
+<html>
+ <body>
+ <p>
+ Provides buffers that help handling data.
+ </p>
+ <p>
+ There are buffers for most primitive data types such as
+ FloatBuffer, IntBuffer, ... They all give means to put/get data from the
+ buffers, to compact, slice or duplicate it, or to wrap an existing
+ array. A buffer also manages the position of the current element in the
+ buffer, lets you rewind to the beginning, skip elements or go to the
+ last element.
+ </p>
+ </body>
+</html>
diff --git a/nio/src/main/java/org/apache/harmony/nio/AddressUtil.java b/nio/src/main/java/org/apache/harmony/nio/AddressUtil.java
new file mode 100644
index 0000000..7c094e7
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/AddressUtil.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Android Notice
+ * In this class the address length was changed from long to int.
+ * This is due to performance optimizations for the device.
+ */
+
+package org.apache.harmony.nio;
+
+import java.io.FileDescriptor;
+import java.nio.Buffer;
+import java.nio.channels.Channel;
+
+import org.apache.harmony.luni.platform.FileDescriptorHandler;
+import org.apache.harmony.nio.internal.DirectBuffer;
+import org.apache.harmony.nio.internal.FileChannelImpl;
+
+public class AddressUtil {
+
+ /**
+ * Gets the start address of a direct buffer.
+ * <p>
+ * This method corresponds to the JNI function:
+ *
+ * <pre>
+ * void* GetDirectBufferAddress(JNIEnv* env, jobject buf);
+ * </pre>
+ *
+ * @param buf
+ * the direct buffer whose address shall be returned must not be
+ * <code>null</code>.
+ * @return the address of the buffer given, or zero if the buffer is not a
+ * direct Buffer.
+ */
+ public static int getDirectBufferAddress(Buffer buf) {
+ if (!(buf instanceof DirectBuffer)) {
+ return 0;
+ }
+ return ((DirectBuffer) buf).getEffectiveAddress().toInt();
+ }
+
+ /**
+ * Gets the address of native resource held by the given channel, if has
+ * any.
+ *
+ * For network related channel, including SocketChannel, ServerSocketChannel
+ * and DatagramChannel, this method returns a int of Socket handler in Linux
+ * while returns a SOCKET (UINT_PTR) in windows.
+ *
+ * For FileChannel, this method returns the native file descriptor.
+ *
+ * For other channels, this method return 0, which means unsupported
+ * operation.
+ *
+ * @param channel
+ * the given channel which may holds a native resource address
+ * @return the address of native resource held by the given channel, if any,
+ * otherwise return 0
+ */
+ public static int getChannelAddress(Channel channel){
+ if(channel instanceof FileDescriptorHandler){
+ return getFDAddress(((FileDescriptorHandler) channel).getFD());
+ }else if(channel instanceof FileChannelImpl){
+ return ((FileChannelImpl) channel).getHandle();
+ }
+ return 0;
+ }
+
+ private static native int getFDAddress(FileDescriptor fd);
+} \ No newline at end of file
diff --git a/nio/src/main/java/org/apache/harmony/nio/FileChannelFactory.java b/nio/src/main/java/org/apache/harmony/nio/FileChannelFactory.java
new file mode 100644
index 0000000..5abe24a
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/FileChannelFactory.java
@@ -0,0 +1,56 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Android Notice
+ * In this class the address length was changed from long to int.
+ * This is due to performance optimizations for the device.
+ */
+
+package org.apache.harmony.nio;
+
+
+import java.nio.channels.FileChannel;
+
+import org.apache.harmony.nio.internal.ReadOnlyFileChannel;
+import org.apache.harmony.nio.internal.ReadWriteFileChannel;
+import org.apache.harmony.nio.internal.WriteOnlyFileChannel;
+import org.apache.harmony.nio.internal.nls.Messages;
+import org.apache.harmony.luni.platform.IFileSystem;
+
+/**
+ * A simple factory to provide a generic way to create FileChannel
+ * implementation from within the java.io package.
+ */
+public class FileChannelFactory {
+ public static FileChannel getFileChannel(Object stream, int fd, int mode) {
+ switch(mode){
+ case IFileSystem.O_RDONLY:
+ return new ReadOnlyFileChannel(stream, fd);
+ case IFileSystem.O_WRONLY:
+ return new WriteOnlyFileChannel(stream, fd);
+ case IFileSystem.O_RDWR:
+ return new ReadWriteFileChannel(stream, fd);
+ case IFileSystem.O_RDWRSYNC:
+ return new ReadWriteFileChannel(stream, fd);
+ case IFileSystem.O_APPEND:
+ return new WriteOnlyFileChannel(stream, fd, true);
+ default:
+ // nio.09=Unknown file channel type: {0}
+ throw new RuntimeException(Messages.getString("nio.09", mode)); //$NON-NLS-1$
+ }
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/Util.java b/nio/src/main/java/org/apache/harmony/nio/Util.java
new file mode 100644
index 0000000..f895a51
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/Util.java
@@ -0,0 +1,162 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio;
+
+import org.apache.harmony.nio.internal.nls.Messages;
+
+/*
+ * Static methods. Used by io and nio packages.
+ *
+ */
+public final class Util {
+
+ // -------------------------------------------------------------------
+ // Constructor
+ // -------------------------------------------------------------------
+
+ /*
+ * No instance.
+ */
+ private Util() {
+ super();
+ }
+
+ // -------------------------------------------------------------------
+ // Routine methods.
+ // -------------------------------------------------------------------
+
+ /*
+ * Check array bounds method for methods like doSomething(Object[], offset,
+ * length). Exception throws order is IndexOutOfBoundsException for negative
+ * index, NullPointerException for null array, IndexOutOfBoundsException for
+ * offset+length > array.length
+ */
+ public static void assertArrayIndex(Object[] array, int offset, int length) {
+ if (offset < 0 || length < 0) {
+ // nio.05=Negative index specified
+ throw new IndexOutOfBoundsException(Messages.getString("nio.05")); //$NON-NLS-1$
+ }
+ if ((long) offset + (long) length > array.length) {
+ // nio.04=Size mismatch
+ throw new IndexOutOfBoundsException(Messages.getString("nio.04")); //$NON-NLS-1$
+ }
+ }
+
+ public static void assertArrayIndex(boolean[] array, int offset, int length) {
+ if (offset < 0 || length < 0) {
+ // nio.05=Negative index specified
+ throw new IndexOutOfBoundsException(Messages.getString("nio.05")); //$NON-NLS-1$
+ }
+ if ((long) offset + (long) length > array.length) {
+ // nio.04=Size mismatch
+ throw new IndexOutOfBoundsException(Messages.getString("nio.04")); //$NON-NLS-1$
+ }
+ }
+
+ public static void assertArrayIndex(byte[] array, int offset, int length) {
+ if (offset < 0 || length < 0) {
+ // nio.05=Negative index specified
+ throw new IndexOutOfBoundsException(Messages.getString("nio.05")); //$NON-NLS-1$
+ }
+ if ((long) offset + (long) length > array.length) {
+ // nio.04=Size mismatch
+ throw new IndexOutOfBoundsException(Messages.getString("nio.04")); //$NON-NLS-1$
+ }
+ }
+
+ public static void assertArrayIndex(short[] array, int offset, int length) {
+ if (offset < 0 || length < 0) {
+ // nio.05=Negative index specified
+ throw new IndexOutOfBoundsException(Messages.getString("nio.05")); //$NON-NLS-1$
+ }
+ if ((long) offset + (long) length > array.length) {
+ // nio.04=Size mismatch
+ throw new IndexOutOfBoundsException(Messages.getString("nio.04")); //$NON-NLS-1$
+ }
+ }
+
+ public static void assertArrayIndex(int[] array, int offset, int length) {
+ if (offset < 0 || length < 0) {
+ // nio.05=Negative index specified
+ throw new IndexOutOfBoundsException(Messages.getString("nio.05")); //$NON-NLS-1$
+ }
+ if ((long) offset + (long) length > array.length) {
+ // nio.04=Size mismatch
+ throw new IndexOutOfBoundsException(Messages.getString("nio.04")); //$NON-NLS-1$
+ }
+ }
+
+ public static void assertArrayIndex(long[] array, int offset, int length) {
+ if (offset < 0 || length < 0) {
+ // nio.05=Negative index specified
+ throw new IndexOutOfBoundsException(Messages.getString("nio.05")); //$NON-NLS-1$
+ }
+ if ((long) offset + (long) length > array.length) {
+ // nio.04=Size mismatch
+ throw new IndexOutOfBoundsException(Messages.getString("nio.04")); //$NON-NLS-1$
+ }
+ }
+
+ public static void assertArrayIndex(float[] array, int offset, int length) {
+ if (offset < 0 || length < 0) {
+ // nio.05=Negative index specified
+ throw new IndexOutOfBoundsException(Messages.getString("nio.05")); //$NON-NLS-1$
+ }
+ if ((long) offset + (long) length > array.length) {
+ // nio.04=Size mismatch
+ throw new IndexOutOfBoundsException(Messages.getString("nio.04")); //$NON-NLS-1$
+ }
+ }
+
+ public static void assertArrayIndex(double[] array, int offset, int length) {
+ if (offset < 0 || length < 0) {
+ // nio.05=Negative index specified
+ throw new IndexOutOfBoundsException(Messages.getString("nio.05")); //$NON-NLS-1$
+ }
+ if ((long) offset + (long) length > array.length) {
+ // nio.04=Size mismatch
+ throw new IndexOutOfBoundsException(Messages.getString("nio.04")); //$NON-NLS-1$
+ }
+ }
+
+ public static void assertArrayIndex(char[] array, int offset, int length) {
+ if (offset < 0 || length < 0) {
+ // nio.05=Negative index specified
+ throw new IndexOutOfBoundsException(Messages.getString("nio.05")); //$NON-NLS-1$
+ }
+ if ((long) offset + (long) length > array.length) {
+ // nio.04=Size mismatch
+ throw new IndexOutOfBoundsException(Messages.getString("nio.04")); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * Check array bounds method for methods like doSomething(Object[], offset,
+ * length). Exception throws order is IndexOutOfBoundsException for negative
+ * index, IndexOutOfBoundsException for offset+length > array.length
+ */
+ public static void assertArrayIndex(int arrayLength, int offset, int length) {
+ if (offset < 0 || length < 0) {
+ // nio.05=Negative index specified
+ throw new IndexOutOfBoundsException(Messages.getString("nio.05")); //$NON-NLS-1$
+ }
+ if ((long) offset + (long) length > arrayLength) {
+ // nio.04=Size mismatch
+ throw new IndexOutOfBoundsException(Messages.getString("nio.04")); //$NON-NLS-1$
+ }
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
new file mode 100644
index 0000000..ddd56e5
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
@@ -0,0 +1,910 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Android Notice
+ * In this class the address length was changed from long to int.
+ * This is due to performance optimizations for the device.
+ */
+
+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.ClosedChannelException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.IllegalBlockingModeException;
+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;
+import org.apache.harmony.luni.util.ErrorCodeException;
+import org.apache.harmony.nio.AddressUtil;
+
+/*
+ * 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 = 1;
+
+ private static final int ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK = -211;
+
+ private static final byte[] stubArray = new byte[0];
+
+ // -------------------------------------------------------------------
+ // 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;
+
+ private final Object readLock = new Object();
+
+ 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);
+ }
+
+ /*
+ * for native call
+ */
+ private DatagramChannelImpl(){
+ super(SelectorProvider.provider());
+ fd = new FileDescriptor();
+ connectAddress = new InetSocketAddress(0);
+ }
+
+ // -------------------------------------------------------------------
+ // Methods for getting internal DatagramSocket.
+ // -------------------------------------------------------------------
+
+ /*
+ * Getting the internal DatagramSocket If we have not the socket, we create
+ * a new one.
+ */
+ @Override
+ synchronized public DatagramSocket socket() {
+ if (null == socket) {
+ 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()
+ */
+ @Override
+ synchronized public boolean isConnected() {
+ return connected;
+ }
+
+ /*
+ *
+ * @see java.nio.channels.DatagramChannel#connect(java.net.SocketAddress)
+ */
+ @Override
+ 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()
+ */
+ @Override
+ 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)
+ */
+ @Override
+ public SocketAddress receive(ByteBuffer target) throws IOException {
+ // must not null and not readonly
+ checkWritable(target);
+ // must open
+ checkOpen();
+
+ if (!isBound) {
+ return null;
+ }
+
+ SocketAddress retAddr = null;
+ try {
+ begin();
+
+ // receive real data packet, (not peek)
+ synchronized (readLock) {
+ boolean loop = isBlocking();
+ if (!target.isDirect()) {
+ retAddr = receiveImpl(target, loop);
+ } else {
+ retAddr = receiveDirectImpl(target, loop);
+ }
+ }
+ } catch (InterruptedIOException e) {
+ // this line used in Linux
+ return null;
+ } finally {
+ end(null != retAddr);
+ }
+ return retAddr;
+ }
+
+ private SocketAddress receiveImpl(ByteBuffer target, boolean loop)
+ throws IOException {
+ SocketAddress retAddr = null;
+ DatagramPacket receivePacket;
+ int oldposition = target.position();
+ int received = 0;
+ if (target.hasArray()) {
+ receivePacket = new DatagramPacket(target.array(), target
+ .position()
+ + target.arrayOffset(), target.remaining());
+ } else {
+ receivePacket = new DatagramPacket(new byte[target.remaining()], target.remaining());
+ }
+ do {
+ if (isConnected()) {
+ received = networkSystem.recvConnectedDatagram(fd, receivePacket,
+ receivePacket.getData(), receivePacket.getOffset(),
+ receivePacket.getLength(), isBlocking() ? 0
+ : DEFAULT_TIMEOUT, false);
+ } else {
+ received = 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()) {
+
+ if (received > 0) {
+ if (target.hasArray()) {
+ target.position(oldposition + received);
+ } else {
+ // copy the data of received packet
+ target.put(receivePacket.getData(), 0, received);
+ }
+ }
+ retAddr = receivePacket.getSocketAddress();
+ break;
+ }
+ } while (loop);
+ return retAddr;
+ }
+
+ private SocketAddress receiveDirectImpl(ByteBuffer target, boolean loop) throws IOException
+ {
+ SocketAddress retAddr = null;
+ DatagramPacket receivePacket = new DatagramPacket(
+ stubArray, 0);
+ int oldposition = target.position();
+ int received = 0;
+ do {
+ int address = AddressUtil.getDirectBufferAddress(target);
+ if (isConnected()) {
+ received = networkSystem.recvConnectedDatagramDirect(fd, receivePacket,
+ address, target.position(),
+ target.remaining(), isBlocking() ? 0
+ : DEFAULT_TIMEOUT, false);
+ } else {
+ received = networkSystem.receiveDatagramDirect(fd, receivePacket,
+ address, target.position(),
+ target.remaining(), 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
+ if (received > 0) {
+ target.position(oldposition + received);
+ }
+ retAddr = receivePacket.getSocketAddress();
+ break;
+ }
+ } while (loop);
+ return retAddr;
+ }
+
+ /*
+ * @see java.nio.channels.DatagramChannel#send(java.nio.ByteBuffer,
+ * java.net.SocketAddress)
+ */
+ @Override
+ public int send(ByteBuffer source, SocketAddress socketAddress)
+ throws IOException {
+ // must not null
+ checkNotNull(source);
+ // must open
+ checkOpen();
+
+ // transfer socketAddress
+ InetSocketAddress isa = (InetSocketAddress) socketAddress;
+ 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 = null;
+ int length = source.remaining();
+ int oldposition = source.position();
+ int start = oldposition;
+ if (source.isDirect()) {
+ synchronized (writeLock) {
+ int data_address = AddressUtil
+ .getDirectBufferAddress(source);
+ sendCount = networkSystem.sendDatagramDirect(fd,
+ data_address, start, length, isa.getPort(), false,
+ trafficClass, isa.getAddress());
+ }
+ } else {
+ if (source.hasArray()) {
+ array = source.array();
+ start += source.arrayOffset();
+ } else {
+ array = new byte[length];
+ source.get(array);
+ start = 0;
+ }
+ synchronized (writeLock) {
+ sendCount = networkSystem.sendDatagram(fd, array, start,
+ length, isa.getPort(), false, trafficClass, isa
+ .getAddress());
+ }
+ }
+ source.position(oldposition + sendCount);
+ return sendCount;
+ } finally {
+ end(sendCount >= 0);
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Methods for read and write.
+ // -------------------------------------------------------------------
+
+ /*
+ *
+ * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer)
+ */
+ @Override
+ public int read(ByteBuffer target) throws IOException {
+ if (null == target) {
+ throw new NullPointerException();
+ }
+ // status must be open and connected
+ checkOpenConnected();
+ // target buffer must be not null and not readonly
+ checkWritable(target);
+
+ if (!target.hasRemaining()) {
+ return 0;
+ }
+
+ int readCount = 0;
+ if (target.isDirect() || target.hasArray()) {
+ readCount = readImpl(target);
+ if(readCount > 0){
+ target.position(target.position() + readCount);
+ }
+
+ } else {
+ byte[] readArray = new byte[target.remaining()];
+ ByteBuffer readBuffer = ByteBuffer.wrap(readArray);
+ readCount = readImpl(readBuffer);
+ if(readCount > 0){
+ target.put(readArray, 0, readCount);
+ }
+ }
+ return readCount;
+ }
+
+ /*
+ *
+ * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer[], int,
+ * int)
+ */
+ @Override
+ public long read(ByteBuffer[] targets, int offset, int length)
+ throws IOException {
+ if (length < 0 || offset < 0
+ || (long) length + (long) offset > targets.length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ // status must be open and connected
+ checkOpenConnected();
+
+ int totalCount = 0;
+ for (int val = offset; val < length; val++) {
+ // target buffer must be not null and not readonly
+ checkWritable(targets[val]);
+ totalCount += targets[val].remaining();
+ }
+
+ // read data to readBuffer, and then transfer data from readBuffer to
+ // targets.
+ ByteBuffer readBuffer = ByteBuffer.allocate(totalCount);
+ int readCount;
+ readCount = readImpl(readBuffer);
+ int left = readCount;
+ int index = offset;
+ // transfer data from readBuffer to targets
+ byte[] readArray = readBuffer.array();
+ while (left > 0) {
+ int putLength = Math.min(targets[index].remaining(), left);
+ targets[index].put(readArray, readCount - left, putLength);
+ index++;
+ left -= putLength;
+ }
+ return readCount;
+ }
+
+ /*
+ * read from channel, and store the result in the target.
+ */
+ private int readImpl(ByteBuffer readBuffer) throws IOException {
+ synchronized(readLock){
+ int readCount = 0;
+ try {
+ begin();
+ // timeout == 0 means block read.
+ // DEFAULT_TIMEOUT is used in non-block mode.
+ int timeout = isBlocking() ? 0 : DEFAULT_TIMEOUT;
+ int start = readBuffer.position();
+ int length = readBuffer.remaining();
+ if (readBuffer.isDirect()) {
+ int address = AddressUtil.getDirectBufferAddress(readBuffer);
+ if (isConnected()) {
+ readCount = networkSystem.recvConnectedDatagramDirect(fd,
+ null, address, start, length, timeout, false);
+ } else {
+ readCount = networkSystem.receiveDatagramDirect(fd,
+ null, address, start, length, timeout, false);
+ }
+ } else {
+ // the target is assured to have array.
+ byte[] target = readBuffer.array();
+ start += readBuffer.arrayOffset();
+ if (isConnected()) {
+ readCount = networkSystem.recvConnectedDatagram(fd, null,
+ target, start, length, timeout, false);
+ } else {
+ readCount = networkSystem.receiveDatagram(fd, null, target,
+ start, length, timeout, false);
+ }
+ }
+ return readCount;
+ } catch (InterruptedIOException e) {
+ // InterruptedIOException will be thrown when timeout.
+ return 0;
+ } finally {
+ end(readCount > 0);
+ }
+ }
+ }
+
+ /*
+ * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer)
+ */
+ @Override
+ public int write(ByteBuffer source) throws IOException {
+ // source buffer must be not null
+ checkNotNull(source);
+ // status must be open and connected
+ checkOpenConnected();
+ // return immediately if source is full
+ if (!source.hasRemaining()) {
+ return 0;
+ }
+
+ ByteBuffer writeBuffer = null;
+ byte[] writeArray = null;
+ int oldposition = source.position();
+ int result;
+ if (source.isDirect() || source.hasArray()) {
+ writeBuffer = source;
+ } else {
+ writeArray = new byte[source.remaining()];
+ source.get(writeArray);
+ writeBuffer = ByteBuffer.wrap(writeArray);
+ }
+ result = writeImpl(writeBuffer);
+ if (result > 0) {
+ source.position(oldposition + result);
+ }
+ return result;
+ }
+
+ /*
+ * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer[], int,
+ * int)
+ */
+ @Override
+ public long write(ByteBuffer[] sources, int offset, int length)
+ throws IOException {
+ if (length < 0 || offset < 0
+ || (long) length + (long) offset > sources.length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ // status must be open and connected
+ checkOpenConnected();
+ int count = calculateByteBufferArray(sources, offset, length);
+ if (0 == count) {
+ return 0;
+ }
+ ByteBuffer writeBuf = ByteBuffer.allocate(count);
+ for (int val = offset; val < length+offset; val++) {
+ ByteBuffer source = sources[val];
+ int oldPosition = source.position();
+ writeBuf.put(source);
+ source.position(oldPosition);
+ }
+ writeBuf.flip();
+ int result = writeImpl(writeBuf);
+ int val = offset;
+ int written = result;
+ while (result > 0) {
+ ByteBuffer source = sources[val];
+ int gap = Math.min(result, source.remaining());
+ source.position(source.position() + gap);
+ val++;
+ result -= gap;
+ }
+ return written;
+ }
+
+ /*
+ * write the source. return the count of bytes written.
+ */
+ private int writeImpl(ByteBuffer buf) throws IOException {
+ synchronized(writeLock){
+ int result = 0;
+ try {
+ begin();
+ int length = buf.remaining();
+ int start = buf.position();
+
+ if (buf.isDirect()) {
+ int address = AddressUtil.getDirectBufferAddress(buf);
+ result = networkSystem.sendConnectedDatagramDirect(fd, address,
+ start, length, isBound);
+ } else {
+ // buf is assured to have array.
+ start += buf.arrayOffset();
+ result = networkSystem.sendConnectedDatagram(fd, buf.array(),
+ start, length, isBound);
+ }
+ return result;
+ } catch (SocketException e) {
+ if (e.getCause() instanceof ErrorCodeException) {
+ if (ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK == ((ErrorCodeException) e
+ .getCause()).getErrorCode()) {
+ return result;
+ }
+ }
+ throw e;
+ } finally {
+ end(result > 0);
+ }
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Protected Inherited methods
+ // -------------------------------------------------------------------
+
+ /*
+ * do really closing action here
+ */
+ @Override
+ 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)
+ */
+ @Override
+ @SuppressWarnings("unused")
+ protected void implConfigureBlocking(boolean blockingMode)
+ throws IOException {
+ // Do nothing here. For real read/write operation in nonblocking mode,
+ // it uses select system call. Whether a channel is blocking can be
+ // decided by isBlocking() method.
+ }
+
+ // -------------------------------------------------------------------
+ // 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 checkWritable(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;
+ }
+
+ private int calculateByteBufferArray(ByteBuffer[] sources, int offset,
+ int length) {
+ int sum = 0;
+ for (int val = offset; val < offset + length; val++) {
+ sum += sources[val].remaining();
+ }
+ return sum;
+ }
+
+ /*
+ * 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
+ */
+ @Override
+ public DatagramChannel getChannel() {
+ return channelImpl;
+ }
+
+ /*
+ * @see java.net.DatagramSocket#isBound()
+ */
+ @Override
+ public boolean isBound() {
+ return channelImpl.isBound;
+ }
+
+ /*
+ * @see java.net.DatagramSocket#isConnected()
+ */
+ @Override
+ public boolean isConnected() {
+ return channelImpl.isConnected();
+ }
+
+ /*
+ * @see java.net.DatagramSocket#getInetAddress()
+ */
+ @Override
+ public InetAddress getInetAddress() {
+ if (null == channelImpl.connectAddress) {
+ return null;
+ }
+ return channelImpl.connectAddress.getAddress();
+ }
+
+ /*
+ * @see java.net.DatagramSocket#getLocalAddress()
+ */
+ @Override
+ public InetAddress getLocalAddress() {
+ return channelImpl.getLocalAddress();
+ }
+
+ /*
+ * @see java.net.DatagramSocket#getPort()
+ */
+ @Override
+ public int getPort() {
+ if (null == channelImpl.connectAddress) {
+ return -1;
+ }
+ return channelImpl.connectAddress.getPort();
+ }
+
+ /*
+ * @see java.net.DatagramSocket#bind(java.net.SocketAddress)
+ */
+ @Override
+ public void bind(SocketAddress localAddr) throws SocketException {
+ if (channelImpl.isConnected()) {
+ throw new AlreadyConnectedException();
+ }
+ super.bind(localAddr);
+ channelImpl.isBound = true;
+ }
+
+ /*
+ * @see java.net.DatagramSocket#receive(java.net.DatagramPacket)
+ */
+ @Override
+ public void receive(DatagramPacket packet) throws IOException {
+ if (!channelImpl.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ super.receive(packet);
+ }
+
+ /*
+ * @see java.net.DatagramSocket#send(java.net.DatagramPacket)
+ */
+ @Override
+ public void send(DatagramPacket packet) throws IOException {
+ if (!channelImpl.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ super.send(packet);
+ }
+
+ /*
+ * @see java.net.DatagramSocket#close()
+ */
+ @Override
+ public void close() {
+ synchronized (channelImpl) {
+ if (channelImpl.isOpen()) {
+ try {
+ channelImpl.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ super.close();
+ }
+ }
+
+ /*
+ * @see java.net.DatagramSocket#disconnect()
+ */
+ @Override
+ public void disconnect() {
+ try {
+ channelImpl.disconnect();
+ } catch (IOException e) {
+ // Ignore
+ }
+ super.disconnect();
+ }
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/DirectBuffer.java b/nio/src/main/java/org/apache/harmony/nio/internal/DirectBuffer.java
new file mode 100644
index 0000000..ec12665
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/DirectBuffer.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.internal;
+
+import org.apache.harmony.luni.platform.PlatformAddress;
+
+public interface DirectBuffer {
+ // BEGIN android-changed
+ // Copied from a newer version of harmony
+ PlatformAddress getEffectiveAddress();
+
+ PlatformAddress getBaseAddress();
+
+ boolean isAddressValid();
+
+ void addressValidityCheck();
+
+ void free();
+
+ int getByteCapacity();
+ // END android-changed
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/FileChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/FileChannelImpl.java
new file mode 100644
index 0000000..54a7c2e
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/FileChannelImpl.java
@@ -0,0 +1,656 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Android Notice
+ * In this class the address length was changed from long to int.
+ * This is due to performance optimizations for the device.
+ *
+ * Also this class was copied from a newer version of harmony.
+ */
+
+package org.apache.harmony.nio.internal;
+
+import java.io.Closeable;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+
+import org.apache.harmony.luni.platform.IFileSystem;
+import org.apache.harmony.luni.platform.Platform;
+import org.apache.harmony.luni.platform.PlatformAddress;
+import org.apache.harmony.luni.platform.PlatformAddressFactory;
+import org.apache.harmony.nio.internal.nls.Messages;
+
+/*
+ * The file channel impl class is the bridge between the logical channels
+ * described by the NIO channel framework, and the file system implementation
+ * provided by the port layer.
+ *
+ * This class is non-API, but implements the API of the FileChannel interface.
+ *
+ */
+public abstract class FileChannelImpl extends FileChannel {
+
+ // Reference to the portable file system code.
+ private static final IFileSystem fileSystem = Platform.getFileSystem();
+
+ private static final int ALLOC_GRANULARITY;
+
+ static {
+ try {
+ ALLOC_GRANULARITY = fileSystem.getAllocGranularity();
+ } catch (IOException e) {
+ throw new Error(e);
+ }
+
+ }
+
+ // Handle to the open file
+ private final int handle;
+
+ // The object that will track all outstanding locks on this channel.
+ private final LockManager lockManager = new LockManager();
+
+ private class RepositioningLock {}
+ private final Object repositioningLock = new RepositioningLock();
+
+ private final Object stream;
+
+ /*
+ * Create a new file channel implementation class that wraps the given file
+ * handle and operates in the specified mode.
+ *
+ */
+ public FileChannelImpl(Object stream, int handle) {
+ super();
+ this.handle = handle;
+ this.stream = stream;
+ }
+
+ /*
+ * Helper method to throw an exception if the channel is already closed.
+ * Note that we don't bother to synchronize on this test since the file may
+ * be closed by operations beyond our control anyways.
+ */
+ protected final void openCheck() throws ClosedChannelException {
+ if (!isOpen()) {
+ throw new ClosedChannelException();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.nio.channels.spi.AbstractInterruptibleChannel#implCloseChannel()
+ */
+ protected void implCloseChannel() throws IOException {
+ if (stream instanceof Closeable) {
+ ((Closeable) stream).close();
+ }
+ }
+
+ protected FileLock basicLock(long position, long size, boolean shared,
+ boolean wait) throws IOException {
+ if ((position < 0) || (size < 0)) {
+ // nio.0A=Lock position and size must be non-negative.
+ throw new IllegalArgumentException(
+ Messages.getString("nio.0A")); //$NON-NLS-1$
+ }
+ int lockType = shared ? IFileSystem.SHARED_LOCK_TYPE
+ : IFileSystem.EXCLUSIVE_LOCK_TYPE;
+ FileLock pendingLock = new FileLockImpl(this, position, size, shared);
+ lockManager.addLock(pendingLock);
+
+ if (fileSystem.lock(handle, position, size, lockType, wait)) {
+ return pendingLock;
+ }
+
+ // Lock acquisition failed
+ lockManager.removeLock(pendingLock);
+ return null;
+ }
+
+ /*
+ * Acquire a lock on the receiver, blocks if the lock cannot be obtained
+ * immediately.
+ *
+ * @see java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public final FileLock lock(long position, long size, boolean shared)
+ throws IOException {
+ openCheck();
+ FileLock resultLock = null;
+ {
+ boolean completed = false;
+ try {
+ begin();
+ resultLock = basicLock(position, size, shared, true);
+ completed = true;
+ } finally {
+ end(completed);
+ }
+ }
+ return resultLock;
+ }
+
+ /*
+ * Attempts to acquire the given lock, but does not block. If the lock
+ * cannot be acquired the method returns null.
+ *
+ * @see java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public final FileLock tryLock(long position, long size, boolean shared)
+ throws IOException {
+ openCheck();
+ return basicLock(position, size, shared, false);
+ }
+
+ /*
+ * Non-API method to release a given lock on a file channel. Assumes that
+ * the lock will mark itself invalid after successful unlocking.
+ */
+ void release(FileLock lock) throws IOException {
+ openCheck();
+ fileSystem.unlock(handle, lock.position(), lock.size());
+ lockManager.removeLock(lock);
+ }
+
+ /*
+ * Flush the contents of the file to disk, and the metadata if asked.
+ */
+ public void force(boolean metadata) throws IOException {
+ openCheck();
+ // Forcing data-only on a read-only file is a no-op.
+ if (metadata) {
+ fileSystem.fflush(handle, metadata);
+ }
+ }
+
+ public abstract MappedByteBuffer map(MapMode mode, long position, long size)
+ throws IOException;
+
+ protected final MappedByteBuffer mapImpl(int mapMode, long position,
+ long size) throws IOException {
+ if (position + size > size()) {
+ fileSystem.truncate(handle, position + size);
+ }
+ long alignment = position - position % ALLOC_GRANULARITY;
+ int offset = (int) (position - alignment);
+ PlatformAddress address = PlatformAddressFactory.allocMap(handle, alignment, size
+ + offset, mapMode);
+ MappedByteBuffer buffer = null;
+ try {
+ buffer = MappedByteBufferFactory.getBuffer(address, mapMode, size,
+ offset);
+ } catch (Exception e) {
+ throw new IOException(e.getMessage());
+ }
+ return buffer;
+ }
+
+ /*
+ * Returns the current file position.
+ */
+ public long position() throws IOException {
+ openCheck();
+ return fileSystem.seek(handle, 0L, IFileSystem.SEEK_CUR);
+ }
+
+ /*
+ * Sets the file pointer.
+ */
+ public FileChannel position(long newPosition) throws IOException {
+ openCheck();
+ if (newPosition < 0) {
+ // nio.0B=New position must be non-negative.
+ throw new IllegalArgumentException(
+ Messages.getString("nio.0B")); //$NON-NLS-1$
+ }
+
+ synchronized (repositioningLock) {
+ fileSystem.seek(handle, newPosition, IFileSystem.SEEK_SET);
+ }
+ return this;
+ }
+
+ public int read(ByteBuffer buffer, long position) throws IOException {
+ if (null == buffer){
+ throw new NullPointerException();
+ }
+ if (position < 0){
+ throw new IllegalArgumentException();
+ }
+ openCheck();
+ if (!buffer.hasRemaining()){
+ return 0;
+ }
+ synchronized (repositioningLock) {
+ int bytesRead = 0;
+ long preReadPosition = position();
+ position(position);
+ try {
+ bytesRead = read(buffer);
+ } finally {
+ position(preReadPosition);
+ }
+ return bytesRead;
+ }
+ }
+
+ public int read(ByteBuffer buffer) throws IOException {
+ openCheck();
+ if (!buffer.hasRemaining()){
+ return 0;
+ }
+ boolean completed = false;
+ int bytesRead = 0;
+ synchronized (repositioningLock) {
+ if (buffer.isDirect()) {
+ DirectBuffer directBuffer = (DirectBuffer) buffer;
+ int address = directBuffer.getEffectiveAddress().toInt();
+ try {
+ begin();
+ /*
+ * if (bytesRead <= EOF) delt by read completed = false;
+ */
+ bytesRead = (int) fileSystem.readDirect(handle, address,
+ buffer.position(), buffer.remaining());
+ completed = true;
+ } finally {
+ end(completed && bytesRead >= 0);
+ }
+ } else {
+ try {
+ begin();
+ /*
+ * if (bytesRead <= EOF) delt by read completed = false;
+ */
+ bytesRead = (int) fileSystem.read(handle, buffer.array(),
+ buffer.arrayOffset() + buffer.position(), buffer
+ .remaining());
+ completed = true;
+ } finally {
+ end(completed && bytesRead >= 0);
+ }
+ }
+ if (bytesRead > 0) {
+ buffer.position(buffer.position() + bytesRead);
+ }
+ }
+ return bytesRead;
+ }
+
+ public long read(ByteBuffer[] buffers, int offset, int length)
+ throws IOException {
+ int count = 0;
+ if (offset < 0 || length < 0 || offset + length > buffers.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ openCheck();
+ for (int i = offset; i < offset + length; i++) {
+ count += buffers[i].remaining();
+ }
+ if (0 == count) {
+ return 0;
+ }
+ if (size() == 0) {
+ return -1;
+ }
+ ByteBuffer[] directBuffers = new ByteBuffer[length];
+ int[] handles = new int[length];
+ int[] offsets = new int[length];
+ int[] lengths = new int[length];
+ for (int i = 0; i < length; i++) {
+ ByteBuffer buffer = buffers[i + offset];
+ if (!buffer.isDirect()) {
+ buffer = ByteBuffer.allocateDirect(buffer.remaining());
+ directBuffers[i] = buffer;
+ offsets[i] = 0;
+ } else {
+ offsets[i] = buffer.position();
+ }
+ handles[i] = ((DirectBuffer) buffer).getEffectiveAddress().toInt();
+ lengths[i] = buffer.remaining();
+ }
+ long bytesRead = 0;
+ {
+ boolean completed = false;
+ try {
+ begin();
+ synchronized (repositioningLock) {
+ bytesRead = fileSystem.readv(handle, handles, offsets,
+ lengths, length);
+
+ }
+ completed = true;
+ /*
+ * if (bytesRead < EOF) //delt by readv? completed = false;
+ */
+ } finally {
+ end(completed);
+ }
+ }
+ int end = offset + length;
+ long bytesRemaining = bytesRead;
+ for (int i = offset; i < end && bytesRemaining > 0; i++) {
+ if (buffers[i].isDirect()) {
+ if (lengths[i] < bytesRemaining) {
+ int pos = buffers[i].limit();
+ buffers[i].position(pos);
+ bytesRemaining -= lengths[i];
+ } else {
+ int pos = (int) bytesRemaining;
+ buffers[i].position(pos);
+ break;
+ }
+ } else {
+ ByteBuffer buf = directBuffers[i - offset];
+ if (bytesRemaining < buf.remaining()){
+ // this is the last step.
+ int pos = buf.position();
+ buffers[i].put(buf);
+ buffers[i].position(pos + (int)bytesRemaining);
+ bytesRemaining = 0;
+ } else {
+ bytesRemaining -= buf.remaining();
+ buffers[i].put(buf);
+ }
+ }
+ }
+ return bytesRead;
+ }
+
+ /*
+ * Returns the current file size, as an integer number of bytes.
+ */
+ public long size() throws IOException {
+ openCheck();
+ synchronized (repositioningLock) {
+ long currentPosition = fileSystem.seek(handle, 0L,
+ IFileSystem.SEEK_CUR);
+ long endOfFilePosition = fileSystem.seek(handle, 0L,
+ IFileSystem.SEEK_END);
+ fileSystem.seek(handle, currentPosition, IFileSystem.SEEK_SET);
+ return endOfFilePosition;
+ }
+ }
+
+ public long transferFrom(ReadableByteChannel src, long position, long count)
+ throws IOException {
+ openCheck();
+ if (!src.isOpen()) {
+ throw new ClosedChannelException();
+ }
+ if (position < 0 || count < 0 || position > Integer.MAX_VALUE
+ || count > Integer.MAX_VALUE) {
+ throw new IllegalArgumentException();
+ }
+ if(position > size()) {
+ return 0;
+ }
+
+ ByteBuffer buffer = null;
+
+ try {
+ if (src instanceof FileChannel) {
+ FileChannel fileSrc = (FileChannel) src;
+ long size = fileSrc.size();
+ long filePosition = fileSrc.position();
+ count = Math.min(count, size - filePosition);
+ buffer = fileSrc.map(MapMode.READ_ONLY, filePosition, count);
+ fileSrc.position(filePosition + count);
+ } else {
+ buffer = ByteBuffer.allocateDirect((int) count);
+ src.read(buffer);
+ buffer.flip();
+ }
+ return write(buffer, position);
+ } finally {
+ // unmap the buffer
+ if (buffer != null) {
+ // all children of FileChannelImpl currently returns
+ // an instance of DirectBuffer from map() method
+ ((DirectBuffer) buffer).free();
+ }
+ }
+ }
+
+ public long transferTo(long position, long count, WritableByteChannel target)
+ throws IOException {
+ openCheck();
+ if (!target.isOpen()) {
+ throw new ClosedChannelException();
+ }
+ if (target instanceof ReadOnlyFileChannel) {
+ throw new NonWritableChannelException();
+ }
+ if (position < 0 || count < 0 || position > Integer.MAX_VALUE
+ || count > Integer.MAX_VALUE) {
+ throw new IllegalArgumentException();
+ }
+
+ if (count == 0 || position >= size()) {
+ return 0;
+ }
+ ByteBuffer buffer = null;
+ count = Math.min(count, size() - position);
+ if (target instanceof SocketChannelImpl) {
+ // only socket can be transfered by system call
+ return kernelTransfer(handle, ((SocketChannelImpl) target).getFD(),
+ position, count);
+ }
+
+ try {
+ buffer = map(MapMode.READ_ONLY, position, count);
+ return target.write(buffer);
+ } finally {
+ // unmap the buffer
+ if (buffer != null) {
+ // all children of FileChannelImpl currently returns
+ // an instance of DirectBuffer from map() method
+ ((DirectBuffer) buffer).free();
+ }
+ }
+ }
+
+ private long kernelTransfer(int l, FileDescriptor fd, long position,
+ long count) throws IOException {
+ boolean completed = false;
+ try {
+ begin();
+ long ret = fileSystem.transfer(l, fd, position, count);
+ completed = true;
+ return ret;
+ } finally {
+ end(completed);
+ }
+ }
+
+ public FileChannel truncate(long size) throws IOException {
+ openCheck();
+ if (size < 0) {
+ throw new IllegalArgumentException();
+ }
+ if (size < size()) {
+ synchronized (repositioningLock) {
+ long position = position();
+ fileSystem.truncate(handle, size);
+ /*
+ * FIXME: currently the port library always modifies the
+ * position to given size. not sure it is a bug or intended
+ * behaviour, so I always reset the position to proper value as
+ * Java Spec.
+ */
+ position(position > size ? size : position);
+ }
+ }
+ return this;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.nio.channels.WritableByteChannel#write(java.nio.ByteBuffer)
+ */
+
+ public int write(ByteBuffer buffer, long position) throws IOException {
+ if (null == buffer){
+ throw new NullPointerException();
+ }
+ if (position < 0){
+ throw new IllegalArgumentException();
+ }
+ openCheck();
+ if (!buffer.hasRemaining()){
+ return 0;
+ }
+ int bytesWritten = 0;
+ synchronized (repositioningLock) {
+ long preWritePosition = position();
+ position(position);
+ try {
+ bytesWritten = writeImpl(buffer);
+ } finally {
+ position(preWritePosition);
+ }
+ }
+ return bytesWritten;
+ }
+
+ public int write(ByteBuffer buffer) throws IOException {
+ openCheck();
+ return writeImpl(buffer);
+ }
+
+ private int writeImpl(ByteBuffer buffer) throws IOException {
+ int bytesWritten;
+ boolean completed = false;
+ synchronized (repositioningLock) {
+ if (buffer.isDirect()) {
+ DirectBuffer directBuffer = (DirectBuffer) buffer;
+ int address = directBuffer.getEffectiveAddress().toInt();
+ try {
+ begin();
+ bytesWritten = (int) fileSystem.writeDirect(handle,
+ address, buffer.position(), buffer.remaining());
+ completed = true;
+ } finally {
+ end(completed);
+ }
+ } else {
+ try {
+ begin();
+ bytesWritten = (int) fileSystem.write(handle, buffer
+ .array(), buffer.arrayOffset() + buffer.position(),
+ buffer.remaining());
+ completed = true;
+ } finally {
+ end(completed);
+ }
+ }
+ if (bytesWritten > 0) {
+ buffer.position(buffer.position() + bytesWritten);
+ }
+ }
+ return bytesWritten;
+ }
+
+ public long write(ByteBuffer[] buffers, int offset, int length)
+ throws IOException {
+ if (offset < 0 || length < 0 || (offset + length) > buffers.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ openCheck();
+ int count = 0;
+ for (int i = offset; i < offset + length; i++) {
+ count += buffers[i].remaining();
+ }
+ if (0 == count) {
+ return 0;
+ }
+ int[] handles = new int[length];
+ int[] offsets = new int[length];
+ int[] lengths = new int[length];
+
+ // list of allocated direct ByteBuffers to prevent them from being GC-ed
+ DirectBuffer[] allocatedBufs = new DirectBuffer[length];
+
+ for (int i = 0; i < length; i++) {
+ ByteBuffer buffer = buffers[i + offset];
+ if (!buffer.isDirect()) {
+ ByteBuffer directBuffer = ByteBuffer.allocateDirect(buffer
+ .remaining());
+ directBuffer.put(buffer);
+ directBuffer.flip();
+ buffer = directBuffer;
+ allocatedBufs[i] = (DirectBuffer) directBuffer;
+ offsets[i] = 0;
+ } else {
+ offsets[i] = buffer.position();
+ allocatedBufs[i] = null;
+ }
+ handles[i] = ((DirectBuffer) buffer).getEffectiveAddress().toInt();
+ lengths[i] = buffer.remaining();
+ }
+
+ long bytesWritten = 0;
+ boolean completed = false;
+ synchronized (repositioningLock) {
+ try {
+ begin();
+ bytesWritten = fileSystem.writev(handle, handles, offsets,
+ lengths, length);
+ completed = true;
+ } finally {
+ end(completed);
+
+ // free temporary direct buffers
+ for (int i = 0; i < length; ++i) {
+ if (allocatedBufs[i] != null) {
+ allocatedBufs[i].free();
+ }
+ }
+ }
+ }
+
+ long bytesRemaining = bytesWritten;
+ for (int i = offset; i < length + offset; i++) {
+ if (bytesRemaining > buffers[i].remaining()) {
+ int pos = buffers[i].limit();
+ buffers[i].position(pos);
+ bytesRemaining -= buffers[i].remaining();
+ } else {
+ int pos = buffers[i].position() + (int) bytesRemaining;
+ buffers[i].position(pos);
+ break;
+ }
+ }
+ return bytesWritten;
+ }
+
+ public int getHandle(){
+ return handle;
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/FileLockImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/FileLockImpl.java
new file mode 100644
index 0000000..4e0ddc9
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/FileLockImpl.java
@@ -0,0 +1,73 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.internal;
+
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+
+/*
+ * The concrete implementation of an NIO file lock object.
+ *
+ */
+final class FileLockImpl extends FileLock {
+
+ // Remembers if this lock has been released via the API.
+ private boolean isReleased = false;
+
+ /*
+ * Returns a new file lock object with the given parameters.
+ *
+ * @param channel the file channel hosting the lock. @param position the
+ * start position of the lock, in bytes @param size the length of the lock,
+ * in bytes @param shared whether this lock is shared (true) or exclusive
+ * (false)
+ */
+ public FileLockImpl(FileChannel channel, long position, long size,
+ boolean shared) {
+ super(channel, position, size, shared);
+ }
+
+ /*
+ * Tests to see if the lock is valid. A lock can be invalidated if the
+ * channel it is acquired on is closed or if it is released. (non-Javadoc)
+ *
+ * @see java.nio.channels.FileLock#isValid()
+ */
+ public boolean isValid() {
+ return !isReleased && channel().isOpen();
+ }
+
+ /*
+ * Releases the file lock on the channel that acquired it. Releasing an
+ * invalid lock has no effect.
+ *
+ * @see java.nio.channels.FileLock#release()
+ */
+ public void release() throws IOException {
+ if (!channel().isOpen()) {
+ throw new ClosedChannelException();
+ }
+
+ if (!isReleased) {
+ ((FileChannelImpl) channel()).release(this);
+ isReleased = true;
+ }
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java b/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java
new file mode 100644
index 0000000..6752732
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.internal;
+
+import java.io.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;
+
+import org.apache.harmony.nio.Util;
+import org.apache.harmony.nio.internal.nls.Messages;
+
+
+/*
+ * 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();
+ }
+ // nio.06=InputStreamReader is closed.
+ throw new IOException(Messages.getString("nio.06")); //$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;
+ }
+ Util.assertArrayIndex(buf, offset, length);
+ // 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;
+ }
+ // nio.06=InputStreamReader is closed.
+ throw new IOException(Messages.getString("nio.06")); //$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 {
+ Util.assertArrayIndex(str.length(), offset, count);
+ 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) {
+ // nio.07=Writer is closed.
+ throw new IOException(Messages.getString("nio.07")); //$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 {
+ Util.assertArrayIndex(buf, offset, count);
+ 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) {
+ // nio.07=Writer is closed.
+ throw new IOException(Messages.getString("nio.07")); //$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) {
+ // nio.07=Writer is closed.
+ throw new IOException(Messages.getString("nio.07")); //$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;
+ }
+ }
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/LockManager.java b/nio/src/main/java/org/apache/harmony/nio/internal/LockManager.java
new file mode 100644
index 0000000..3504460
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/LockManager.java
@@ -0,0 +1,80 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.internal;
+
+import java.nio.channels.FileLock;
+import java.nio.channels.OverlappingFileLockException;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * The lock manager is responsible for tracking acquired and pending locks on
+ * the underlying file channel.
+ *
+ */
+final class LockManager {
+ // The set of acquired and pending locks.
+ private final Comparator<FileLock> lockComparator = new Comparator<FileLock>() {
+ public int compare(FileLock lock1, FileLock lock2) {
+ long position1 = lock1.position();
+ long position2 = lock2.position();
+ return position1 > position2 ? 1 : (position1 < position2 ? -1 : 0);
+ }
+ };
+
+ private final SortedSet<FileLock> locks = new TreeSet<FileLock>(
+ lockComparator);
+
+ /*
+ * Default Constructor.
+ */
+ protected LockManager() {
+ super();
+ }
+
+ /*
+ * Add a new pending lock to the manager. Throws an exception if the lock
+ * would overlap an existing lock. Once the lock is acquired it remains in
+ * this set as an acquired lock.
+ */
+ synchronized void addLock(FileLock lock)
+ throws OverlappingFileLockException {
+ long lockEnd = lock.position() + lock.size();
+ for (Iterator<FileLock> keyItr = locks.iterator(); keyItr.hasNext();) {
+ FileLock existingLock = keyItr.next();
+ if (existingLock.position() > lockEnd) {
+ // This, and all remaining locks, start beyond our end (so
+ // cannot overlap).
+ break;
+ }
+ if (existingLock.overlaps(lock.position(), lock.size())) {
+ throw new OverlappingFileLockException();
+ }
+ }
+ locks.add(lock);
+ }
+
+ /*
+ * Removes an acquired lock from the lock manager. If the lock did not exist
+ * in the lock manager the operation is a no-op.
+ */
+ synchronized void removeLock(FileLock lock) {
+ locks.remove(lock);
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/MappedByteBufferFactory.java b/nio/src/main/java/org/apache/harmony/nio/internal/MappedByteBufferFactory.java
new file mode 100644
index 0000000..f3f5a35
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/MappedByteBufferFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.internal;
+
+import java.lang.reflect.Constructor;
+import java.nio.MappedByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import org.apache.harmony.luni.platform.PlatformAddress;
+
+class MappedByteBufferFactory {
+
+ static final Constructor constructor;
+
+ static {
+ constructor = AccessController
+ .doPrivileged(new PrivilegedAction<Constructor>() {
+ public Constructor run() {
+ try {
+ Class wrapperClazz = ClassLoader
+ .getSystemClassLoader().loadClass(
+ "java.nio.MappedByteBufferAdapter"); //$NON-NLS-1$
+ Constructor result = wrapperClazz
+ .getConstructor(new Class[] {
+ PlatformAddress.class, int.class,
+ int.class, int.class });
+ result.setAccessible(true);
+ return result;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+
+ static MappedByteBuffer getBuffer(PlatformAddress addr, int mapmode,
+ long size, int offset) throws Exception {
+ // Spec points out explicitly that the size of map should be no greater than
+ // Integer.MAX_VALUE, so long to int cast is safe here.
+ return (MappedByteBuffer) constructor.newInstance(new Object[] { addr,
+ new Integer((int) size), new Integer(offset),
+ new Integer(mapmode) });
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/PipeImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/PipeImpl.java
new file mode 100644
index 0000000..beceac4
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/PipeImpl.java
@@ -0,0 +1,194 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.internal;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.Pipe;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+import org.apache.harmony.luni.platform.FileDescriptorHandler;
+
+/*
+ * default implementation of Pipe
+ *
+ */
+
+final class PipeImpl extends Pipe {
+
+ private SinkChannelImpl sink;
+
+ private SourceChannelImpl source;
+
+ private int serverPort;
+
+ public PipeImpl() throws IOException {
+ super();
+ try {
+ sink = new SinkChannelImpl(SelectorProvider.provider());
+ source = new SourceChannelImpl(SelectorProvider.provider());
+ sink.finishConnect();
+ source.accept();
+ source.closeServer();
+ } catch(IOException ioe){
+ reset();
+ throw ioe;
+ } catch(RuntimeException e){
+ reset();
+ throw e;
+ }
+ }
+
+ private void reset(){
+ if(sink != null){
+ try {
+ sink.close();
+ } catch (Exception e) {
+ }
+ }
+ if(source != null){
+ try {
+ source.closeServer();
+ } catch (Exception e) {
+ }
+ try {
+ source.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ /*
+ * @see java.nio.channels.Pipe#sink()
+ */
+ public SinkChannel sink() {
+ return sink;
+ }
+
+ /*
+ * @see java.nio.channels.Pipe#source()
+ */
+ public SourceChannel source() {
+ return source;
+ }
+
+ /*
+ * default implementation of SourceChannel
+ */
+ private class SourceChannelImpl extends Pipe.SourceChannel implements
+ FileDescriptorHandler {
+
+ private SocketChannelImpl sourceSocket;
+
+ private ServerSocketChannel sourceServer;
+
+ /*
+ * constructor
+ */
+ protected SourceChannelImpl(SelectorProvider provider)
+ throws IOException {
+ super(provider);
+ sourceServer = provider.openServerSocketChannel();
+ sourceServer.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ serverPort = sourceServer.socket().getLocalPort();
+ }
+
+ void closeServer() throws IOException {
+ sourceServer.close();
+ }
+
+ void accept() throws IOException {
+ sourceSocket = (SocketChannelImpl) sourceServer.accept();
+ }
+
+ protected void implCloseSelectableChannel() throws IOException {
+ sourceSocket.close();
+ }
+
+ protected void implConfigureBlocking(boolean blockingMode)
+ throws IOException {
+ sourceSocket.configureBlocking(blockingMode);
+ }
+
+ public int read(ByteBuffer buffer) throws IOException {
+ return sourceSocket.read(buffer);
+ }
+
+ public long read(ByteBuffer[] buffers) throws IOException {
+ return read(buffers, 0, buffers.length);
+ }
+
+ public long read(ByteBuffer[] buffers, int offset, int length)
+ throws IOException {
+ return sourceSocket.read(buffers, offset, length);
+ }
+
+ public FileDescriptor getFD() {
+ return sourceSocket.getFD();
+ }
+ }
+
+ /*
+ * default implementation of SinkChannel
+ */
+ private class SinkChannelImpl extends Pipe.SinkChannel implements
+ FileDescriptorHandler {
+
+ private SocketChannelImpl sinkSocket;
+
+ protected SinkChannelImpl(SelectorProvider provider) throws IOException {
+ super(provider);
+ sinkSocket = (SocketChannelImpl) provider.openSocketChannel();
+ }
+
+ public boolean finishConnect() throws IOException {
+ return sinkSocket.connect(new InetSocketAddress(InetAddress
+ .getLocalHost(), serverPort));
+ }
+
+ protected void implCloseSelectableChannel() throws IOException {
+ sinkSocket.close();
+ }
+
+ protected void implConfigureBlocking(boolean blockingMode)
+ throws IOException {
+ sinkSocket.configureBlocking(blockingMode);
+ }
+
+ public int write(ByteBuffer buffer) throws IOException {
+ return sinkSocket.write(buffer);
+ }
+
+ public long write(ByteBuffer[] buffers) throws IOException {
+ return write(buffers, 0, buffers.length);
+ }
+
+ public long write(ByteBuffer[] buffers, int offset, int length)
+ throws IOException {
+ return sinkSocket.write(buffers, offset, length);
+ }
+
+ public FileDescriptor getFD() {
+ return sinkSocket.getFD();
+ }
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/ReadOnlyFileChannel.java b/nio/src/main/java/org/apache/harmony/nio/internal/ReadOnlyFileChannel.java
new file mode 100644
index 0000000..559fc89
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/ReadOnlyFileChannel.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Android Notice
+ * In this class the address length was changed from long to int.
+ * This is due to performance optimizations for the device.
+ */
+
+package org.apache.harmony.nio.internal;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.ReadableByteChannel;
+
+import org.apache.harmony.luni.platform.IMemorySystem;
+
+public final class ReadOnlyFileChannel extends FileChannelImpl {
+ public ReadOnlyFileChannel(Object stream, int handle) {
+ super(stream, handle);
+ }
+
+ public final int write(ByteBuffer buffer, long position) throws IOException {
+ if (null == buffer){
+ throw new NullPointerException();
+ }
+ if (position < 0){
+ throw new IllegalArgumentException();
+ }
+ throw new NonWritableChannelException();
+ }
+
+ public final int write(ByteBuffer buffer) throws IOException {
+ openCheck();
+ throw new NonWritableChannelException();
+ }
+
+ public final long write(ByteBuffer[] buffers, int offset, int length)
+ throws IOException {
+ if (offset < 0 || length < 0 || (offset + length) > buffers.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ openCheck();
+ throw new NonWritableChannelException();
+ }
+
+ public final FileChannel truncate(long size) throws IOException {
+ openCheck();
+ if (size < 0) {
+ throw new IllegalArgumentException();
+ }
+ throw new NonWritableChannelException();
+ }
+
+ public final long transferFrom(ReadableByteChannel src, long position,
+ long count) throws IOException {
+ openCheck();
+ if (!src.isOpen()) {
+ throw new ClosedChannelException();
+ }
+ throw new NonWritableChannelException();
+ }
+
+ public final MappedByteBuffer map(MapMode mode, long position, long size)
+ throws IOException {
+ openCheck();
+ if (mode == null) {
+ throw new NullPointerException();
+ }
+ if (position < 0 || size < 0 || size > Integer.MAX_VALUE) {
+ throw new IllegalArgumentException();
+ }
+ if (mode != MapMode.READ_ONLY) {
+ throw new NonWritableChannelException();
+ }
+ return super.mapImpl(IMemorySystem.MMAP_READ_ONLY, position, size);
+ }
+
+ public final void force(boolean metadata) throws IOException {
+ openCheck();
+ return;
+ }
+
+ protected final FileLock basicLock(long position, long size,
+ boolean shared, boolean wait) throws IOException {
+ if (!shared) {
+ throw new NonWritableChannelException();
+ }
+ return super.basicLock(position, size, shared, true);
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/ReadWriteFileChannel.java b/nio/src/main/java/org/apache/harmony/nio/internal/ReadWriteFileChannel.java
new file mode 100644
index 0000000..626cb95
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/ReadWriteFileChannel.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Android Notice
+ * In this class the address length was changed from long to int.
+ * This is due to performance optimizations for the device.
+ */
+
+package org.apache.harmony.nio.internal;
+
+import java.io.IOException;
+import java.nio.MappedByteBuffer;
+
+import org.apache.harmony.luni.platform.IMemorySystem;
+
+public final class ReadWriteFileChannel extends FileChannelImpl {
+ public ReadWriteFileChannel(Object stream, int handle) {
+ super(stream, handle);
+ }
+
+ public final MappedByteBuffer map(MapMode mode, long position, long size)
+ throws IOException {
+ openCheck();
+ if (mode == null) {
+ throw new NullPointerException();
+ }
+ if (position < 0 || size < 0 || size > Integer.MAX_VALUE) {
+ throw new IllegalArgumentException();
+ }
+ int mapMode;
+ if (mode == MapMode.READ_ONLY) {
+ mapMode = IMemorySystem.MMAP_READ_ONLY;
+ } else if (mode == MapMode.READ_WRITE) {
+ mapMode = IMemorySystem.MMAP_READ_WRITE;
+ } else {
+ mapMode = IMemorySystem.MMAP_WRITE_COPY;
+ }
+ return mapImpl(mapMode, position, size);
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/SelectionKeyImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/SelectionKeyImpl.java
new file mode 100644
index 0000000..f863928
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/SelectionKeyImpl.java
@@ -0,0 +1,94 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.internal;
+
+import java.nio.channels.CancelledKeyException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.AbstractSelectionKey;
+
+/*
+ * Default implementation of SelectionKey
+ */
+final class SelectionKeyImpl extends AbstractSelectionKey {
+
+ private AbstractSelectableChannel channel;
+
+ int oldInterestOps;
+
+ private int interestOps;
+
+ private int readyOps;
+
+ private SelectorImpl selector;
+
+ public SelectionKeyImpl(AbstractSelectableChannel channel, int operations,
+ Object attachment, SelectorImpl selector) {
+ super();
+ this.channel = channel;
+ interestOps = operations;
+ this.selector = selector;
+ attach(attachment);
+ }
+
+ public SelectableChannel channel() {
+ return channel;
+ }
+
+ public int interestOps() {
+ checkValid();
+ synchronized (selector.keysLock) {
+ return interestOps;
+ }
+ }
+
+ public SelectionKey interestOps(int operations) {
+ checkValid();
+ if ((operations & ~(channel().validOps())) != 0) {
+ throw new IllegalArgumentException();
+ }
+ synchronized (selector.keysLock) {
+ interestOps = operations;
+ }
+ return this;
+ }
+
+ public int readyOps() {
+ checkValid();
+ return readyOps;
+ }
+
+ public Selector selector() {
+ return selector;
+ }
+
+ /*
+ * package private method for setting the ready operation by selector
+ */
+ void setReadyOps(int readyOps) {
+ this.readyOps = readyOps;
+ }
+
+ private void checkValid() {
+ if (!isValid()) {
+ throw new CancelledKeyException();
+ }
+ }
+
+} \ No newline at end of file
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/SelectorImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/SelectorImpl.java
new file mode 100644
index 0000000..b8b6a15
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/SelectorImpl.java
@@ -0,0 +1,404 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.internal;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.IllegalSelectorException;
+import java.nio.channels.Pipe;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.AbstractSelectionKey;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.harmony.luni.platform.FileDescriptorHandler;
+import org.apache.harmony.luni.platform.Platform;
+
+/*
+ * Default implementation of java.nio.channels.Selector
+ *
+ */
+final class SelectorImpl extends AbstractSelector {
+
+ private static final int MOCK_WRITEBUF_SIZE = 1;
+
+ private static final int MOCK_READBUF_SIZE = 8;
+
+ private static final int NA = 0;
+
+ private static final int READABLE = 1;
+
+ private static final int WRITEABLE = 2;
+
+ private static final int SELECT_BLOCK = -1;
+
+ private static final int SELECT_NOW = 0;
+
+ // keysLock is used to brief synchronization when get selectionKeys snapshot
+ // before selection
+ final Object keysLock = new Object();
+
+ private final Set<SelectionKey> keys = new HashSet<SelectionKey>();
+
+ private Set<SelectionKey> unmodifiableKeys = Collections
+ .unmodifiableSet(keys);
+
+ private final Set<SelectionKey> selectedKeys = new HashSet<SelectionKey>();
+
+ private Set<SelectionKey> unaddableSelectedKeys = new UnaddableSet<SelectionKey>(
+ selectedKeys);
+
+ // sink and source are used by wakeup()
+ private Pipe.SinkChannel sink;
+
+ private Pipe.SourceChannel source;
+
+ private FileDescriptor sourcefd;
+
+ private SelectionKey[] readableChannels;
+
+ private SelectionKey[] writableChannels;
+
+ private List<FileDescriptor> readableFDs = new ArrayList<FileDescriptor>();
+
+ private List<FileDescriptor> writableFDs = new ArrayList<FileDescriptor>();
+
+ private FileDescriptor[] readable;
+
+ private FileDescriptor[] writable;
+
+ public SelectorImpl(SelectorProvider selectorProvider) {
+ super(selectorProvider);
+ try {
+ Pipe mockSelector = selectorProvider.openPipe();
+ sink = mockSelector.sink();
+ source = mockSelector.source();
+ sourcefd = ((FileDescriptorHandler)source).getFD();
+ source.configureBlocking(false);
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+
+ /*
+ * @see java.nio.channels.spi.AbstractSelector#implCloseSelector()
+ */
+ protected void implCloseSelector() throws IOException {
+ doCancel();
+ for (SelectionKey sk : keys) {
+ deregister((AbstractSelectionKey) sk);
+ }
+ wakeup();
+ }
+
+ /*
+ * @see java.nio.channels.spi.AbstractSelector#register(java.nio.channels.spi.AbstractSelectableChannel,
+ * int, java.lang.Object)
+ */
+ protected SelectionKey register(AbstractSelectableChannel channel,
+ int operations, Object attachment) {
+ if (!provider().equals(channel.provider())) {
+ throw new IllegalSelectorException();
+ }
+ synchronized (this) {
+ synchronized (keys) {
+ SelectionKey sk = new SelectionKeyImpl(channel, operations,
+ attachment, this);
+ keys.add(sk);
+ return sk;
+ }
+ }
+ }
+
+ /*
+ * @see java.nio.channels.Selector#keys()
+ */
+ public synchronized Set<SelectionKey> keys() {
+ closeCheck();
+ return unmodifiableKeys;
+ }
+
+ private void closeCheck() {
+ if (!isOpen()) {
+ throw new ClosedSelectorException();
+ }
+ }
+
+ /*
+ * @see java.nio.channels.Selector#select()
+ */
+ public int select() throws IOException {
+ return selectInternal(SELECT_BLOCK);
+ }
+
+ /*
+ * @see java.nio.channels.Selector#select(long)
+ */
+ public int select(long timeout) throws IOException {
+ if (timeout < 0) {
+ throw new IllegalArgumentException();
+ }
+ return selectInternal((0 == timeout) ? SELECT_BLOCK : timeout);
+ }
+
+ /*
+ * @see java.nio.channels.Selector#selectNow()
+ */
+ public int selectNow() throws IOException {
+ return selectInternal(SELECT_NOW);
+ }
+
+ private int selectInternal(long timeout) throws IOException {
+ closeCheck();
+ synchronized (this) {
+ synchronized (keys) {
+ synchronized (selectedKeys) {
+ doCancel();
+ int[] readyChannels = null;
+ boolean isBlock = (SELECT_NOW != timeout);
+ if (keys.size() == 0) {
+ return 0;
+ }
+ prepareChannels();
+ try {
+ if (isBlock) {
+ begin();
+ }
+ readyChannels = Platform.getNetworkSystem().select(readable, writable, timeout);
+ } finally {
+ // clear results for next select
+ readableFDs.clear();
+ writableFDs.clear();
+ if (isBlock) {
+ end();
+ }
+ }
+ return processSelectResult(readyChannels);
+ }
+ }
+ }
+ }
+
+ private boolean isConnected(SelectionKeyImpl key) {
+ SelectableChannel channel = key.channel();
+ if (channel instanceof SocketChannel) {
+ return ((SocketChannel) channel).isConnected();
+ }
+ return true;
+ }
+
+ // Prepares and adds channels to list for selection
+ private void prepareChannels() {
+ readableFDs.add(sourcefd);
+ List<SelectionKey> readChannelList = new ArrayList<SelectionKey>();
+ readChannelList.add(source.keyFor(this));
+ List<SelectionKey> writeChannelList = new ArrayList<SelectionKey>();
+ synchronized (keysLock) {
+ for (Iterator<SelectionKey> i = keys.iterator(); i.hasNext();) {
+ SelectionKeyImpl key = (SelectionKeyImpl) i.next();
+ key.oldInterestOps = key.interestOps();
+ boolean isReadableChannel = ((SelectionKey.OP_ACCEPT | SelectionKey.OP_READ) & key.oldInterestOps) != 0;
+ boolean isWritableChannel = ((SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE) & key.oldInterestOps) != 0;
+ SelectableChannel channel = key.channel();
+ if (isReadableChannel) {
+ readChannelList.add(channel.keyFor(this));
+ readableFDs.add(((FileDescriptorHandler)channel).getFD());
+ }
+ if (isWritableChannel) {
+ writeChannelList.add(channel.keyFor(this));
+ writableFDs.add(((FileDescriptorHandler)channel).getFD());
+ }
+ }
+ }
+ readableChannels = readChannelList.toArray(new SelectionKey[0]);
+ writableChannels = writeChannelList.toArray(new SelectionKey[0]);
+ readable = readableFDs.toArray(new FileDescriptor[0]);
+ writable = writableFDs.toArray(new FileDescriptor[0]);
+ }
+
+ // Analyses selected channels and adds keys of ready channels to
+ // selectedKeys list
+ private int processSelectResult(int[] readyChannels) throws IOException {
+ if (0 == readyChannels.length) {
+ return 0;
+ }
+ // if the mock channel is selected, read the content.
+ if (READABLE == readyChannels[0]) {
+ ByteBuffer readbuf = ByteBuffer.allocate(MOCK_READBUF_SIZE);
+ while (source.read(readbuf) > 0) {
+ readbuf.flip();
+ }
+ }
+ int selected = 0;
+ for (int i = 1; i < readyChannels.length; i++) {
+ SelectionKeyImpl key = (SelectionKeyImpl) (i >= readable.length ? writableChannels[i
+ - readable.length]
+ : readableChannels[i]);
+ if (null == key) {
+ continue;
+ }
+ boolean isOldSelectedKey = selectedKeys.contains(key);
+ int selectedOp = 0;
+ // set ready ops
+ switch (readyChannels[i]) {
+ case NA:
+ selectedOp = 0;
+ break;
+ case READABLE:
+ selectedOp = (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)
+ & key.oldInterestOps;
+ break;
+ case WRITEABLE:
+ if (isConnected(key)) {
+ selectedOp = SelectionKey.OP_WRITE & key.oldInterestOps;
+ } else {
+ selectedOp = SelectionKey.OP_CONNECT & key.oldInterestOps;
+ }
+ break;
+ }
+
+ if (0 != selectedOp) {
+ if (isOldSelectedKey && key.readyOps() != selectedOp) {
+ key.setReadyOps(key.readyOps() | selectedOp);
+ selected++;
+ } else if (!isOldSelectedKey) {
+ key.setReadyOps(selectedOp);
+ selectedKeys.add(key);
+ selected++;
+ }
+ }
+ }
+ readableChannels = null;
+ writableChannels = null;
+ return selected;
+ }
+
+ /*
+ * @see java.nio.channels.Selector#selectedKeys()
+ */
+ public synchronized Set<SelectionKey> selectedKeys() {
+ closeCheck();
+ return unaddableSelectedKeys;
+ }
+
+ private void doCancel() {
+ Set<SelectionKey> cancelledKeys = cancelledKeys();
+ synchronized (cancelledKeys) {
+ if (cancelledKeys.size() > 0) {
+ for (SelectionKey currentkey : cancelledKeys) {
+ deregister((AbstractSelectionKey) currentkey);
+ keys.remove(currentkey);
+ selectedKeys.remove(currentkey);
+ }
+ }
+ cancelledKeys.clear();
+ }
+ }
+
+ /*
+ * @see java.nio.channels.Selector#wakeup()
+ */
+ public Selector wakeup() {
+ try {
+ sink.write(ByteBuffer.allocate(MOCK_WRITEBUF_SIZE));
+ } catch (IOException e) {
+ // do nothing
+ }
+ return this;
+ }
+
+ private static class UnaddableSet<E> implements Set<E> {
+
+ private Set<E> set;
+
+ UnaddableSet(Set<E> set) {
+ this.set = set;
+ }
+
+ public boolean equals(Object object) {
+ return set.equals(object);
+ }
+
+ public int hashCode() {
+ return set.hashCode();
+ }
+
+ public boolean add(E object) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean addAll(Collection<? extends E> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void clear() {
+ set.clear();
+ }
+
+ public boolean contains(Object object) {
+ return set.contains(object);
+ }
+
+ public boolean containsAll(Collection<?> c) {
+ return set.containsAll(c);
+ }
+
+ public boolean isEmpty() {
+ return set.isEmpty();
+ }
+
+ public Iterator<E> iterator() {
+ return set.iterator();
+ }
+
+ public boolean remove(Object object) {
+ return set.remove(object);
+ }
+
+ public boolean removeAll(Collection<?> c) {
+ return set.removeAll(c);
+ }
+
+ public boolean retainAll(Collection<?> c) {
+ return set.retainAll(c);
+ }
+
+ public int size() {
+ return set.size();
+ }
+
+ public Object[] toArray() {
+ return set.toArray();
+ }
+
+ public <T> T[] toArray(T[] a) {
+ return set.toArray(a);
+ }
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java
new file mode 100644
index 0000000..d774b3a
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/SelectorProviderImpl.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.internal;
+
+import java.io.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();
+ }
+
+ /*
+ *
+ * @see java.nio.channels.spi.SelectorProvider#openSelector()
+ */
+ public AbstractSelector openSelector() throws IOException {
+ return new SelectorImpl(this);
+ }
+
+ /*
+ *
+ * @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);
+ }
+
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
new file mode 100644
index 0000000..0786498
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
@@ -0,0 +1,320 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.internal;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketImpl;
+import java.net.SocketTimeoutException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NotYetBoundException;
+import java.nio.channels.SelectableChannel;
+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;
+
+/*
+ * 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;
+
+ // -------------------------------------------------------------------
+ // Instance variables
+ // -------------------------------------------------------------------
+
+ // The fd to interact with native code
+ private final FileDescriptor fd;
+
+ // The internal 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 class AcceptLock {}
+ private final Object acceptLock = new AcceptLock();
+
+ // ----------------------------------------------------
+ // 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);
+ }
+
+ // for native call
+ private ServerSocketChannelImpl() throws IOException {
+ super(SelectorProvider.provider());
+ status = SERVER_STATUS_OPEN;
+ fd = new FileDescriptor();
+ impl = SocketImplProvider.getServerSocketImpl(fd);
+ socket = new ServerSocketAdapter(impl, this);
+ isBound = false;
+ }
+
+ // ----------------------------------------------------
+ // 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) {
+ throw new NotYetBoundException();
+ }
+
+ SocketChannel sockChannel = SocketChannel.open();
+ Socket socketGot = sockChannel.socket();
+
+ try {
+ begin();
+
+ synchronized (acceptLock) {
+ synchronized (blockingLock()) {
+ boolean isBlocking = isBlocking();
+ if (!isBlocking) {
+ // for non blocking mode, use select to see whether
+ // there are any pending connections.
+ int[] tryResult = Platform.getNetworkSystem().select(
+ new FileDescriptor[] { this.fd },
+ new FileDescriptor[0], 0);
+ if (0 == tryResult.length || 0 == tryResult[0]) {
+ // no pending connections, returns immediately.
+ return null;
+ }
+ }
+ // do accept.
+ do {
+ try {
+ ((ServerSocketAdapter) socket).accept(socketGot,
+ (SocketChannelImpl) sockChannel);
+ // select successfully, break out immediately.
+ break;
+ } catch (SocketTimeoutException e) {
+ // continue to accept if the channel is in blocking
+ // mode.
+ }
+ } while (isBlocking);
+ }
+ }
+ } finally {
+ end(socketGot.isConnected());
+ }
+ return sockChannel;
+ }
+
+ // -------------------------------------------------------------------
+ // Protected inherited methods
+ // -------------------------------------------------------------------
+
+ /*
+ * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking
+ *
+ * (boolean)
+ */
+ protected void implConfigureBlocking(boolean blockingMode)
+ throws IOException {
+ // Do nothing here. For real accept() operation in nonblocking mode,
+ // it uses INetworkSystem.select. Whether a channel is blocking can be
+ // decided by isBlocking() method.
+ }
+
+ /*
+ *
+ * @see java.nio.channels.spi.AbstractSelectableChannel#implCloseSelectableChannel()
+ */
+ synchronized protected void implCloseSelectableChannel() throws IOException {
+ status = SERVER_STATUS_CLOSED;
+ if (!socket.isClosed()) {
+ socket.close();
+ }
+ }
+
+ /*
+ * Gets the FileDescriptor
+ */
+ public FileDescriptor getFD() {
+ return fd;
+ }
+
+ // ----------------------------------------------------
+ // Adapter classes.
+ // ----------------------------------------------------
+
+ /*
+ * The adapter class of ServerSocket.
+ */
+ private class ServerSocketAdapter extends ServerSocket {
+ /*
+ * The related ServerSocketChannel.
+ */
+ ServerSocketChannelImpl channelImpl;
+
+ /*
+ * The Constructor.
+ */
+ 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);
+ channelImpl.isBound = true;
+ }
+
+ /*
+ * @see java.net.ServerSocket#accept()
+ *
+ * If the channel is in non-blocking mode and there is no connection
+ * ready to be accepted, invoking this method will cause an
+ * IllegalBlockingModeException.
+ */
+ public Socket accept() throws IOException {
+ if (!isBound) {
+ throw new IllegalBlockingModeException();
+ }
+ SocketChannel sc = channelImpl.accept();
+ if (null == sc) {
+ throw new IllegalBlockingModeException();
+ }
+ return sc.socket();
+ }
+
+ /*
+ * do the accept.
+ */
+ private Socket accept(Socket aSocket, SocketChannelImpl sockChannel)
+ throws IOException {
+ // 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);
+ sockChannel.setConnected();
+ }
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkAccept(aSocket.getInetAddress().getHostAddress(),
+ aSocket.getPort());
+ }
+ connectOK = true;
+ } 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;
+ }
+ }
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java b/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
new file mode 100644
index 0000000..bc8a9bb
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
@@ -0,0 +1,1047 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.internal;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketImpl;
+import java.net.SocketOptions;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ConnectionPendingException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NoConnectionPendingException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.UnresolvedAddressException;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.nio.channels.spi.SelectorProvider;
+
+import org.apache.harmony.luni.net.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.ErrorCodeException;
+import org.apache.harmony.nio.AddressUtil;
+import org.apache.harmony.nio.internal.nls.Messages;
+
+/*
+ *
+ * The default implementation class of java.nio.channels.SocketChannel.
+ *
+ */
+class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler {
+
+ // -------------------------------------------------------------------
+ // Class variables
+ // -------------------------------------------------------------------
+
+ private static final int EOF = -1;
+
+ private static final int ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK = -211;
+
+ // The singleton to do the native network operation.
+ static final INetworkSystem networkSystem = Platform.getNetworkSystem();
+
+ // status un-init, not initialized.
+ static final int SOCKET_STATUS_UNINIT = EOF;
+
+ // status before connect.
+ static final int SOCKET_STATUS_UNCONNECTED = 0;
+
+ // status connection pending
+ static final int SOCKET_STATUS_PENDING = 1;
+
+ // status after connection success
+ static final int SOCKET_STATUS_CONNECTED = 2;
+
+ // status closed.
+ static final int SOCKET_STATUS_CLOSED = 3;
+
+ // timeout used for non-block mode.
+ private static final int TIMEOUT_NONBLOCK = 0;
+
+ // timeout used for block mode.
+ private static final int TIMEOUT_BLOCK = EOF;
+
+ // step used for connect
+ private static final int HY_SOCK_STEP_START = 0;
+
+ // step used for finishConnect
+ private static final int HY_PORT_SOCKET_STEP_CHECK = 1;
+
+ // connect success
+ private static final int CONNECT_SUCCESS = 0;
+
+ // -------------------------------------------------------------------
+ // 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;
+
+ private final Object readLock = new Object();
+
+ private final Object writeLock = new Object();
+
+ // BEGIN android-changed
+ // this content is a struct used in connect_withtimeout().
+ // The structure its holding has a size of 392 bytes.
+ private byte[] connectContext = new byte[392];
+ // END android-changed
+
+ // 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);
+ }
+
+ /*
+ * for native call
+ */
+ private SocketChannelImpl(){
+ super(SelectorProvider.provider());
+ fd = new FileDescriptor();
+ connectAddress = new InetSocketAddress(0);
+ status = SOCKET_STATUS_CONNECTED;
+ }
+
+ // Keep this to see if need next version
+ // SocketChannelImpl(SelectorProvider selectorProvider, FileDescriptor fd,
+ // SocketImpl si) {
+ // super(selectorProvider);
+ // fd = fd;
+ // networkSystem = OSNetworkSystem.getOSNetworkSystem();
+ // status = SOCKET_STATUS_UNCONNECTED;
+ // networkSystem.createSocket(fd, true);
+ // }
+
+ /*
+ * Package private constructor.
+ */
+ SocketChannelImpl(Socket aSocket, FileDescriptor aFd) {
+ super(SelectorProvider.provider());
+ socket = aSocket;
+ fd = aFd;
+ status = SOCKET_STATUS_UNCONNECTED;
+ }
+
+ // -------------------------------------------------------------------
+ // Methods for getting internal Socket.
+ // -------------------------------------------------------------------
+
+ /*
+ * Getting the internal Socket If we have not the socket, we create a new
+ * one.
+ */
+ @Override
+ synchronized public Socket socket() {
+ if (null == socket) {
+ try {
+ InetAddress addr = null;
+ int port = 0;
+ if (connectAddress != null) {
+ addr = connectAddress.getAddress();
+ port = connectAddress.getPort();
+ }
+ socket = new SocketAdapter(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()
+ */
+ @Override
+ 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()
+ */
+ @Override
+ synchronized public boolean isConnectionPending() {
+ return status == SOCKET_STATUS_PENDING;
+ }
+
+ /*
+ * @see java.nio.channels.SocketChannel#connect(java.net.SocketAddress)
+ */
+ @Override
+ public boolean connect(SocketAddress socketAddress) throws IOException {
+ // status must be open and unconnected
+ checkUnconnected();
+
+ // check the address
+ InetSocketAddress inetSocketAddress = validateAddress(socketAddress);
+
+ int port = inetSocketAddress.getPort();
+ String hostName = inetSocketAddress.getAddress().getHostName();
+ // security check
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkConnect(hostName, port);
+ }
+
+ // connect result
+ int result = EOF;
+ boolean finished = false;
+
+ try {
+ if (!isBound) {
+ // bind
+ networkSystem.bind2(fd, 0, true, InetAddress
+ .getByAddress(new byte[] { 0, 0, 0, 0 }));
+ isBound = true;
+ }
+
+ if (isBlocking()) {
+ begin();
+ 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);
+ // set back to nonblocking to work around with a bug in portlib
+ if (!this.isBlocking()) {
+ networkSystem.setNonBlocking(fd, true);
+ }
+ }
+ finished = (CONNECT_SUCCESS == result);
+ isBound = finished;
+ } catch (IOException e) {
+ if (e instanceof ConnectException && !isBlocking()) {
+ status = SOCKET_STATUS_PENDING;
+ } else {
+ if (isOpen()) {
+ close();
+ finished = true;
+ }
+ throw e;
+ }
+ } finally {
+ if (isBlocking()) {
+ end(finished);
+ }
+ }
+
+ // set local port
+ localPort = networkSystem.getSocketLocalPort(fd, false);
+ localAddress = networkSystem.getSocketLocalAddress(fd, false);
+
+ // set the connected address.
+ connectAddress = inetSocketAddress;
+ synchronized (this) {
+ if (isBlocking()) {
+ status = (finished ? SOCKET_STATUS_CONNECTED
+ : SOCKET_STATUS_UNCONNECTED);
+ } else {
+ status = SOCKET_STATUS_PENDING;
+ }
+ }
+ return finished;
+ }
+
+ /*
+ * @see java.nio.channels.SocketChannel#finishConnect()
+ */
+ @Override
+ public boolean finishConnect() throws IOException {
+ // status check
+ synchronized (this) {
+ if (!isOpen()) {
+ throw new ClosedChannelException();
+ }
+ if (status == SOCKET_STATUS_CONNECTED) {
+ return true;
+ }
+ if (status != SOCKET_STATUS_PENDING) {
+ throw new NoConnectionPendingException();
+ }
+ }
+
+ // finish result
+ int result = EOF;
+ boolean finished = false;
+
+ try {
+ begin();
+ result = networkSystem.connectWithTimeout(fd,
+ isBlocking() ? -1 : 0, trafficClass, connectAddress
+ .getAddress(), connectAddress.getPort(),
+ HY_PORT_SOCKET_STEP_CHECK, connectContext);
+ finished = (result == CONNECT_SUCCESS);
+ isBound = finished;
+ localAddress = networkSystem.getSocketLocalAddress(fd, false);
+ } catch (ConnectException e) {
+ if (isOpen()) {
+ close();
+ finished = true;
+ }
+ throw e;
+ } finally {
+ end(finished);
+ }
+
+ synchronized (this) {
+ status = (finished ? SOCKET_STATUS_CONNECTED : status);
+ isBound = finished;
+ }
+ return finished;
+ }
+
+ // -------------------------------------------------------------------
+ // Methods for read and write
+ // -------------------------------------------------------------------
+ /*
+ * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer)
+ */
+ @Override
+ public int read(ByteBuffer target) throws IOException {
+ if (null == target) {
+ throw new NullPointerException();
+ }
+ checkOpenConnected();
+ if (!target.hasRemaining()) {
+ return 0;
+ }
+
+ int readCount;
+ if (target.isDirect() || target.hasArray()) {
+ readCount = readImpl(target);
+ if (readCount > 0) {
+ target.position(target.position() + readCount);
+ }
+ } else {
+ ByteBuffer readBuffer = null;
+ byte[] readArray = null;
+ readArray = new byte[target.remaining()];
+ readBuffer = ByteBuffer.wrap(readArray);
+ readCount = readImpl(readBuffer);
+ if (readCount > 0) {
+ target.put(readArray, 0, readCount);
+ }
+ }
+ return readCount;
+ }
+
+ /*
+ * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer[], int,
+ * int)
+ */
+ @Override
+ public long read(ByteBuffer[] targets, int offset, int length)
+ throws IOException {
+ if (!isIndexValid(targets, offset, length)) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ checkOpenConnected();
+ int totalCount = calculateByteBufferArray(targets, offset, length);
+ if (0 == totalCount) {
+ return 0;
+ }
+ byte[] readArray = new byte[totalCount];
+ ByteBuffer readBuffer = ByteBuffer.wrap(readArray);
+ int readCount;
+ // read data to readBuffer, and then transfer data from readBuffer to
+ // targets.
+ readCount = readImpl(readBuffer);
+ if (readCount > 0) {
+ int left = readCount;
+ int index = offset;
+ // transfer data from readArray to targets
+ while (left > 0) {
+ int putLength = Math.min(targets[index].remaining(), left);
+ targets[index].put(readArray, readCount - left, putLength);
+ index++;
+ left -= putLength;
+ }
+ }
+ return readCount;
+ }
+
+ private boolean isIndexValid(ByteBuffer[] targets, int offset, int length) {
+ return (length >= 0) && (offset >= 0)
+ && ((long)length + (long)offset <= targets.length);
+ }
+
+ /*
+ * read from channel, and store the result in the target.
+ *
+ * @param target output parameter
+ */
+ private int readImpl(ByteBuffer target) throws IOException {
+ synchronized(readLock){
+ int readCount = 0;
+ try {
+ if (isBlocking()) {
+ begin();
+ }
+ int offset = target.position();
+ int length = target.remaining();
+ if (target.isDirect()) {
+ int address = AddressUtil.getDirectBufferAddress(target);
+ readCount = networkSystem.readDirect(fd, address, offset,
+ length, (isBlocking() ? TIMEOUT_BLOCK
+ : TIMEOUT_NONBLOCK));
+ } else {
+ // target is assured to have array.
+ byte[] array = target.array();
+ offset += target.arrayOffset();
+ readCount = networkSystem.read(fd, array, offset, length,
+ (isBlocking() ? TIMEOUT_BLOCK : TIMEOUT_NONBLOCK));
+ }
+ return readCount;
+ } finally {
+ if (isBlocking()) {
+ end(readCount > 0);
+ }
+ }
+ }
+ }
+
+ /*
+ *
+ * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer)
+ */
+ @Override
+ public int write(ByteBuffer source) throws IOException {
+ if (null == source) {
+ throw new NullPointerException();
+ }
+ checkOpenConnected();
+ if (!source.hasRemaining()) {
+ return 0;
+ }
+ return writeImpl(source);
+ }
+
+ /*
+ * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer[], int,
+ * int)
+ */
+ @Override
+ public long write(ByteBuffer[] sources, int offset, int length)
+ throws IOException {
+ if (!isIndexValid(sources, offset, length)) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ checkOpenConnected();
+ int count = calculateByteBufferArray(sources, offset, length);
+ if (0 == count) {
+ return 0;
+ }
+ ByteBuffer writeBuf = ByteBuffer.allocate(count);
+ for (int val = offset; val < length+offset; val++) {
+ ByteBuffer source = sources[val];
+ int oldPosition = source.position();
+ writeBuf.put(source);
+ source.position(oldPosition);
+ }
+ writeBuf.flip();
+ int result = writeImpl(writeBuf);
+ int val = offset;
+ int written = result;
+ while (result > 0) {
+ ByteBuffer source = sources[val];
+ int gap = Math.min(result, source.remaining());
+ source.position(source.position() + gap);
+ val++;
+ result -= gap;
+ }
+ return written;
+ }
+
+ private int calculateByteBufferArray(ByteBuffer[] sources, int offset,
+ int length) {
+ int sum = 0;
+ for (int val = offset; val < offset + length; val++) {
+ sum = sum + sources[val].remaining();
+ }
+ return sum;
+ }
+
+ /*
+ * write the source. return the count of bytes written.
+ */
+ private int writeImpl(ByteBuffer source) throws IOException {
+ synchronized(writeLock){
+ if (!source.hasRemaining()) {
+ return 0;
+ }
+ int writeCount = 0;
+ try {
+ int pos = source.position();
+ int length = source.remaining();
+ if (isBlocking()) {
+ begin();
+ }
+ if (source.isDirect()) {
+ int address = AddressUtil.getDirectBufferAddress(source);
+ writeCount = networkSystem
+ .writeDirect(fd, address, pos, length);
+ } else if (source.hasArray()) {
+ pos += source.arrayOffset();
+ writeCount = networkSystem.write(fd, source.array(), pos,
+ length);
+ } else {
+ byte[] array = new byte[length];
+ source.get(array);
+ writeCount = networkSystem.write(fd, array, 0, length);
+ }
+ source.position(pos + writeCount);
+ } catch (SocketException e) {
+ if (e.getCause() instanceof ErrorCodeException) {
+ if (ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK == ((ErrorCodeException) e
+ .getCause()).getErrorCode()) {
+ return writeCount;
+ }
+ }
+ throw e;
+ } finally {
+ if (isBlocking()) {
+ end(writeCount >= 0);
+ }
+ }
+ return writeCount;
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // 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
+ */
+ @Override
+ synchronized protected void implCloseSelectableChannel() throws IOException {
+ if (SOCKET_STATUS_CLOSED != status) {
+ status = SOCKET_STATUS_CLOSED;
+ if (null != socket && !socket.isClosed()) {
+ socket.close();
+ } else {
+ networkSystem.socketClose(fd);
+ }
+ }
+ }
+
+ /*
+ * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean)
+ */
+ @Override
+ protected void implConfigureBlocking(boolean blockMode) throws IOException {
+ synchronized (blockingLock()) {
+ networkSystem.setNonBlocking(fd, !blockMode);
+ }
+ }
+
+ /*
+ * get the fd
+ */
+ public FileDescriptor getFD() {
+ return fd;
+ }
+
+ // -------------------------------------------------------------------
+ // Adapter classes for internal socket.
+ // -------------------------------------------------------------------
+
+ private static class SocketAdapter extends Socket {
+
+ // ----------------------------------------------------
+ // Class Variables
+ // ----------------------------------------------------
+
+ SocketChannelImpl channel;
+
+ SocketImpl socketImpl;
+
+ // ----------------------------------------------------
+ // Methods
+ // ----------------------------------------------------
+
+ SocketAdapter(SocketImpl socketimpl, SocketChannelImpl channel)
+ throws SocketException {
+ super(socketimpl);
+ socketImpl = socketimpl;
+ this.channel = channel;
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getChannel()
+ */
+ @Override
+ public SocketChannel getChannel() {
+ return channel;
+ }
+
+ /*
+ *
+ * @see java.net.Socket#isBound()
+ */
+ @Override
+ public boolean isBound() {
+ return channel.isBound;
+ }
+
+ /*
+ *
+ * @see java.net.Socket#isConnected()
+ */
+ @Override
+ public boolean isConnected() {
+ return channel.isConnected();
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getLocalAddress()
+ */
+ @Override
+ public InetAddress getLocalAddress() {
+ try {
+ return channel.getLocalAddress();
+ } catch (UnknownHostException e) {
+ return null;
+ }
+ }
+
+ /*
+ *
+ * @see java.net.Socket#connect(java.net.SocketAddress, int)
+ */
+ @Override
+ public void connect(SocketAddress remoteAddr, int timeout)
+ throws IOException {
+ if (!channel.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ if (isConnected()) {
+ throw new AlreadyConnectedException();
+ }
+ super.connect(remoteAddr, timeout);
+ channel.localAddress = networkSystem.getSocketLocalAddress(
+ channel.fd, false);
+ if (super.isConnected()) {
+ channel.setConnected();
+ channel.isBound = super.isBound();
+ }
+ }
+
+ /*
+ *
+ * @see java.net.Socket#bind(java.net.SocketAddress)
+ */
+ @Override
+ public void bind(SocketAddress localAddr) throws IOException {
+ if (channel.isConnected()) {
+ throw new AlreadyConnectedException();
+ }
+ if (SocketChannelImpl.SOCKET_STATUS_PENDING == channel.status) {
+ throw new ConnectionPendingException();
+ }
+ super.bind(localAddr);
+ // keep here to see if need next version
+ // channel.Address = getLocalSocketAddress();
+ // channel.localport = getLocalPort();
+ channel.isBound = true;
+
+ }
+
+ /*
+ *
+ * @see java.net.Socket#close()
+ */
+ @Override
+ public void close() throws IOException {
+ synchronized (channel) {
+ if (channel.isOpen()) {
+ channel.close();
+ } else {
+ super.close();
+ }
+ channel.status = SocketChannelImpl.SOCKET_STATUS_CLOSED;
+ }
+ }
+
+ @Override
+ public boolean getReuseAddress() throws SocketException {
+ checkOpen();
+ return ((Boolean) socketImpl.getOption(SocketOptions.SO_REUSEADDR))
+ .booleanValue();
+ }
+
+ @Override
+ public synchronized int getReceiveBufferSize() throws SocketException {
+ checkOpen();
+ return ((Integer) socketImpl.getOption(SocketOptions.SO_RCVBUF))
+ .intValue();
+ }
+
+ @Override
+ public synchronized int getSendBufferSize() throws SocketException {
+ checkOpen();
+ return ((Integer) socketImpl.getOption(SocketOptions.SO_SNDBUF))
+ .intValue();
+ }
+
+ @Override
+ public synchronized int getSoTimeout() throws SocketException {
+ checkOpen();
+ return ((Integer) socketImpl.getOption(SocketOptions.SO_TIMEOUT))
+ .intValue();
+ }
+
+ @Override
+ public int getTrafficClass() throws SocketException {
+ checkOpen();
+ return ((Number) socketImpl.getOption(SocketOptions.IP_TOS))
+ .intValue();
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getKeepAlive()
+ */
+ @Override
+ public boolean getKeepAlive() throws SocketException {
+ checkOpen();
+ return ((Boolean) socketImpl.getOption(SocketOptions.SO_KEEPALIVE))
+ .booleanValue();
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getOOBInline()
+ */
+ @Override
+ public boolean getOOBInline() throws SocketException {
+ checkOpen();
+ return ((Boolean) socketImpl.getOption(SocketOptions.SO_OOBINLINE))
+ .booleanValue();
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getSoLinger()
+ */
+ @Override
+ public int getSoLinger() throws SocketException {
+ checkOpen();
+ return ((Integer) socketImpl.getOption(SocketOptions.SO_LINGER))
+ .intValue();
+ }
+
+ /*
+ * @see java.net.Socket#getTcpNoDelay()
+ */
+ @Override
+ public boolean getTcpNoDelay() throws SocketException {
+ checkOpen();
+ return ((Boolean) socketImpl.getOption(SocketOptions.TCP_NODELAY))
+ .booleanValue();
+ }
+
+ /*
+ * @see java.net.Socket#getOutputStream()
+ */
+ @Override
+ public OutputStream getOutputStream() throws IOException {
+ if (!channel.isOpen()) {
+ // nio.00=Socket is closed
+ throw new SocketException(Messages.getString("nio.00")); //$NON-NLS-1$
+ }
+ if (!channel.isConnected()) {
+ // nio.01=Socket is not connected
+ throw new SocketException(Messages.getString("nio.01")); //$NON-NLS-1$
+ }
+ if (isOutputShutdown()) {
+ // nio.02=Socket output is shutdown
+ throw new SocketException(Messages.getString("nio.02")); //$NON-NLS-1$
+ }
+ return new SocketChannelOutputStream(channel);
+ }
+
+ /*
+ *
+ * @see java.net.Socket#getInputStream()
+ */
+ @Override
+ public InputStream getInputStream() throws IOException {
+ if (!channel.isOpen()) {
+ // nio.00=Socket is closed
+ throw new SocketException(Messages.getString("nio.00")); //$NON-NLS-1$
+ }
+ if (!channel.isConnected()) {
+ // nio.01=Socket is not connected
+ throw new SocketException(Messages.getString("nio.01")); //$NON-NLS-1$
+ }
+ if (isInputShutdown()) {
+ // nio.03=Socket input is shutdown
+ throw new SocketException(Messages.getString("nio.03")); //$NON-NLS-1$
+ }
+ return new SocketChannelInputStream(channel);
+ }
+
+ /*
+ * Checks whether the channel is open
+ */
+ private void checkOpen() throws SocketException {
+ if (isClosed()) {
+ // nio.00=Socket is closed
+ throw new SocketException(Messages.getString("nio.00")); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * used for net and nio exchange
+ */
+ public SocketImpl getImpl() {
+ return socketImpl;
+ }
+ }
+
+ /*
+ * This output stream delegates all operations to the associated channel.
+ * Throws an IllegalBlockingModeException if the channel is in non-blocking
+ * mode when performing write operations.
+ */
+ private static class SocketChannelOutputStream extends OutputStream {
+ SocketChannel channel;
+
+ public SocketChannelOutputStream(SocketChannel channel) {
+ this.channel = channel;
+ }
+
+ /*
+ * Closes this stream and channel
+ *
+ * @exception IOException thrown if an error occurs during the close
+ */
+ @Override
+ public void close() throws IOException {
+ channel.close();
+ }
+
+ /*
+ * @see java.io.OutputStream#write(byte[], int, int)
+ */
+ @Override
+ public void write(byte[] buffer, int offset, int count)
+ throws IOException {
+ if (0 > offset || 0 > count || count + offset > buffer.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ ByteBuffer buf = ByteBuffer.wrap(buffer, offset, count);
+ if (!channel.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ channel.write(buf);
+ }
+
+ /*
+ * @see java.io.OutputStream#write(int)
+ */
+ @Override
+ public void write(int oneByte) throws IOException {
+ if (!channel.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ ByteBuffer buffer = ByteBuffer.allocate(1);
+ buffer.put(0, (byte) (oneByte & 0xFF));
+ channel.write(buffer);
+ }
+ }
+
+ /*
+ * This input stream delegates all operations to the associated channel.
+ * Throws an IllegalBlockingModeException if the channel is in non-blocking
+ * mode when performing read operations.
+ */
+ private static class SocketChannelInputStream extends InputStream {
+ SocketChannel channel;
+
+ public SocketChannelInputStream(SocketChannel channel) {
+ this.channel = channel;
+ }
+
+ /*
+ * Closes this stream and channel.
+ */
+ @Override
+ public void close() throws IOException {
+ channel.close();
+ }
+
+ /*
+ * @see java.io.InputStream#read()
+ */
+ @Override
+ public int read() throws IOException {
+ if (!channel.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ ByteBuffer buf = ByteBuffer.allocate(1);
+ int result = channel.read(buf);
+ // BEGIN android-changed: input was already consumed
+ return (-1 == result) ? result : buf.get(0) & 0xFF;
+ // END android-changed
+ }
+
+ /*
+ * @see java.io.InputStream#read(byte[], int, int)
+ */
+ @Override
+ public int read(byte[] buffer, int offset, int count)
+ throws IOException {
+ if (0 > offset || 0 > count || count + offset > buffer.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (!channel.isBlocking()) {
+ throw new IllegalBlockingModeException();
+ }
+ ByteBuffer buf = ByteBuffer.wrap(buffer, offset, count);
+ return channel.read(buf);
+ }
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/WriteOnlyFileChannel.java b/nio/src/main/java/org/apache/harmony/nio/internal/WriteOnlyFileChannel.java
new file mode 100644
index 0000000..ffcdd14
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/WriteOnlyFileChannel.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Android Notice
+ * In this class the address length was changed from long to int.
+ * This is due to performance optimizations for the device.
+ */
+
+package org.apache.harmony.nio.internal;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.FileLock;
+import java.nio.channels.NonReadableChannelException;
+import java.nio.channels.WritableByteChannel;
+
+public final class WriteOnlyFileChannel extends FileChannelImpl {
+
+ private boolean append = false;
+
+ public WriteOnlyFileChannel(Object stream, int handle) {
+ super(stream, handle);
+ }
+
+ public WriteOnlyFileChannel(Object stream, int handle, boolean isAppend) {
+ super(stream, handle);
+ append = isAppend;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.apache.harmony.nio.internal.FileChannelImpl#position()
+ */
+ public long position() throws IOException {
+ return append ? size() : super.position();
+ }
+
+ public long transferTo(long position, long count, WritableByteChannel target)
+ throws IOException {
+ openCheck();
+ if (!target.isOpen()) {
+ throw new ClosedChannelException();
+ }
+ throw new NonReadableChannelException();
+ }
+
+ public long read(ByteBuffer[] buffers, int offset, int length)
+ throws IOException {
+ if (offset < 0 || length < 0 || offset + length > buffers.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ openCheck();
+ throw new NonReadableChannelException();
+ }
+
+ public int read(ByteBuffer buffer) throws IOException {
+ openCheck();
+ throw new NonReadableChannelException();
+ }
+
+ public int read(ByteBuffer buffer, long position) throws IOException {
+ if (null == buffer) {
+ throw new NullPointerException();
+ }
+ if (position < 0){
+ throw new IllegalArgumentException();
+ }
+ throw new NonReadableChannelException();
+ }
+
+ public MappedByteBuffer map(MapMode mode, long position, long size)
+ throws IOException {
+ openCheck();
+ if (mode == null) {
+ throw new NullPointerException();
+ }
+ if (position < 0 || size < 0 || size > Integer.MAX_VALUE) {
+ throw new IllegalArgumentException();
+ }
+ throw new NonReadableChannelException();
+ }
+
+ public int write(ByteBuffer buffer) throws IOException {
+ if (append) {
+ position(size());
+ }
+ return super.write(buffer);
+ }
+
+ protected final FileLock basicLock(long position, long size,
+ boolean shared, boolean wait) throws IOException {
+ if (shared) {
+ throw new NonReadableChannelException();
+ }
+ return super.basicLock(position, size, shared, wait);
+ }
+
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/nls/Messages.java b/nio/src/main/java/org/apache/harmony/nio/internal/nls/Messages.java
new file mode 100644
index 0000000..35c3900
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/nls/Messages.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * THE FILE HAS BEEN AUTOGENERATED BY MSGTOOL TOOL.
+ * All changes made to this file manually will be overwritten
+ * if this tool runs again. Better make changes in the template file.
+ */
+
+package org.apache.harmony.nio.internal.nls;
+
+import org.apache.harmony.luni.util.MsgHelp;
+
+/**
+ * This class retrieves strings from a resource bundle and returns them,
+ * formatting them with MessageFormat when required.
+ * <p>
+ * It is used by the system classes to provide national language support, by
+ * looking up messages in the <code>
+ * org.apache.harmony.nio.internal.nls.messages
+ * </code>
+ * resource bundle. Note that if this file is not available, or an invalid key
+ * is looked up, or resource bundle support is not available, the key itself
+ * will be returned as the associated message. This means that the <em>KEY</em>
+ * should a reasonable human-readable (english) string.
+ *
+ */
+public class Messages {
+
+ private static final String sResource =
+ "org.apache.harmony.nio.internal.nls.messages"; //$NON-NLS-1$
+
+ /**
+ * Retrieves a message which has no arguments.
+ *
+ * @param msg
+ * String the key to look up.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg) {
+ return MsgHelp.getString(sResource, msg);
+ }
+
+ /**
+ * Retrieves a message which takes 1 argument.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param arg
+ * Object the object to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, Object arg) {
+ return getString(msg, new Object[] { arg });
+ }
+
+ /**
+ * Retrieves a message which takes 1 integer argument.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param arg
+ * int the integer to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, int arg) {
+ return getString(msg, new Object[] { Integer.toString(arg) });
+ }
+
+ /**
+ * Retrieves a message which takes 1 character argument.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param arg
+ * char the character to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, char arg) {
+ return getString(msg, new Object[] { String.valueOf(arg) });
+ }
+
+ /**
+ * Retrieves a message which takes 2 arguments.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param arg1
+ * Object an object to insert in the formatted output.
+ * @param arg2
+ * Object another object to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, Object arg1, Object arg2) {
+ return getString(msg, new Object[] { arg1, arg2 });
+ }
+
+ /**
+ * Retrieves a message which takes several arguments.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param args
+ * Object[] the objects to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, Object[] args) {
+ return MsgHelp.getString(sResource, msg, args);
+ }
+}
diff --git a/nio/src/main/java/org/apache/harmony/nio/internal/nls/messages.properties b/nio/src/main/java/org/apache/harmony/nio/internal/nls/messages.properties
new file mode 100644
index 0000000..79d1c84
--- /dev/null
+++ b/nio/src/main/java/org/apache/harmony/nio/internal/nls/messages.properties
@@ -0,0 +1,28 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# messages for EN locale
+nio.00=Socket is closed
+nio.01=Socket is not connected
+nio.02=Socket output is shutdown
+nio.03=Socket input is shutdown
+nio.04=Size mismatch
+nio.05=Negative index specified
+nio.06=InputStreamReader is closed.
+nio.07=Writer is closed.
+nio.08=Cannot use the direct byte buffer after it has been explicitly freed.
+nio.09=Unknown file channel type: {0}
+nio.0A=Lock position and size must be non-negative.
+nio.0B=New position must be non-negative.
diff --git a/nio/src/main/native/org_apache_harmony_nio_AddressUtil.cpp b/nio/src/main/native/org_apache_harmony_nio_AddressUtil.cpp
new file mode 100644
index 0000000..cb665de
--- /dev/null
+++ b/nio/src/main/native/org_apache_harmony_nio_AddressUtil.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#include "JNIHelp.h"
+#include "AndroidSystemNatives.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define SOCKET_CAST(x) ((struct hysocket_struct*) x)->sock
+
+typedef jint OSSOCKET;
+
+typedef struct hysocket_struct
+{
+ OSSOCKET sock;
+ unsigned short family;
+} hysocket_struct;
+
+typedef struct hysocket_struct *hysocket_t;
+
+/*
+ * Internal helper function.
+ *
+ * Get the file descriptor.
+ */
+static jint getFd(JNIEnv* env, jclass clazz, jobject fd)
+{
+ jclass descriptorCLS;
+ jfieldID descriptorFID;
+ hysocket_t* hysocketP;
+
+ descriptorCLS = env->FindClass("java/io/FileDescriptor");
+ if (NULL == descriptorCLS){
+ return 0;
+ }
+ descriptorFID = env->GetFieldID(descriptorCLS, "descriptor", "I");
+ if (NULL == descriptorFID){
+ return 0;
+ }
+ jint result = env->GetIntField(fd, descriptorFID);
+ hysocketP = (hysocket_t*) (result);
+ return SOCKET_CAST(hysocketP);
+}
+
+/*
+ * JNI registration
+ */
+static JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "getFDAddress", "(Ljava/io/FileDescriptor;)I", (void*) getFd }
+};
+
+int register_org_apache_harmony_nio_AddressUtil(JNIEnv* env)
+{
+ return jniRegisterNativeMethods(env, "org/apache/harmony/nio/AddressUtil",
+ gMethods, NELEM(gMethods));
+}
diff --git a/nio/src/main/native/sub.mk b/nio/src/main/native/sub.mk
new file mode 100644
index 0000000..750d216
--- /dev/null
+++ b/nio/src/main/native/sub.mk
@@ -0,0 +1,16 @@
+# This file is included by the top-level libcore Android.mk.
+# It's not a normal makefile, so we don't include CLEAR_VARS
+# or BUILD_*_LIBRARY.
+
+LOCAL_SRC_FILES := \
+ org_apache_harmony_nio_AddressUtil.cpp
+
+LOCAL_C_INCLUDES +=
+
+# Any shared/static libs that are listed here must also
+# be listed in libs/nativehelper/Android.mk.
+# TODO: fix this requirement
+
+LOCAL_SHARED_LIBRARIES +=
+
+LOCAL_STATIC_LIBRARIES +=
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/AbstractBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/AbstractBufferTest.java
new file mode 100644
index 0000000..57c1471
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/AbstractBufferTest.java
@@ -0,0 +1,306 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.InvalidMarkException;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests a java.nio.Buffer instance.
+ */
+public class AbstractBufferTest extends TestCase {
+
+ protected Buffer baseBuf;
+
+ protected void setUp() throws Exception{
+ super.setUp();
+ baseBuf = ByteBuffer.allocate(10);
+ }
+
+ protected void tearDown() throws Exception{
+ super.tearDown();
+ }
+
+ public void testCapacity() {
+ assertTrue(0 <= baseBuf.position() && baseBuf.position() <= baseBuf.limit()
+ && baseBuf.limit() <= baseBuf.capacity());
+ }
+
+ public void testClear() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ Buffer ret = baseBuf.clear();
+ assertSame(ret, baseBuf);
+ assertEquals(baseBuf.position(), 0);
+ assertEquals(baseBuf.limit(), baseBuf.capacity());
+ try {
+ baseBuf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$S
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ public void testFlip() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ Buffer ret = baseBuf.flip();
+ assertSame(ret, baseBuf);
+ assertEquals(baseBuf.position(), 0);
+ assertEquals(baseBuf.limit(), oldPosition);
+ try {
+ baseBuf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ public void testHasRemaining() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ assertEquals(baseBuf.hasRemaining(), baseBuf.position() < baseBuf.limit());
+ baseBuf.position(baseBuf.limit());
+ assertFalse(baseBuf.hasRemaining());
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ public void testIsReadOnly() {
+ baseBuf.isReadOnly();
+ }
+
+ /*
+ * Class under test for int limit()
+ */
+ public void testLimit() {
+ assertTrue(0 <= baseBuf.position() && baseBuf.position() <= baseBuf.limit()
+ && baseBuf.limit() <= baseBuf.capacity());
+ }
+
+ /*
+ * Class under test for Buffer limit(int)
+ */
+ public void testLimitint() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ Buffer ret = baseBuf.limit(baseBuf.limit());
+ assertSame(ret, baseBuf);
+
+ baseBuf.mark();
+ baseBuf.limit(baseBuf.capacity());
+ assertEquals(baseBuf.limit(), baseBuf.capacity());
+ // position should not change
+ assertEquals(baseBuf.position(), oldPosition);
+ // mark should be valid
+ baseBuf.reset();
+
+ if (baseBuf.capacity() > 0) {
+ baseBuf.limit(baseBuf.capacity());
+ baseBuf.position(baseBuf.capacity());
+ baseBuf.mark();
+ baseBuf.limit(baseBuf.capacity() - 1);
+ // position should be the new limit
+ assertEquals(baseBuf.position(), baseBuf.limit());
+ // mark should be invalid
+ try {
+ baseBuf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ try {
+ baseBuf.limit(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ baseBuf.limit(baseBuf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ public void testMark() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ Buffer ret = baseBuf.mark();
+ assertSame(ret, baseBuf);
+
+ baseBuf.mark();
+ baseBuf.position(baseBuf.limit());
+ baseBuf.reset();
+ assertEquals(baseBuf.position(), oldPosition);
+
+ baseBuf.mark();
+ baseBuf.position(baseBuf.limit());
+ baseBuf.reset();
+ assertEquals(baseBuf.position(), oldPosition);
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ /*
+ * Class under test for int position()
+ */
+ public void testPosition() {
+ assertTrue(0 <= baseBuf.position() && baseBuf.position() <= baseBuf.limit()
+ && baseBuf.limit() <= baseBuf.capacity());
+ }
+
+ /*
+ * Class under test for Buffer position(int)
+ */
+ public void testPositionint() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ try {
+ baseBuf.position(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ baseBuf.position(baseBuf.limit() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ baseBuf.mark();
+ baseBuf.position(baseBuf.position());
+ baseBuf.reset();
+ assertEquals(baseBuf.position(), oldPosition);
+
+ baseBuf.position(0);
+ assertEquals(baseBuf.position(), 0);
+ baseBuf.position(baseBuf.limit());
+ assertEquals(baseBuf.position(), baseBuf.limit());
+
+ if (baseBuf.capacity() > 0) {
+ baseBuf.limit(baseBuf.capacity());
+ baseBuf.position(baseBuf.limit());
+ baseBuf.mark();
+ baseBuf.position(baseBuf.limit() - 1);
+ assertEquals(baseBuf.position(), baseBuf.limit() - 1);
+ // mark should be invalid
+ try {
+ baseBuf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ Buffer ret = baseBuf.position(0);
+ assertSame(ret, baseBuf);
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ public void testRemaining() {
+ assertEquals(baseBuf.remaining(), baseBuf.limit() - baseBuf.position());
+ }
+
+ public void testReset() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ baseBuf.mark();
+ baseBuf.position(baseBuf.limit());
+ baseBuf.reset();
+ assertEquals(baseBuf.position(), oldPosition);
+
+ baseBuf.mark();
+ baseBuf.position(baseBuf.limit());
+ baseBuf.reset();
+ assertEquals(baseBuf.position(), oldPosition);
+
+ Buffer ret = baseBuf.reset();
+ assertSame(ret, baseBuf);
+
+ baseBuf.clear();
+ try {
+ baseBuf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ public void testRewind() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ Buffer ret = baseBuf.rewind();
+ assertEquals(baseBuf.position(), 0);
+ assertSame(ret, baseBuf);
+ try {
+ baseBuf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/AllTests.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/AllTests.java
new file mode 100644
index 0000000..cefb2da
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/AllTests.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite for java.nio package
+ *
+ */
+public class AllTests {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite("Tests for java.nio");
+ //$JUnit-BEGIN$
+ suite.addTestSuite(ReadOnlyHeapShortBufferTest.class);
+ suite.addTestSuite(ReadOnlyLongBufferTest.class);
+ suite.addTestSuite(BufferOverflowExceptionTest.class);
+ suite.addTestSuite(CharBufferTest.class);
+ suite.addTestSuite(DirectShortBufferTest.class);
+ suite.addTestSuite(ReadOnlyHeapIntBufferTest.class);
+ suite.addTestSuite(HeapIntBufferTest.class);
+ suite.addTestSuite(WrappedDoubleBufferTest.class);
+ suite.addTestSuite(WrappedCharBufferTest2.class);
+ suite.addTestSuite(HeapLongBufferTest.class);
+ suite.addTestSuite(ByteOrderTest.class);
+ suite.addTestSuite(ReadOnlyFloatBufferTest.class);
+ suite.addTestSuite(WrappedFloatBufferTest.class);
+ suite.addTestSuite(DirectLongBufferTest.class);
+ suite.addTestSuite(ReadOnlyWrappedByteBufferTest.class);
+ suite.addTestSuite(ReadOnlyWrappedLongBufferTest.class);
+ suite.addTestSuite(HeapFloatBufferTest.class);
+ suite.addTestSuite(WrappedCharBufferTest1.class);
+ suite.addTestSuite(WrappedShortBufferTest.class);
+ suite.addTestSuite(ReadOnlyWrappedIntBufferTest.class);
+ suite.addTestSuite(AbstractBufferTest.class);
+ suite.addTestSuite(ReadOnlyCharBufferTest.class);
+ suite.addTestSuite(SliceHeapByteBufferTest.class);
+ suite.addTestSuite(LongBufferTest.class);
+ suite.addTestSuite(DuplicateWrappedByteBufferTest.class);
+ suite.addTestSuite(FloatBufferTest.class);
+ suite.addTestSuite(ReadOnlyHeapCharBufferTest.class);
+ suite.addTestSuite(WrappedLongBufferTest.class);
+ suite.addTestSuite(ReadOnlyWrappedShortBufferTest.class);
+ suite.addTestSuite(ByteBufferTest.class);
+ suite.addTestSuite(ReadOnlyBufferExceptionTest.class);
+ suite.addTestSuite(ReadOnlyDirectByteBufferTest.class);
+ suite.addTestSuite(ReadOnlyHeapDoubleBufferTest.class);
+ suite.addTestSuite(ReadOnlyShortBufferTest.class);
+ suite.addTestSuite(DoubleBufferTest.class);
+ suite.addTestSuite(ReadOnlyWrappedFloatBufferTest.class);
+ suite.addTestSuite(ShortBufferTest.class);
+ suite.addTestSuite(BufferTest.class);
+ suite.addTestSuite(DirectFloatBufferTest.class);
+ suite.addTestSuite(SliceWrappedByteBufferTest.class);
+ suite.addTestSuite(DirectCharBufferTest.class);
+ suite.addTestSuite(SliceDirectByteBufferTest.class);
+ suite.addTestSuite(ReadOnlyHeapLongBufferTest.class);
+ suite.addTestSuite(DirectIntBufferTest.class);
+ suite.addTestSuite(HeapByteBufferTest.class);
+ suite.addTestSuite(ReadOnlyWrappedDoubleBufferTest.class);
+ suite.addTestSuite(DuplicateHeapByteBufferTest.class);
+ suite.addTestSuite(HeapShortBufferTest.class);
+ suite.addTestSuite(InvalidMarkExceptionTest.class);
+ suite.addTestSuite(DirectDoubleBufferTest.class);
+ suite.addTestSuite(ReadOnlyHeapByteBufferTest.class);
+ suite.addTestSuite(ReadOnlyIntBufferTest.class);
+ suite.addTestSuite(HeapDoubleBufferTest.class);
+ suite.addTestSuite(DirectByteBufferTest.class);
+ suite.addTestSuite(ReadOnlyWrappedCharBufferTest1.class);
+ suite.addTestSuite(IntBufferTest.class);
+ suite.addTestSuite(ReadOnlyDoubleBufferTest.class);
+ suite.addTestSuite(ReadOnlyHeapFloatBufferTest.class);
+ suite.addTestSuite(WrappedByteBufferTest.class);
+ suite.addTestSuite(BufferUnderflowExceptionTest.class);
+ suite.addTestSuite(DuplicateDirectByteBufferTest.class);
+ suite.addTestSuite(WrappedIntBufferTest.class);
+ suite.addTestSuite(HeapCharBufferTest.class);
+ //$JUnit-END$
+ return suite;
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java
new file mode 100644
index 0000000..4046739
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+public class BufferOverflowExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new BufferOverflowException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new BufferOverflowException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferTest.java
new file mode 100644
index 0000000..a7cc642
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferTest.java
@@ -0,0 +1,324 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.Buffer;
+import java.nio.InvalidMarkException;
+
+import junit.framework.TestCase;
+
+/**
+ * Test a java.nio.Buffer instance.
+ */
+public class BufferTest extends TestCase {
+
+ public static void testBufferInstance(Buffer buf) {
+ // save state
+ int oldPosition = buf.position();
+ int oldLimit = buf.limit();
+
+ testCapacity(buf);
+ testClear(buf);
+ testFlip(buf);
+ testHasRemaining(buf);
+ testIsReadOnly(buf);
+ testLimit(buf);
+ testLimitint(buf);
+ testMark(buf);
+ testPosition(buf);
+ testPositionint(buf);
+ testRemaining(buf);
+ testReset(buf);
+ testRewind(buf);
+
+ // check state, should not change
+ assertEquals(buf.position(), oldPosition);
+ assertEquals(buf.limit(), oldLimit);
+ }
+
+ public static void testCapacity(Buffer buf) {
+ assertTrue(0 <= buf.position() && buf.position() <= buf.limit()
+ && buf.limit() <= buf.capacity());
+ }
+
+ public static void testClear(Buffer buf) {
+ // save state
+ int oldPosition = buf.position();
+ int oldLimit = buf.limit();
+
+ Buffer ret = buf.clear();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // restore state
+ buf.limit(oldLimit);
+ buf.position(oldPosition);
+ }
+
+ public static void testFlip(Buffer buf) {
+ // save state
+ int oldPosition = buf.position();
+ int oldLimit = buf.limit();
+
+ Buffer ret = buf.flip();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), oldPosition);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // restore state
+ buf.limit(oldLimit);
+ buf.position(oldPosition);
+ }
+
+ public static void testHasRemaining(Buffer buf) {
+ // save state
+ int oldPosition = buf.position();
+ int oldLimit = buf.limit();
+
+ assertEquals(buf.hasRemaining(), buf.position() < buf.limit());
+ buf.position(buf.limit());
+ assertFalse(buf.hasRemaining());
+
+ // restore state
+ buf.limit(oldLimit);
+ buf.position(oldPosition);
+ }
+
+ public static void testIsReadOnly(Buffer buf) {
+ buf.isReadOnly();
+ }
+
+ /*
+ * Class under test for int limit()
+ */
+ public static void testLimit(Buffer buf) {
+ assertTrue(0 <= buf.position() && buf.position() <= buf.limit()
+ && buf.limit() <= buf.capacity());
+ }
+
+ /*
+ * Class under test for Buffer limit(int)
+ */
+ public static void testLimitint(Buffer buf) {
+ // save state
+ int oldPosition = buf.position();
+ int oldLimit = buf.limit();
+
+ Buffer ret = buf.limit(buf.limit());
+ assertSame(ret, buf);
+
+ buf.mark();
+ buf.limit(buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ // position should not change
+ assertEquals(buf.position(), oldPosition);
+ // mark should be valid
+ buf.reset();
+
+ if (buf.capacity() > 0) {
+ buf.limit(buf.capacity());
+ buf.position(buf.capacity());
+ buf.mark();
+ buf.limit(buf.capacity() - 1);
+ // position should be the new limit
+ assertEquals(buf.position(), buf.limit());
+ // mark should be invalid
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ try {
+ buf.limit(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.limit(buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ // restore state
+ buf.limit(oldLimit);
+ buf.position(oldPosition);
+ }
+
+ public static void testMark(Buffer buf) {
+ // save state
+ int oldPosition = buf.position();
+ int oldLimit = buf.limit();
+
+ Buffer ret = buf.mark();
+ assertSame(ret, buf);
+
+ buf.mark();
+ buf.position(buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), oldPosition);
+
+ buf.mark();
+ buf.position(buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), oldPosition);
+
+ // restore state
+ buf.limit(oldLimit);
+ buf.position(oldPosition);
+ }
+
+ /*
+ * Class under test for int position()
+ */
+ public static void testPosition(Buffer buf) {
+ assertTrue(0 <= buf.position() && buf.position() <= buf.limit()
+ && buf.limit() <= buf.capacity());
+ }
+
+ /*
+ * Class under test for Buffer position(int)
+ */
+ public static void testPositionint(Buffer buf) {
+ // save state
+ int oldPosition = buf.position();
+ int oldLimit = buf.limit();
+
+ try {
+ buf.position(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.position(buf.limit() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ buf.mark();
+ buf.position(buf.position());
+ buf.reset();
+ assertEquals(buf.position(), oldPosition);
+
+ buf.position(0);
+ assertEquals(buf.position(), 0);
+ buf.position(buf.limit());
+ assertEquals(buf.position(), buf.limit());
+
+ if (buf.capacity() > 0) {
+ buf.limit(buf.capacity());
+ buf.position(buf.limit());
+ buf.mark();
+ buf.position(buf.limit() - 1);
+ assertEquals(buf.position(), buf.limit() - 1);
+ // mark should be invalid
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ Buffer ret = buf.position(0);
+ assertSame(ret, buf);
+
+ // restore state
+ buf.limit(oldLimit);
+ buf.position(oldPosition);
+ }
+
+ public static void testRemaining(Buffer buf) {
+ assertEquals(buf.remaining(), buf.limit() - buf.position());
+ }
+
+ public static void testReset(Buffer buf) {
+ // save state
+ int oldPosition = buf.position();
+ int oldLimit = buf.limit();
+
+ buf.mark();
+ buf.position(buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), oldPosition);
+
+ buf.mark();
+ buf.position(buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), oldPosition);
+
+ Buffer ret = buf.reset();
+ assertSame(ret, buf);
+
+ buf.clear();
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // restore state
+ buf.limit(oldLimit);
+ buf.position(oldPosition);
+ }
+
+ public static void testRewind(Buffer buf) {
+ // save state
+ int oldPosition = buf.position();
+ int oldLimit = buf.limit();
+
+ Buffer ret = buf.rewind();
+ assertEquals(buf.position(), 0);
+ assertSame(ret, buf);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // restore state
+ buf.limit(oldLimit);
+ buf.position(oldPosition);
+ }
+
+ public void testNothing() {
+ // to remove JUnit warning
+ }
+
+} \ No newline at end of file
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java
new file mode 100644
index 0000000..3372473
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java
@@ -0,0 +1,45 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferUnderflowException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for BufferUnderflowException
+ */
+public class BufferUnderflowExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new BufferUnderflowException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new BufferUnderflowException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteBufferTest.java
new file mode 100644
index 0000000..6e22230
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteBufferTest.java
@@ -0,0 +1,2306 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.InvalidMarkException;
+import java.nio.LongBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.nio.ShortBuffer;
+import java.util.Arrays;
+
+/**
+ * Tests java.nio.ByteBuffer
+ *
+ */
+public class ByteBufferTest extends AbstractBufferTest {
+ protected static final int SMALL_TEST_LENGTH = 5;
+ protected static final int BUFFER_LENGTH = 250;
+
+ protected ByteBuffer buf;
+
+ protected void setUp() throws Exception {
+ buf = ByteBuffer.allocate(10);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /*
+ * test for method static ByteBuffer allocate(int capacity)
+ * test covers following usecases:
+ * 1. case for check ByteBuffer testBuf properties
+ * 2. case expected IllegalArgumentException
+ */
+
+ public void test_AllocateI() {
+ // case: ByteBuffer testBuf properties is satisfy the conditions specification
+ ByteBuffer testBuf = ByteBuffer.allocate(20);
+ assertEquals(testBuf.position(), 0);
+ assertEquals(testBuf.limit(), testBuf.capacity());
+ assertEquals(testBuf.arrayOffset(), 0);
+
+ // case: expected IllegalArgumentException
+ try {
+ testBuf = ByteBuffer.allocate(-20);
+ fail("allocate method does not throws expected exception");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+ }
+
+ /*
+ * test for method static ByteBuffer allocateDirect(int capacity)
+ */
+
+ public void test_AllocateDirectI() {
+ // case: ByteBuffer testBuf properties is satisfy the conditions specification
+ ByteBuffer testBuf = ByteBuffer.allocateDirect(20);
+ assertEquals(testBuf.position(), 0);
+ assertEquals(testBuf.limit(), testBuf.capacity());
+
+ // case: expected IllegalArgumentException
+ try {
+ testBuf = ByteBuffer.allocate(-20);
+ fail("allocate method does not throws expected exception");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+ }
+
+ public void testArray() {
+ if (buf.hasArray()) {
+ byte array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ } else {
+ if (buf.isReadOnly()) {
+ try {
+ buf.array();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ // expected
+ // Note:can not tell when to throw
+ // UnsupportedOperationException
+ // or ReadOnlyBufferException, so catch all.
+ }
+ } else {
+ try {
+ buf.array();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ }
+ }
+
+ public void testArrayOffset() {
+ if (buf.hasArray()) {
+ byte array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ } else {
+ if (buf.isReadOnly()) {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ // expected
+ // Note:can not tell when to throw
+ // UnsupportedOperationException
+ // or ReadOnlyBufferException, so catch all.
+ }
+ } else {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ }
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ ByteBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+ }
+
+ public void testCompact() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ ByteBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (byte) 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (byte) 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+ buf.position(1);
+ buf.limit(SMALL_TEST_LENGTH);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (byte) 1, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ // compare to self
+ assertEquals(0, buf.compareTo(buf));
+
+ // normal cases
+ if (!buf.isReadOnly()) {
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+ buf.clear();
+ ByteBuffer other = ByteBuffer.allocate(buf.capacity());
+ loadTestData1(buf);
+ loadTestData1(other);
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ other.limit(SMALL_TEST_LENGTH);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ }
+
+ assertTrue(ByteBuffer.wrap(new byte[21]).compareTo(ByteBuffer.allocateDirect(21)) == 0);
+ }
+
+ public void testDuplicate() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ ByteBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // duplicate share the same content with buf
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ ByteBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ ByteBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for byte get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer get(byte[])
+ */
+ public void testGetbyteArray() {
+ byte array[] = new byte[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ ByteBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i));
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ try {
+ buf.get((byte[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer get(byte[], int, int)
+ */
+ public void testGetbyteArrayintint() {
+ buf.clear();
+ byte array[] = new byte[buf.capacity()];
+
+ try {
+ buf.get(new byte[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get((byte[])null, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ ByteBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for byte get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHasArray() {
+ if (buf.hasArray()) {
+ assertNotNull(buf.array());
+ } else {
+ if (buf.isReadOnly()) {
+ try {
+ buf.array();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ // expected
+ // Note:can not tell when to throw
+ // UnsupportedOperationException
+ // or ReadOnlyBufferException, so catch all.
+ }
+ } else {
+ try {
+ buf.array();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ }
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ loadTestData1(buf);
+ ByteBuffer readonly = buf.asReadOnlyBuffer();
+ ByteBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+ duplicate.position(buf.capacity()/2);
+ assertTrue(buf.hashCode()!= duplicate.hashCode());
+ }
+
+ //for the testHashCode() method of readonly subclasses
+ protected void readOnlyHashCode() {
+ //create a new buffer initiated with some data
+ ByteBuffer buf = ByteBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ buf.clear();
+ ByteBuffer readonly = buf.asReadOnlyBuffer();
+ ByteBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(),readonly.hashCode());
+ duplicate.position(buf.capacity()/2);
+ assertTrue(buf.hashCode()!= duplicate.hashCode());
+ }
+
+ public void testIsDirect() {
+ buf.isDirect();
+ }
+
+ public void testOrder() {
+ // BIG_ENDIAN is the default byte order
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ assertEquals(ByteOrder.LITTLE_ENDIAN, buf.order());
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+
+ // Regression test for HARMONY-798
+ buf.order((ByteOrder)null);
+ assertEquals(ByteOrder.LITTLE_ENDIAN, buf.order());
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ /*
+ * test for method public final ByteBuffer order(ByteOrder bo)
+ * test covers following usecases:
+ * 1. case for check
+ */
+
+ public void test_OrderLjava_lang_ByteOrder() {
+ // BIG_ENDIAN is the default byte order
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ assertEquals(ByteOrder.LITTLE_ENDIAN, buf.order());
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+
+ // Regression test for HARMONY-798
+ buf.order((ByteOrder)null);
+ assertEquals(ByteOrder.LITTLE_ENDIAN, buf.order());
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer put(byte)
+ */
+ public void testPutbyte() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.put((byte) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ ByteBuffer ret = buf.put((byte) i);
+ assertEquals(buf.get(i), (byte) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put((byte) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer put(byte[])
+ */
+ public void testPutbyteArray() {
+ byte array[] = new byte[1];
+ if (buf.isReadOnly()) {
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (byte) i;
+ ByteBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (byte) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.put((byte[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer put(byte[], int, int)
+ */
+ public void testPutbyteArrayintint() {
+ buf.clear();
+ byte array[] = new byte[buf.capacity()];
+ if (buf.isReadOnly()) {
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ try {
+ buf.put(new byte[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ buf.put(array, 2, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((byte[])null, 2, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ ByteBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer put(java.nio.ByteBuffer)
+ */
+ public void testPutByteBuffer() {
+ ByteBuffer other = ByteBuffer.allocate(buf.capacity());
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.put(other);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.clear();
+ buf.put((ByteBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(ByteBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ try {
+ buf.put((ByteBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ ByteBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer put(int, byte)
+ */
+ public void testPutintbyte() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.put(0, (byte) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ ByteBuffer ret = buf.put(i, (byte) i);
+ assertEquals(buf.get(i), (byte) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, (byte) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), (byte) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ ByteBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, (byte) 0, slice.capacity());
+ buf.put(2, (byte) 100);
+ assertEquals(slice.get(1), 100);
+ }
+ }
+
+ public void testToString() {
+ String str = buf.toString();
+ assertTrue(str.indexOf("Byte") >= 0 || str.indexOf("byte") >= 0);
+ assertTrue(str.indexOf("" + buf.position()) >= 0);
+ assertTrue(str.indexOf("" + buf.limit()) >= 0);
+ assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+ }
+
+ public void testAsCharBuffer() {
+ CharBuffer charBuffer;
+ byte bytes[] = new byte[2];
+ char value;
+
+ // test BIG_ENDIAN char buffer, read
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ charBuffer = buf.asCharBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, charBuffer.order());
+ while (charBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = charBuffer.get();
+ assertEquals(bytes2char(bytes, buf.order()), value);
+ }
+
+ // test LITTLE_ENDIAN char buffer, read
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ charBuffer = buf.asCharBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, charBuffer.order());
+ while (charBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = charBuffer.get();
+ assertEquals(bytes2char(bytes, buf.order()), value);
+ }
+
+ if (!buf.isReadOnly()) {
+ // test BIG_ENDIAN char buffer, write
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ charBuffer = buf.asCharBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, charBuffer.order());
+ while (charBuffer.remaining() > 0) {
+ value = (char) charBuffer.remaining();
+ charBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, char2bytes(value, buf.order())));
+ }
+
+ // test LITTLE_ENDIAN char buffer, write
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ charBuffer = buf.asCharBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, charBuffer.order());
+ while (charBuffer.remaining() > 0) {
+ value = (char) charBuffer.remaining();
+ charBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, char2bytes(value, buf.order())));
+ }
+ }
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testAsDoubleBuffer() {
+ DoubleBuffer doubleBuffer;
+ byte bytes[] = new byte[8];
+ double value;
+
+ // test BIG_ENDIAN double buffer, read
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ doubleBuffer = buf.asDoubleBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, doubleBuffer.order());
+ while (doubleBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = doubleBuffer.get();
+ if (!(Double.isNaN(bytes2double(bytes, buf.order())) && Double
+ .isNaN(value))) {
+ assertEquals(bytes2double(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ // test LITTLE_ENDIAN double buffer, read
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ doubleBuffer = buf.asDoubleBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, doubleBuffer.order());
+ while (doubleBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = doubleBuffer.get();
+ if (!(Double.isNaN(bytes2double(bytes, buf.order())) && Double
+ .isNaN(value))) {
+ assertEquals(bytes2double(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ if (!buf.isReadOnly()) {
+ // test BIG_ENDIAN double buffer, write
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ doubleBuffer = buf.asDoubleBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, doubleBuffer.order());
+ while (doubleBuffer.remaining() > 0) {
+ value = (double) doubleBuffer.remaining();
+ doubleBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, double2bytes(value, buf.order())));
+ }
+
+ // test LITTLE_ENDIAN double buffer, write
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ doubleBuffer = buf.asDoubleBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, doubleBuffer.order());
+ while (doubleBuffer.remaining() > 0) {
+ value = (double) doubleBuffer.remaining();
+ doubleBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, double2bytes(value, buf.order())));
+ }
+ }
+
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testAsFloatBuffer() {
+ FloatBuffer floatBuffer;
+ byte bytes[] = new byte[4];
+ float value;
+
+ // test BIG_ENDIAN float buffer, read
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ floatBuffer = buf.asFloatBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, floatBuffer.order());
+ while (floatBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = floatBuffer.get();
+ if (!(Float.isNaN(bytes2float(bytes, buf.order())) && Float
+ .isNaN(value))) {
+ assertEquals(bytes2float(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ // test LITTLE_ENDIAN float buffer, read
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ floatBuffer = buf.asFloatBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, floatBuffer.order());
+ while (floatBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = floatBuffer.get();
+ if (!(Float.isNaN(bytes2float(bytes, buf.order())) && Float
+ .isNaN(value))) {
+ assertEquals(bytes2float(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ if (!buf.isReadOnly()) {
+ // test BIG_ENDIAN float buffer, write
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ floatBuffer = buf.asFloatBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, floatBuffer.order());
+ while (floatBuffer.remaining() > 0) {
+ value = (float) floatBuffer.remaining();
+ floatBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, float2bytes(value, buf.order())));
+ }
+
+ // test LITTLE_ENDIAN float buffer, write
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ floatBuffer = buf.asFloatBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, floatBuffer.order());
+ while (floatBuffer.remaining() > 0) {
+ value = (float) floatBuffer.remaining();
+ floatBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, float2bytes(value, buf.order())));
+ }
+ }
+
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testAsIntBuffer() {
+ IntBuffer intBuffer;
+ byte bytes[] = new byte[4];
+ int value;
+
+ // test BIG_ENDIAN int buffer, read
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ intBuffer = buf.asIntBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, intBuffer.order());
+ while (intBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = intBuffer.get();
+ assertEquals(bytes2int(bytes, buf.order()), value);
+ }
+
+ // test LITTLE_ENDIAN int buffer, read
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ intBuffer = buf.asIntBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, intBuffer.order());
+ while (intBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = intBuffer.get();
+ assertEquals(bytes2int(bytes, buf.order()), value);
+ }
+
+ if (!buf.isReadOnly()) {
+ // test BIG_ENDIAN int buffer, write
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ intBuffer = buf.asIntBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, intBuffer.order());
+ while (intBuffer.remaining() > 0) {
+ value = (int) intBuffer.remaining();
+ intBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, int2bytes(value, buf.order())));
+ }
+
+ // test LITTLE_ENDIAN int buffer, write
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ intBuffer = buf.asIntBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, intBuffer.order());
+ while (intBuffer.remaining() > 0) {
+ value = (int) intBuffer.remaining();
+ intBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, int2bytes(value, buf.order())));
+ }
+ }
+
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testAsLongBuffer() {
+ LongBuffer longBuffer;
+ byte bytes[] = new byte[8];
+ long value;
+
+ // test BIG_ENDIAN long buffer, read
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ longBuffer = buf.asLongBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, longBuffer.order());
+ while (longBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = longBuffer.get();
+ assertEquals(bytes2long(bytes, buf.order()), value);
+ }
+
+ // test LITTLE_ENDIAN long buffer, read
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ longBuffer = buf.asLongBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, longBuffer.order());
+ while (longBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = longBuffer.get();
+ assertEquals(bytes2long(bytes, buf.order()), value);
+ }
+
+ if (!buf.isReadOnly()) {
+ // test BIG_ENDIAN long buffer, write
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ longBuffer = buf.asLongBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, longBuffer.order());
+ while (longBuffer.remaining() > 0) {
+ value = (long) longBuffer.remaining();
+ longBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, long2bytes(value, buf.order())));
+ }
+
+ // test LITTLE_ENDIAN long buffer, write
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ longBuffer = buf.asLongBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, longBuffer.order());
+ while (longBuffer.remaining() > 0) {
+ value = (long) longBuffer.remaining();
+ longBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, long2bytes(value, buf.order())));
+ }
+ }
+
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testAsShortBuffer() {
+ ShortBuffer shortBuffer;
+ byte bytes[] = new byte[2];
+ short value;
+
+ // test BIG_ENDIAN short buffer, read
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ shortBuffer = buf.asShortBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, shortBuffer.order());
+ while (shortBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = shortBuffer.get();
+ assertEquals(bytes2short(bytes, buf.order()), value);
+ }
+
+ // test LITTLE_ENDIAN short buffer, read
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ shortBuffer = buf.asShortBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, shortBuffer.order());
+ while (shortBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = shortBuffer.get();
+ assertEquals(bytes2short(bytes, buf.order()), value);
+ }
+
+ if (!buf.isReadOnly()) {
+ // test BIG_ENDIAN short buffer, write
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ shortBuffer = buf.asShortBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, shortBuffer.order());
+ while (shortBuffer.remaining() > 0) {
+ value = (short) shortBuffer.remaining();
+ shortBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, short2bytes(value, buf.order())));
+ }
+
+ // test LITTLE_ENDIAN short buffer, write
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ shortBuffer = buf.asShortBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, shortBuffer.order());
+ while (shortBuffer.remaining() > 0) {
+ value = (short) shortBuffer.remaining();
+ shortBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, short2bytes(value, buf.order())));
+ }
+ }
+
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetChar() {
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ char value;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ assertEquals(i * nbytes, buf.position());
+ buf.mark();
+ buf.get(bytes);
+ buf.reset();
+ value = buf.getChar();
+ assertEquals(bytes2char(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getChar();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetCharint() {
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ char value;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ buf.position(i);
+ value = buf.getChar(i);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertEquals(bytes2char(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getChar(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.getChar(buf.limit() - nbytes + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutChar() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.putChar((char) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ char value = 0;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (char) i;
+ buf.mark();
+ buf.putChar(value);
+ assertEquals((i + 1) * nbytes, buf.position());
+ buf.reset();
+ buf.get(bytes);
+ assertTrue(Arrays.equals(char2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putChar(value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutCharint() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.putChar(0, (char) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ char value = 0;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (char) i;
+ buf.position(i);
+ buf.putChar(i, value);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertTrue(Arrays.equals(char2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putChar(-1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.putChar(buf.limit() - nbytes + 1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+
+ try {
+ ByteBuffer.allocateDirect(16).putChar(Integer.MAX_VALUE, 'h');
+ } catch (IndexOutOfBoundsException e) {
+ //expected
+ }
+ }
+
+ public void testGetDouble() {
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ double value;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ assertEquals(i * nbytes, buf.position());
+ buf.mark();
+ buf.get(bytes);
+ buf.reset();
+ value = buf.getDouble();
+ if (!(Double.isNaN(bytes2double(bytes, buf.order())) && Double
+ .isNaN(value))) {
+ assertEquals(bytes2double(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ try {
+ buf.getDouble();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetDoubleint() {
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ double value;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ buf.position(i);
+ value = buf.getDouble(i);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ if (!(Double.isNaN(bytes2double(bytes, buf.order())) && Double
+ .isNaN(value))) {
+ assertEquals(bytes2double(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ try {
+ buf.getDouble(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.getDouble(buf.limit() - nbytes + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+
+ try {
+ ByteBuffer.allocateDirect(16).getDouble(Integer.MAX_VALUE);
+ } catch (IndexOutOfBoundsException e) {
+ //expected
+ }
+ }
+
+ public void testPutDouble() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.putDouble((double) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ double value = 0;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (double) i;
+ buf.mark();
+ buf.putDouble(value);
+ assertEquals((i + 1) * nbytes, buf.position());
+ buf.reset();
+ buf.get(bytes);
+ assertTrue(Arrays.equals(double2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putDouble(value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutDoubleint() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.putDouble(0, (double) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ double value = 0;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (double) i;
+ buf.position(i);
+ buf.putDouble(i, value);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertTrue(Arrays.equals(double2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putDouble(-1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.putDouble(buf.limit() - nbytes + 1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetFloat() {
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ float value;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ assertEquals(i * nbytes, buf.position());
+ buf.mark();
+ buf.get(bytes);
+ buf.reset();
+ value = buf.getFloat();
+ if (!(Float.isNaN(bytes2float(bytes, buf.order())) && Float
+ .isNaN(value))) {
+ assertEquals(bytes2float(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ try {
+ buf.getFloat();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetFloatint() {
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ float value;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ buf.position(i);
+ value = buf.getFloat(i);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ if (!(Float.isNaN(bytes2float(bytes, buf.order())) && Float
+ .isNaN(value))) {
+ assertEquals(bytes2float(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ try {
+ buf.getFloat(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.getFloat(buf.limit() - nbytes + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutFloat() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.putFloat((float) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ float value = 0;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (float) i;
+ buf.mark();
+ buf.putFloat(value);
+ assertEquals((i + 1) * nbytes, buf.position());
+ buf.reset();
+ buf.get(bytes);
+ assertTrue(Arrays.equals(float2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putFloat(value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutFloatint() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.putFloat(0, (float) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ float value = 0;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (float) i;
+ buf.position(i);
+ buf.putFloat(i, value);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertTrue(Arrays.equals(float2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putFloat(-1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.putFloat(buf.limit() - nbytes + 1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetInt() {
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ int value;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ assertEquals(i * nbytes, buf.position());
+ buf.mark();
+ buf.get(bytes);
+ buf.reset();
+ value = buf.getInt();
+ assertEquals(bytes2int(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getInt();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetIntint() {
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ int value;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ buf.position(i);
+ value = buf.getInt(i);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertEquals(bytes2int(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getInt(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.getInt(buf.limit() - nbytes + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ try {
+ ByteBuffer.allocateDirect(16).getInt(Integer.MAX_VALUE);
+ } catch (IndexOutOfBoundsException e) {
+ //expected
+ }
+ }
+
+ public void testPutInt() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.putInt((int) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ int value = 0;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (int) i;
+ buf.mark();
+ buf.putInt(value);
+ assertEquals((i + 1) * nbytes, buf.position());
+ buf.reset();
+ buf.get(bytes);
+ assertTrue(Arrays.equals(int2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putInt(value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutIntint() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.putInt(0, (int) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ int value = 0;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (int) i;
+ buf.position(i);
+ buf.putInt(i, value);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertTrue(Arrays.equals(int2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putInt(-1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.putInt(buf.limit() - nbytes + 1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetLong() {
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ long value;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ assertEquals(i * nbytes, buf.position());
+ buf.mark();
+ buf.get(bytes);
+ buf.reset();
+ value = buf.getLong();
+ assertEquals(bytes2long(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getLong();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetLongint() {
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ long value;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ buf.position(i);
+ value = buf.getLong(i);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertEquals(bytes2long(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getLong(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.getLong(buf.limit() - nbytes + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutLong() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.putLong((long) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ long value = 0;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (long) i;
+ buf.mark();
+ buf.putLong(value);
+ assertEquals((i + 1) * nbytes, buf.position());
+ buf.reset();
+ buf.get(bytes);
+ assertTrue(Arrays.equals(long2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putLong(value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutLongint() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.putLong(0, (long) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ long value = 0;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (long) i;
+ buf.position(i);
+ buf.putLong(i, value);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertTrue(Arrays.equals(long2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putLong(-1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.putLong(buf.limit() - nbytes + 1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetShort() {
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ short value;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ assertEquals(i * nbytes, buf.position());
+ buf.mark();
+ buf.get(bytes);
+ buf.reset();
+ value = buf.getShort();
+ assertEquals(bytes2short(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getShort();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetShortint() {
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ short value;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ buf.position(i);
+ value = buf.getShort(i);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertEquals(bytes2short(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getShort(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.getShort(buf.limit() - nbytes + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutShort() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.putShort((short) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ short value = 0;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (short) i;
+ buf.mark();
+ buf.putShort(value);
+ assertEquals((i + 1) * nbytes, buf.position());
+ buf.reset();
+ buf.get(bytes);
+ assertTrue(Arrays.equals(short2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putShort(value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutShortint() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.putShort(0, (short) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ short value = 0;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (short) i;
+ buf.position(i);
+ buf.putShort(i, value);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertTrue(Arrays.equals(short2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putShort(-1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.putShort(buf.limit() - nbytes + 1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ /**
+ * @tests java.nio.ByteBuffer.wrap(byte[],int,int)
+ */
+ public void testWrappedByteBuffer_null_array() {
+ // Regression for HARMONY-264
+ byte array[] = null;
+ try {
+ ByteBuffer.wrap(array, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+ try {
+ ByteBuffer.wrap(new byte[10], Integer.MAX_VALUE, 2);
+ fail("Should throw IndexOutOfBoundsException"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ }
+ }
+
+ /*
+ * test for method static ByteBuffer wrap(byte[] array)
+ * test covers following usecases:
+ * 1. case for check ByteBuffer buf2 properties
+ * 2. case for check equal between buf2 and byte array[]
+ * 3. case for check a buf2 dependens to array[]
+ */
+
+ public void test_Wrap$B() {
+ byte array[] = new byte[BUFFER_LENGTH];
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ ByteBuffer buf2 = ByteBuffer.wrap(array);
+
+ // case: ByteBuffer buf2 properties is satisfy the conditions specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.limit(), array.length);
+ assertEquals(buf2.position(), 0);
+
+ // case: ByteBuffer buf2 is equal to byte array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: ByteBuffer buf2 is depended to byte array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+ }
+
+ /*
+ * test for method static ByteBuffer wrap(byte[] array, int offset, int length)
+ * test covers following usecases:
+ * 1. case for check ByteBuffer buf2 properties
+ * 2. case for check equal between buf2 and byte array[]
+ * 3. case for check a buf2 dependens to array[]
+ * 4. case expected IndexOutOfBoundsException
+ */
+
+ public void test_Wrap$BII() {
+ byte array[] = new byte[BUFFER_LENGTH];
+ int offset = 5;
+ int length = BUFFER_LENGTH - offset;
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ ByteBuffer buf2 = ByteBuffer.wrap(array, offset, length);
+
+ // case: ByteBuffer buf2 properties is satisfy the conditions specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.position(), offset);
+ assertEquals(buf2.limit(), offset + length);
+ assertEquals(buf2.arrayOffset(), 0);
+
+ // case: ByteBuffer buf2 is equal to byte array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: ByteBuffer buf2 is depended to byte array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: expected IndexOutOfBoundsException
+ try {
+ offset = 7;
+ buf2 = ByteBuffer.wrap(array, offset, length);
+ fail("wrap method does not throws expected exception");
+ } catch (IndexOutOfBoundsException e) {
+ //expected
+ }
+ }
+
+ private void loadTestData1(byte array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (byte) i;
+ }
+ }
+
+ private void loadTestData2(byte array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (byte) (length - i);
+ }
+ }
+
+ private void loadTestData1(ByteBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (byte) i);
+ }
+ }
+
+ private void loadTestData2(ByteBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (byte) (buf.capacity() - i));
+ }
+ }
+
+ private void assertContentEquals(ByteBuffer buf, byte array[],
+ int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i]);
+ }
+ }
+
+ private void assertContentEquals(ByteBuffer buf, ByteBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i));
+ }
+ }
+
+ private void assertContentLikeTestData1(ByteBuffer buf,
+ int startIndex, byte startValue, int length) {
+ byte value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value);
+ value = (byte) (value + 1);
+ }
+ }
+
+ private int bytes2int(byte bytes[], ByteOrder order) {
+ int nbytes = 4, bigHead, step;
+ if (order == ByteOrder.BIG_ENDIAN) {
+ bigHead = 0;
+ step = 1;
+ } else {
+ bigHead = nbytes - 1;
+ step = -1;
+ }
+ int result = 0;
+ int p = bigHead;
+ for (int i = 0; i < nbytes; i++) {
+ result = result << 8;
+ result = result | (bytes[p] & 0xff);
+ p += step;
+ }
+ return result;
+ }
+
+ private long bytes2long(byte bytes[], ByteOrder order) {
+ int nbytes = 8, bigHead, step;
+ if (order == ByteOrder.BIG_ENDIAN) {
+ bigHead = 0;
+ step = 1;
+ } else {
+ bigHead = nbytes - 1;
+ step = -1;
+ }
+ long result = 0;
+ int p = bigHead;
+ for (int i = 0; i < nbytes; i++) {
+ result = result << 8;
+ result = result | (bytes[p] & 0xff);
+ p += step;
+ }
+ return result;
+ }
+
+ private short bytes2short(byte bytes[], ByteOrder order) {
+ int nbytes = 2, bigHead, step;
+ if (order == ByteOrder.BIG_ENDIAN) {
+ bigHead = 0;
+ step = 1;
+ } else {
+ bigHead = nbytes - 1;
+ step = -1;
+ }
+ short result = 0;
+ int p = bigHead;
+ for (int i = 0; i < nbytes; i++) {
+ result = (short) (result << 8);
+ result = (short) (result | (bytes[p] & 0xff));
+ p += step;
+ }
+ return result;
+ }
+
+ private char bytes2char(byte bytes[], ByteOrder order) {
+ return (char) bytes2short(bytes, order);
+ }
+
+ private float bytes2float(byte bytes[], ByteOrder order) {
+ return Float.intBitsToFloat(bytes2int(bytes, order));
+ }
+
+ private double bytes2double(byte bytes[], ByteOrder order) {
+ return Double.longBitsToDouble(bytes2long(bytes, order));
+ }
+
+ private byte[] int2bytes(int value, ByteOrder order) {
+ int nbytes = 4, smallHead, step;
+ if (order == ByteOrder.BIG_ENDIAN) {
+ smallHead = nbytes - 1;
+ step = -1;
+ } else {
+ smallHead = 0;
+ step = 1;
+ }
+ byte bytes[] = new byte[nbytes];
+ int p = smallHead;
+ for (int i = 0; i < nbytes; i++) {
+ bytes[p] = (byte) (value & 0xff);
+ value = value >> 8;
+ p += step;
+ }
+ return bytes;
+ }
+
+ private byte[] long2bytes(long value, ByteOrder order) {
+ int nbytes = 8, smallHead, step;
+ if (order == ByteOrder.BIG_ENDIAN) {
+ smallHead = nbytes - 1;
+ step = -1;
+ } else {
+ smallHead = 0;
+ step = 1;
+ }
+ byte bytes[] = new byte[nbytes];
+ int p = smallHead;
+ for (int i = 0; i < nbytes; i++) {
+ bytes[p] = (byte) (value & 0xff);
+ value = value >> 8;
+ p += step;
+ }
+ return bytes;
+ }
+
+ private byte[] short2bytes(short value, ByteOrder order) {
+ int nbytes = 2, smallHead, step;
+ if (order == ByteOrder.BIG_ENDIAN) {
+ smallHead = nbytes - 1;
+ step = -1;
+ } else {
+ smallHead = 0;
+ step = 1;
+ }
+ byte bytes[] = new byte[nbytes];
+ int p = smallHead;
+ for (int i = 0; i < nbytes; i++) {
+ bytes[p] = (byte) (value & 0xff);
+ value = (short) (value >> 8);
+ p += step;
+ }
+ return bytes;
+ }
+
+ private byte[] char2bytes(char value, ByteOrder order) {
+ return short2bytes((short) value, order);
+ }
+
+ private byte[] float2bytes(float value, ByteOrder order) {
+ return int2bytes(Float.floatToRawIntBits(value), order);
+ }
+
+ private byte[] double2bytes(double value, ByteOrder order) {
+ return long2bytes(Double.doubleToRawLongBits(value), order);
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteOrderTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteOrderTest.java
new file mode 100644
index 0000000..3a0907c
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteOrderTest.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteOrder;
+
+import junit.framework.TestCase;
+
+/**
+ * Test java.nio.ByteOrder
+ *
+ */
+public class ByteOrderTest extends TestCase {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(ByteOrderTest.class);
+ }
+
+ public void testToString() {
+ assertEquals(ByteOrder.BIG_ENDIAN.toString(), "BIG_ENDIAN");
+ assertEquals(ByteOrder.LITTLE_ENDIAN.toString(), "LITTLE_ENDIAN");
+ }
+
+ public void testNativeOrder() {
+ ByteOrder o = ByteOrder.nativeOrder();
+ assertTrue(o == ByteOrder.BIG_ENDIAN || o == ByteOrder.LITTLE_ENDIAN);
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java
new file mode 100644
index 0000000..0a4ded9
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java
@@ -0,0 +1,1253 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.io.IOException;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.InvalidMarkException;
+import java.nio.ReadOnlyBufferException;
+
+/**
+ * Tests java.nio.CharBuffer
+ *
+ */
+public class CharBufferTest extends AbstractBufferTest {
+ protected static final int SMALL_TEST_LENGTH = 5;
+
+ protected static final int BUFFER_LENGTH = 20;
+
+ protected CharBuffer buf;
+
+ private static char[] chars = "123456789a".toCharArray();
+
+ protected void setUp() throws Exception{
+ char[] charscopy = new char[chars.length];
+ System.arraycopy(chars, 0, charscopy, 0, chars.length);
+ buf = CharBuffer.wrap(charscopy);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception{
+ buf = null;
+ baseBuf = null;
+ }
+
+ /*
+ * test for method static CharBuffer allocate(int capacity) test covers
+ * following usecases: 1. case for check CharBuffer testBuf properties 2.
+ * case expected IllegalArgumentException
+ */
+
+ public void test_AllocateI() {
+ // case: CharBuffer testBuf properties is satisfy the conditions
+ // specification
+ CharBuffer testBuf = CharBuffer.allocate(20);
+ assertEquals(testBuf.position(), 0);
+ assertEquals(testBuf.limit(), testBuf.capacity());
+ assertEquals(testBuf.arrayOffset(), 0);
+
+ // case: expected IllegalArgumentException
+ try {
+ testBuf = CharBuffer.allocate(-20);
+ fail("allocate method does not throws expected exception");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ }
+
+ public void testArray() {
+ char array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testArrayOffset() {
+ char array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ CharBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertEquals(buf.capacity(), readonly.capacity());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ int originalPosition = (buf.position() + buf.limit()) / 2;
+ buf.position(originalPosition);
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertEquals(buf.capacity(), readonly.capacity());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), originalPosition);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), originalPosition);
+ }
+
+ public void testCompact() {
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ CharBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (char) 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (char) 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(5);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (char) 1, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ // compare to self
+ assertEquals(0, buf.compareTo(buf));
+
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+ buf.clear();
+ CharBuffer other = CharBuffer.allocate(buf.capacity());
+ other.put(buf);
+ other.clear();
+ buf.clear();
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ assertTrue(buf.compareTo(other) == 0);
+ assertTrue(other.compareTo(buf) == 0);
+ other.limit(SMALL_TEST_LENGTH);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ }
+
+ public void testDuplicate() {
+ // mark the position 0
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ CharBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertEquals(buf.capacity(), duplicate.capacity());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to
+ // buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // mark another position
+ buf.clear();
+ int originalPosition = (buf.position() + buf.limit()) / 2;
+ buf.position(originalPosition);
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertEquals(buf.capacity(), duplicate.capacity());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to
+ // buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), originalPosition);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), originalPosition);
+
+ // duplicate share the same content with buf
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ CharBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ CharBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > 5);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for char get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer get(char[])
+ */
+ public void testGetcharArray() {
+ char array[] = new char[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ CharBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i));
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer get(char[], int, int)
+ */
+ public void testGetcharArrayintint() {
+ buf.clear();
+ char array[] = new char[buf.capacity()];
+
+ try {
+ buf.get(new char[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get((char[])null, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ CharBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for char get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ loadTestData1(buf);
+ CharBuffer readonly = buf.asReadOnlyBuffer();
+ CharBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+ duplicate.position(buf.capacity() / 2);
+ assertTrue(buf.hashCode() != duplicate.hashCode());
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer put(char)
+ */
+ public void testPutchar() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ CharBuffer ret = buf.put((char) i);
+ assertEquals(buf.get(i), (char) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put((char) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer put(char[])
+ */
+ public void testPutcharArray() {
+ char array[] = new char[1];
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (char) i;
+ CharBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (char) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.put((char[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer put(char[], int, int)
+ */
+ public void testPutcharArrayintint() {
+ buf.clear();
+ char array[] = new char[buf.capacity()];
+ try {
+ buf.put((char[]) null, 0, 1);
+ fail("Should throw NullPointerException"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(new char[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((char[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ CharBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer put(java.nio.CharBuffer)
+ */
+ public void testPutCharBuffer() {
+ CharBuffer other = CharBuffer.allocate(buf.capacity());
+
+ try {
+ buf.put((CharBuffer) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(CharBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.flip();
+ buf.put((CharBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ CharBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer put(int, char)
+ */
+ public void testPutintchar() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ CharBuffer ret = buf.put(i, (char) i);
+ assertEquals(buf.get(i), (char) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, (char) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), (char) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ CharBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, (char) 0, slice.capacity());
+ buf.put(2, (char) 500);
+ assertEquals(slice.get(1), 500);
+ }
+ }
+
+ public void testToString() {
+ String expected = "";
+ for (int i = buf.position(); i < buf.limit(); i++) {
+ expected += buf.get(i);
+ }
+ String str = buf.toString();
+ assertEquals(expected, str);
+ }
+
+ public void testCharAt() {
+ for (int i = 0; i < buf.remaining(); i++) {
+ assertEquals(buf.get(buf.position() + i), buf.charAt(i));
+ }
+ try {
+ buf.charAt(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.charAt(buf.remaining());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testLength() {
+ assertEquals(buf.length(), buf.remaining());
+ }
+
+ public void testSubSequence() {
+ try {
+ buf.subSequence(-1, buf.length());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.subSequence(buf.length() + 1, buf.length() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.subSequence(buf.length(), buf.length()).length(), 0);
+ try {
+ buf.subSequence(1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.subSequence(1, buf.length() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ assertEquals(buf.subSequence(0, buf.length()).toString(), buf
+ .toString());
+
+ if (buf.length() >= 2) {
+ assertEquals(buf.subSequence(1, buf.length() - 1).toString(), buf
+ .toString().substring(1, buf.length() - 1));
+ }
+ }
+
+ public void testPutString() {
+ String str = " ";
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ str = "" + (char) i;
+ CharBuffer ret = buf.put(str);
+ assertEquals(buf.get(i), (char) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(str);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.put((String) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutStringintint() {
+ buf.clear();
+ String str = String.valueOf(new char[buf.capacity()]);
+
+ // Throw a BufferOverflowException and no character is transfered to
+ // CharBuffer
+ try {
+ buf.put(String.valueOf(new char[buf.capacity() + 1]), 0, buf
+ .capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.put((String) null, 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ assertEquals(0, buf.position());
+
+ buf.clear();
+ try {
+ buf.put(str, -1, str.length());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(str, str.length() + 1, str.length() + 2);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((String) null, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ buf.put(str, str.length(), str.length());
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(str, 2, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(str, 2, str.length() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ char array[] = new char[buf.capacity()];
+ loadTestData2(array, 0, array.length);
+ str = String.valueOf(array);
+
+ CharBuffer ret = buf.put(str, 0, str.length());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, str.toCharArray(), 0, str.length());
+ assertSame(ret, buf);
+ }
+
+ void loadTestData1(char array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (char) i;
+ }
+ }
+
+ void loadTestData2(char array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (char) (length - i);
+ }
+ }
+
+ void loadTestData1(CharBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (char) i);
+ }
+ }
+
+ void loadTestData2(CharBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (char) (buf.capacity() - i));
+ }
+ }
+
+ private void assertContentEquals(CharBuffer buf, char array[], int offset,
+ int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i]);
+ }
+ }
+
+ private void assertContentEquals(CharBuffer buf, CharBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i));
+ }
+ }
+
+ private void assertContentLikeTestData1(CharBuffer buf, int startIndex,
+ char startValue, int length) {
+ char value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value);
+ value = (char) (value + 1);
+ }
+ }
+
+ public void testAppendSelf() throws Exception {
+ CharBuffer cb = CharBuffer.allocate(10);
+ CharBuffer cb2 = cb.duplicate();
+ cb.append(cb);
+ assertEquals(10, cb.position());
+ cb.clear();
+ assertEquals(cb2, cb);
+
+ cb.put("abc");
+ cb2 = cb.duplicate();
+ cb.append(cb);
+ assertEquals(10, cb.position());
+ cb.clear();
+ cb2.clear();
+ assertEquals(cb2, cb);
+
+ cb.put("edfg");
+ cb.clear();
+ cb2 = cb.duplicate();
+ cb.append(cb);
+ assertEquals(10, cb.position());
+ cb.clear();
+ cb2.clear();
+ assertEquals(cb, cb2);
+ }
+
+ public void testAppendOverFlow() throws IOException {
+ CharBuffer cb = CharBuffer.allocate(1);
+ CharSequence cs = "String";
+ cb.put('A');
+ try {
+ cb.append('C');
+ fail("should throw BufferOverflowException.");
+ } catch (BufferOverflowException ex) {
+ // expected;
+ }
+ try {
+ cb.append(cs);
+ fail("should throw BufferOverflowException.");
+ } catch (BufferOverflowException ex) {
+ // expected;
+ }
+ try {
+ cb.append(cs, 1, 2);
+ fail("should throw BufferOverflowException.");
+ } catch (BufferOverflowException ex) {
+ // expected;
+ }
+ }
+
+ public void testReadOnlyMap() throws IOException {
+ CharBuffer cb = CharBuffer.wrap("ABCDE").asReadOnlyBuffer();
+ CharSequence cs = "String";
+ try {
+ cb.append('A');
+ fail("should throw ReadOnlyBufferException.");
+ } catch (ReadOnlyBufferException ex) {
+ // expected;
+ }
+ try {
+ cb.append(cs);
+ fail("should throw ReadOnlyBufferException.");
+ } catch (ReadOnlyBufferException ex) {
+ // expected;
+ }
+ try {
+ cb.append(cs, 1, 2);
+ fail("should throw ReadOnlyBufferException.");
+ } catch (ReadOnlyBufferException ex) {
+ // expected;
+ }
+ cb.append(cs, 1, 1);
+ }
+
+ public void testAppendCNormal() throws IOException {
+ CharBuffer cb = CharBuffer.allocate(2);
+ cb.put('A');
+ assertSame(cb, cb.append('B'));
+ assertEquals('B', cb.get(1));
+ }
+
+ public void testAppendCharSequenceNormal() throws IOException {
+ CharBuffer cb = CharBuffer.allocate(10);
+ cb.put('A');
+ assertSame(cb, cb.append("String"));
+ assertEquals("AString", cb.flip().toString());
+ cb.append(null);
+ assertEquals("null", cb.flip().toString());
+ }
+
+ public void testAppendCharSequenceIINormal() throws IOException {
+ CharBuffer cb = CharBuffer.allocate(10);
+ cb.put('A');
+ assertSame(cb, cb.append("String", 1, 3));
+ assertEquals("Atr", cb.flip().toString());
+
+ cb.append(null, 0, 1);
+ assertEquals("n", cb.flip().toString());
+ }
+
+ public void testAppendCharSequenceII_IllegalArgument() throws IOException {
+ CharBuffer cb = CharBuffer.allocate(10);
+ cb.append("String", 0, 0);
+ cb.append("String", 2, 2);
+ try {
+ cb.append("String", -1, 1);
+ fail("should throw IndexOutOfBoundsException.");
+ } catch (IndexOutOfBoundsException ex) {
+ // expected;
+ }
+ try {
+ cb.append("String", -1, -1);
+ fail("should throw IndexOutOfBoundsException.");
+ } catch (IndexOutOfBoundsException ex) {
+ // expected;
+ }
+ try {
+ cb.append("String", 3, 2);
+ fail("should throw IndexOutOfBoundsException.");
+ } catch (IndexOutOfBoundsException ex) {
+ // expected;
+ }
+ try {
+ cb.append("String", 3, 0);
+ fail("should throw IndexOutOfBoundsException.");
+ } catch (IndexOutOfBoundsException ex) {
+ // expected;
+ }
+ try {
+ cb.append("String", 3, 110);
+ fail("should throw IndexOutOfBoundsException.");
+ } catch (IndexOutOfBoundsException ex) {
+ // expected;
+ }
+ }
+
+ public void testReadCharBuffer() throws IOException {
+ CharBuffer source = CharBuffer.wrap("String");
+ CharBuffer target = CharBuffer.allocate(10);
+ assertEquals(6, source.read(target));
+ assertEquals("String", target.flip().toString());
+ // return -1 when nothing to read
+ assertEquals(-1, source.read(target));
+ // NullPointerException
+ try {
+ assertEquals(-1, source.read(null));
+ fail("should throw NullPointerException.");
+ } catch (NullPointerException ex) {
+ // expected;
+ }
+
+ }
+
+ public void testReadReadOnly() throws IOException {
+ CharBuffer source = CharBuffer.wrap("String");
+ CharBuffer target = CharBuffer.allocate(10).asReadOnlyBuffer();
+ try {
+ source.read(target);
+ fail("should throw ReadOnlyBufferException.");
+ } catch (ReadOnlyBufferException ex) {
+ // expected;
+ }
+ // if target has no remaining, needn't to check the isReadOnly
+ target.flip();
+ assertEquals(0, source.read(target));
+ }
+
+ public void testReadOverflow() throws IOException {
+ CharBuffer source = CharBuffer.wrap("String");
+ CharBuffer target = CharBuffer.allocate(1);
+ assertEquals(1, source.read(target));
+ assertEquals("S", target.flip().toString());
+ assertEquals(1, source.position());
+ }
+
+ public void testReadSelf() throws Exception {
+ CharBuffer source = CharBuffer.wrap("abuffer");
+ try {
+ source.read(source);
+ fail("should throw IAE.");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testHasArray() {
+ assertTrue(buf.hasArray());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.nativeOrder(), buf.order());
+ }
+
+ public void testIsReadOnly() {
+ assertFalse(buf.isReadOnly());
+ }
+
+ /*
+ * test for method static CharBuffer wrap(char[] array) test covers
+ * following usecases: 1. case for check CharBuffer buf2 properties 2. case
+ * for check equal between buf2 and char array[] 3. case for check a buf2
+ * dependens to array[]
+ */
+
+ public void test_Wrap$C() {
+ char array[] = new char[BUFFER_LENGTH];
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ CharBuffer buf2 = CharBuffer.wrap(array);
+
+ // case: CharBuffer buf2 properties is satisfy the conditions
+ // specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.limit(), array.length);
+ assertEquals(buf2.position(), 0);
+
+ // case: CharBuffer buf2 is equal to char array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: CharBuffer buf2 is depended to char array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+ }
+
+ /*
+ * test for method static CharBuffer wrap(char[] array, int offset, int length)
+ * test covers following usecases:
+ * 1. case for check CharBuffer buf2 properties
+ * 2. case for check equal between buf2 and char array[]
+ * 3. case for check a buf2 dependens to array[]
+ * 4. case expected IndexOutOfBoundsException
+ */
+
+ public void test_Wrap$CII() {
+ char array[] = new char[BUFFER_LENGTH];
+ int offset = 5;
+ int length = BUFFER_LENGTH - offset;
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ CharBuffer buf2 = CharBuffer.wrap(array, offset, length);
+
+ // case: CharBuffer buf2 properties is satisfy the conditions specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.position(), offset);
+ assertEquals(buf2.limit(), offset + length);
+ assertEquals(buf2.arrayOffset(), 0);
+
+ // case: CharBuffer buf2 is equal to char array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: CharBuffer buf2 is depended to char array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: expected IndexOutOfBoundsException
+ try {
+ offset = 7;
+ buf2 = CharBuffer.wrap(array, offset, length);
+ fail("wrap method does not throws expected exception");
+ } catch (IndexOutOfBoundsException e) {
+ //expected
+ }
+ }
+
+ /*
+ * test for method static CharBuffer wrap(CharSequence csq)
+ * test covers following usecases:
+ * 1. case for check StringBuffer
+ * 2. case for check StringBuilder
+ * 3. case for check String
+ * 4. case for check CharBuffer
+ */
+
+ public void test_WrapLjava_lang_CharSequence() {
+ // added this if clause to prevent Tests failing under special conditions.
+ // If the test extending this test is made for a read only buffer it fails
+ // when it trys to call loadTestData1.
+ if(buf.isReadOnly()) {
+ char[] charscopy = new char[chars.length];
+ System.arraycopy(chars, 0, charscopy, 0, chars.length);
+ buf = CharBuffer.wrap(charscopy);
+ }
+ loadTestData1(buf);
+ buf.rewind();
+ StringBuffer testStrBuffer = new StringBuffer(buf);
+ StringBuilder testStrBuilder = new StringBuilder(buf);
+ String testStr = buf.toString();
+
+ //case: StringBuffer
+ CharBuffer bufStrBf = CharBuffer.wrap(testStrBuffer);
+ assertTrue(bufStrBf.isReadOnly());
+ assertEquals(bufStrBf.capacity(), testStrBuffer.length());
+ assertEquals(bufStrBf.limit(), testStrBuffer.length());
+ assertEquals(bufStrBf.position(), 0);
+ assertContentEquals(bufStrBf, buf);
+
+ // case: StringBuilder
+ CharBuffer bufStrBl = CharBuffer.wrap(testStrBuilder);
+ assertTrue(bufStrBl.isReadOnly());
+ assertEquals(bufStrBl.capacity(), testStrBuilder.length());
+ assertEquals(bufStrBl.limit(), testStrBuilder.length());
+ assertEquals(bufStrBl.position(), 0);
+ assertContentEquals(bufStrBl, buf);
+
+ // case: String
+ CharBuffer bufStr = CharBuffer.wrap(testStr);
+ assertTrue(bufStr.isReadOnly());
+ assertEquals(bufStr.capacity(), testStr.length());
+ assertEquals(bufStr.limit(), testStr.length());
+ assertEquals(bufStr.position(), 0);
+ assertContentEquals(bufStr, buf);
+
+ // case: CharBuffer
+ CharBuffer bufChBf = CharBuffer.wrap(buf);
+ assertTrue(bufChBf.isReadOnly());
+ assertEquals(bufChBf.capacity(), buf.length());
+ assertEquals(bufChBf.limit(), buf.length());
+ assertEquals(bufChBf.position(), 0);
+ assertContentEquals(bufChBf, buf);
+ }
+
+ /*
+ * test for method public static CharBuffer wrap(CharSequence csq, int start, int end)
+ * test covers following usecases:
+ * 1. case for check StringBuffer
+ * 2. case for check StringBuilder
+ * 3. case for check String
+ * 4. case for check CharBuffer
+ */
+
+ public void test_WrapLjava_lang_CharSequenceII() {
+ int start = buf.position();
+ int end = buf.limit();
+ CharBuffer buf2 = CharBuffer.wrap(buf.toString() + buf.toString()); //buf.toString() + buf.toString() //"123456789a123456789a"
+
+ //case: StringBuffer
+ StringBuffer testStrBuffer = new StringBuffer(buf2);
+ CharBuffer bufStrBf = CharBuffer.wrap(testStrBuffer, start, end);
+ assertTrue(bufStrBf.isReadOnly());
+ assertEquals(bufStrBf.capacity(), testStrBuffer.length());
+ assertEquals(bufStrBf.limit(), end);
+ assertEquals(bufStrBf.position(), start);
+ assertEquals(bufStrBf.toString(), buf.toString());
+
+ // case: StringBuilder
+ StringBuilder testStrBuilder = new StringBuilder(buf2);
+ CharBuffer bufStrBl = CharBuffer.wrap(testStrBuilder, start, end);
+ assertTrue(bufStrBl.isReadOnly());
+ assertEquals(bufStrBl.capacity(), testStrBuilder.length());
+ assertEquals(bufStrBl.limit(), end);
+ assertEquals(bufStrBl.position(), start);
+ assertEquals(bufStrBl.toString(), buf.toString());
+
+ // case: String
+ String testStr = new String(buf2.toString());
+ CharBuffer bufStr = CharBuffer.wrap(testStr, start, end);
+ assertTrue(bufStr.isReadOnly());
+ assertEquals(bufStr.capacity(), testStr.length());
+ assertEquals(bufStr.limit(), end);
+ assertEquals(bufStr.position(), start);
+ assertEquals(bufStr.toString(), buf.toString());
+
+ // case: CharBuffer
+ CharBuffer bufChBf = CharBuffer.wrap(buf2, start, end);
+ assertTrue(bufChBf.isReadOnly());
+ assertEquals(bufChBf.capacity(), buf2.length());
+ assertEquals(bufChBf.limit(), end);
+ assertEquals(bufChBf.position(), start);
+ assertEquals(bufChBf.toString(), buf.toString());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectByteBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectByteBufferTest.java
new file mode 100644
index 0000000..776f505
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectByteBufferTest.java
@@ -0,0 +1,58 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+
+public class DirectByteBufferTest extends ByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ /**
+ * @tests java.nio.ByteBuffer#allocateDirect(int)
+ *
+ */
+ public void testAllocatedByteBuffer_IllegalArg() {
+ try {
+ ByteBuffer.allocateDirect(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testIsReadOnly() {
+ assertFalse(buf.isReadOnly());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectCharBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectCharBufferTest.java
new file mode 100644
index 0000000..83cfc9d
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectCharBufferTest.java
@@ -0,0 +1,61 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectCharBufferTest extends CharBufferTest {
+
+ public void setUp(){
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*2).asCharBuffer();
+ super.loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ public void tearDown(){
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectDoubleBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectDoubleBufferTest.java
new file mode 100644
index 0000000..561c0fa
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectDoubleBufferTest.java
@@ -0,0 +1,60 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectDoubleBufferTest extends DoubleBufferTest {
+ public void setUp(){
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*8).asDoubleBuffer();
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ public void tearDown(){
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectFloatBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectFloatBufferTest.java
new file mode 100644
index 0000000..8739c1b
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectFloatBufferTest.java
@@ -0,0 +1,61 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectFloatBufferTest extends FloatBufferTest {
+ public void setUp(){
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*4).asFloatBuffer();
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ public void tearDown(){
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectIntBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectIntBufferTest.java
new file mode 100644
index 0000000..393366e
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectIntBufferTest.java
@@ -0,0 +1,61 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectIntBufferTest extends IntBufferTest {
+ public void setUp(){
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*4).asIntBuffer();
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ public void tearDown(){
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectLongBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectLongBufferTest.java
new file mode 100644
index 0000000..245cd25
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectLongBufferTest.java
@@ -0,0 +1,62 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+
+public class DirectLongBufferTest extends LongBufferTest {
+ public void setUp(){
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*8).asLongBuffer();
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ public void tearDown(){
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectShortBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectShortBufferTest.java
new file mode 100644
index 0000000..9ae290a
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectShortBufferTest.java
@@ -0,0 +1,61 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectShortBufferTest extends ShortBufferTest {
+ public void setUp(){
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*2).asShortBuffer();
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ public void tearDown(){
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java
new file mode 100644
index 0000000..86f86ab
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java
@@ -0,0 +1,741 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.DoubleBuffer;
+import java.nio.InvalidMarkException;
+
+/**
+ * Tests java.nio.DoubleBuffer
+ */
+public class DoubleBufferTest extends AbstractBufferTest {
+
+ protected static final int SMALL_TEST_LENGTH = 5;
+
+ protected static final int BUFFER_LENGTH = 20;
+
+ protected DoubleBuffer buf;
+
+ protected void setUp() throws Exception {
+ buf = DoubleBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ buf = null;
+ baseBuf = null;
+ }
+
+ /*
+ * test for method static DoubleBuffer allocate(int capacity) test covers
+ * following usecases: 1. case for check DoubleBuffer testBuf properties 2.
+ * case expected IllegalArgumentException
+ */
+
+ public void test_AllocateI() {
+ // case: DoubleBuffer testBuf properties is satisfy the conditions
+ // specification
+ DoubleBuffer testBuf = DoubleBuffer.allocate(20);
+ assertEquals(testBuf.position(), 0);
+ assertEquals(testBuf.limit(), testBuf.capacity());
+ assertEquals(testBuf.arrayOffset(), 0);
+
+ // case: expected IllegalArgumentException
+ try {
+ testBuf = DoubleBuffer.allocate(-20);
+ fail("allocate method does not throws expected exception");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test with bit sequences that represent the IEEE754 doubles Positive
+ * infinity, negative infinity, and NaN.
+ */
+ public void testNaNs() {
+ long[] nans = new long[] { 0x7ff0000000000000L, 0xfff0000000000000L,
+ 0x7ff8000000000000L };
+ for (int i = 0; i < nans.length; i++) {
+ long longBitsIn = nans[i];
+ double dbl = Double.longBitsToDouble(longBitsIn);
+ long longBitsOut = Double.doubleToRawLongBits(dbl);
+ // Sanity check
+ assertTrue(longBitsIn == longBitsOut);
+
+ // Store the double and retrieve it
+ ByteBuffer buffer = ByteBuffer.allocate(8);
+ buffer.putDouble(dbl);
+ double bufDoubleOut = buffer.getDouble(0);
+
+ // Check the bits sequence was not normalized
+ long bufLongOut = Double.doubleToRawLongBits(bufDoubleOut);
+ assertTrue(longBitsIn == bufLongOut);
+ }
+ }
+
+ public void testArray() {
+ double array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testArrayOffset() {
+ double array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ DoubleBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+ }
+
+ public void testCompact() {
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ DoubleBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0.0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0.0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(5);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 1.0, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ DoubleBuffer other = DoubleBuffer.allocate(buf.capacity());
+ loadTestData1(other);
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ other.limit(5);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ }
+
+ public void testDuplicate() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ DoubleBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // duplicate share the same content with buf
+ // FIXME
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ DoubleBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ DoubleBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > 5);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for double get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i), 0.01);
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer get(double[])
+ */
+ public void testGetdoubleArray() {
+ double array[] = new double[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ DoubleBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i), 0.01);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer get(double[], int, int)
+ */
+ public void testGetdoubleArrayintint() {
+ buf.clear();
+ double array[] = new double[buf.capacity()];
+
+ try {
+ buf.get(new double[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get((double[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ DoubleBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for double get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i), 0.01);
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHasArray() {
+ assertTrue(buf.hasArray());
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ DoubleBuffer readonly = buf.asReadOnlyBuffer();
+ DoubleBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+
+ assertTrue(buf.capacity() > 5);
+ duplicate.position(buf.capacity() / 2);
+ assertTrue(buf.hashCode() != duplicate.hashCode());
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.nativeOrder(), buf.order());
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer put(double)
+ */
+ public void testPutdouble() {
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ DoubleBuffer ret = buf.put((double) i);
+ assertEquals(buf.get(i), (double) i, 0.0);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer put(double[])
+ */
+ public void testPutdoubleArray() {
+ double array[] = new double[1];
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (double) i;
+ DoubleBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (double) i, 0.0);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer put(double[], int, int)
+ */
+ public void testPutdoubleArrayintint() {
+ buf.clear();
+ double array[] = new double[buf.capacity()];
+
+ try {
+ buf.put(new double[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((double[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ DoubleBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer put(java.nio.DoubleBuffer)
+ */
+ public void testPutDoubleBuffer() {
+ DoubleBuffer other = DoubleBuffer.allocate(buf.capacity());
+
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(DoubleBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ DoubleBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer put(int, double)
+ */
+ public void testPutintdouble() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ DoubleBuffer ret = buf.put(i, (double) i);
+ assertEquals(buf.get(i), (double) i, 0.0);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ DoubleBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ // FIXME:
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, 0, slice.capacity());
+ buf.put(2, 500);
+ assertEquals(slice.get(1), 500, 0.0);
+ }
+ }
+
+ public void testToString() {
+ String str = buf.toString();
+ assertTrue(str.indexOf("Double") >= 0 || str.indexOf("double") >= 0);
+ assertTrue(str.indexOf("" + buf.position()) >= 0);
+ assertTrue(str.indexOf("" + buf.limit()) >= 0);
+ assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+ }
+
+ /*
+ * test for method static DoubleBuffer wrap(double[] array) test covers
+ * following usecases: 1. case for check DoubleBuffer buf2 properties 2.
+ * case for check equal between buf2 and double array[] 3. case for check a
+ * buf2 dependens to array[]
+ */
+
+ public void test_Wrap$D() {
+ double array[] = new double[BUFFER_LENGTH];
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ DoubleBuffer buf2 = DoubleBuffer.wrap(array);
+
+ // case: DoubleBuffer buf2 properties is satisfy the conditions
+ // specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.limit(), array.length);
+ assertEquals(buf2.position(), 0);
+
+ // case: DoubleBuffer buf2 is equal to double array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: DoubleBuffer buf2 is depended to double array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+ }
+
+ /*
+ * test for method static DoubleBuffer wrap(double[] array, int offset, int
+ * length) test covers following usecases: 1. case for check DoubleBuffer
+ * buf2 properties 2. case for check equal between buf2 and double array[]
+ * 3. case for check a buf2 dependens to array[] 4. case expected
+ * IndexOutOfBoundsException
+ */
+
+ public void test_Wrap$DII() {
+ double array[] = new double[BUFFER_LENGTH];
+ int offset = 5;
+ int length = BUFFER_LENGTH - offset;
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ DoubleBuffer buf2 = DoubleBuffer.wrap(array, offset, length);
+
+ // case: DoubleBuffer buf2 properties is satisfy the conditions
+ // specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.position(), offset);
+ assertEquals(buf2.limit(), offset + length);
+ assertEquals(buf2.arrayOffset(), 0);
+
+ // case: DoubleBuffer buf2 is equal to double array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: DoubleBuffer buf2 is depended to double array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: expected IndexOutOfBoundsException
+ try {
+ offset = 7;
+ buf2 = DoubleBuffer.wrap(array, offset, length);
+ fail("wrap method does not throws expected exception");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ void loadTestData1(double array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (double) i;
+ }
+ }
+
+ void loadTestData2(double array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (double) length - i;
+ }
+ }
+
+ void loadTestData1(DoubleBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (double) i);
+ }
+ }
+
+ void loadTestData2(DoubleBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (double) buf.capacity() - i);
+ }
+ }
+
+ private void assertContentEquals(DoubleBuffer buf, double array[],
+ int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i], 0.01);
+ }
+ }
+
+ private void assertContentEquals(DoubleBuffer buf, DoubleBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i), 0.01);
+ }
+ }
+
+ private void assertContentLikeTestData1(DoubleBuffer buf, int startIndex,
+ double startValue, int length) {
+ double value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value, 0.01);
+ value = value + 1.0;
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateDirectByteBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateDirectByteBufferTest.java
new file mode 100644
index 0000000..656241a
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateDirectByteBufferTest.java
@@ -0,0 +1,31 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class DuplicateDirectByteBufferTest extends DirectByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.duplicate();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateHeapByteBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateHeapByteBufferTest.java
new file mode 100644
index 0000000..9f44d7a
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateHeapByteBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class DuplicateHeapByteBufferTest extends HeapByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.duplicate();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateWrappedByteBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateWrappedByteBufferTest.java
new file mode 100644
index 0000000..2796b88
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateWrappedByteBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class DuplicateWrappedByteBufferTest extends WrappedByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.duplicate();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java
new file mode 100644
index 0000000..64c831b
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java
@@ -0,0 +1,749 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.InvalidMarkException;
+
+/**
+ * Tests java.nio.FloatBuffer
+ *
+ */
+public class FloatBufferTest extends AbstractBufferTest {
+
+ protected static final int SMALL_TEST_LENGTH = 5;
+
+ protected static final int BUFFER_LENGTH = 20;
+
+ protected FloatBuffer buf;
+
+ protected void setUp() throws Exception {
+ buf = FloatBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ buf = null;
+ baseBuf = null;
+ }
+
+ /*
+ * test for method static FloatBuffer allocate(int capacity) test covers
+ * following usecases: 1. case for check FloatBuffer testBuf properties 2.
+ * case expected IllegalArgumentException
+ */
+
+ public void test_AllocateI() {
+ // case: FloatBuffer testBuf properties is satisfy the conditions
+ // specification
+ FloatBuffer testBuf = FloatBuffer.allocate(20);
+ assertEquals(testBuf.position(), 0);
+ assertEquals(testBuf.limit(), testBuf.capacity());
+ assertEquals(testBuf.arrayOffset(), 0);
+
+ // case: expected IllegalArgumentException
+ try {
+ testBuf = FloatBuffer.allocate(-20);
+ fail("allocate method does not throws expected exception");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testArray() {
+ float array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testArrayOffset() {
+ float array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ FloatBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+ }
+
+ public void testCompact() {
+
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ FloatBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0.0f, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0.0f, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(5);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 1.0f, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ try {
+ buf.compareTo(null);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // compare to self
+ assertEquals(0, buf.compareTo(buf));
+
+ // normal cases
+ assertTrue(buf.capacity() > 5);
+ buf.clear();
+ FloatBuffer other = FloatBuffer.allocate(buf.capacity());
+ loadTestData1(other);
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ other.limit(5);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ }
+
+ public void testDuplicate() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ FloatBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // duplicate share the same content with buf
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ FloatBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ FloatBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > 5);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for float get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i), 0.01);
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer get(float[])
+ */
+ public void testGetfloatArray() {
+ float array[] = new float[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ FloatBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i), 0.01);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ try {
+ buf.position(buf.limit());
+ buf.get((float[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ buf.get(new float[0]);
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer get(float[], int, int)
+ */
+ public void testGetfloatArrayintint() {
+ buf.clear();
+ float array[] = new float[buf.capacity()];
+
+ try {
+ buf.get(new float[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get((float[])null, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ FloatBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for float get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i), 0.01);
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHasArray() {
+ assertNotNull(buf.array());
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ FloatBuffer readonly = buf.asReadOnlyBuffer();
+ FloatBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+
+ assertTrue(buf.capacity() > 5);
+ duplicate.position(buf.capacity() / 2);
+ assertTrue(buf.hashCode() != duplicate.hashCode());
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testOrder() {
+ buf.order();
+ if (buf.hasArray()) {
+ assertEquals(ByteOrder.nativeOrder(), buf.order());
+ }
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer put(float)
+ */
+ public void testPutfloat() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ FloatBuffer ret = buf.put((float) i);
+ assertEquals(buf.get(i), (float) i, 0.0);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer put(float[])
+ */
+ public void testPutfloatArray() {
+ float array[] = new float[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (float) i;
+ FloatBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (float) i, 0.0);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.position(buf.limit());
+ buf.put((float[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer put(float[], int, int)
+ */
+ public void testPutfloatArrayintint() {
+ buf.clear();
+ float array[] = new float[buf.capacity()];
+ try {
+ buf.put(new float[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((float[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ FloatBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer put(java.nio.FloatBuffer)
+ */
+ public void testPutFloatBuffer() {
+ FloatBuffer other = FloatBuffer.allocate(buf.capacity());
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(FloatBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.flip();
+ buf.put((FloatBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ buf.clear();
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ FloatBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer put(int, float)
+ */
+ public void testPutintfloat() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ FloatBuffer ret = buf.put(i, (float) i);
+ assertEquals(buf.get(i), (float) i, 0.0);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ FloatBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, 0, slice.capacity());
+ buf.put(2, 500);
+ assertEquals(slice.get(1), 500, 0.0);
+ }
+ }
+
+ public void testToString() {
+ String str = buf.toString();
+ assertTrue(str.indexOf("Float") >= 0 || str.indexOf("float") >= 0);
+ assertTrue(str.indexOf("" + buf.position()) >= 0);
+ assertTrue(str.indexOf("" + buf.limit()) >= 0);
+ assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+ }
+
+ /*
+ * test for method static FloatBuffer wrap(float[] array) test covers
+ * following usecases: 1. case for check FloatBuffer buf2 properties 2. case
+ * for check equal between buf2 and float array[] 3. case for check a buf2
+ * dependens to array[]
+ */
+
+ public void test_Wrap$S() {
+ float array[] = new float[BUFFER_LENGTH];
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ FloatBuffer buf2 = FloatBuffer.wrap(array);
+
+ // case: FloatBuffer buf2 properties is satisfy the conditions
+ // specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.limit(), array.length);
+ assertEquals(buf2.position(), 0);
+
+ // case: FloatBuffer buf2 is equal to float array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: FloatBuffer buf2 is depended to float array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+ }
+
+ /*
+ * test for method static FloatBuffer wrap(float[] array, int offset, int
+ * length) test covers following usecases: 1. case for check FloatBuffer
+ * buf2 properties 2. case for check equal between buf2 and float array[] 3.
+ * case for check a buf2 dependens to array[] 4. case expected
+ * IndexOutOfBoundsException
+ */
+
+ public void test_Wrap$SII() {
+ float array[] = new float[BUFFER_LENGTH];
+ int offset = 5;
+ int length = BUFFER_LENGTH - offset;
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ FloatBuffer buf2 = FloatBuffer.wrap(array, offset, length);
+
+ // case: FloatBuffer buf2 properties is satisfy the conditions
+ // specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.position(), offset);
+ assertEquals(buf2.limit(), offset + length);
+ assertEquals(buf2.arrayOffset(), 0);
+
+ // case: FloatBuffer buf2 is equal to float array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: FloatBuffer buf2 is depended to float array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: expected IndexOutOfBoundsException
+ try {
+ offset = 7;
+ buf2 = FloatBuffer.wrap(array, offset, length);
+ fail("wrap method does not throws expected exception");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ void loadTestData1(float array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (float) i;
+ }
+ }
+
+ void loadTestData2(float array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (float) length - i;
+ }
+ }
+
+ void loadTestData1(FloatBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (float) i);
+ }
+ }
+
+ void loadTestData2(FloatBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (float) buf.capacity() - i);
+ }
+ }
+
+ void assertContentEquals(FloatBuffer buf, float array[],
+ int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i], 0.01);
+ }
+ }
+
+ void assertContentEquals(FloatBuffer buf, FloatBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i), 0.01);
+ }
+ }
+
+ void assertContentLikeTestData1(FloatBuffer buf,
+ int startIndex, float startValue, int length) {
+ float value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value, 0.01);
+ value = value + 1.0f;
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapByteBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapByteBufferTest.java
new file mode 100644
index 0000000..2f8e44b
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapByteBufferTest.java
@@ -0,0 +1,60 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+
+
+public class HeapByteBufferTest extends ByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ByteBuffer.allocate(BUFFER_LENGTH);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ /**
+ * @tests java.nio.ByteBuffer#allocate(int)
+ *
+ */
+ public void testAllocatedByteBuffer_IllegalArg() {
+ try {
+ ByteBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testHasArray() {
+ assertTrue(buf.hasArray());
+ }
+
+ public void testIsReadOnly() {
+ assertFalse(buf.isReadOnly());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapCharBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapCharBufferTest.java
new file mode 100644
index 0000000..a0c8d74
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapCharBufferTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.CharBuffer;
+
+
+public class HeapCharBufferTest extends CharBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = CharBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testAllocatedCharBuffer_IllegalArg() {
+ try {
+ CharBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapDoubleBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapDoubleBufferTest.java
new file mode 100644
index 0000000..2985899
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapDoubleBufferTest.java
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+
+public class HeapDoubleBufferTest extends DoubleBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = DoubleBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testAllocatedDoubleBuffer_IllegalArg() {
+ try {
+ DoubleBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapFloatBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapFloatBufferTest.java
new file mode 100644
index 0000000..f90b34e
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapFloatBufferTest.java
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.FloatBuffer;
+
+public class HeapFloatBufferTest extends FloatBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = FloatBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testAllocatedFloatBuffer_IllegalArg() {
+ try {
+ FloatBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapIntBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapIntBufferTest.java
new file mode 100644
index 0000000..0d68835
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapIntBufferTest.java
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.IntBuffer;
+
+public class HeapIntBufferTest extends IntBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = IntBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testAllocatedIntBuffer_IllegalArg() {
+ try {
+ IntBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapLongBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapLongBufferTest.java
new file mode 100644
index 0000000..f4f2ae1
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapLongBufferTest.java
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.LongBuffer;
+
+public class HeapLongBufferTest extends LongBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = LongBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testAllocatedLongBuffer_IllegalArg() {
+ try {
+ LongBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapShortBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapShortBufferTest.java
new file mode 100644
index 0000000..327a035
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapShortBufferTest.java
@@ -0,0 +1,42 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ShortBuffer;
+
+public class HeapShortBufferTest extends ShortBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ShortBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testAllocatedShortBuffer_IllegalArg() {
+ try {
+ ShortBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/IntBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/IntBufferTest.java
new file mode 100644
index 0000000..18a6860
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/IntBufferTest.java
@@ -0,0 +1,738 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+import java.nio.InvalidMarkException;
+
+/**
+ * Tests java.nio.IntBuffer
+ *
+ */
+public class IntBufferTest extends AbstractBufferTest {
+
+
+ protected static final int SMALL_TEST_LENGTH = 5;
+
+ protected static final int BUFFER_LENGTH = 20;
+
+ protected IntBuffer buf;
+
+ protected void setUp() throws Exception {
+ buf = IntBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ buf = null;
+ baseBuf = null;
+ }
+
+ /*
+ * test for method static IntBuffer allocate(int capacity) test covers
+ * following usecases: 1. case for check IntBuffer testBuf properties 2.
+ * case expected IllegalArgumentException
+ */
+
+ public void test_AllocateI() {
+ // case: IntBuffer testBuf properties is satisfy the conditions
+ // specification
+ IntBuffer testBuf = IntBuffer.allocate(20);
+ assertEquals(testBuf.position(), 0);
+ assertEquals(testBuf.limit(), testBuf.capacity());
+ assertEquals(testBuf.arrayOffset(), 0);
+
+ // case: expected IllegalArgumentException
+ try {
+ testBuf = IntBuffer.allocate(-20);
+ fail("allocate method does not throws expected exception");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testArray() {
+ int array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testArrayOffset() {
+ int array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ IntBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+ }
+
+ public void testCompact() {
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ IntBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(5);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 1, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ // compare to self
+ assertEquals(0, buf.compareTo(buf));
+
+ // normal cases
+ assertTrue(buf.capacity() > 5);
+ buf.clear();
+ IntBuffer other = IntBuffer.allocate(buf.capacity());
+ loadTestData1(other);
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ other.limit(5);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ }
+
+ public void testDuplicate() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ IntBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // duplicate share the same content with buf
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ IntBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ IntBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > 5);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for int get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer get(int[])
+ */
+ public void testGetintArray() {
+ int array[] = new int[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ IntBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i));
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ try {
+ buf.get((int[])null);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer get(int[], int, int)
+ */
+ public void testGetintArrayintint() {
+ buf.clear();
+ int array[] = new int[buf.capacity()];
+
+ try {
+ buf.get(new int[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get((int[])null, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ IntBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for int get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHasArray() {
+ assertNotNull(buf.array());
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ IntBuffer readonly = buf.asReadOnlyBuffer();
+ IntBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+
+ assertTrue(buf.capacity() > 5);
+ duplicate.position(buf.capacity() / 2);
+ assertTrue(buf.hashCode() != duplicate.hashCode());
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testOrder() {
+ buf.order();
+ assertEquals(ByteOrder.nativeOrder(), buf.order());
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer put(int)
+ */
+ public void testPutint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ IntBuffer ret = buf.put((int) i);
+ assertEquals(buf.get(i), (int) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer put(int[])
+ */
+ public void testPutintArray() {
+ int array[] = new int[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (int) i;
+ IntBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (int) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.position(buf.limit());
+ buf.put((int[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer put(int[], int, int)
+ */
+ public void testPutintArrayintint() {
+ buf.clear();
+ int array[] = new int[buf.capacity()];
+ try {
+ buf.put(new int[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((int[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ IntBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer put(java.nio.IntBuffer)
+ */
+ public void testPutIntBuffer() {
+ IntBuffer other = IntBuffer.allocate(buf.capacity());
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(IntBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.flip();
+ buf.put((IntBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ IntBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer put(int, int)
+ */
+ public void testPutintint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ IntBuffer ret = buf.put(i, (int) i);
+ assertEquals(buf.get(i), (int) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ IntBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, 0, slice.capacity());
+ buf.put(2, 500);
+ assertEquals(slice.get(1), 500);
+ }
+ }
+
+ public void testToString() {
+ String str = buf.toString();
+ assertTrue(str.indexOf("Int") >= 0 || str.indexOf("int") >= 0);
+ assertTrue(str.indexOf("" + buf.position()) >= 0);
+ assertTrue(str.indexOf("" + buf.limit()) >= 0);
+ assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+ }
+
+ /*
+ * test for method static IntBuffer wrap(int[] array) test covers following
+ * usecases: 1. case for check IntBuffer buf2 properties 2. case for check
+ * equal between buf2 and int array[] 3. case for check a buf2 dependens to
+ * array[]
+ */
+
+ public void test_Wrap$I() {
+ int array[] = new int[BUFFER_LENGTH];
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ IntBuffer buf2 = IntBuffer.wrap(array);
+
+ // case: IntBuffer buf2 properties is satisfy the conditions
+ // specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.limit(), array.length);
+ assertEquals(buf2.position(), 0);
+
+ // case: IntBuffer buf2 is equal to int array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: IntBuffer buf2 is depended to int array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+ }
+
+ /*
+ * test for method static IntBuffer wrap(int[] array, int offset, int
+ * length) test covers following usecases: 1. case for check IntBuffer buf2
+ * properties 2. case for check equal between buf2 and int array[] 3. case
+ * for check a buf2 dependens to array[] 4. case expected
+ * IndexOutOfBoundsException
+ */
+
+ public void test_Wrap$III() {
+ int array[] = new int[BUFFER_LENGTH];
+ int offset = 5;
+ int length = BUFFER_LENGTH - offset;
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ IntBuffer buf2 = IntBuffer.wrap(array, offset, length);
+
+ // case: IntBuffer buf2 properties is satisfy the conditions
+ // specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.position(), offset);
+ assertEquals(buf2.limit(), offset + length);
+ assertEquals(buf2.arrayOffset(), 0);
+
+ // case: IntBuffer buf2 is equal to int array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: IntBuffer buf2 is depended to int array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: expected IndexOutOfBoundsException
+ try {
+ offset = 7;
+ buf2 = IntBuffer.wrap(array, offset, length);
+ fail("wrap method does not throws expected exception");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ void loadTestData1(int array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (int)i;
+ }
+ }
+
+ void loadTestData2(int array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (int)length - i;
+ }
+ }
+
+ void loadTestData1(IntBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (int)i);
+ }
+ }
+
+ void loadTestData2(IntBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (int)buf.capacity() - i);
+ }
+ }
+
+ void assertContentEquals(IntBuffer buf, int array[],
+ int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i]);
+ }
+ }
+
+ void assertContentEquals(IntBuffer buf, IntBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i));
+ }
+ }
+
+ void assertContentLikeTestData1(IntBuffer buf,
+ int startIndex, int startValue, int length) {
+ int value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value);
+ value = value + 1;
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java
new file mode 100644
index 0000000..f291ff4
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java
@@ -0,0 +1,41 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.InvalidMarkException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+public class InvalidMarkExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new InvalidMarkException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new InvalidMarkException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/LongBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/LongBufferTest.java
new file mode 100644
index 0000000..3fb15a6
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/LongBufferTest.java
@@ -0,0 +1,745 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.InvalidMarkException;
+import java.nio.LongBuffer;
+
+/**
+ * Tests java.nio.LongBuffer
+ *
+ */
+public class LongBufferTest extends AbstractBufferTest {
+
+
+ protected static final int SMALL_TEST_LENGTH = 5;
+
+ protected static final int BUFFER_LENGTH = 20;
+
+ protected LongBuffer buf;
+
+ protected void setUp() throws Exception {
+ buf = LongBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ buf = null;
+ baseBuf = null;
+ }
+
+ /*
+ * test for method static LongBuffer allocate(int capacity) test covers
+ * following usecases: 1. case for check LongBuffer testBuf properties 2.
+ * case expected IllegalArgumentException
+ */
+
+ public void test_AllocateI() {
+ // case: LongBuffer testBuf properties is satisfy the conditions
+ // specification
+ LongBuffer testBuf = LongBuffer.allocate(20);
+ assertEquals(testBuf.position(), 0);
+ assertEquals(testBuf.limit(), testBuf.capacity());
+ assertEquals(testBuf.arrayOffset(), 0);
+
+ // case: expected IllegalArgumentException
+ try {
+ testBuf = LongBuffer.allocate(-20);
+ fail("allocate method does not throws expected exception");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testArray() {
+ long array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testArrayOffset() {
+ long array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ LongBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+ }
+
+ public void testCompact() {
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ LongBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(5);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 1, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ // compare to self
+ assertEquals(0, buf.compareTo(buf));
+
+ // normal cases
+ assertTrue(buf.capacity() > 5);
+ buf.clear();
+ LongBuffer other = LongBuffer.allocate(buf.capacity());
+ loadTestData1(other);
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ other.limit(5);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ }
+
+ public void testDuplicate() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ LongBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // duplicate share the same content with buf
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ LongBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ LongBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > 5);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for long get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer get(long[])
+ */
+ public void testGetlongArray() {
+ long array[] = new long[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ LongBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i));
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ try {
+ buf.position(buf.limit());
+ buf.get((long[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer get(long[], int, int)
+ */
+ public void testGetlongArrayintint() {
+ buf.clear();
+ long array[] = new long[buf.capacity()];
+
+ try {
+ buf.get(new long[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get((long[])null, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ LongBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for long get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHasArray() {
+ assertNotNull(buf.array());
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ LongBuffer readonly = buf.asReadOnlyBuffer();
+ LongBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+
+ assertTrue(buf.capacity() > 5);
+ duplicate.position(buf.capacity() / 2);
+ assertTrue(buf.hashCode() != duplicate.hashCode());
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testOrder() {
+ buf.order();
+ assertEquals(ByteOrder.nativeOrder(), buf.order());
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer put(long)
+ */
+ public void testPutlong() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ LongBuffer ret = buf.put((long) i);
+ assertEquals(buf.get(i), (long) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer put(long[])
+ */
+ public void testPutlongArray() {
+ long array[] = new long[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (long) i;
+ LongBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (long) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.position(buf.limit());
+ buf.put((long[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer put(long[], int, int)
+ */
+ public void testPutlongArrayintint() {
+ buf.clear();
+ long array[] = new long[buf.capacity()];
+ try {
+ buf.put(new long[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((long[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ LongBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer put(java.nio.LongBuffer)
+ */
+ public void testPutLongBuffer() {
+ LongBuffer other = LongBuffer.allocate(buf.capacity());
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(LongBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.flip();
+ buf.put((LongBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ LongBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer put(int, long)
+ */
+ public void testPutintlong() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ LongBuffer ret = buf.put(i, (long) i);
+ assertEquals(buf.get(i), (long) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ LongBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, 0, slice.capacity());
+ buf.put(2, 500);
+ assertEquals(slice.get(1), 500);
+ }
+ }
+
+ public void testToString() {
+ String str = buf.toString();
+ assertTrue(str.indexOf("Long") >= 0 || str.indexOf("long") >= 0);
+ assertTrue(str.indexOf("" + buf.position()) >= 0);
+ assertTrue(str.indexOf("" + buf.limit()) >= 0);
+ assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+ }
+
+ /*
+ * test for method public static LongBuffer wrap(long[] array) test covers
+ * following usecases: 1. case for check LongBuffer buf2 properties 2. case
+ * for check equal between buf2 and ling array[] 3. case for check a buf2
+ * dependens to array[]
+ */
+
+ public void test_Wrap$L() {
+ long array[] = new long[BUFFER_LENGTH];
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ LongBuffer buf2 = LongBuffer.wrap(array);
+
+ // case: LongBuffer buf2 properties is satisfy the conditions
+ // specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.limit(), array.length);
+ assertEquals(buf2.position(), 0);
+
+ // case: LongBuffer buf2 is equal to long array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: LongBuffer buf2 is depended to long array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+ }
+
+ /*
+ * test for method public static LongBuffer wrap(long[] array, int offset,
+ * int length) test covers following usecases: 1. case for check LongBuffer
+ * buf2 properties 2. case for check equal between buf2 and long array[] 3.
+ * case for check a buf2 dependens to array[] 4. case expected
+ * IndexOutOfBoundsException
+ */
+
+ public void test_Wrap$LII() {
+ long array[] = new long[BUFFER_LENGTH];
+ int offset = 5;
+ int length = BUFFER_LENGTH - offset;
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ LongBuffer buf2 = LongBuffer.wrap(array, offset, length);
+
+ // case: LongBuffer buf2 properties is satisfy the conditions
+ // specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.position(), offset);
+ assertEquals(buf2.limit(), offset + length);
+ assertEquals(buf2.arrayOffset(), 0);
+
+ // case: LongBuffer buf2 is equal to long array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: LongBuffer buf2 is depended to long array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: expected IndexOutOfBoundsException
+ try {
+ offset = 7;
+ buf2 = LongBuffer.wrap(array, offset, length);
+ fail("wrap method does not throws expected exception");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ void loadTestData1(long array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (long) i;
+ }
+ }
+
+ void loadTestData2(long array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (long) length - i;
+ }
+ }
+
+ void loadTestData1(LongBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (long) i);
+ }
+ }
+
+ void loadTestData2(LongBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (long) buf.capacity() - i);
+ }
+ }
+
+ void assertContentEquals(LongBuffer buf, long array[],
+ int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i]);
+ }
+ }
+
+ void assertContentEquals(LongBuffer buf, LongBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i));
+ }
+ }
+
+ void assertContentLikeTestData1(LongBuffer buf,
+ int startIndex, long startValue, int length) {
+ long value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value);
+ value = value + 1;
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java
new file mode 100644
index 0000000..856bd5b
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java
@@ -0,0 +1,41 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ReadOnlyBufferException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+public class ReadOnlyBufferExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new ReadOnlyBufferException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new ReadOnlyBufferException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyCharBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyCharBufferTest.java
new file mode 100644
index 0000000..e84cc9c
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyCharBufferTest.java
@@ -0,0 +1,209 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.CharBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyCharBufferTest extends CharBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ buf = null;
+ baseBuf = null;
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ }
+ }
+
+ public void testHashCode() {
+ CharBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(), duplicate.hashCode());
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testCompact() {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutchar() {
+ try {
+ buf.put((char) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutcharArray() {
+ char array[] = new char[1];
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((char[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutcharArrayintint() {
+ char array[] = new char[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((char[]) null, 0, 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(new char[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutCharBuffer() {
+ CharBuffer other = CharBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((CharBuffer) null);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintchar() {
+ try {
+ buf.put(0, (char) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(-1, (char) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutStringintint() {
+ buf.clear();
+ String str = String.valueOf(new char[buf.capacity()]);
+ try {
+ buf.put(str, 0, str.length());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((String) null, 0, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(str, -1, str.length());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ String longStr = String.valueOf(new char[buf.capacity()+1]);
+ try {
+ buf.put(longStr, 0, longStr.length());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutString() {
+ String str = " ";
+ try {
+ buf.put(str);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((String)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDirectByteBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDirectByteBufferTest.java
new file mode 100644
index 0000000..20c7914
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDirectByteBufferTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class ReadOnlyDirectByteBufferTest extends DirectByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testHashCode() {
+ super.readOnlyHashCode();
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDoubleBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDoubleBufferTest.java
new file mode 100644
index 0000000..0834d33
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDoubleBufferTest.java
@@ -0,0 +1,160 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyDoubleBufferTest extends DoubleBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ }
+ }
+
+ public void testHashCode() {
+ DoubleBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(), duplicate.hashCode());
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testCompact() {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutdouble() {
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutdoubleArray() {
+ double array[] = new double[1];
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((double[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutdoubleArrayintint() {
+ double array[] = new double[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((double[]) null, 0, 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(new double[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutDoubleBuffer() {
+ DoubleBuffer other = DoubleBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((DoubleBuffer) null);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintdouble() {
+ try {
+ buf.put(0, (double) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(-1, (double) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyFloatBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyFloatBufferTest.java
new file mode 100644
index 0000000..3acc5c4
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyFloatBufferTest.java
@@ -0,0 +1,161 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.FloatBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyFloatBufferTest extends FloatBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ //expected
+ }
+ }
+
+ public void testHashCode() {
+ FloatBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(), duplicate.hashCode());
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testCompact() {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutfloat() {
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutfloatArray() {
+ float array[] = new float[1];
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((float[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutfloatArrayintint() {
+ float array[] = new float[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((float[]) null, 0, 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(new float[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutFloatBuffer() {
+ FloatBuffer other = FloatBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((FloatBuffer) null);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintfloat() {
+ try {
+ buf.put(0, (float) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(-1, (float) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapByteBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapByteBufferTest.java
new file mode 100644
index 0000000..7452a24
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapByteBufferTest.java
@@ -0,0 +1,43 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class ReadOnlyHeapByteBufferTest extends HeapByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testHashCode() {
+ super.readOnlyHashCode();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapCharBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapCharBufferTest.java
new file mode 100644
index 0000000..4c7792a
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapCharBufferTest.java
@@ -0,0 +1,35 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.CharBuffer;
+
+
+public class ReadOnlyHeapCharBufferTest extends ReadOnlyCharBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = CharBuffer.allocate(BUFFER_LENGTH);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapDoubleBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapDoubleBufferTest.java
new file mode 100644
index 0000000..5c229a2
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapDoubleBufferTest.java
@@ -0,0 +1,34 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+
+public class ReadOnlyHeapDoubleBufferTest extends ReadOnlyDoubleBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = DoubleBuffer.allocate(BUFFER_LENGTH);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapFloatBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapFloatBufferTest.java
new file mode 100644
index 0000000..f2c6644
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapFloatBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.FloatBuffer;
+
+public class ReadOnlyHeapFloatBufferTest extends ReadOnlyFloatBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = FloatBuffer.allocate(BUFFER_LENGTH);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapIntBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapIntBufferTest.java
new file mode 100644
index 0000000..f9a3877
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapIntBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.IntBuffer;
+
+public class ReadOnlyHeapIntBufferTest extends ReadOnlyIntBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = IntBuffer.allocate(BUFFER_LENGTH);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapLongBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapLongBufferTest.java
new file mode 100644
index 0000000..efba978
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapLongBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.LongBuffer;
+
+public class ReadOnlyHeapLongBufferTest extends ReadOnlyLongBufferTest{
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = LongBuffer.allocate(BUFFER_LENGTH);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapShortBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapShortBufferTest.java
new file mode 100644
index 0000000..bbbd616
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapShortBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ShortBuffer;
+
+public class ReadOnlyHeapShortBufferTest extends ReadOnlyShortBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ShortBuffer.allocate(BUFFER_LENGTH);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyIntBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyIntBufferTest.java
new file mode 100644
index 0000000..61e78a6
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyIntBufferTest.java
@@ -0,0 +1,161 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.IntBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyIntBufferTest extends IntBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ //expected
+ }
+ }
+
+ public void testHashCode() {
+ IntBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(), duplicate.hashCode());
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testCompact() {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutint() {
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintArray() {
+ int array[] = new int[1];
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((int[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutintArrayintint() {
+ int array[] = new int[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((int[]) null, -1, 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(new int[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutIntBuffer() {
+ IntBuffer other = IntBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((IntBuffer) null);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintint() {
+ try {
+ buf.put(0, (int) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(-1, (int) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyLongBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyLongBufferTest.java
new file mode 100644
index 0000000..b670606
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyLongBufferTest.java
@@ -0,0 +1,161 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.LongBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyLongBufferTest extends LongBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ //expected
+ }
+ }
+
+ public void testHashCode() {
+ LongBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(), duplicate.hashCode());
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testCompact() {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutlong() {
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutlongArray() {
+ long array[] = new long[1];
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((long[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutlongArrayintint() {
+ long array[] = new long[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((long[]) null, 0, 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(new long[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutLongBuffer() {
+ LongBuffer other = LongBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((LongBuffer) null);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintlong() {
+ try {
+ buf.put(0, (long) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(-1, (long) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyShortBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyShortBufferTest.java
new file mode 100644
index 0000000..611f6bf
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyShortBufferTest.java
@@ -0,0 +1,161 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ReadOnlyBufferException;
+import java.nio.ShortBuffer;
+
+public class ReadOnlyShortBufferTest extends ShortBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ //expected
+ }
+ }
+
+ public void testHashCode() {
+ ShortBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(), duplicate.hashCode());
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testCompact() {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutshort() {
+ try {
+ buf.put((short)0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutshortArray() {
+ short array[] = new short[1];
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((short[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutshortArrayintint() {
+ short array[] = new short[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((short[]) null, 0, 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(new short[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutShortBuffer() {
+ ShortBuffer other = ShortBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((ShortBuffer) null);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintshort() {
+ try {
+ buf.put(0, (short) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(-1, (short) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedByteBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedByteBufferTest.java
new file mode 100644
index 0000000..031d75b
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedByteBufferTest.java
@@ -0,0 +1,45 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class ReadOnlyWrappedByteBufferTest extends WrappedByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testHashCode() {
+ super.readOnlyHashCode();
+ }
+
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedCharBufferTest1.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedCharBufferTest1.java
new file mode 100644
index 0000000..57c04bf
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedCharBufferTest1.java
@@ -0,0 +1,34 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.CharBuffer;
+
+public class ReadOnlyWrappedCharBufferTest1 extends ReadOnlyCharBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = CharBuffer.wrap(new char[BUFFER_LENGTH]);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedDoubleBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedDoubleBufferTest.java
new file mode 100644
index 0000000..d1ba9df
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedDoubleBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+
+public class ReadOnlyWrappedDoubleBufferTest extends ReadOnlyDoubleBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = DoubleBuffer.wrap(new double[BUFFER_LENGTH]);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedFloatBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedFloatBufferTest.java
new file mode 100644
index 0000000..affddaa
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedFloatBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.FloatBuffer;
+
+public class ReadOnlyWrappedFloatBufferTest extends ReadOnlyFloatBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = FloatBuffer.wrap(new float[BUFFER_LENGTH]);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedIntBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedIntBufferTest.java
new file mode 100644
index 0000000..a4d0155
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedIntBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.IntBuffer;
+
+public class ReadOnlyWrappedIntBufferTest extends ReadOnlyIntBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = IntBuffer.wrap(new int[BUFFER_LENGTH]);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedLongBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedLongBufferTest.java
new file mode 100644
index 0000000..58491da
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedLongBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.LongBuffer;
+
+public class ReadOnlyWrappedLongBufferTest extends ReadOnlyLongBufferTest{
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = LongBuffer.wrap(new long[BUFFER_LENGTH]);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedShortBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedShortBufferTest.java
new file mode 100644
index 0000000..0ecb3a4
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedShortBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ShortBuffer;
+
+public class ReadOnlyWrappedShortBufferTest extends ReadOnlyShortBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ShortBuffer.wrap(new short[BUFFER_LENGTH]);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ShortBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ShortBufferTest.java
new file mode 100644
index 0000000..86bad2d
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/ShortBufferTest.java
@@ -0,0 +1,725 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.InvalidMarkException;
+import java.nio.ShortBuffer;
+
+/**
+ * Tests java.nio.ShortBuffer
+ *
+ */
+public class ShortBufferTest extends AbstractBufferTest {
+
+ protected static final int SMALL_TEST_LENGTH = 5;
+
+ protected static final int BUFFER_LENGTH = 20;
+
+ protected ShortBuffer buf;
+
+ protected void setUp() throws Exception {
+ buf = ShortBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ buf = null;
+ baseBuf = null;
+ }
+
+ /*
+ * test for method static ShortBuffer allocate(int capacity) test covers
+ * following usecases: 1. case for check ShortBuffer testBuf properties 2.
+ * case expected IllegalArgumentException
+ */
+
+ public void test_AllocateI() {
+ // case: ShortBuffer testBuf properties is satisfy the conditions
+ // specification
+ ShortBuffer testBuf = ShortBuffer.allocate(20);
+ assertEquals(testBuf.position(), 0);
+ assertEquals(testBuf.limit(), testBuf.capacity());
+ assertEquals(testBuf.arrayOffset(), 0);
+
+ // case: expected IllegalArgumentException
+ try {
+ testBuf = ShortBuffer.allocate(-20);
+ fail("allocate method does not throws expected exception");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testArray() {
+ short array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testArrayOffset() {
+ short array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ ShortBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+ }
+
+ public void testCompact() {
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ ShortBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (short) 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (short) 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(5);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (short) 1, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ // compare to self
+ assertEquals(0, buf.compareTo(buf));
+
+ // normal cases
+ assertTrue(buf.capacity() > 5);
+ buf.clear();
+ ShortBuffer other = ShortBuffer.allocate(buf.capacity());
+ loadTestData1(other);
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ other.limit(5);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ }
+
+ public void testDuplicate() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ ShortBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // duplicate share the same content with buf
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ ShortBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ ShortBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > 5);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for short get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer get(short[])
+ */
+ public void testGetshortArray() {
+ short array[] = new short[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ ShortBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i));
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer get(short[], int, int)
+ */
+ public void testGetshortArrayintint() {
+ buf.clear();
+ short array[] = new short[buf.capacity()];
+
+ try {
+ buf.get(new short[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get((short[])null, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ ShortBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for short get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHasArray() {
+ assertNotNull(buf.array());
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ ShortBuffer readonly = buf.asReadOnlyBuffer();
+ ShortBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+
+ assertTrue(buf.capacity() > 5);
+ duplicate.position(buf.capacity() / 2);
+ assertTrue(buf.hashCode() != duplicate.hashCode());
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testOrder() {
+ buf.order();
+ assertEquals(ByteOrder.nativeOrder(), buf.order());
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer put(short)
+ */
+ public void testPutshort() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ ShortBuffer ret = buf.put((short) i);
+ assertEquals(buf.get(i), (short) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put((short) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer put(short[])
+ */
+ public void testPutshortArray() {
+ short array[] = new short[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (short) i;
+ ShortBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (short) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.position(buf.limit());
+ buf.put((short[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer put(short[], int, int)
+ */
+ public void testPutshortArrayintint() {
+ buf.clear();
+ short array[] = new short[buf.capacity()];
+ try {
+ buf.put(new short[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((short[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ ShortBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer put(java.nio.ShortBuffer)
+ */
+ public void testPutShortBuffer() {
+ ShortBuffer other = ShortBuffer.allocate(buf.capacity());
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(ShortBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.flip();
+ buf.put((ShortBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ ShortBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer put(int, short)
+ */
+ public void testPutintshort() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ ShortBuffer ret = buf.put(i, (short) i);
+ assertEquals(buf.get(i), (short) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, (short) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), (short) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ ShortBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, (short) 0, slice.capacity());
+ buf.put(2, (short) 500);
+ assertEquals(slice.get(1), 500);
+ }
+ }
+
+ public void testToString() {
+ String str = buf.toString();
+ assertTrue(str.indexOf("Short") >= 0 || str.indexOf("short") >= 0);
+ assertTrue(str.indexOf("" + buf.position()) >= 0);
+ assertTrue(str.indexOf("" + buf.limit()) >= 0);
+ assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+ }
+
+ /*
+ * test for method static ShortBuffer wrap(short[] array) test covers
+ * following usecases: 1. case for check ShortBuffer buf2 properties 2. case
+ * for check equal between buf2 and short array[] 3. case for check a buf2
+ * dependens to array[]
+ */
+
+ public void test_Wrap$S() {
+ short array[] = new short[BUFFER_LENGTH];
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ ShortBuffer buf2 = ShortBuffer.wrap(array);
+
+ // case: ShortBuffer buf2 properties is satisfy the conditions
+ // specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.limit(), array.length);
+ assertEquals(buf2.position(), 0);
+
+ // case: ShortBuffer buf2 is equal to short array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: ShortBuffer buf2 is depended to short array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+ }
+
+ /*
+ * test for method static ShortBuffer wrap(short[] array, int offset, int
+ * length) test covers following usecases: 1. case for check ShortBuffer
+ * buf2 properties 2. case for check equal between buf2 and short array[] 3.
+ * case for check a buf2 dependens to array[] 4. case expected
+ * IndexOutOfBoundsException
+ */
+
+ public void test_Wrap$SII() {
+ short array[] = new short[BUFFER_LENGTH];
+ int offset = 5;
+ int length = BUFFER_LENGTH - offset;
+ loadTestData1(array, 0, BUFFER_LENGTH);
+ ShortBuffer buf2 = ShortBuffer.wrap(array, offset, length);
+
+ // case: ShortBuffer buf2 properties is satisfy the conditions
+ // specification
+ assertEquals(buf2.capacity(), array.length);
+ assertEquals(buf2.position(), offset);
+ assertEquals(buf2.limit(), offset + length);
+ assertEquals(buf2.arrayOffset(), 0);
+
+ // case: ShortBuffer buf2 is equal to short array[]
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: ShortBuffer buf2 is depended to short array[]
+ loadTestData2(array, 0, buf.capacity());
+ assertContentEquals(buf2, array, 0, array.length);
+
+ // case: expected IndexOutOfBoundsException
+ try {
+ offset = 7;
+ buf2 = ShortBuffer.wrap(array, offset, length);
+ fail("wrap method does not throws expected exception");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ void loadTestData1(short array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (short) i;
+ }
+ }
+
+ void loadTestData2(short array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (short) (length - i);
+ }
+ }
+
+ void loadTestData1(ShortBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (short) i);
+ }
+ }
+
+ void loadTestData2(ShortBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (short) (buf.capacity() - i));
+ }
+ }
+
+ void assertContentEquals(ShortBuffer buf, short array[],
+ int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i]);
+ }
+ }
+
+ void assertContentEquals(ShortBuffer buf, ShortBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i));
+ }
+ }
+
+ void assertContentLikeTestData1(ShortBuffer buf,
+ int startIndex, short startValue, int length) {
+ short value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value);
+ value = (short) (value + 1);
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceDirectByteBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceDirectByteBufferTest.java
new file mode 100644
index 0000000..541cde0
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceDirectByteBufferTest.java
@@ -0,0 +1,32 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class SliceDirectByteBufferTest extends DirectByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf.position(1).limit(BUFFER_LENGTH-1);
+ buf = buf.slice();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceHeapByteBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceHeapByteBufferTest.java
new file mode 100644
index 0000000..9f9f7aa
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceHeapByteBufferTest.java
@@ -0,0 +1,33 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class SliceHeapByteBufferTest extends HeapByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf.position(1).limit(BUFFER_LENGTH-1);
+ buf = buf.slice();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceWrappedByteBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceWrappedByteBufferTest.java
new file mode 100644
index 0000000..f1ddfb9
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceWrappedByteBufferTest.java
@@ -0,0 +1,33 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+
+public class SliceWrappedByteBufferTest extends WrappedByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf.position(1).limit(BUFFER_LENGTH-1);
+ buf = buf.slice();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedByteBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedByteBufferTest.java
new file mode 100644
index 0000000..6460d2e
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedByteBufferTest.java
@@ -0,0 +1,97 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+
+public class WrappedByteBufferTest extends ByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ByteBuffer.wrap(new byte[BUFFER_LENGTH]);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ /**
+ * @tests java.nio.ByteBuffer#allocate(byte[],int,int)
+ *
+ */
+ public void testWrappedByteBuffer_IllegalArg() {
+ byte array[] = new byte[BUFFER_LENGTH];
+ try {
+ ByteBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ByteBuffer.wrap(array, BUFFER_LENGTH + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ByteBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ByteBuffer.wrap(array, 0, BUFFER_LENGTH + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ByteBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ByteBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ByteBuffer.wrap((byte[])null, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testHasArray() {
+ assertTrue(buf.hasArray());
+ }
+
+ public void testIsReadOnly() {
+ assertFalse(buf.isReadOnly());
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest1.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest1.java
new file mode 100644
index 0000000..9181a77
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest1.java
@@ -0,0 +1,84 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.CharBuffer;
+
+public class WrappedCharBufferTest1 extends CharBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = CharBuffer.wrap(new char[BUFFER_LENGTH]);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ /**
+ * @tests java.nio.CharBuffer#allocate(char[],int,int)
+ *
+ */
+ public void testWrappedCharBuffer_IllegalArg() {
+ char array[] = new char[BUFFER_LENGTH];
+ try {
+ CharBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(array, BUFFER_LENGTH + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(array, 0, BUFFER_LENGTH + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap((char[])null, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest2.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest2.java
new file mode 100644
index 0000000..1e98d63
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest2.java
@@ -0,0 +1,129 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.CharBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class WrappedCharBufferTest2 extends ReadOnlyCharBufferTest {
+ protected static final String TEST_STRING = "123456789abcdef12345";
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = CharBuffer.wrap(TEST_STRING);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ public void testWrappedCharSequence_IllegalArg() {
+ String str = TEST_STRING;
+ try {
+ CharBuffer.wrap(str, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(str, 21, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(str, 2, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(str, 0, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap((String)null, -1, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testPutcharArrayintint() {
+ char array[] = new char[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((char[]) null, 0, 1);
+ fail("Should throw NullPointerException"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(new char[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw BufferOverflowException"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw IndexOutOfBoundsException"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testPutCharBuffer() {
+ CharBuffer other = CharBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((CharBuffer) null);
+ fail("Should throw NullPointerException"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw IllegalArgumentException"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedDoubleBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedDoubleBufferTest.java
new file mode 100644
index 0000000..f89b41e
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedDoubleBufferTest.java
@@ -0,0 +1,87 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+
+public class WrappedDoubleBufferTest extends DoubleBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = DoubleBuffer.wrap(new double[BUFFER_LENGTH]);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ /**
+ * @tests java.nio.CharBuffer#allocate(char[],int,int)
+ *
+ */
+ public void testWrappedDoubleuffer_IllegalArg() {
+ double array[] = new double[20];
+ try {
+ DoubleBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ DoubleBuffer.wrap(array, 21, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ DoubleBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ DoubleBuffer.wrap(array, 0, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ DoubleBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ DoubleBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ DoubleBuffer.wrap((double[])null, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+
+ DoubleBuffer buf = DoubleBuffer.wrap(array, 2, 16);
+ assertEquals(buf.position(), 2);
+ assertEquals(buf.limit(), 18);
+ assertEquals(buf.capacity(), 20);
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedFloatBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedFloatBufferTest.java
new file mode 100644
index 0000000..43b13c3
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedFloatBufferTest.java
@@ -0,0 +1,87 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.FloatBuffer;
+
+public class WrappedFloatBufferTest extends FloatBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = FloatBuffer.wrap(new float[BUFFER_LENGTH]);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ /**
+ * @tests java.nio.CharBuffer#allocate(char[],int,int)
+ *
+ */
+ public void testWrappedFloatBuffer_IllegalArg() {
+ float array[] = new float[20];
+ try {
+ FloatBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ FloatBuffer.wrap(array, 21, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ FloatBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ FloatBuffer.wrap(array, 0, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ FloatBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ FloatBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ FloatBuffer.wrap((float[])null, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+
+ FloatBuffer buf = FloatBuffer.wrap(array, 2, 16);
+ assertEquals(buf.position(), 2);
+ assertEquals(buf.limit(), 18);
+ assertEquals(buf.capacity(), 20);
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedIntBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedIntBufferTest.java
new file mode 100644
index 0000000..383e964
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedIntBufferTest.java
@@ -0,0 +1,87 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.IntBuffer;
+
+public class WrappedIntBufferTest extends IntBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = IntBuffer.wrap(new int[BUFFER_LENGTH]);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ /**
+ * @tests java.nio.CharBuffer#allocate(char[],int,int)
+ *
+ */
+ public void testWrappedIntBuffer_IllegalArg() {
+ int array[] = new int[20];
+ try {
+ IntBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ IntBuffer.wrap(array, 21, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ IntBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ IntBuffer.wrap(array, 0, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ IntBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ IntBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ IntBuffer.wrap((int[])null, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+
+ IntBuffer buf = IntBuffer.wrap(array, 2, 16);
+ assertEquals(buf.position(), 2);
+ assertEquals(buf.limit(), 18);
+ assertEquals(buf.capacity(), 20);
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedLongBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedLongBufferTest.java
new file mode 100644
index 0000000..581c912
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedLongBufferTest.java
@@ -0,0 +1,87 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.LongBuffer;
+
+public class WrappedLongBufferTest extends LongBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = LongBuffer.wrap(new long[BUFFER_LENGTH]);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ /**
+ * @tests java.nio.CharBuffer#allocate(char[],int,int)
+ *
+ */
+ public void testWrappedLongBuffer_IllegalArg() {
+ long array[] = new long[20];
+ try {
+ LongBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ LongBuffer.wrap(array, 21, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ LongBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ LongBuffer.wrap(array, 0, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ LongBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ LongBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ LongBuffer.wrap((long[])null, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+
+ LongBuffer buf = LongBuffer.wrap(array, 2, 16);
+ assertEquals(buf.position(), 2);
+ assertEquals(buf.limit(), 18);
+ assertEquals(buf.capacity(), 20);
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedShortBufferTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedShortBufferTest.java
new file mode 100644
index 0000000..9c6f781
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedShortBufferTest.java
@@ -0,0 +1,87 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ShortBuffer;
+
+public class WrappedShortBufferTest extends ShortBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ShortBuffer.wrap(new short[BUFFER_LENGTH]);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ /**
+ * @tests java.nio.CharBuffer#allocate(char[],int,int)
+ *
+ */
+ public void testWrappedShortBuffer_IllegalArg() {
+ short array[] = new short[20];
+ try {
+ ShortBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ShortBuffer.wrap(array, 21, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ShortBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ShortBuffer.wrap(array, 0, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ShortBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ShortBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ShortBuffer.wrap((short[])null, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+
+ ShortBuffer buf = ShortBuffer.wrap(array, 2, 16);
+ assertEquals(buf.position(), 2);
+ assertEquals(buf.limit(), 18);
+ assertEquals(buf.capacity(), 20);
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AllTests.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AllTests.java
new file mode 100644
index 0000000..0ecd41c
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AllTests.java
@@ -0,0 +1,67 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(AllTests.class.getName());
+ //$JUnit-BEGIN$
+ suite.addTestSuite(AlreadyConnectedExceptionTest.class);
+ suite.addTestSuite(AsynchronousCloseExceptionTest.class);
+ suite.addTestSuite(CancelledKeyExceptionTest.class);
+ suite.addTestSuite(ChannelsTest.class);
+ suite.addTestSuite(ClosedByInterruptExceptionTest.class);
+ suite.addTestSuite(ClosedChannelExceptionTest.class);
+ suite.addTestSuite(ClosedSelectorExceptionTest.class);
+ suite.addTestSuite(ConnectionPendingExceptionTest.class);
+ suite.addTestSuite(DatagramChannelTest.class);
+ suite.addTestSuite(FileChannelLockingTest.class);
+ suite.addTestSuite(FileChannelTest.class);
+ suite.addTestSuite(FileLockInterruptionExceptionTest.class);
+ suite.addTestSuite(FileLockTest.class);
+ suite.addTestSuite(IllegalBlockingModeExceptionTest.class);
+ suite.addTestSuite(IllegalSelectorExceptionTest.class);
+ suite.addTestSuite(MapModeTest.class);
+ suite.addTestSuite(NoConnectionPendingExceptionTest.class);
+ suite.addTestSuite(NonReadableChannelExceptionTest.class);
+ suite.addTestSuite(NonWritableChannelExceptionTest.class);
+ suite.addTestSuite(NotYetBoundExceptionTest.class);
+ suite.addTestSuite(NotYetConnectedExceptionTest.class);
+ suite.addTestSuite(OverlappingFileLockExceptionTest.class);
+ suite.addTestSuite(PipeTest.class);
+ suite.addTestSuite(SelectableChannelTest.class);
+ suite.addTestSuite(SelectionKeyTest.class);
+ suite.addTestSuite(SelectorTest.class);
+ suite.addTestSuite(ServerSocketChannelTest.class);
+ suite.addTestSuite(SinkChannelTest.class);
+ suite.addTestSuite(SocketChannelTest.class);
+ suite.addTestSuite(SourceChannelTest.class);
+ suite.addTestSuite(UnresolvedAddressExceptionTest.class);
+ suite.addTestSuite(UnsupportedAddressTypeExceptionTest.class);
+ // $JUnit-END$
+ return suite;
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java
new file mode 100644
index 0000000..ee1efe2
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.AlreadyConnectedException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for AlreadyConnectedException
+ */
+public class AlreadyConnectedExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new AlreadyConnectedException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new AlreadyConnectedException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java
new file mode 100644
index 0000000..d766d0d
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.AsynchronousCloseException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for AsynchronousCloseException
+ */
+public class AsynchronousCloseExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new AsynchronousCloseException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new AsynchronousCloseException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java
new file mode 100644
index 0000000..e823622
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.CancelledKeyException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for CancelledKeyException
+ */
+public class CancelledKeyExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new CancelledKeyException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new CancelledKeyException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ChannelsTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ChannelsTest.java
new file mode 100644
index 0000000..acf5c75
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ChannelsTest.java
@@ -0,0 +1,683 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+
+import tests.support.Support_PortManager;
+
+import junit.framework.TestCase;
+
+/**
+ * Note: the test case uses a temp text file named "test" which contains 31
+ * characters : "P@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]"
+ *
+ */
+
+public class ChannelsTest extends TestCase {
+ private static final String CODE_SET = "GB2312"; //$NON-NLS-1$
+
+ private static final String BAD_CODE_SET = "GB2313"; //$NON-NLS-1$
+
+ private FileInputStream fins;
+
+ private FileOutputStream fouts;
+
+ private final int writebufSize = 60;
+
+ private final int testNum = 10;
+
+ private final int fileSize = 31;// the file size
+
+ private File tmpFile;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ // Make the test file same in every test
+ tmpFile = File.createTempFile("test","tmp");
+ tmpFile.deleteOnExit();
+ this.writeFileSame();
+ }
+
+ protected void tearDown() throws Exception {
+ if (null != this.fins) {
+ this.fins.close();
+ this.fins = null;
+ }
+ if (null != this.fouts) {
+ this.fouts.close();
+ this.fouts = null;
+ }
+
+ tmpFile.delete();
+ super.tearDown();
+
+ }
+
+ private void writeFileSame() throws IOException {
+ this.fouts = new FileOutputStream(tmpFile);
+ byte[] bit = new byte[1];
+ bit[0] = 80;
+ this.fouts.write(bit);
+ this.fouts.flush();
+ String writebuf = ""; //$NON-NLS-1$
+ for (int val = 0; val < this.writebufSize / 2; val++) {
+ writebuf = writebuf + ((char) (val + 64));
+ }
+ this.fouts.write(writebuf.getBytes());
+ }
+
+ /*
+ * This private method is to assert if the file size is the same as the
+ * compare Number in the test
+ */
+ private void assertFileSizeSame(File fileToTest, int compareNumber)
+ throws IOException {
+ FileInputStream file = new FileInputStream(fileToTest);
+ assertEquals(file.available(), compareNumber);
+ file.close();
+ }
+
+ // test if new Channel to input is null
+ public void testNewChannelInputStream_InputNull() throws IOException {
+ ByteBuffer byteBuf = ByteBuffer.allocate(this.testNum);
+ this.fins = null;
+ int readres = this.testNum;
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ assertNotNull(rbChannel);
+ try {
+ readres = rbChannel.read(byteBuf);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(this.testNum, readres);
+ }
+
+ // test if buffer to read is null
+ public void testNewChannelInputStream_BufferNull() throws IOException {
+ ByteBuffer byteBuf = ByteBuffer.allocate(this.testNum);
+ int readres = this.testNum;
+ this.fins = new FileInputStream(tmpFile);
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ assertNotNull(rbChannel);
+ try {
+ readres = rbChannel.read(null);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(this.testNum, readres);
+ readres = 0;
+ try {
+ readres = rbChannel.read(byteBuf);
+ } catch (NullPointerException e) {
+ fail();
+ }
+ assertEquals(this.testNum, readres);
+ }
+
+ /*
+ * Test method for 'java.nio.channels.Channels.NewChannel'
+ */
+ public void testNewChannelInputStream() throws IOException {
+ int bufSize = 10;
+ int readres = 0;
+ byte[] byteArray = new byte[bufSize];
+ ByteBuffer byteBuf = ByteBuffer.allocate(bufSize);
+ this.fins = new FileInputStream(tmpFile);
+ readres = this.fins.read(byteArray);
+
+ assertEquals(bufSize, readres);
+ assertFalse(0 == this.fins.available());
+
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ // fins still reads.
+ assertFalse(0 == this.fins.available());
+ readres = this.fins.read(byteArray);
+ assertEquals(bufSize, readres);
+
+ // rbChannel also reads.
+ assertNotNull(rbChannel);
+ readres = rbChannel.read(byteBuf);
+
+ assertEquals(bufSize, readres);
+ InputStream ins = Channels.newInputStream(rbChannel);
+ assertNotNull(ins);
+ assertEquals(0, ins.available());
+ }
+
+ // test if fout to change is null
+ public void testNewChannelOutputStream_inputNull() throws IOException {
+ int writeres = this.testNum;
+ ByteBuffer writebuf = ByteBuffer.allocate(this.writebufSize);
+ for (int val = 0; val < this.writebufSize / 2; val++) {
+ writebuf.putChar((char) (val + 64));
+ }
+ this.fouts = null;
+ WritableByteChannel rbChannel = Channels.newChannel(this.fouts);
+ writeres = rbChannel.write(writebuf);
+ assertEquals(0, writeres);
+
+ writebuf.flip();
+ try {
+ writeres = rbChannel.write(writebuf);
+ fail("Should throw NPE.");
+ } catch (NullPointerException e) {
+ }
+ }
+
+ // test if write buf is null
+ public void testNewChannelOutputStream_BufNull() throws IOException {
+ int writeres = this.testNum;
+ ByteBuffer writebuf = null;
+ try {
+ this.fouts = new FileOutputStream(tmpFile);
+ } catch (FileNotFoundException e) {
+ fail();
+ }
+
+ WritableByteChannel rbChannel = Channels.newChannel(this.fouts);
+ try {
+ writeres = rbChannel.write(writebuf);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(this.testNum, writeres);
+ }
+
+ /*
+ * Test method for 'java.nio.channels.Channels.NewChannel(OutputStream)'
+ */
+ public void testNewChannelOutputStream() throws IOException {
+ int writeNum = 0;
+ ByteBuffer writebuf = ByteBuffer.allocateDirect(this.writebufSize);
+ for (int val = 0; val < this.writebufSize / 2; val++) {
+ writebuf.putChar((char) (val + 64));
+ }
+ this.fouts = new FileOutputStream(tmpFile);
+ WritableByteChannel testChannel = this.fouts.getChannel();
+ WritableByteChannel rbChannel = Channels.newChannel(this.fouts);
+
+ assertTrue(testChannel.isOpen());
+ assertTrue(rbChannel.isOpen());
+
+ byte[] bit = new byte[1];
+ bit[0] = 80;
+ this.fouts.write(bit);
+ this.fouts.flush();
+ this.fins = new FileInputStream(tmpFile);
+ assertEquals(this.fins.available(), 1);
+ this.fins.close();
+
+ writeNum = rbChannel.write(writebuf);
+ // write success ,but output null
+ assertEquals(0, writeNum);
+ // close of fouts does not affect on channel
+ this.fouts.close();
+ writeNum = rbChannel.write(writebuf);
+ assertEquals(0, writeNum);
+ try {
+ writeNum = testChannel.write(writebuf);
+ fail();
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ assertEquals(0, writeNum);
+ // close of rbchannel does affect on testchannel(same channel)
+ rbChannel.close();
+ try {
+ writeNum = testChannel.write(writebuf);
+ fail();
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testNewInputStreamReadableByteChannel_InputNull()
+ throws Exception {
+ byte[] readbuf = new byte[this.testNum];
+ this.fins = new FileInputStream(tmpFile);
+ ReadableByteChannel readbc = this.fins.getChannel();
+ assertEquals(this.fileSize, this.fins.available());
+ assertTrue(readbc.isOpen());
+ InputStream testins = Channels.newInputStream(null);
+ assertNotNull(testins);
+
+ try {
+ testins.read(readbuf);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, testins.available());
+ try {
+ testins.close();
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+
+ }
+
+ public void testNewInputStreamReadableByteChannel() throws Exception {
+ ByteBuffer readbcbuf = ByteBuffer.allocateDirect(this.testNum);
+ byte[] readbuf = new byte[this.testNum];
+ this.fins = new FileInputStream(tmpFile);
+ ReadableByteChannel readbc = this.fins.getChannel();
+ assertEquals(this.fileSize, this.fins.available());
+ assertTrue(readbc.isOpen());
+ InputStream testins = Channels.newInputStream(readbc);
+ // read in testins and fins use the same pointer
+ testins.read(readbuf);
+ assertEquals(this.fins.available(), this.fileSize - this.testNum);
+ int readNum = readbc.read(readbcbuf);
+ assertEquals(readNum, this.testNum);
+ assertEquals(this.fins.available(), this.fileSize - this.testNum * 2);
+ testins.read(readbuf);
+ assertEquals(this.fins.available(), this.fileSize - this.testNum * 3);
+ // readbc.close() affect testins
+ readbc.close();
+ assertFalse(readbc.isOpen());
+ try {
+ testins.read(readbuf);
+ fail();
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testNewOutputStreamWritableByteChannel_InputNull()
+ throws Exception {
+ byte[] writebuf = new byte[this.testNum];
+ OutputStream testouts = Channels.newOutputStream(null);
+ assertNotNull(testouts);
+ try {
+ testouts.write(writebuf);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ testouts.flush();
+ try {
+ testouts.close();
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ WritableByteChannel writebc = Channels.newChannel((OutputStream) null);
+ assertTrue(writebc.isOpen());
+ OutputStream testoutputS = Channels.newOutputStream(writebc);
+ try {
+ testoutputS.write(writebuf);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testNewOutputStreamWritableByteChannel() throws Exception {
+ byte[] writebuf = new byte[this.testNum];
+ ByteBuffer writebcbuf = ByteBuffer.allocateDirect(this.testNum);
+ this.fouts = new FileOutputStream(tmpFile);
+ WritableByteChannel writebc = this.fouts.getChannel();
+
+ assertTrue(writebc.isOpen());
+ OutputStream testouts = Channels.newOutputStream(writebc);
+
+ // read in testins and fins use the same pointer
+ testouts.write(writebuf);
+ this.assertFileSizeSame(tmpFile, this.testNum);
+ writebc.write(writebcbuf);
+ this.assertFileSizeSame(tmpFile, this.testNum * 2);
+ testouts.write(writebuf);
+ this.assertFileSizeSame(tmpFile, this.testNum * 3);
+ // readbc.close() affect testins
+ writebc.close();
+ assertFalse(writebc.isOpen());
+ try {
+ testouts.write(writebuf);
+ fail();
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testnewReaderCharsetError() throws Exception {
+ this.fins = new FileInputStream(tmpFile);
+
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ try {
+ Channels.newReader(rbChannel, Charset.forName(BAD_CODE_SET)
+ .newDecoder(), //$NON-NLS-1$
+ -1);
+ fail();
+ } catch (UnsupportedCharsetException e) {
+ // correct
+ }
+ }
+
+ public void testnewWriterCharsetError() throws Exception {
+ this.fouts = new FileOutputStream(tmpFile);
+ WritableByteChannel wbChannel = Channels.newChannel(this.fouts);
+ try {
+ Channels.newWriter(wbChannel, Charset.forName(BAD_CODE_SET)
+ .newEncoder(), -1);
+ fail();
+ } catch (UnsupportedCharsetException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for
+ * 'java.nio.channels.Channels.newReader(ReadableByteChannel, String)'
+ */
+ public void testNewReaderReadableByteChannelString_InputNull()
+ throws IOException {
+ int bufSize = this.testNum;
+ int readres = 0;
+ CharBuffer charBuf = CharBuffer.allocate(bufSize);
+ this.fins = new FileInputStream(tmpFile);
+ // channel null
+ Reader testReader = Channels.newReader(null, Charset.forName(CODE_SET)
+ .newDecoder(), -1);
+ assertNotNull(testReader);
+ assertFalse(testReader.ready());
+ try {
+ readres = testReader.read((CharBuffer) null);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, readres);
+ try {
+ readres = testReader.read(charBuf);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+
+ this.fins = null;
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ // channel with null inputs
+ testReader = Channels.newReader(rbChannel, Charset.forName(CODE_SET)
+ .newDecoder(), //$NON-NLS-1$
+ -1);
+ assertNotNull(testReader);
+ assertFalse(testReader.ready());
+ try {
+ readres = testReader.read(charBuf);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for
+ * 'java.nio.channels.Channels.newReader(ReadableByteChannel, String)'
+ */
+ public void testNewReaderReadableByteChannelString_internalBufferZero()
+ throws IOException {
+ int bufSize = this.testNum;
+ int readres = 0;
+ CharBuffer charBuf = CharBuffer.allocate(bufSize);
+ this.fins = new FileInputStream(tmpFile);
+ // channel null
+ Reader testReader = Channels.newReader(null, Charset.forName(CODE_SET)
+ .newDecoder(), //$NON-NLS-1$
+ 0);
+ assertNotNull(testReader);
+ assertFalse(testReader.ready());
+ try {
+ readres = testReader.read((CharBuffer) null);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, readres);
+ try {
+ readres = testReader.read(charBuf);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ this.fins = null;
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ // channel with null inputs
+ testReader = Channels.newReader(rbChannel, Charset.forName(CODE_SET)
+ .newDecoder(), //$NON-NLS-1$
+ -1);
+ assertNotNull(testReader);
+ assertFalse(testReader.ready());
+ try {
+ readres = testReader.read(charBuf);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for
+ * 'java.nio.channels.Channels.newReader(ReadableByteChannel, String)'
+ */
+ public void testNewReaderReadableByteChannelString() throws IOException {
+ int bufSize = this.testNum;
+ int readres = 0;
+ CharBuffer charBuf = CharBuffer.allocate(bufSize);
+ this.fins = new FileInputStream(tmpFile);
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ Reader testReader = Channels.newReader(rbChannel, Charset.forName(
+ CODE_SET).newDecoder(), //$NON-NLS-1$
+ -1);
+ Reader testReader_s = Channels.newReader(rbChannel, CODE_SET); //$NON-NLS-1$
+
+ assertEquals(this.fileSize, this.fins.available());
+ // not ready...
+ assertFalse(testReader.ready());
+ assertFalse(testReader_s.ready());
+ // still reads
+ readres = testReader.read(charBuf);
+ assertEquals(bufSize, readres);
+ assertEquals(0, this.fins.available());
+
+ try {
+ readres = testReader.read((CharBuffer) null);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+
+ readres = testReader_s.read(charBuf);
+ assertEquals(0, readres);
+ assertTrue(testReader.ready());
+ assertFalse(testReader_s.ready());
+ }
+
+ /*
+ * Zero-Buffer
+ */
+ public void testNewWriterWritableByteChannelString_internalBufZero()
+ throws IOException {
+
+ String writebuf = ""; //$NON-NLS-1$
+ for (int val = 0; val < this.writebufSize / 2; val++) {
+ writebuf = writebuf + ((char) (val + 64));
+ }
+ // null channel
+ Writer testWriter = Channels.newWriter(null, Charset.forName(CODE_SET)
+ .newEncoder(), //$NON-NLS-1$
+ -1);
+ // can write to buffer
+ testWriter.write(writebuf);
+ try {
+ testWriter.flush();
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testWriter.close();
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+
+ // channel with null input
+ this.fouts = null;
+ WritableByteChannel wbChannel = Channels.newChannel(this.fouts);
+ testWriter = Channels.newWriter(wbChannel, Charset.forName(CODE_SET)
+ .newEncoder(), //$NON-NLS-1$
+ -1);
+ // can write to buffer
+ testWriter.write(writebuf);
+ try {
+ testWriter.flush();
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testWriter.close();
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * this test cannot be passed when buffer set to 0!
+ */
+ public void testNewWriterWritableByteChannelString_InputNull()
+ throws IOException {
+ this.fouts = new FileOutputStream(tmpFile);
+ WritableByteChannel wbChannel = Channels.newChannel(this.fouts);
+ Writer testWriter = Channels.newWriter(wbChannel, Charset.forName(
+ CODE_SET).newEncoder(), //$NON-NLS-1$
+ 1);
+
+ String writebuf = ""; //$NON-NLS-1$
+ for (int val = 0; val < this.writebufSize / 2; val++) {
+ writebuf = writebuf + ((char) (val + 64));
+ }
+ // can write to buffer
+ testWriter.write(writebuf);
+ testWriter.flush();
+ testWriter.close();
+
+ }
+
+ /*
+ * Test method for
+ * 'java.nio.channels.Channels.newWriter(WritableByteChannel, String)'
+ */
+ public void testNewWriterWritableByteChannelString() throws IOException {
+ this.fouts = new FileOutputStream(tmpFile);
+ WritableByteChannel wbChannel = Channels.newChannel(this.fouts);
+ Writer testWriter = Channels.newWriter(wbChannel, CODE_SET); //$NON-NLS-1$
+ Writer testWriter_s = Channels.newWriter(wbChannel, Charset.forName(
+ CODE_SET).newEncoder(), //$NON-NLS-1$
+ -1);
+
+ String writebuf = ""; //$NON-NLS-1$
+ for (int val = 0; val < this.writebufSize / 2; val++) {
+ writebuf = writebuf + ((char) (val + 64));
+ }
+ byte[] bit = new byte[1];
+ bit[0] = 80;
+ this.fouts.write(bit);
+ this.assertFileSizeSame(tmpFile, 1);
+
+ // writer continues to write after '1',what the fouts write
+ testWriter.write(writebuf);
+ testWriter.flush();
+ this.assertFileSizeSame(tmpFile, this.writebufSize / 2 + 1);
+ // testwriter_s does not know if testwrite writes
+ testWriter_s.write(writebuf);
+ testWriter.flush();
+ this.assertFileSizeSame(tmpFile, this.writebufSize / 2 + 1);
+ // testwriter_s even does not know if himself writes?
+ testWriter_s.write(writebuf);
+ testWriter.flush();
+ this.assertFileSizeSame(tmpFile, this.writebufSize / 2 + 1);
+
+ // close the fouts, no longer writable for testWriter
+ for (int val = 0; val < this.writebufSize; val++) {
+ writebuf = writebuf + ((char) (val + 64));
+ }
+ this.fouts.close();
+ testWriter_s.write(writebuf);
+ testWriter.flush();
+ this.assertFileSizeSame(tmpFile, this.writebufSize / 2 + 1);
+ }
+
+ /**
+ * @tests java.nio.channels.Channels#newReader(ReadableByteChannel channel,
+ * String charsetName)
+ */
+ public void test_newReader_LReadableByteChannel_LString()
+ throws IOException {
+ InetSocketAddress localAddr = new InetSocketAddress("127.0.0.1",
+ Support_PortManager.getNextPort());
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(localAddr);
+
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(localAddr);
+ sc.configureBlocking(false);
+ assertFalse(sc.isBlocking());
+
+ ssc.accept().close();
+ ssc.close();
+ assertFalse(sc.isBlocking());
+
+ Reader reader = Channels.newReader(sc, "UTF16");
+ int i = reader.read();
+ assertEquals(-1, i);
+
+ try {
+ Channels.newInputStream(sc).read();
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+
+ sc.close();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java
new file mode 100644
index 0000000..eca50a3
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.ClosedByInterruptException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for ClosedByInterruptException
+ */
+public class ClosedByInterruptExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new ClosedByInterruptException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new ClosedByInterruptException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java
new file mode 100644
index 0000000..57b5d12
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.ClosedChannelException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for ClosedChannelException
+ */
+public class ClosedChannelExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new ClosedChannelException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new ClosedChannelException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java
new file mode 100644
index 0000000..006b88f
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.ClosedSelectorException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for ClosedSelectorException
+ */
+public class ClosedSelectorExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new ClosedSelectorException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new ClosedSelectorException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java
new file mode 100644
index 0000000..d293d86
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.ConnectionPendingException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for ConnectionPendingException
+ */
+public class ConnectionPendingExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new ConnectionPendingException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new ConnectionPendingException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
new file mode 100644
index 0000000..b1c6143
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
@@ -0,0 +1,2643 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.UnresolvedAddressException;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.nio.channels.spi.SelectorProvider;
+import java.security.Permission;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/**
+ * Test for DatagramChannel
+ *
+ */
+public class DatagramChannelTest extends TestCase {
+
+ private static final int CAPACITY_NORMAL = 200;
+
+ private static final int CAPACITY_1KB = 1024;
+
+ private static final int CAPACITY_64KB = 65536;
+
+ private static final int CAPACITY_ZERO = 0;
+
+ private static final int CAPACITY_ONE = 1;
+
+ private static final int TIME_UNIT = 500;
+
+ private InetSocketAddress localAddr1;
+
+ private InetSocketAddress localAddr2;
+
+ private DatagramChannel channel1;
+
+ private DatagramChannel channel2;
+
+ private DatagramSocket datagramSocket1;
+
+ private DatagramSocket datagramSocket2;
+
+ // The port to be used in test cases.
+ private int testPort;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.channel1 = DatagramChannel.open();
+ this.channel2 = DatagramChannel.open();
+ int[] ports = Support_PortManager.getNextPortsForUDP(5);
+ this.localAddr1 = new InetSocketAddress("127.0.0.1", ports[0]);
+ this.localAddr2 = new InetSocketAddress("127.0.0.1", ports[1]);
+ this.datagramSocket1 = new DatagramSocket(ports[2]);
+ this.datagramSocket2 = new DatagramSocket(ports[3]);
+ testPort = ports[4];
+ }
+
+ protected void tearDown() throws Exception {
+ if (null != this.channel1) {
+ try {
+ this.channel1.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ if (null != this.channel2) {
+ try {
+ this.channel2.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ if (null != this.datagramSocket1) {
+ try {
+ this.datagramSocket1.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ if (null != this.datagramSocket2) {
+ try {
+ this.datagramSocket2.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ localAddr1 = null;
+ localAddr2 = null;
+ super.tearDown();
+ }
+
+ // -------------------------------------------------------------------
+ // Test for methods in abstract class.
+ // -------------------------------------------------------------------
+ /*
+ * Test method for 'java.nio.channels.DatagramChannel.validOps()'
+ */
+ public void testValidOps() {
+ MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+ .provider());
+ MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+ int val = this.channel1.validOps();
+ assertEquals(5, val);
+ assertEquals(val, testMock.validOps());
+ assertEquals(val, testMocknull.validOps());
+ }
+
+ /*
+ * Test method for 'java.nio.channels.DatagramChannel.open()'
+ */
+ public void testOpen() {
+ MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+ .provider());
+ MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+ assertNull(testMocknull.provider());
+ assertNotNull(testMock.provider());
+ assertEquals(this.channel1.provider(), testMock.provider());
+ assertEquals(5, testMock.validOps());
+ }
+
+ /*
+ * Test method for 'java.nio.channels.DatagramChannel.read(ByteBuffer)'
+ */
+ public void testReadByteBufferArray() throws IOException {
+ final int testNum = 0;
+ long readres = testNum;
+ MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+ .provider());
+ MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+ int bufSize = 10;
+ ByteBuffer[] readBuf = null;
+ try {
+ this.channel1.read(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ readres = testMock.read(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ readBuf = new ByteBuffer[bufSize];
+ try {
+ readres = this.channel1.read(readBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ readres = testMock.read(readBuf);
+ assertEquals(testNum, readres);
+ readres = testMocknull.read(readBuf);
+ assertEquals(testNum, readres);
+ }
+
+ /*
+ * Test method for 'java.nio.channels.DatagramChannel.read(ByteBuffer)'
+ */
+ public void testReadByteBufferArray_BufNull() throws IOException {
+ MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+ .provider());
+ MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+
+ ByteBuffer[] readBuf = null;
+ try {
+ this.channel1.read(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMock.read(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMocknull.read(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for 'java.nio.channels.DatagramChannel.write(ByteBuffer)'
+ */
+ public void testWriteByteBuffer() throws IOException {
+ MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+ .provider());
+ MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+ int bufSize = 10;
+ ByteBuffer[] readBuf = null;
+ try {
+ this.channel1.write(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMock.write(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ readBuf = new ByteBuffer[bufSize];
+ try {
+ this.channel1.write(readBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ long writeres = 0;
+ writeres = testMock.write(readBuf);
+
+ assertEquals(0, writeres);
+ writeres = testMocknull.write(readBuf);
+ assertEquals(0, writeres);
+ }
+
+ /*
+ * Test method for 'java.nio.channels.DatagramChannel.write(ByteBuffer)'
+ */
+ public void testWriteByteBuffer_Bufnull() throws IOException {
+ MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+ .provider());
+ MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+ ByteBuffer[] readBuf = null;
+ try {
+ this.channel1.write(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMock.write(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMocknull.write(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Test for socket()
+ // -------------------------------------------------------------------
+
+ /**
+ * Test method for 'DatagramChannelImpl.socket()'
+ *
+ * @throws SocketException
+ */
+ public void testSocket_BasicStatusBeforeConnect() throws SocketException {
+ assertFalse(this.channel1.isConnected());// not connected
+ DatagramSocket s1 = this.channel1.socket();
+ assertSocketBeforeConnect(s1);
+ DatagramSocket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.socket()'
+ *
+ * @throws IOException
+ */
+ public void testSocket_Block_BasicStatusAfterConnect() throws IOException {
+ this.channel1.connect(localAddr1);
+ DatagramSocket s1 = this.channel1.socket();
+ assertSocketAfterConnect(s1);
+ DatagramSocket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ public void testSocket_NonBlock_BasicStatusAfterConnect()
+ throws IOException {
+ this.channel1.connect(localAddr1);
+ this.channel1.configureBlocking(false);
+ DatagramSocket s1 = this.channel1.socket();
+ assertSocketAfterConnect(s1);
+ DatagramSocket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.socket()'
+ *
+ * @throws IOException
+ */
+ public void testSocket_ActionsBeforeConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ DatagramSocket s = this.channel1.socket();
+ assertSocketActionBeforeConnect(s);
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.socket()'
+ *
+ * @throws IOException
+ */
+ public void testSocket_Block_ActionsAfterConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ this.channel1.connect(localAddr1);
+ DatagramSocket s = this.channel1.socket();
+ assertSocketActionAfterConnect(s);
+ }
+
+ public void testSocket_NonBlock_ActionsAfterConnect() throws IOException {
+ this.channel1.connect(localAddr1);
+ this.channel1.configureBlocking(false);
+ DatagramSocket s = this.channel1.socket();
+ assertSocketActionAfterConnect(s);
+ }
+
+ private void assertSocketBeforeConnect(DatagramSocket s)
+ throws SocketException {
+ assertFalse(s.isBound());
+ assertFalse(s.isClosed());
+ assertFalse(s.isConnected());
+ assertFalse(s.getBroadcast());
+ assertFalse(s.getReuseAddress());
+ assertNull(s.getInetAddress());
+ assertEquals(s.getLocalAddress().getHostAddress(), "0.0.0.0");
+ assertEquals(s.getLocalPort(), 0);
+ assertNull(s.getLocalSocketAddress());
+ assertEquals(s.getPort(), -1);
+ assertTrue(s.getReceiveBufferSize() >= 8192);
+ assertNull(s.getRemoteSocketAddress());
+ assertFalse(s.getReuseAddress());
+ assertTrue(s.getSendBufferSize() >= 8192);
+ assertEquals(s.getSoTimeout(), 0);
+ assertEquals(s.getTrafficClass(), 0);
+ }
+
+ private void assertSocketAfterConnect(DatagramSocket s)
+ throws SocketException {
+ assertTrue(s.isBound());
+ assertFalse(s.isClosed());
+ assertTrue(s.isConnected());
+ assertFalse(s.getBroadcast());
+ assertFalse(s.getReuseAddress());
+ assertSame(s.getInetAddress(), localAddr1.getAddress());
+ assertEquals(s.getLocalAddress(), localAddr1.getAddress());
+ assertNotNull(s.getLocalSocketAddress());
+ assertEquals(s.getPort(), localAddr1.getPort());
+ assertTrue(s.getReceiveBufferSize() >= 8192);
+ // not same , but equals
+ assertNotSame(s.getRemoteSocketAddress(), (SocketAddress) localAddr1);
+ assertEquals(s.getRemoteSocketAddress(), (SocketAddress) localAddr1);
+ assertFalse(s.getReuseAddress());
+ assertTrue(s.getSendBufferSize() >= 8192);
+ assertEquals(s.getSoTimeout(), 0);
+ assertEquals(s.getTrafficClass(), 0);
+ }
+
+ private void assertSocketActionBeforeConnect(DatagramSocket s)
+ throws IOException {
+ s.connect(localAddr2);
+ assertFalse(this.channel1.isConnected());
+ assertFalse(s.isConnected());
+
+ s.disconnect();
+ assertFalse(this.channel1.isConnected());
+ assertFalse(s.isConnected());
+
+ s.close();
+ assertTrue(s.isClosed());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ private void assertSocketActionAfterConnect(DatagramSocket s)
+ throws IOException {
+ assertEquals(s.getPort(), localAddr1.getPort());
+ s.connect(localAddr2);
+ assertTrue(this.channel1.isConnected());
+ assertTrue(s.isConnected());
+ // not changed
+ assertEquals(s.getPort(), localAddr1.getPort());
+
+ s.disconnect();
+ assertFalse(this.channel1.isConnected());
+ assertFalse(s.isConnected());
+
+ s.close();
+ assertTrue(s.isClosed());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ // -------------------------------------------------------------------
+ // Test for configureBlocking()
+ // -------------------------------------------------------------------
+
+ public void testConfigureBlocking_Read() throws Exception {
+ assertTrue(this.channel1.isBlocking());
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_1KB);
+ new Thread() {
+ public void run() {
+ try {
+ sleep(TIME_UNIT * 5);
+ channel1.configureBlocking(false);
+ assertFalse(channel1.isBlocking());
+ datagramSocket1.close();
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }.start();
+ SocketAddress addr = channel1.receive(buf);
+ assertNull(addr);
+ }
+
+ // -------------------------------------------------------------------
+ // Test for isConnected()
+ // -------------------------------------------------------------------
+
+ /**
+ * Test method for 'DatagramChannelImpl.isConnected()'
+ *
+ * @throws IOException
+ */
+ public void testIsConnected_WithServer() throws IOException {
+ connectLocalServer();
+ disconnectAfterConnected();
+ this.datagramSocket1.close();
+ this.channel1.close();
+ assertFalse(this.channel1.isConnected());
+ }
+
+ // -------------------------------------------------------------------
+ // Test for connect()
+ // -------------------------------------------------------------------
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ */
+ public void testConnect_BlockWithServer() throws IOException {
+ // blocking mode
+ assertTrue(this.channel1.isBlocking());
+ connectLocalServer();
+ datagramSocket1.close();
+ disconnectAfterConnected();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ */
+ public void testConnect_BlockNoServer() throws IOException {
+ connectWithoutServer();
+ disconnectAfterConnected();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ */
+ public void testConnect_NonBlockWithServer() throws IOException {
+ // Non blocking mode
+ this.channel1.configureBlocking(false);
+ connectLocalServer();
+ datagramSocket1.close();
+ disconnectAfterConnected();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ */
+ public void testConnect_Null() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ try {
+ this.channel1.connect(null);
+ fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ */
+ public void testConnect_UnsupportedType() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ class SubSocketAddress extends SocketAddress {
+ private static final long serialVersionUID = 1L;
+
+ public SubSocketAddress() {
+ super();
+ }
+ }
+ SocketAddress newTypeAddress = new SubSocketAddress();
+ try {
+ this.channel1.connect(newTypeAddress);
+ fail("Should throw an UnsupportedAddressTypeException here.");
+ } catch (UnsupportedAddressTypeException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ */
+ public void testConnect_Unresolved() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ InetSocketAddress unresolved = new InetSocketAddress(
+ "unresolved address", 1080);
+ try {
+ this.channel1.connect(unresolved);
+ fail("Should throw an UnresolvedAddressException here."); //$NON-NLS-1$
+ } catch (UnresolvedAddressException e) {
+ // OK.
+ }
+ }
+
+ public void testConnect_EmptyHost() throws Exception {
+ assertFalse(this.channel1.isConnected());
+
+ assertEquals(this.channel1, this.channel1
+ .connect(new InetSocketAddress("", 1081))); //$NON-NLS-1$
+
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ *
+ */
+ public void testConnect_ClosedChannelException() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ClosedChannelException."); //$NON-NLS-1$
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ *
+ */
+ public void testConnect_IllegalStateException() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isConnected());
+ // connect after connected.
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw IllegalStateException."); //$NON-NLS-1$
+ } catch (IllegalStateException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ *
+ */
+ public void testConnect_CheckOpenBeforeStatus() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isConnected());
+ // connect after connected.
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ // checking open is before checking status.
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ClosedChannelException."); //$NON-NLS-1$
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ private void disconnectAfterConnected() throws IOException {
+ assertTrue(this.channel1.isConnected());
+ this.channel1.disconnect();
+ assertFalse(this.channel1.isConnected());
+ }
+
+ private void disconnectAfterClosed() throws IOException {
+ assertFalse(this.channel1.isOpen());
+ assertFalse(this.channel1.isConnected());
+ this.channel1.disconnect();
+ assertFalse(this.channel1.isConnected());
+ }
+
+ private void connectLocalServer() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.datagramSocket1.isBound());
+ assertSame(this.channel1, this.channel1.connect(localAddr1));
+ assertTrue(this.channel1.isConnected());
+ }
+
+ private void connectWithoutServer() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.datagramSocket1.close();
+ assertTrue(this.datagramSocket1.isClosed());
+ assertSame(this.channel1, this.channel1.connect(localAddr1));
+ assertTrue(this.channel1.isConnected());
+ }
+
+ // -------------------------------------------------------------------
+ // Test for disconnect()
+ // -------------------------------------------------------------------
+
+ /**
+ * Test method for 'DatagramChannelImpl.disconnect()'
+ *
+ * @throws IOException
+ */
+ public void testDisconnect_BeforeConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ assertEquals(this.channel1, this.channel1.disconnect());
+ assertFalse(this.channel1.isConnected());
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.disconnect()'
+ *
+ * @throws IOException
+ */
+ public void testDisconnect_UnconnectedClosed() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ assertEquals(this.channel1, this.channel1.disconnect());
+ assertFalse(this.channel1.isConnected());
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.disconnect()'
+ *
+ * @throws IOException
+ */
+ public void testDisconnect_BlockWithServerChannelClosed()
+ throws IOException {
+ assertTrue(this.channel1.isBlocking());
+ connectLocalServer();
+ // disconnect after channel close
+ this.channel1.close();
+ disconnectAfterClosed();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.disconnect()'
+ *
+ * @throws IOException
+ */
+ public void testDisconnect_NonBlockWithServerChannelClosed()
+ throws IOException {
+ this.channel1.configureBlocking(false);
+ connectLocalServer();
+ // disconnect after channel close
+ this.channel1.close();
+ disconnectAfterClosed();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.disconnect()'
+ *
+ * @throws IOException
+ */
+ public void testDisconnect_BlockWithServerServerClosed() throws IOException {
+ assertTrue(this.channel1.isBlocking());
+ connectLocalServer();
+ // disconnect after server close
+ this.datagramSocket1.close();
+ assertTrue(this.channel1.isOpen());
+ assertTrue(this.channel1.isConnected());
+ disconnectAfterConnected();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.disconnect()'
+ *
+ * @throws IOException
+ */
+ public void testDisconnect_NonBlockWithServerServerClosed()
+ throws IOException {
+ this.channel1.configureBlocking(false);
+ assertFalse(this.channel1.isBlocking());
+ connectLocalServer();
+ // disconnect after server close
+ this.datagramSocket1.close();
+ assertTrue(this.channel1.isOpen());
+ assertTrue(this.channel1.isConnected());
+ disconnectAfterConnected();
+ }
+
+ // -------------------------------------------------------------------
+ // Test for receive(): Behavior Without Server.
+ // -------------------------------------------------------------------
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedNull() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ try {
+ this.channel1.receive(null);
+ fail("Should throw a NPE here."); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedReadonly() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL)
+ .asReadOnlyBuffer();
+ assertTrue(dst.isReadOnly());
+ try {
+ this.channel1.receive(dst);
+ fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedBufEmpty() throws Exception {
+ this.channel1.configureBlocking(false);
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ assertNull(this.channel1.receive(dst));
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedBufZero() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_ZERO);
+ assertNull(this.channel1.receive(dst));
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedBufNotEmpty() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ // buf is not empty
+ dst.put((byte) 88);
+ assertEquals(dst.position() + CAPACITY_NORMAL - 1, dst.limit());
+ assertNull(this.channel1.receive(dst));
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedBufFull() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_ONE);
+ // buf is full
+ dst.put((byte) 88);
+ assertEquals(dst.position(), dst.limit());
+ assertNull(this.channel1.receive(dst));
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedClose() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ try {
+ assertNull(this.channel1.receive(dst));
+ fail("Should throw a ClosedChannelException here."); //$NON-NLS-1$
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedCloseNull() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ // checking buffer before checking open
+ try {
+ this.channel1.receive(null);
+ fail("Should throw a NPE here."); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedCloseReadonly() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL)
+ .asReadOnlyBuffer();
+ assertTrue(dst.isReadOnly());
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ try {
+ this.channel1.receive(dst);
+ fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerBufEmpty() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNonBlockNoServer(CAPACITY_NORMAL);
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_BlockNoServerNull() throws Exception {
+ assertTrue(this.channel1.isBlocking());
+ receiveNoServerNull();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerNull() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNoServerNull();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_BlockNoServerReadonly() throws Exception {
+ assertTrue(this.channel1.isBlocking());
+ receiveNoServerReadonly();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerReadonly() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNoServerReadonly();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerBufZero() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNonBlockNoServer(CAPACITY_ZERO);
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerBufNotEmpty() throws Exception {
+ this.channel1.configureBlocking(false);
+ connectWithoutServer();
+ ByteBuffer dst = allocateNonEmptyBuf();
+ assertNull(this.channel1.receive(dst));
+ }
+
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerBufFull() throws Exception {
+ this.channel1.configureBlocking(false);
+ connectWithoutServer();
+ ByteBuffer dst = allocateFullBuf();
+ assertNull(this.channel1.receive(dst));
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_BlockNoServerChannelClose() throws Exception {
+ assertTrue(this.channel1.isBlocking());
+ receiveNoServerChannelClose();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerChannelClose() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNoServerChannelClose();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_BlockNoServerCloseNull() throws Exception {
+ assertTrue(this.channel1.isBlocking());
+ receiveNoServerChannelCloseNull();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerCloseNull() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNoServerChannelCloseNull();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerCloseReadonly() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNoServerChannelCloseReadonly();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_BlockNoServerCloseReadonly() throws Exception {
+ assertTrue(this.channel1.isBlocking());
+ receiveNoServerChannelCloseReadonly();
+ }
+
+ private void receiveNoServerNull() throws IOException {
+ connectWithoutServer();
+ try {
+ this.channel1.receive(null);
+ fail("Should throw a NPE here."); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // OK.
+ }
+ }
+
+ private void receiveNoServerReadonly() throws IOException {
+ connectWithoutServer();
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL)
+ .asReadOnlyBuffer();
+ assertTrue(dst.isReadOnly());
+ try {
+ this.channel1.receive(dst);
+ fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // OK.
+ }
+ }
+
+ private void receiveNonBlockNoServer(int size) throws IOException {
+ connectWithoutServer();
+ ByteBuffer dst = ByteBuffer.allocateDirect(size);
+ assertNull(this.channel1.receive(dst));
+ }
+
+ private void receiveNoServerChannelClose() throws IOException {
+ connectWithoutServer();
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ try {
+ assertNull(this.channel1.receive(dst));
+ fail("Should throw a ClosedChannelException here."); //$NON-NLS-1$
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ private void receiveNoServerChannelCloseNull() throws IOException {
+ connectWithoutServer();
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ try {
+ this.channel1.receive(null);
+ fail("Should throw a NPE here."); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // OK.
+ }
+ }
+
+ private void receiveNoServerChannelCloseReadonly() throws IOException {
+ connectWithoutServer();
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL)
+ .asReadOnlyBuffer();
+ assertTrue(dst.isReadOnly());
+ try {
+ this.channel1.receive(dst);
+ fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // OK.
+ }
+ }
+
+ private ByteBuffer allocateFullBuf() {
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_ONE);
+ // buf is full
+ dst.put((byte) 88);
+ assertEquals(dst.position(), dst.limit());
+ return dst;
+ }
+
+ private ByteBuffer allocateNonEmptyBuf() {
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ // buf is not empty
+ dst.put((byte) 88);
+ dst.put((byte) 99);
+ assertEquals(dst.position() + CAPACITY_NORMAL - 2, dst.limit());
+ return dst;
+ }
+
+ // -------------------------------------------------------------------
+ // Test for send(): Behavior without server.
+ // -------------------------------------------------------------------
+
+ private void sendDataBlocking(InetSocketAddress addr, ByteBuffer writeBuf)
+ throws IOException {
+ InetSocketAddress ipAddr = addr;
+ assertEquals(CAPACITY_NORMAL, this.channel1.send(writeBuf, ipAddr));
+ assertTrue(this.channel1.isOpen());
+ assertTrue(this.channel1.isBlocking());
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ }
+
+ private void sendDataNonBlocking(InetSocketAddress addr, ByteBuffer writeBuf)
+ throws IOException {
+ InetSocketAddress ipAddr = addr;
+ this.channel1.configureBlocking(false);
+ assertEquals(CAPACITY_NORMAL, this.channel1.send(writeBuf, ipAddr));
+ assertTrue(this.channel1.isOpen());
+ assertFalse(this.channel1.isBlocking());
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ }
+
+ /*
+ * Test method for 'DatagramChannelImpl.send(ByteBuffer, SocketAddress)'
+ */
+ public void testSend_NoServerBlockingCommon() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ sendDataBlocking(localAddr1, writeBuf);
+ }
+
+ public void testSend_NoServerNonblockingCommon() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ sendDataNonBlocking(localAddr1, writeBuf);
+ }
+
+ public void testSend_NoServerTwice() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ sendDataBlocking(localAddr1, writeBuf);
+ // can not buffer twice!
+ assertEquals(0, this.channel1.send(writeBuf, localAddr1));
+ try {
+ channel1.send(writeBuf, localAddr2);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // correct
+ }
+ }
+
+ public void testSend_NoServerNonBlockingTwice() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ sendDataNonBlocking(localAddr1, writeBuf);
+ // can not buffer twice!
+ assertEquals(0, this.channel1.send(writeBuf, localAddr1));
+ try {
+ channel1.send(writeBuf, localAddr2);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // correct
+ }
+ }
+
+ public void testSend_NoServerBufNull() throws IOException {
+ try {
+ sendDataBlocking(localAddr1, null);
+ fail("Should throw a NPE here.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testSend_NoServerBufNullTwice() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ try {
+ sendDataBlocking(localAddr1, null);
+ fail("Should throw a NPE here.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ sendDataBlocking(localAddr1, writeBuf);
+ try {
+ channel1.send(null, localAddr2);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testSend_NoServerAddrNull() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ try {
+ sendDataBlocking(null, writeBuf);
+ fail("Should throw a NPE here.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testSend_NoServerAddrNullTwice() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ try {
+ sendDataBlocking(null, writeBuf);
+ fail("Should throw a NPE here.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ sendDataBlocking(localAddr1, writeBuf);
+ try {
+ channel1.send(writeBuf, null);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Test for receive()and send(): Send and Receive with Real Data
+ // -------------------------------------------------------------------
+
+ public void testReceiveSend_Block_Normal() throws Exception {
+ this.channel1.socket().bind(localAddr2);
+ sendByChannel("some normal string in testReceiveSend_Normal",
+ localAddr2);
+ receiveByChannel(CAPACITY_NORMAL, localAddr2,
+ "some normal string in testReceiveSend_Normal");
+ }
+
+ public void testReceiveSend_Block_NotBound() throws Exception {
+ // not bound
+ sendByChannel("some normal string in testReceiveSend_Normal",
+ localAddr2);
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+ assertNull(channel1.receive(buf));
+ assertFalse(channel1.socket().isBound());
+ }
+
+ public void testReceiveSend_NonBlock_NotBound() throws Exception {
+ // not bound
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+ sendByChannel("some normal string in testReceiveSend_Normal",
+ localAddr2);
+ ByteBuffer buf = ByteBuffer.wrap(new byte[CAPACITY_NORMAL]);
+ assertNull((InetSocketAddress) this.channel1.receive(buf));
+ }
+
+ public void testReceiveSend_Block_Normal_S2C() throws Exception {
+ this.channel1.socket().bind(localAddr2);
+ sendByDatagramSocket(
+ "some normal string in testReceiveSend_Normal_S2C", localAddr2);
+ receiveByChannel(CAPACITY_NORMAL, localAddr2,
+ "some normal string in testReceiveSend_Normal_S2C");
+ }
+
+ public void testReceiveSend_Block_Normal_C2S() throws Exception {
+ this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+ String str1 = "some normal string in testReceiveSend_Normal_C2S";
+ sendByChannel(str1, localAddr2);
+ receiveByDatagramSocket(CAPACITY_NORMAL, localAddr2, str1);
+ }
+
+ public void testReceiveSend_NonBlock_Normal_C2S() throws Exception {
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+ this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+ String str1 = "some normal string in testReceiveSend_Normal_C2S";
+ sendByChannel(str1, localAddr2);
+ receiveByDatagramSocket(CAPACITY_NORMAL, localAddr2, str1);
+ }
+
+ public void testReceiveSend_Normal_S2S() throws Exception {
+ String msg = "normal string in testReceiveSend_Normal_S2S";
+ this.datagramSocket1 = new DatagramSocket(testPort);
+ DatagramPacket rdp = new DatagramPacket(msg.getBytes(), msg.length(),
+ localAddr2);
+ datagramSocket2 = new DatagramSocket(localAddr2.getPort());
+ this.datagramSocket1.send(rdp);
+ byte[] buf = new byte[CAPACITY_NORMAL];
+ this.datagramSocket2.setSoTimeout(TIME_UNIT);
+ rdp = new DatagramPacket(buf, buf.length);
+ this.datagramSocket2.receive(rdp);
+ assertEquals(new String(buf, 0, CAPACITY_NORMAL).trim(), msg);
+ }
+
+ public void testReceiveSend_Block_Empty() throws Exception {
+ this.channel1.socket().bind(localAddr2);
+ sendByChannel("", localAddr2);
+ receiveByChannel(CAPACITY_NORMAL, localAddr2, "");
+ }
+
+ public void testReceiveSend_NonBlock_Empty() throws Exception {
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+ this.channel1.socket().bind(localAddr2);
+ sendByChannel("", localAddr2);
+ receiveByChannel(CAPACITY_NORMAL, localAddr2, "");
+ }
+
+ public void testReceiveSend_Block_Empty_S2C() throws Exception {
+ this.channel1.socket().bind(localAddr2);
+ sendByDatagramSocket("", localAddr2);
+ receiveByChannel(CAPACITY_NORMAL, localAddr2, "");
+ }
+
+ public void testReceiveSend_NonBlock_Empty_S2C() throws Exception {
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+ this.channel1.socket().bind(localAddr2);
+ sendByDatagramSocket("", localAddr2);
+ receiveByChannel(CAPACITY_NORMAL, localAddr2, "");
+ }
+
+ public void testReceiveSend_Block_Empty_C2S() throws Exception {
+ this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+ sendByChannel("", localAddr2);
+ receiveByDatagramSocket(CAPACITY_NORMAL, localAddr2, "");
+ }
+
+ public void testReceiveSend_NonBlock_Empty_C2S() throws Exception {
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+ this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+ sendByChannel("", localAddr2);
+ receiveByDatagramSocket(CAPACITY_NORMAL, localAddr2, "");
+ }
+
+ public void testReceiveSend_Empty_S2S() throws Exception {
+ String msg = "";
+ this.datagramSocket1 = new DatagramSocket(testPort);
+ DatagramPacket rdp = new DatagramPacket(msg.getBytes(), msg.length(),
+ localAddr2);
+ datagramSocket2 = new DatagramSocket(localAddr2.getPort());
+ this.datagramSocket1.send(rdp);
+ byte[] buf = new byte[CAPACITY_NORMAL];
+ this.datagramSocket2.setSoTimeout(TIME_UNIT);
+ rdp = new DatagramPacket(buf, buf.length);
+ this.datagramSocket2.receive(rdp);
+ assertEquals(new String(buf, 0, CAPACITY_NORMAL).trim(), msg);
+ }
+
+ public void testReceiveSend_Block_Oversize() throws Exception {
+ this.channel1.socket().bind(localAddr2);
+ sendByChannel("0123456789", localAddr2);
+ receiveByChannel(5, localAddr2, "01234");
+ }
+
+ public void testReceiveSend_Block_Oversize_C2S() throws Exception {
+ this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+ sendByChannel("0123456789", localAddr2);
+ receiveByDatagramSocket(5, localAddr2, "01234");
+ }
+
+ public void testReceiveSend_NonBlock_Oversize_C2S() throws Exception {
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+ this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+ sendByChannel("0123456789", localAddr2);
+ receiveByDatagramSocket(5, localAddr2, "01234");
+ }
+
+ public void testReceiveSend_Block_Oversize_S2C() throws Exception {
+ this.channel1.socket().bind(localAddr2);
+ sendByDatagramSocket("0123456789", localAddr2);
+ receiveByChannel(5, localAddr2, "01234");
+ }
+
+ public void testReceiveSend_8K() throws Exception {
+ StringBuffer str8k = new StringBuffer();
+ for (int i = 0; i < 8 * CAPACITY_1KB; i++) {
+ str8k.append("a");
+ }
+ String str = str8k.toString();
+ this.channel1.socket().bind(localAddr2);
+ sendByChannel(str, localAddr2);
+ receiveByChannel(8 * CAPACITY_1KB, localAddr2, str);
+ }
+
+ public void testReceiveSend_64K() throws Exception {
+ StringBuffer str64k = new StringBuffer();
+ for (int i = 0; i < CAPACITY_64KB; i++) {
+ str64k.append("a");
+ }
+ String str = str64k.toString();
+ try {
+ Thread.sleep(TIME_UNIT);
+ channel2.send(ByteBuffer.wrap(str.getBytes()), localAddr1);
+ fail("Should throw SocketException!");
+ } catch (SocketException e) {
+ //expected
+ }
+ }
+
+ private void sendByChannel(String data, InetSocketAddress address)
+ throws Exception {
+ try {
+ assertEquals(data.length(), this.channel2.send(ByteBuffer.wrap(data
+ .getBytes()), address));
+ } finally {
+ this.channel2.close();
+ }
+ }
+
+ private void sendByDatagramSocket(String data, InetSocketAddress address)
+ throws Exception {
+ this.datagramSocket1 = new DatagramSocket(testPort);
+ DatagramPacket rdp = new DatagramPacket(data.getBytes(), data.length(),
+ address);
+ this.datagramSocket1.send(rdp);
+ }
+
+ private void receiveByChannel(int bufSize, InetSocketAddress address,
+ String expectedString) throws IOException {
+ try {
+ ByteBuffer buf = ByteBuffer.wrap(new byte[bufSize]);
+ InetSocketAddress returnAddr = null;
+ long startTime = System.currentTimeMillis();
+ do {
+ returnAddr = (InetSocketAddress) this.channel1.receive(buf);
+ // continue loop when channel1 is non-blocking and no data was
+ // received.
+ if (channel1.isBlocking() || null != returnAddr) {
+ break;
+ }
+ // avoid dead loop
+ assertTimeout(startTime, 10000);
+ } while (true);
+ int length = returnAddr.getAddress().getAddress().length;
+ for (int i = 0; i < length; i++) {
+ assertEquals(returnAddr.getAddress().getAddress()[i],
+ InetAddress.getByName("127.0.0.1").getAddress()[i]);
+ }
+ // port is NOT equal
+ assertFalse(returnAddr.getPort() == address.getPort());
+ assertEquals(new String(buf.array(), 0, bufSize).trim(),
+ expectedString);
+ } finally {
+ this.channel1.close();
+ }
+ }
+
+ /*
+ * Fails if the difference between current time and start time is greater
+ * than timeout.
+ */
+ private void assertTimeout(long startTime, long timeout) {
+ long currentTime = System.currentTimeMillis();
+ if ((currentTime - startTime) > timeout) {
+ fail("Timeout");
+ }
+ }
+
+ private void receiveByDatagramSocket(int bufSize,
+ InetSocketAddress address, String expectedString)
+ throws IOException {
+ byte[] buf = new byte[bufSize];
+ this.datagramSocket1.setSoTimeout(6000);
+ DatagramPacket rdp = new DatagramPacket(buf, buf.length);
+ this.datagramSocket1.receive(rdp);
+ assertEquals(new String(buf, 0, bufSize).trim(), expectedString);
+ }
+
+ // -------------------------------------------------------------------
+ // Test for security check of receive and send
+ // -------------------------------------------------------------------
+
+ private class mockAddress extends SocketAddress {
+ private static final long serialVersionUID = 1L;
+ }
+
+ public void testSend_MockSocketAddress() throws Exception {
+
+ SocketAddress badAddr = new mockAddress();
+ final SecurityManager sm = System.getSecurityManager();
+ System.setSecurityManager(new MockSecurityManager());
+ try {
+ // no problem.
+ this.channel1
+ .send(ByteBuffer.allocate(CAPACITY_NORMAL), localAddr1);
+ // re open
+ this.channel1.close();
+ this.channel1 = DatagramChannel.open();
+ try {
+ this.channel1.send(ByteBuffer.allocate(CAPACITY_NORMAL),
+ badAddr);
+ fail("Should throw ClassCastException");
+ } catch (ClassCastException e) {
+ // ok
+ }
+ } finally {
+ System.setSecurityManager(sm);
+ }
+ }
+
+ public void testRead_Security() throws Exception {
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+ String strHello = "hello";
+ localAddr1 = new InetSocketAddress("127.0.0.1", testPort);
+ this.channel1.socket().bind(localAddr1);
+ this.channel2.socket().bind(localAddr2);
+ this.channel1.connect(localAddr2);
+ this.channel2.send(ByteBuffer.wrap(strHello.getBytes()), localAddr1);
+ final SecurityManager sm = System.getSecurityManager();
+ System.setSecurityManager(new MockSecurityManager("10.0.0.1"));
+
+ // seems no security check
+ try {
+ assertEquals(strHello.length(), this.channel1.read(buf));
+ } finally {
+ System.setSecurityManager(sm);
+ }
+ }
+
+ public void testReceive_Peek_Security_Nonblocking() throws Exception {
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+ String strHello = "hello";
+ localAddr1 = new InetSocketAddress("127.0.0.1", testPort);
+ this.channel1.socket().bind(localAddr1);
+ sendByChannel(strHello, localAddr1);
+ final SecurityManager sm = System.getSecurityManager();
+ try {
+ System.setSecurityManager(new MockSecurityManager("10.0.0.1"));
+ this.channel1.configureBlocking(false);
+ // for accepted addr, no problem.
+ assertNull(this.channel1.receive(buf));
+ } finally {
+ System.setSecurityManager(sm);
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Test for write()
+ // -------------------------------------------------------------------
+
+ private void connectWriteBuf(InetSocketAddress ipAddr, ByteBuffer buf)
+ throws IOException {
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(buf));
+ assertEquals(0, this.channel1.write(buf));
+ }
+
+ private void noconnectWrite(ByteBuffer buf) throws IOException {
+ try {
+ this.channel1.write(buf);
+ fail("should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for 'DatagramChannelImpl.write(ByteBuffer)'
+ */
+ public void testWriteByteBuffer_Block() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ connectWriteBuf(localAddr1, writeBuf);
+ }
+
+ public void testWriteByteBuffer_NonBlock() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ this.channel1.configureBlocking(false);
+ connectWriteBuf(localAddr1, writeBuf);
+ }
+
+ public void testWriteByteBuffer_Block_closed() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ noconnectWrite(writeBuf);
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ this.channel1.close();
+ try {
+ channel1.write(writeBuf);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBuffer_NonBlock_closed() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ // non block mode
+ this.channel1.configureBlocking(false);
+ noconnectWrite(writeBuf);
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ this.channel1.close();
+ try {
+ channel1.write(writeBuf);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBuffer_Block_BufNull() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(0);
+ InetSocketAddress ipAddr = localAddr1;
+ try {
+ this.channel1.write((ByteBuffer) null);
+ fail("Should throw NPE.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ try {
+ this.channel1.write((ByteBuffer) null);
+ fail("Should throw NPE.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, this.channel1.write(writeBuf));
+ datagramSocket1.close();
+ try {
+ this.channel1.write((ByteBuffer) null);
+ fail("Should throw NPE.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBuffer_NonBlock_BufNull() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(0);
+ InetSocketAddress ipAddr = localAddr1;
+
+ // non block mode
+ this.channel1.configureBlocking(false);
+
+ try {
+ this.channel1.write((ByteBuffer) null);
+ fail("Should throw NPE.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ try {
+ this.channel1.write((ByteBuffer) null);
+ fail("Should throw NPE.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, this.channel1.write(writeBuf));
+ datagramSocket1.close();
+ try {
+ this.channel1.write((ByteBuffer) null);
+ fail("Should throw NPE.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for 'DatagramChannelImpl.write(ByteBuffer[], int, int)'
+ */
+ public void testWriteByteBufferArrayIntInt_Block() throws IOException {
+ ByteBuffer[] writeBuf = new ByteBuffer[2];
+ writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ writeBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ try {
+ this.channel1.write(writeBuf, 0, 2);
+ fail("Should throw NotYetConnectedException.");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+ // cannot be buffered again!
+ assertEquals(0, this.channel1.write(writeBuf, 0, 1));
+
+ }
+
+ public void testWriteByteBufferArrayIntInt_NonBlock() throws IOException {
+ ByteBuffer[] writeBuf = new ByteBuffer[2];
+ writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ writeBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ // non-block mode
+ this.channel1.configureBlocking(false);
+ try {
+ this.channel1.write(writeBuf, 0, 2);
+ fail("Should throw NotYetConnectedException.");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+ // cannot be buffered again!
+ assertEquals(0, this.channel1.write(writeBuf, 0, 1));
+
+ }
+
+ public void testWriteByteBufferArrayIntInt_NoConnectIndexBad()
+ throws IOException {
+ ByteBuffer[] writeBuf = new ByteBuffer[2];
+ writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ writeBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ try {
+ this.channel1.write(writeBuf, -1, 2);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ try {
+ this.channel1.write(writeBuf, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+ // cannot be buffered again!
+ assertEquals(0, this.channel1.write(writeBuf, 0, 1));
+ }
+
+ public void testWriteByteBufferArrayIntInt_ConnectedIndexBad()
+ throws IOException {
+ ByteBuffer[] writeBuf = new ByteBuffer[2];
+ writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ writeBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ try {
+ this.channel1.write(writeBuf, -1, 2);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ try {
+ this.channel1.write(writeBuf, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBufferArrayIntInt_BufNullNoConnect()
+ throws IOException {
+ ByteBuffer[] writeBuf = new ByteBuffer[2];
+ writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ try {
+ this.channel1.write(null, 0, 2);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ this.channel1.write(null, -1, 2);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ try {
+ this.channel1.write(null, 0, 3);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBufferArrayIntInt_BufNullConnect()
+ throws IOException {
+ ByteBuffer[] writeBuf = new ByteBuffer[2];
+ writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ try {
+ this.channel1.write(null, 0, 2);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ this.channel1.write(writeBuf, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ datagramSocket1.close();
+ try {
+ this.channel1.write(null, 0, 2);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Test for read()
+ // -------------------------------------------------------------------
+
+ /*
+ * Test method for 'DatagramChannelImpl.read(ByteBuffer)'
+ */
+ public void testReadByteBuffer() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ try {
+ this.channel1.read(readBuf);
+ fail("should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isConnected());
+ this.channel1.configureBlocking(false);
+ // note : blocking-mode will make the read process endless!
+ assertEquals(0, this.channel1.read(readBuf));
+ this.channel1.close();
+ try {
+ this.channel1.read(readBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ public void testReadByteBuffer_bufNull() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocateDirect(0);
+ InetSocketAddress ipAddr = localAddr1;
+ try {
+ this.channel1.read(readBuf);
+ fail("should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ try {
+ channel1.read((ByteBuffer) null);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ this.channel1.configureBlocking(false);
+ // note : blocking-mode will make the read process endless!
+ assertEquals(0, this.channel1.read(readBuf));
+ datagramSocket1.close();
+ }
+
+ /*
+ * Test method for 'DatagramChannelImpl.read(ByteBuffer[], int, int)'
+ */
+ public void testReadByteBufferArrayIntInt() throws IOException {
+ ByteBuffer[] readBuf = new ByteBuffer[2];
+ readBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ readBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ try {
+ this.channel1.read(readBuf, 0, 2);
+ fail("should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ this.channel1.configureBlocking(false);
+ // note : blocking-mode will make the read process endless!
+ assertEquals(0, this.channel1.read(readBuf, 0, 1));
+ assertEquals(0, this.channel1.read(readBuf, 0, 2));
+ datagramSocket1.close();
+ //regression test for HARMONY-932
+ try {
+ DatagramChannel.open().read(new ByteBuffer[] {}, 2, Integer.MAX_VALUE);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ try {
+ DatagramChannel.open().write(new ByteBuffer[] {}, 2, Integer.MAX_VALUE);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ try {
+ DatagramChannel.open().write((ByteBuffer[])null, -1, 2);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ }
+
+ public void testReadByteBufferArrayIntInt_BufNull() throws IOException {
+ ByteBuffer[] readBuf = new ByteBuffer[2];
+ readBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ try {
+ this.channel1.read(null, 0, 0);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ this.channel1.configureBlocking(false);
+ // note : blocking-mode will make the read process endless!
+ try {
+ this.channel1.read(null, 0, 0);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, this.channel1.read(readBuf, 0, 1));
+ try {
+ this.channel1.read(readBuf, 0, 2);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ this.channel1.read(readBuf, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ datagramSocket1.close();
+ }
+
+ // -------------------------------------------------------------------
+ // test read and write
+ // -------------------------------------------------------------------
+
+ public void testReadWrite_configureBlock() throws Exception {
+ byte[] targetArray = new byte[2];
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+
+ new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(TIME_UNIT);
+ channel1.configureBlocking(false);
+ channel1.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ }.start();
+ try {
+ this.channel1.read(targetBuf);
+ fail("should throw AsynchronousCloseException");
+ } catch (AsynchronousCloseException e) {
+ // ok
+ }
+ }
+
+ public void testReadWrite_Block_Zero() throws Exception {
+ byte[] sourceArray = new byte[0];
+ byte[] targetArray = new byte[0];
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(0, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ int readCount = this.channel2.read(targetBuf);
+
+ assertEquals(0, readCount);
+ }
+
+ public void testReadWrite_Block_Normal() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ readWriteReadData(this.channel1, sourceArray, this.channel2,
+ targetArray, CAPACITY_NORMAL, "testReadWrite_Block_Normal");
+ }
+
+ public void testReadWrite_Block_Empty() throws Exception {
+ // empty buf
+ byte[] sourceArray = "".getBytes();
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+
+ // bind and connect
+
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(0, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ // empty message let the reader blocked
+ closeBlockedReaderChannel2(targetBuf);
+ }
+
+ public void testReadWrite_changeBlock_Empty() throws Exception {
+ // empty buf
+ byte[] sourceArray = "".getBytes();
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+
+ // bind and connect
+
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(0, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ // empty message let the reader blocked
+ new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(TIME_UNIT);
+ channel2.configureBlocking(false);
+ Thread.sleep(TIME_UNIT * 5);
+ channel2.close();
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }.start();
+ try {
+ assertTrue(this.channel2.isBlocking());
+ this.channel2.read(targetBuf);
+ fail("Should throw AsynchronousCloseException");
+ } catch (AsynchronousCloseException e) {
+ assertFalse(this.channel2.isBlocking());
+ // OK.
+ }
+ }
+
+ public void testReadWrite_Block_8KB() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_1KB * 8];
+ byte[] targetArray = new byte[CAPACITY_1KB * 8];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ readWriteReadData(this.channel1, sourceArray, this.channel2,
+ targetArray, 8 * CAPACITY_1KB, "testReadWrite_Block_8KB");
+ }
+
+ /*
+ * sender write the sourceArray whose size is dataSize, and receiver read
+ * the data into targetArray
+ */
+ private void readWriteReadData(DatagramChannel sender, byte[] sourceArray,
+ DatagramChannel receiver, byte[] targetArray, int dataSize,
+ String methodName) throws IOException {
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(dataSize, sender.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+
+ int count = 0;
+ int total = 0;
+ long beginTime = System.currentTimeMillis();
+ while (total < dataSize && (count = receiver.read(targetBuf)) != -1) {
+ total = total + count;
+ // 3s timeout to avoid dead loop
+ if (System.currentTimeMillis() - beginTime > 3000){
+ break;
+ }
+ }
+
+ assertEquals(dataSize, total);
+ assertEquals(targetBuf.position(), total);
+ targetBuf.flip();
+ targetArray = targetBuf.array();
+ for (int i = 0; i < targetArray.length; i++) {
+ assertEquals(targetArray[i], (byte) i);
+ }
+ }
+
+ public void testReadWrite_Block_64K() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_64KB];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ try {
+ channel1.write(sourceBuf);
+ fail("Should throw IOException");
+ } catch (IOException e) {
+ // too big
+ }
+ }
+
+ public void testReadWrite_Block_DifferentAddr() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr1);// the different addr
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ // the wrong connected addr will make the read blocked.
+ // we close the blocked channel
+ closeBlockedReaderChannel2(targetBuf);
+ }
+
+ public void testReadWrite_Block_WriterNotBind() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ // bind and connect
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ closeBlockedReaderChannel2(targetBuf);
+ }
+
+ public void testReadWrite_Block_WriterBindLater() throws Exception {
+
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+
+ // bind and connect
+ // writer channel1 is bound later
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(TIME_UNIT);
+ // bind later
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+ channel1.socket().bind(localAddr2);
+ channel1.connect(localAddr1);
+ // write later
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, channel1.write(sourceBuf));
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }.start();
+
+ int count = 0;
+ int total = 0;
+ long beginTime = System.currentTimeMillis();
+ while (total < CAPACITY_NORMAL && (count = channel2.read(targetBuf)) != -1) {
+ total = total + count;
+ // 3s timeout to avoid dead loop
+ if (System.currentTimeMillis() - beginTime > 3000){
+ break;
+ }
+ }
+
+ assertEquals(CAPACITY_NORMAL, total);
+ assertEquals(targetBuf.position(), total);
+ targetBuf.flip();
+ targetArray = targetBuf.array();
+ for (int i = 0; i < targetArray.length; i++) {
+ assertEquals(targetArray[i], (byte) i);
+ }
+
+ }
+
+ public void testReadWrite_Block_ReaderNotBind() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ // reader channel2 is not bound
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ closeBlockedReaderChannel2(targetBuf);
+
+ }
+
+ private void closeBlockedReaderChannel2(ByteBuffer targetBuf)
+ throws IOException {
+ new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(TIME_UNIT);
+ channel2.close();
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }.start();
+ try {
+ assertTrue(this.channel2.isBlocking());
+ this.channel2.read(targetBuf);
+ fail("Should throw AsynchronousCloseException");
+ } catch (AsynchronousCloseException e) {
+ // OK.
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Test read and write in non-block mode.
+ // -------------------------------------------------------------------
+ public void testReadWrite_NonBlock_Normal() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ readWriteReadData(this.channel1, sourceArray, this.channel2,
+ targetArray, CAPACITY_NORMAL, "testReadWrite_NonBlock_Normal");
+ }
+
+ public void testReadWrite_NonBlock_8KB() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_1KB * 8];
+ byte[] targetArray = new byte[CAPACITY_1KB * 8];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ readWriteReadData(this.channel1, sourceArray, this.channel2,
+ targetArray, 8 * CAPACITY_1KB, "testReadWrite_NonBlock_8KB");
+ }
+
+ public void testReadWrite_NonBlock_DifferentAddr() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr1);// the different addr
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ assertEquals(0, this.channel2.read(targetBuf));
+ }
+
+ public void testReadWrite_NonBlock_WriterNotBind() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+
+ // bind and connect
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ assertEquals(0, this.channel2.read(targetBuf));
+ }
+
+ public void testReadWrite_NonBlock_ReaderNotBind() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ assertEquals(0, this.channel2.read(targetBuf));
+ }
+
+ public void test_write_LBuffer_positioned() throws Exception {
+ // Regression test for Harmony-683
+ int postion = 16;
+ DatagramChannel dc = DatagramChannel.open();
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ dc.connect(localAddr1);
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ sourceBuf.position(postion);
+ assertEquals(CAPACITY_NORMAL - postion, dc.write(sourceBuf));
+ }
+
+ public void test_send_LBuffer_LSocketAddress_PositonNotZero()
+ throws Exception {
+ // regression test for Harmony-701
+ int CAPACITY_NORMAL = 256;
+ int postion = 16;
+ DatagramChannel dc = DatagramChannel.open();
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ // send ByteBuffer whose position is not zero
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ sourceBuf.position(postion);
+ int ret = dc.send(sourceBuf, localAddr1);
+ // assert send (256 - 16) bytes
+ assertEquals(CAPACITY_NORMAL - postion, ret);
+ // assert the position of ByteBuffer has been set
+ assertEquals(CAPACITY_NORMAL, sourceBuf.position());
+ }
+
+ /**
+ * @tests DatagramChannel#read(ByteBuffer[])
+ */
+ public void test_read_$LByteBuffer() throws Exception {
+ // regression test for Harmony-754
+ channel2.socket().bind(localAddr1);
+ channel1.socket().bind(localAddr2);
+ channel1.connect(localAddr1);
+ channel2.connect(localAddr2);
+ channel2.write(ByteBuffer.allocate(CAPACITY_NORMAL));
+
+ ByteBuffer[] readBuf = new ByteBuffer[2];
+ readBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ readBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+
+ channel1.configureBlocking(true);
+ assertEquals(CAPACITY_NORMAL, channel1.read(readBuf));
+ }
+
+ /**
+ * @tests DatagramChannel#read(ByteBuffer[],int,int)
+ */
+ public void test_read_$LByteBufferII() throws Exception {
+ // regression test for Harmony-754
+ channel2.socket().bind(localAddr1);
+ channel1.socket().bind(localAddr2);
+ channel1.connect(localAddr1);
+ channel2.connect(localAddr2);
+ channel2.write(ByteBuffer.allocate(CAPACITY_NORMAL));
+
+ ByteBuffer[] readBuf = new ByteBuffer[2];
+ readBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ readBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+
+ channel1.configureBlocking(true);
+ assertEquals(CAPACITY_NORMAL, channel1.read(readBuf,0,2));
+ }
+
+ /**
+ * @tests DatagramChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_closed_nullBuf() throws Exception {
+ // regression test for Harmony-754
+ ByteBuffer c = null;
+ DatagramChannel channel = DatagramChannel.open();
+ channel.close();
+ try{
+ channel.read(c);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e){
+ // expected
+ }
+ }
+
+ /**
+ * @tests DatagramChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_NotConnected_nullBuf() throws Exception {
+ // regression test for Harmony-754
+ ByteBuffer c = null;
+ DatagramChannel channel = DatagramChannel.open();
+ try{
+ channel.read(c);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e){
+ // expected
+ }
+ }
+
+ /**
+ * @tests DatagramChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_readOnlyBuf() throws Exception {
+ // regression test for Harmony-754
+ ByteBuffer c = ByteBuffer.allocate(1);
+ DatagramChannel channel = DatagramChannel.open();
+ try{
+ channel.read(c.asReadOnlyBuffer());
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e){
+ // expected
+ }
+ channel.connect(localAddr1);
+ try{
+ channel.read(c.asReadOnlyBuffer());
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e){
+ // expected
+ }
+ }
+
+ /**
+ * @tests DatagramChannel#send(ByteBuffer, SocketAddress)
+ */
+ public void test_send_LByteBuffer_LSocketAddress_closed() throws IOException{
+ // regression test for Harmony-913
+ channel1.close();
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+ try {
+ channel1.send(buf, localAddr1);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ //pass
+ }
+ try {
+ channel1.send(null,localAddr1);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ //pass
+ }
+ try {
+ channel1.send(buf, null);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ //pass
+ }
+ try {
+ channel1.send(null, null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ //pass
+ }
+ }
+
+ /**
+ * @tests DatagramChannel#socket()
+ */
+ public void test_socket_IllegalBlockingModeException() throws Exception {
+ // regression test for Harmony-1036
+ DatagramChannel channel = DatagramChannel.open();
+ channel.configureBlocking(false);
+ DatagramSocket socket = channel.socket();
+ try {
+ socket.send(null);
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ try {
+ socket.receive(null);
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Mock class for security test.
+ // -------------------------------------------------------------------
+ private class MockSecurityManager extends SecurityManager {
+
+ String validHost = null;
+
+ int validPort = -1;
+
+ MockSecurityManager() {
+ super();
+ this.validHost = null;
+ }
+
+ MockSecurityManager(String host) {
+ super();
+ this.validHost = host;
+ }
+
+ MockSecurityManager(int port) {
+ super();
+ this.validPort = port;
+ }
+
+ public void checkPermission(Permission perm) {
+ // no-op
+ }
+
+ public void checkPermission(Permission perm, Object context) {
+ // no-op
+ }
+
+ public void checkConnect(String host, int port) {
+ // our local addr is OK.
+ if (null != this.validHost) {
+ if (!this.validHost.equals(host)) {
+ throw new SecurityException();
+ }
+ }
+ if ("127.0.0.1".equals(host)) {
+ return;
+ }
+ super.checkConnect(host, port);
+ }
+
+ public void checkAccept(String host, int port) {
+ // our local addr is OK.
+ if (null != this.validHost) {
+ if (!this.validHost.equals(host)) {
+ throw new SecurityException();
+ }
+ }
+ if (-1 != this.validPort) {
+ if (this.validPort != port) {
+ throw new SecurityException();
+ }
+ }
+ if ("127.0.0.1".equals(host)) {
+ return;
+ }
+ super.checkAccept(host, port);
+ }
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelLockingTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelLockingTest.java
new file mode 100644
index 0000000..a8df907
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelLockingTest.java
@@ -0,0 +1,196 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.NonReadableChannelException;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.OverlappingFileLockException;
+
+import junit.framework.TestCase;
+
+/**
+ * API tests for the NIO FileChannel locking APIs
+ */
+public class FileChannelLockingTest extends TestCase {
+
+ private FileChannel readOnlyChannel;
+
+ private FileChannel writeOnlyChannel;
+
+ private FileChannel readWriteChannel;
+
+ private final String CONTENT = "The best things in life are nearest: Breath in your nostrils, light in your eyes, "
+ + "flowers at your feet, duties at your hand, the path of right just before you. Then do not grasp at the stars, "
+ + "but do life's plain, common work as it comes, certain that daily duties and daily bread are the sweetest "
+ + " things in life.--Robert Louis Stevenson";
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Create a three temporary files with content.
+ File[] tempFiles = new File[3];
+ for (int i = 0; i < tempFiles.length; i++) {
+ tempFiles[i] = File.createTempFile("testing", "tmp");
+ tempFiles[i].deleteOnExit();
+ FileWriter writer = new FileWriter(tempFiles[i]);
+ writer.write(CONTENT);
+ writer.close();
+ }
+
+ // Open read, write, and read/write channels on the temp files.
+ FileInputStream fileInputStream = new FileInputStream(tempFiles[0]);
+ readOnlyChannel = fileInputStream.getChannel();
+
+ FileOutputStream fileOutputStream = new FileOutputStream(tempFiles[1]);
+ writeOnlyChannel = fileOutputStream.getChannel();
+
+ RandomAccessFile randomAccessFile = new RandomAccessFile(tempFiles[2],
+ "rw");
+ readWriteChannel = randomAccessFile.getChannel();
+ }
+
+ public void test_illegalLocks() throws IOException {
+ // Cannot acquire an exclusive lock on a read-only file channel
+ try {
+ readOnlyChannel.lock();
+ fail("Acquiring a full exclusive lock on a read only channel should fail.");
+ } catch (NonWritableChannelException ex) {
+ // Expected.
+ }
+
+ // Cannot get a shared lock on a write-only file channel.
+ try {
+ writeOnlyChannel.lock(1, 10, true);
+ fail("Acquiring a shared lock on a write-only channel should fail.");
+ } catch (NonReadableChannelException ex) {
+ // expected
+ }
+ }
+
+ public void test_lockReadWrite() throws IOException {
+ // Acquire an exclusive lock across the entire file.
+ FileLock flock = readWriteChannel.lock();
+ if (flock != null) {
+ flock.release();
+ }
+ }
+
+ public void test_illegalLockParameters() throws IOException {
+ // Cannot lock negative positions
+ try {
+ readOnlyChannel.lock(-1, 10, true);
+ fail("Passing illegal args to lock should fail.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ try {
+ writeOnlyChannel.lock(-1, 10, false);
+ fail("Passing illegal args to lock should fail.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ try {
+ readWriteChannel.lock(-1, 10, false);
+ fail("Passing illegal args to lock should fail.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+
+ // Lock a range at the front, shared.
+ FileLock flock1 = readWriteChannel.lock(22, 110, true);
+
+ // Try to acquire an overlapping lock.
+ try {
+ readWriteChannel.lock(75, 210, true);
+ } catch (OverlappingFileLockException exception) {
+ // expected
+ flock1.release();
+ }
+ }
+
+ public void test_lockLLZ() throws IOException {
+ // Lock a range at the front, non-shared.
+ FileLock flock1 = readWriteChannel.lock(0, 10, false);
+
+ // Lock a shared range further in the same file.
+ FileLock flock2 = readWriteChannel.lock(22, 100, true);
+
+ // The spec allows the impl to refuse shared locks
+ flock1.release();
+ flock2.release();
+ }
+
+ public void test_tryLock() throws IOException {
+ try {
+ readOnlyChannel.tryLock();
+ fail("Acquiring a full exclusive lock on a read channel should have thrown an exception.");
+ } catch (NonWritableChannelException ex) {
+ // Expected.
+ }
+ }
+
+ public void test_tryLockLLZ() throws IOException {
+ // It is illegal to request an exclusive lock on a read-only channel
+ try {
+ readOnlyChannel.tryLock(0, 99, false);
+ fail("Acquiring exclusive lock on read-only channel should fail");
+ } catch (NonWritableChannelException ex) {
+ // Expected
+ }
+
+ // It is invalid to request a lock starting before the file start
+ try {
+ readOnlyChannel.tryLock(-99, 0, true);
+ fail("Acquiring an illegal lock value should fail.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+
+ // Acquire a valid lock
+ FileLock tmpLock = readOnlyChannel.tryLock(0, 10, true);
+ assertTrue(tmpLock.isValid());
+ tmpLock.release();
+
+ // Acquire another valid lock -- and don't release it yet
+ FileLock lock = readOnlyChannel.tryLock(10, 788, true);
+ assertTrue(lock.isValid());
+
+ // Overlapping locks are illegal
+ try {
+ readOnlyChannel.tryLock(1, 23, true);
+ fail("Acquiring an overlapping lock should fail.");
+ } catch (OverlappingFileLockException ex) {
+ // Expected
+ }
+
+ // Adjacent locks are legal
+ FileLock adjacentLock = readOnlyChannel.tryLock(1, 3, true);
+ assertTrue(adjacentLock.isValid());
+ adjacentLock.release();
+
+ // Release longer lived lock
+ lock.release();
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
new file mode 100644
index 0000000..10f2fcc
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
@@ -0,0 +1,3271 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.NonReadableChannelException;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.OverlappingFileLockException;
+import java.nio.channels.Pipe;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.channels.FileChannel.MapMode;
+import java.util.Arrays;
+import org.apache.harmony.luni.platform.Platform;
+
+import junit.framework.TestCase;
+
+public class FileChannelTest extends TestCase {
+
+ private static final int CAPACITY = 100;
+
+ private static final int LIMITED_CAPACITY = 2;
+
+ private static final int TIME_OUT = 10000;
+
+ private static final String CONTENT = "MYTESTSTRING needs to be a little long";
+
+ private static final byte[] TEST_BYTES;
+
+ static {
+ try {
+ TEST_BYTES = "test".getBytes("iso8859-1");
+ } catch (UnsupportedEncodingException e) {
+ throw new Error(e);
+ }
+ }
+
+ private static final int CONTENT_LENGTH = CONTENT.length();
+
+ private static final byte[] CONTENT_AS_BYTES = CONTENT.getBytes();
+
+ private static final int CONTENT_AS_BYTES_LENGTH = CONTENT_AS_BYTES.length;
+
+ private FileChannel readOnlyFileChannel;
+
+ private FileChannel writeOnlyFileChannel;
+
+ private FileChannel readWriteFileChannel;
+
+ private File fileOfReadOnlyFileChannel;
+
+ private File fileOfWriteOnlyFileChannel;
+
+ private File fileOfReadWriteFileChannel;
+
+ private ReadableByteChannel readByteChannel;
+
+ private WritableByteChannel writableByteChannel;
+
+ private DatagramChannel datagramChannelSender;
+
+ private DatagramChannel datagramChannelReceiver;
+
+ private ServerSocketChannel serverSocketChannel;
+
+ private SocketChannel socketChannelSender;
+
+ private SocketChannel socketChannelReceiver;
+
+ private Pipe pipe;
+
+ // to read content from FileChannel
+ private FileInputStream fis;
+
+ private FileLock fileLock;
+
+ protected void setUp() throws Exception {
+ fileOfReadOnlyFileChannel = File.createTempFile(
+ "File_of_readOnlyFileChannel", "tmp");
+ fileOfReadOnlyFileChannel.deleteOnExit();
+ fileOfWriteOnlyFileChannel = File.createTempFile(
+ "File_of_writeOnlyFileChannel", "tmp");
+ fileOfWriteOnlyFileChannel.deleteOnExit();
+ fileOfReadWriteFileChannel = File.createTempFile(
+ "File_of_readWriteFileChannel", "tmp");
+ fileOfReadWriteFileChannel.deleteOnExit();
+ fis = null;
+ fileLock = null;
+ readOnlyFileChannel = new FileInputStream(fileOfReadOnlyFileChannel)
+ .getChannel();
+ writeOnlyFileChannel = new FileOutputStream(fileOfWriteOnlyFileChannel)
+ .getChannel();
+ readWriteFileChannel = new RandomAccessFile(fileOfReadWriteFileChannel,
+ "rw").getChannel();
+ }
+
+ protected void tearDown() {
+ if (null != readOnlyFileChannel) {
+ try {
+ readOnlyFileChannel.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != writeOnlyFileChannel) {
+ try {
+ writeOnlyFileChannel.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != readWriteFileChannel) {
+ try {
+ readWriteFileChannel.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != fis) {
+ try {
+ fis.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+
+ if (null != fileLock) {
+ try {
+ fileLock.release();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+
+ if (null != fileOfReadOnlyFileChannel) {
+ fileOfReadOnlyFileChannel.delete();
+ }
+ if (null != fileOfWriteOnlyFileChannel) {
+ fileOfWriteOnlyFileChannel.delete();
+ }
+ if (null != fileOfReadWriteFileChannel) {
+ fileOfReadWriteFileChannel.delete();
+ }
+ if (null != datagramChannelSender) {
+ try {
+ datagramChannelSender.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != datagramChannelReceiver) {
+ try {
+ datagramChannelReceiver.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != serverSocketChannel) {
+ try {
+ serverSocketChannel.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != socketChannelSender) {
+ try {
+ socketChannelSender.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != socketChannelReceiver) {
+ try {
+ socketChannelReceiver.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != pipe) {
+ if (null != pipe.source()) {
+ try {
+ pipe.source().close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != pipe.sink()) {
+ try {
+ pipe.sink().close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#force(boolean)
+ */
+ public void test_forceJ() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ writeOnlyFileChannel.write(writeBuffer);
+ writeOnlyFileChannel.force(true);
+
+ byte[] readBuffer = new byte[CONTENT_AS_BYTES_LENGTH];
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ fis.read(readBuffer);
+ assertTrue(Arrays.equals(CONTENT_AS_BYTES, readBuffer));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#force(boolean)
+ */
+ public void test_forceJ_closed() throws Exception {
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.force(true);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.force(false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#force(boolean)
+ */
+ public void test_forceJ_ReadOnlyChannel() throws Exception {
+ // force on a read only file channel has no effect.
+ readOnlyFileChannel.force(true);
+ readOnlyFileChannel.force(false);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position()
+ */
+ public void test_position_Init() throws Exception {
+ assertEquals(0, readOnlyFileChannel.position());
+ assertEquals(0, writeOnlyFileChannel.position());
+ assertEquals(0, readWriteFileChannel.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position()
+ */
+ public void test_position_ReadOnly() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ assertEquals(0, readOnlyFileChannel.position());
+ ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+ readOnlyFileChannel.read(readBuffer);
+ assertEquals(CONTENT_LENGTH, readOnlyFileChannel.position());
+ }
+
+ /**
+ * Initializes test file.
+ *
+ * @param file
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ private void writeDataToFile(File file) throws FileNotFoundException,
+ IOException {
+ FileOutputStream fos = new FileOutputStream(file);
+ try {
+ fos.write(CONTENT_AS_BYTES);
+ } finally {
+ fos.close();
+ }
+ }
+
+ /**
+ * Initializes large test file.
+ *
+ * @param file the file to be written
+ * @param size the content size to be written
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ private void writeLargeDataToFile(File file, int size) throws FileNotFoundException,
+ IOException {
+ FileOutputStream fos = new FileOutputStream(file);
+ byte[] buf = new byte[size];
+
+ try {
+ // we don't care about content - just need a particular file size
+ fos.write(buf);
+ } finally {
+ fos.close();
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position()
+ */
+ public void test_position_WriteOnly() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ writeOnlyFileChannel.write(writeBuffer);
+ assertEquals(CONTENT_LENGTH, writeOnlyFileChannel.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position()
+ */
+ public void test_position_ReadWrite() throws Exception {
+ writeDataToFile(fileOfReadWriteFileChannel);
+
+ assertEquals(0, readWriteFileChannel.position());
+ ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+ readWriteFileChannel.read(readBuffer);
+ assertEquals(CONTENT_LENGTH, readWriteFileChannel.position());
+
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ readWriteFileChannel.write(writeBuffer);
+ assertEquals(CONTENT_LENGTH * 2, readWriteFileChannel.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position()
+ */
+ public void test_position_Closed() throws Exception {
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.position();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.position();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.position();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position(long)
+ */
+ public void test_positionJ_Closed() throws Exception {
+ final long POSITION = 100;
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.position(POSITION);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.position(POSITION);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.position(POSITION);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position(long)
+ */
+ public void test_positionJ_Negative() throws Exception {
+ final long NEGATIVE_POSITION = -1;
+ try {
+ readOnlyFileChannel.position(NEGATIVE_POSITION);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.position(NEGATIVE_POSITION);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.position(NEGATIVE_POSITION);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position(long)
+ */
+ public void test_positionJ_ReadOnly() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ // set the position of the read only file channel to POSITION
+ final int POSITION = 4;
+ readOnlyFileChannel.position(POSITION);
+
+ // reads the content left to readBuffer through read only file channel
+ ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+ int count = readOnlyFileChannel.read(readBuffer);
+ assertEquals(CONTENT_LENGTH - POSITION, count);
+
+ // asserts the content read is the part which stays beyond the POSITION
+ readBuffer.flip();
+ int i = POSITION;
+ while (readBuffer.hasRemaining()) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ i++;
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position(long)
+ */
+ public void test_positionJ_WriteOnly() throws Exception {
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ // init data to write
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+
+ // set the position of the write only file channel to POSITION
+ final int POSITION = 4;
+ writeOnlyFileChannel.position(POSITION);
+
+ // writes to the write only file channel
+ writeOnlyFileChannel.write(writeBuffer);
+ // force to write out.
+ writeOnlyFileChannel.close();
+
+ // gets the result of the write only file channel
+ byte[] result = new byte[POSITION + CONTENT_LENGTH];
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ fis.read(result);
+
+ // constructs the expected result which has content[0... POSITION] plus
+ // content[0...length()]
+ byte[] expectedResult = new byte[POSITION + CONTENT_LENGTH];
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, 0, POSITION);
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, POSITION,
+ CONTENT_LENGTH);
+
+ // asserts result of the write only file channel same as expected
+ assertTrue(Arrays.equals(expectedResult, result));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#size()
+ */
+ public void test_size_Init() throws Exception {
+ assertEquals(0, readOnlyFileChannel.size());
+ assertEquals(0, writeOnlyFileChannel.size());
+ assertEquals(0, readWriteFileChannel.size());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#size()
+ */
+ public void test_size() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ assertEquals(fileOfReadOnlyFileChannel.length(), readOnlyFileChannel
+ .size());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#size()
+ */
+ public void test_size_Closed() throws Exception {
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.size();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.size();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.size();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#truncate(long)
+ */
+ public void test_truncateJ_Closed() throws Exception {
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.truncate(0);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.truncate(0);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.truncate(-1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#truncate(long)
+ */
+ public void test_truncateJ_IllegalArgument() throws Exception {
+ // regression test for Harmony-941
+ try {
+ readOnlyFileChannel.truncate(-1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.truncate(-1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.truncate(-1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#truncate(long)
+ */
+ public void test_truncateJ_ReadOnly() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ try {
+ readOnlyFileChannel.truncate(readOnlyFileChannel.size());
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ try {
+ readOnlyFileChannel.truncate(0);
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#truncate(long)
+ */
+ public void test_truncateJ() throws Exception {
+ writeDataToFile(fileOfReadWriteFileChannel);
+
+ int truncateLength = CONTENT_LENGTH + 2;
+ assertEquals(readWriteFileChannel, readWriteFileChannel
+ .truncate(truncateLength));
+ assertEquals(CONTENT_LENGTH, fileOfReadWriteFileChannel.length());
+
+ truncateLength = CONTENT_LENGTH;
+ assertEquals(readWriteFileChannel, readWriteFileChannel
+ .truncate(truncateLength));
+ assertEquals(CONTENT_LENGTH, fileOfReadWriteFileChannel.length());
+
+ truncateLength = CONTENT_LENGTH / 2;
+ assertEquals(readWriteFileChannel, readWriteFileChannel
+ .truncate(truncateLength));
+ assertEquals(truncateLength, fileOfReadWriteFileChannel.length());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock()
+ */
+ public void test_lock() throws Exception {
+ MockFileChannel mockFileChannel = new MockFileChannel();
+ // Verify that calling lock() leads to the method
+ // lock(long, long, boolean) being called with a 0 for the
+ // first parameter, Long.MAX_VALUE as the second parameter and false
+ // as the third parameter.
+ mockFileChannel.lock();
+ assertTrue(mockFileChannel.isLockCalled);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_Closed() throws Exception {
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.lock(0, 10, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.lock(0, 10, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.lock(0, 10, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // throws ClosedChannelException before IllegalArgumentException
+ try {
+ readWriteFileChannel.lock(-1, 0, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_IllegalArgument() throws Exception {
+ try {
+ writeOnlyFileChannel.lock(0, -1, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.lock(-1, 0, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.lock(-1, -1, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.lock(Long.MAX_VALUE, 1, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_NonWritable() throws Exception {
+ try {
+ readOnlyFileChannel.lock(0, 10, false);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ // throws NonWritableChannelException before IllegalArgumentException
+ try {
+ readOnlyFileChannel.lock(-1, 0, false);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_NonReadable() throws Exception {
+ try {
+ writeOnlyFileChannel.lock(0, 10, true);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+
+ // throws NonReadableChannelException before IllegalArgumentException
+ try {
+ writeOnlyFileChannel.lock(-1, 0, true);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_Shared() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ fileLock = readOnlyFileChannel.lock(POSITION, SIZE, true);
+ assertTrue(fileLock.isValid());
+ // fileLock.isShared depends on whether the underlying platform support
+ // shared lock, but it works on Windows & Linux.
+ assertTrue(fileLock.isShared());
+ assertSame(readOnlyFileChannel, fileLock.channel());
+ assertEquals(POSITION, fileLock.position());
+ assertEquals(SIZE, fileLock.size());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_NotShared() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ fileLock = writeOnlyFileChannel.lock(POSITION, SIZE, false);
+ assertTrue(fileLock.isValid());
+ assertFalse(fileLock.isShared());
+ assertSame(writeOnlyFileChannel, fileLock.channel());
+ assertEquals(POSITION, fileLock.position());
+ assertEquals(SIZE, fileLock.size());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_Long_MAX_VALUE() throws Exception {
+ final long POSITION = 0;
+ final long SIZE = Long.MAX_VALUE;
+ fileLock = readOnlyFileChannel.lock(POSITION, SIZE, true);
+ assertTrue(fileLock.isValid());
+ assertTrue(fileLock.isShared());
+ assertEquals(POSITION, fileLock.position());
+ assertEquals(SIZE, fileLock.size());
+ assertSame(readOnlyFileChannel, fileLock.channel());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_Overlapping() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ fileLock = writeOnlyFileChannel.lock(POSITION, SIZE, false);
+ assertTrue(fileLock.isValid());
+
+ try {
+ writeOnlyFileChannel.lock(POSITION + 1, SIZE, false);
+ fail("should throw OverlappingFileLockException");
+ } catch (OverlappingFileLockException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_NotOverlapping() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ FileLock fileLock1 = writeOnlyFileChannel.lock(POSITION, SIZE, false);
+ assertTrue(fileLock1.isValid());
+ FileLock fileLock2 = writeOnlyFileChannel.lock(POSITION + SIZE, SIZE,
+ false);
+ assertTrue(fileLock2.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long,long,boolean)
+ */
+ public void test_lockJJZ_After_Release() throws Exception {
+ fileLock = writeOnlyFileChannel.lock(0, 10, false);
+ fileLock.release();
+ // after release file lock can be obtained again.
+ fileLock = writeOnlyFileChannel.lock(0, 10, false);
+ assertTrue(fileLock.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock()
+ */
+ public void test_tryLock() throws Exception {
+ MockFileChannel mockFileChannel = new MockFileChannel();
+ // Verify that calling tryLock() leads to the method
+ // tryLock(long, long, boolean) being called with a 0 for the
+ // first parameter, Long.MAX_VALUE as the second parameter and false
+ // as the third parameter.
+ mockFileChannel.tryLock();
+ assertTrue(mockFileChannel.isTryLockCalled);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_Closed() throws Exception {
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.tryLock(0, 10, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.tryLock(0, 10, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.tryLock(0, 10, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // throws ClosedChannelException before IllegalArgumentException
+ try {
+ readWriteFileChannel.tryLock(-1, 0, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_IllegalArgument() throws Exception {
+ try {
+ writeOnlyFileChannel.tryLock(0, -1, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.tryLock(-1, 0, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.tryLock(-1, -1, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.tryLock(Long.MAX_VALUE, 1, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_NonWritable() throws Exception {
+ try {
+ readOnlyFileChannel.tryLock(0, 10, false);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ // throws NonWritableChannelException before IllegalArgumentException
+ try {
+ readOnlyFileChannel.tryLock(-1, 0, false);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_NonReadable() throws Exception {
+ try {
+ writeOnlyFileChannel.tryLock(0, 10, true);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+
+ // throws NonReadableChannelException before IllegalArgumentException
+ try {
+ writeOnlyFileChannel.tryLock(-1, 0, true);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_Shared() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ fileLock = readOnlyFileChannel.tryLock(POSITION, SIZE, true);
+ assertTrue(fileLock.isValid());
+ // fileLock.isShared depends on whether the underlying platform support
+ // shared lock, but it works on Windows & Linux.
+ assertTrue(fileLock.isShared());
+ assertSame(readOnlyFileChannel, fileLock.channel());
+ assertEquals(POSITION, fileLock.position());
+ assertEquals(SIZE, fileLock.size());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_NotShared() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ fileLock = writeOnlyFileChannel.tryLock(POSITION, SIZE, false);
+ assertTrue(fileLock.isValid());
+ assertFalse(fileLock.isShared());
+ assertSame(writeOnlyFileChannel, fileLock.channel());
+ assertEquals(POSITION, fileLock.position());
+ assertEquals(SIZE, fileLock.size());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_Long_MAX_VALUE() throws Exception {
+ final long POSITION = 0;
+ final long SIZE = Long.MAX_VALUE;
+ fileLock = readOnlyFileChannel.tryLock(POSITION, SIZE, true);
+ assertTrue(fileLock.isValid());
+ assertTrue(fileLock.isShared());
+ assertEquals(POSITION, fileLock.position());
+ assertEquals(SIZE, fileLock.size());
+ assertSame(readOnlyFileChannel, fileLock.channel());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_Overlapping() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ fileLock = writeOnlyFileChannel.lock(POSITION, SIZE, false);
+ assertTrue(fileLock.isValid());
+
+ try {
+ writeOnlyFileChannel.lock(POSITION + 1, SIZE, false);
+ fail("should throw OverlappingFileLockException");
+ } catch (OverlappingFileLockException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_NotOverlapping() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ FileLock fileLock1 = writeOnlyFileChannel
+ .tryLock(POSITION, SIZE, false);
+ assertTrue(fileLock1.isValid());
+
+ FileLock fileLock2 = writeOnlyFileChannel.tryLock(POSITION + SIZE,
+ SIZE, false);
+ assertTrue(fileLock2.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long,long,boolean)
+ */
+ public void test_tryLockJJZ_After_Release() throws Exception {
+ fileLock = writeOnlyFileChannel.tryLock(0, 10, false);
+ fileLock.release();
+
+ // after release file lock can be obtained again.
+ fileLock = writeOnlyFileChannel.tryLock(0, 10, false);
+ assertTrue(fileLock.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer)
+ */
+ public void test_readLByteBuffer_Null() throws Exception {
+ ByteBuffer readBuffer = null;
+
+ try {
+ readOnlyFileChannel.read(readBuffer);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.read(readBuffer);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer)
+ */
+ public void test_readLByteBuffer_Closed() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.read(readBuffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.read(readBuffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.read(readBuffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // should throw ClosedChannelException first
+ readBuffer = null;
+ try {
+ readWriteFileChannel.read(readBuffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer)
+ */
+ public void test_readLByteBuffer_WriteOnly() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ writeOnlyFileChannel.read(readBuffer);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+
+ // first throws NonReadableChannelException
+ readBuffer = null;
+ try {
+ writeOnlyFileChannel.read(readBuffer);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer)
+ */
+ public void test_readLByteBuffer_EmptyFile() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+ int result = readOnlyFileChannel.read(readBuffer);
+ assertEquals(-1, result);
+ assertEquals(0, readBuffer.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer)
+ */
+ public void test_readLByteBuffer_LimitedCapacity() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ ByteBuffer readBuffer = ByteBuffer.allocate(LIMITED_CAPACITY);
+ int result = readOnlyFileChannel.read(readBuffer);
+ assertEquals(LIMITED_CAPACITY, result);
+ assertEquals(LIMITED_CAPACITY, readBuffer.position());
+ readBuffer.flip();
+ for (int i = 0; i < LIMITED_CAPACITY; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer)
+ */
+ public void test_readLByteBuffer() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_AS_BYTES_LENGTH);
+ int result = readOnlyFileChannel.read(readBuffer);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, readBuffer.position());
+ readBuffer.flip();
+ for (int i = 0; i < CONTENT_AS_BYTES_LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer, long)
+ */
+ public void test_readLByteBufferJ_Null() throws Exception {
+ ByteBuffer readBuffer = null;
+
+ try {
+ readOnlyFileChannel.read(readBuffer, 0);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // first throws NullPointerException
+ try {
+ readOnlyFileChannel.read(readBuffer, -1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // first throws NullPointerException
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.read(readBuffer, 0);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.read(readBuffer, 0);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // first throws NullPointerException
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.read(readBuffer, 0);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer, long)
+ */
+ public void test_readLByteBufferJ_Closed() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.read(readBuffer, 0);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.read(readBuffer, 0);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer, long)
+ */
+ public void test_readLByteBufferJ_IllegalArgument() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ readOnlyFileChannel.read(readBuffer, -1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.read(readBuffer, -1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.read(readBuffer, -1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ // throws IllegalArgumentException first.
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.read(readBuffer, -1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer, long)
+ */
+ public void test_readLByteBufferJ_WriteOnly() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ writeOnlyFileChannel.read(readBuffer, 0);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+
+ // throws NonReadableChannelException first.
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.read(readBuffer, 0);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer,long)
+ */
+ public void test_readLByteBufferJ_Emptyfile() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+ int result = readOnlyFileChannel.read(readBuffer, 0);
+ assertEquals(-1, result);
+ assertEquals(0, readBuffer.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer,long)
+ */
+ public void test_readLByteBufferJ_Postion_BeyondFileLimit()
+ throws Exception {
+
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+ int result = readOnlyFileChannel.read(readBuffer,
+ CONTENT_AS_BYTES.length);
+ assertEquals(-1, result);
+ assertEquals(0, readBuffer.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer,long)
+ */
+ public void test_readLByteBufferJ_Postion_As_Long() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+ try {
+ readOnlyFileChannel.read(readBuffer, Long.MAX_VALUE);
+ } catch (IOException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer,long)
+ */
+ public void test_readLByteBufferJ() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+ final int BUFFER_POSITION = 1;
+ readBuffer.position(BUFFER_POSITION);
+
+ final int POSITION = 2;
+ int result = readOnlyFileChannel.read(readBuffer, POSITION);
+ assertEquals(CONTENT_AS_BYTES_LENGTH - POSITION, result);
+ assertEquals(BUFFER_POSITION + result, readBuffer.position());
+
+ readBuffer.flip();
+ readBuffer.position(BUFFER_POSITION);
+ for (int i = POSITION; i < CONTENT_AS_BYTES_LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[])
+ */
+ public void test_read$LByteBuffer() throws Exception {
+ // regression test for Harmony-849
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ readBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+ long readCount = readOnlyFileChannel.read(readBuffers);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, readCount);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, readBuffers[0].position());
+ assertEquals(0, readBuffers[1].position());
+ readBuffers[0].flip();
+ for (int i = 0; i < CONTENT_AS_BYTES_LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffers[0].get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[])
+ */
+ public void test_read$LByteBuffer_mock() throws Exception {
+ FileChannel mockChannel = new MockFileChannel();
+ ByteBuffer[] buffers = new ByteBuffer[2];
+ mockChannel.read(buffers);
+ // Verify that calling read(ByteBuffer[] dsts) leads to the method
+ // read(dsts, 0, dsts.length)
+ assertTrue(((MockFileChannel)mockChannel).isReadCalled);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_Null() throws Exception {
+ ByteBuffer[] readBuffers = null;
+
+ try {
+ readOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readOnlyFileChannel.read(readBuffers, 1, 11);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.read(readBuffers, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // first throws NullPointerException
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_Closed() throws Exception {
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.read(readBuffers, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // regression test for Harmony-902
+ readBuffers[0] = null;
+ try {
+ readOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ try {
+ readWriteFileChannel.read(readBuffers, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_WriteOnly() throws Exception {
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+
+ // first throws NonReadableChannelException.
+ readBuffers[0] = null;
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_IndexOutOfBound() throws Exception {
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ readBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ readOnlyFileChannel.read(readBuffers, 2, 1);
+ fail("should throw IndexOutOfBoundException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.read(null, -1, 0);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.read(readBuffers, -1, 0);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // throws IndexOutOfBoundsException first
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.read(readBuffers, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_EmptyFile() throws Exception {
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ readBuffers[1] = ByteBuffer.allocate(CAPACITY);
+ long result = readOnlyFileChannel.read(readBuffers, 0, 2);
+ assertEquals(-1, result);
+ assertEquals(0, readBuffers[0].position());
+ assertEquals(0, readBuffers[1].position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_EmptyBuffers() throws Exception {
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ try {
+ readOnlyFileChannel.read(readBuffers, 0, 2);
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ try {
+ readOnlyFileChannel.read(readBuffers, 0, 2);
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ long result = readOnlyFileChannel.read(readBuffers, 0, 1);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_EmptyFile_EmptyBuffers()
+ throws Exception {
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ // will not throw NullPointerException
+ long result = readOnlyFileChannel.read(readBuffers, 0, 0);
+ assertEquals(0, result);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_Length_Zero() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(LIMITED_CAPACITY);
+ readBuffers[1] = ByteBuffer.allocate(LIMITED_CAPACITY);
+ long result = readOnlyFileChannel.read(readBuffers, 1, 0);
+ assertEquals(0, result);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_LimitedCapacity() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(LIMITED_CAPACITY);
+ readBuffers[1] = ByteBuffer.allocate(LIMITED_CAPACITY);
+
+ // reads to the second buffer
+ long result = readOnlyFileChannel.read(readBuffers, 1, 1);
+ assertEquals(LIMITED_CAPACITY, result);
+ assertEquals(0, readBuffers[0].position());
+ assertEquals(LIMITED_CAPACITY, readBuffers[1].position());
+
+ readBuffers[1].flip();
+ for (int i = 0; i < LIMITED_CAPACITY; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffers[1].get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ readBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+ // writes to the second buffer
+ assertEquals(CONTENT_AS_BYTES_LENGTH, readOnlyFileChannel.read(
+ readBuffers, 1, 1));
+ assertEquals(0, readBuffers[0].position());
+ assertEquals(CONTENT_AS_BYTES_LENGTH, readBuffers[1].position());
+
+ readBuffers[1].flip();
+ for (int i = 0; i < CONTENT_AS_BYTES_LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffers[1].get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#isOpen()
+ */
+ public void test_isOpen() throws Exception {
+ // Regression for HARMONY-40
+ File logFile = File.createTempFile("out", "tmp");
+ logFile.deleteOnExit();
+ FileOutputStream out = new FileOutputStream(logFile, true);
+ FileChannel channel = out.getChannel();
+ out.write(1);
+ out.close();
+ assertFalse("Assert 0: Channel is still open", channel.isOpen());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position()
+ */
+ public void test_position_append() throws Exception {
+ // Regression test for Harmony-508
+ File tmpfile = File.createTempFile("FileOutputStream", "tmp");
+ tmpfile.deleteOnExit();
+ FileOutputStream fos = new FileOutputStream(tmpfile);
+ byte[] b = new byte[10];
+ for (int i = 0; i < b.length; i++) {
+ b[i] = (byte) i;
+ }
+ fos.write(b);
+ fos.flush();
+ fos.close();
+ FileOutputStream f = new FileOutputStream(tmpfile, true);
+ // Below assertion fails on RI. RI behaviour is counter to spec.
+ assertEquals(10, f.getChannel().position());
+ }
+
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_AbnormalMode() throws IOException {
+ try {
+ writeOnlyFileChannel.map(MapMode.READ_ONLY, 0, CONTENT_LENGTH);
+ fail("should throw NonReadableChannelException.");
+ } catch (NonReadableChannelException ex) {
+ // expected;
+ }
+ try {
+ writeOnlyFileChannel.map(MapMode.READ_WRITE, 0, CONTENT_LENGTH);
+ fail("should throw NonReadableChannelException.");
+ } catch (NonReadableChannelException ex) {
+ // expected;
+ }
+ try {
+ writeOnlyFileChannel.map(MapMode.PRIVATE, 0, CONTENT_LENGTH);
+ fail("should throw NonReadableChannelException.");
+ } catch (NonReadableChannelException ex) {
+ // expected;
+ }
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.map(MapMode.READ_WRITE, 0, -1);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException ex) {
+ // expected;
+ }
+
+ try {
+ readOnlyFileChannel.map(MapMode.READ_WRITE, 0, CONTENT_LENGTH);
+ fail("should throw NonWritableChannelException .");
+ } catch (NonWritableChannelException ex) {
+ // expected;
+ }
+ try {
+ readOnlyFileChannel.map(MapMode.PRIVATE, 0, CONTENT_LENGTH);
+ fail("should throw NonWritableChannelException .");
+ } catch (NonWritableChannelException ex) {
+ // expected;
+ }
+ try {
+ readOnlyFileChannel.map(MapMode.READ_WRITE, -1, CONTENT_LENGTH);
+ fail("should throw IAE.");
+ } catch (IllegalArgumentException ex) {
+ // expected;
+ }
+ try {
+ readOnlyFileChannel.map(MapMode.READ_WRITE, 0, -1);
+ fail("should throw IAE.");
+ } catch (IllegalArgumentException ex) {
+ // expected;
+ }
+
+ try {
+ readOnlyFileChannel.map(MapMode.READ_ONLY, 0, CONTENT_LENGTH + 1);
+ fail("should throw IOException.");
+ } catch (IOException ex) {
+ // expected;
+ }
+ try {
+ readOnlyFileChannel.map(MapMode.READ_ONLY, 2, CONTENT_LENGTH - 1);
+ fail("should throw IOException.");
+ } catch (IOException ex) {
+ // expected;
+ }
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.map(MapMode.READ_WRITE, 0, -1);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException ex) {
+ // expected;
+ }
+ try {
+ readOnlyFileChannel.map(MapMode.READ_ONLY, 2, CONTENT_LENGTH - 1);
+ fail("should throw IOException.");
+ } catch (IOException ex) {
+ // expected;
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.map(MapMode.READ_WRITE, 0, -1);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException ex) {
+ // expected;
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_ReadOnly_CloseChannel() throws IOException {
+ // close channel has no effect on map if mapped
+ assertEquals(0, readWriteFileChannel.size());
+ MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.READ_ONLY,
+ 0, CONTENT_LENGTH);
+ assertEquals(CONTENT_LENGTH, readWriteFileChannel.size());
+ readOnlyFileChannel.close();
+ assertEquals(CONTENT_LENGTH, mapped.limit());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_Private_CloseChannel() throws IOException {
+ MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.PRIVATE, 0,
+ CONTENT_LENGTH);
+ readWriteFileChannel.close();
+ mapped.put(TEST_BYTES);
+ assertEquals(CONTENT_LENGTH, mapped.limit());
+ assertEquals("test".length(), mapped.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_ReadOnly() throws IOException {
+ MappedByteBuffer mapped = null;
+ // try put something to readonly map
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ mapped = readOnlyFileChannel.map(MapMode.READ_ONLY, 0, CONTENT_LENGTH);
+ try {
+ mapped.put(TEST_BYTES);
+ fail("should throw ReadOnlyBufferException.");
+ } catch (ReadOnlyBufferException ex) {
+ // expected;
+ }
+ assertEquals(CONTENT_LENGTH, mapped.limit());
+ assertEquals(CONTENT_LENGTH, mapped.capacity());
+ assertEquals(0, mapped.position());
+
+ // try to get a readonly map from read/write channel
+ writeDataToFile(fileOfReadWriteFileChannel);
+ mapped = readWriteFileChannel.map(MapMode.READ_ONLY, 0, CONTENT
+ .length());
+ assertEquals(CONTENT_LENGTH, mapped.limit());
+ assertEquals(CONTENT_LENGTH, mapped.capacity());
+ assertEquals(0, mapped.position());
+
+ // map not change channel's position
+ assertEquals(0, readOnlyFileChannel.position());
+ assertEquals(0, readWriteFileChannel.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_ReadOnly_NonZeroPosition() throws IOException {
+ this.writeDataToFile(fileOfReadOnlyFileChannel);
+ MappedByteBuffer mapped = readOnlyFileChannel.map(MapMode.READ_ONLY,
+ 10, CONTENT_LENGTH - 10);
+ assertEquals(CONTENT_LENGTH - 10, mapped.limit());
+ assertEquals(CONTENT_LENGTH - 10, mapped.capacity());
+ assertEquals(0, mapped.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_Private() throws IOException {
+ this.writeDataToFile(fileOfReadWriteFileChannel);
+ MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.PRIVATE, 0,
+ CONTENT_LENGTH);
+ assertEquals(CONTENT_LENGTH, mapped.limit());
+ // test copy on write if private
+ ByteBuffer returnByPut = mapped.put(TEST_BYTES);
+ assertSame(returnByPut, mapped);
+ ByteBuffer checkBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+ mapped.force();
+ readWriteFileChannel.read(checkBuffer);
+ assertEquals(CONTENT, new String(checkBuffer.array(), "iso8859-1"));
+
+ // test overflow
+ try {
+ mapped.put(("test" + CONTENT).getBytes("iso8859-1"));
+ fail("should throw BufferOverflowException.");
+ } catch (BufferOverflowException ex) {
+ // expected;
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_Private_NonZeroPosition() throws IOException {
+ MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.PRIVATE, 10,
+ CONTENT_LENGTH - 10);
+ assertEquals(CONTENT_LENGTH - 10, mapped.limit());
+ assertEquals(CONTENT_LENGTH - 10, mapped.capacity());
+ assertEquals(0, mapped.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_ReadWrite() throws IOException {
+ MappedByteBuffer mapped = null;
+ writeDataToFile(fileOfReadWriteFileChannel);
+ mapped = readWriteFileChannel.map(MapMode.READ_WRITE, 0, CONTENT
+ .length());
+
+ // put something will change its channel
+ ByteBuffer returnByPut = mapped.put(TEST_BYTES);
+ assertSame(returnByPut, mapped);
+ String checkString = "test" + CONTENT.substring(4);
+ ByteBuffer checkBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+ mapped.force();
+ readWriteFileChannel.position(0);
+ readWriteFileChannel.read(checkBuffer);
+ assertEquals(checkString, new String(checkBuffer.array(), "iso8859-1"));
+
+ try {
+ mapped.put(("test" + CONTENT).getBytes("iso8859-1"));
+ fail("should throw BufferOverflowException.");
+ } catch (BufferOverflowException ex) {
+ // expected;
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_ReadWrite_NonZeroPosition() throws IOException {
+ // test position non-zero
+ writeDataToFile(fileOfReadWriteFileChannel);
+ MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.READ_WRITE,
+ 10, CONTENT_LENGTH - 10);
+ assertEquals(CONTENT_LENGTH - 10, mapped.limit());
+ assertEquals(CONTENT.length() - 10, mapped.capacity());
+ assertEquals(0, mapped.position());
+ mapped.put(TEST_BYTES);
+ ByteBuffer checkBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+ readWriteFileChannel.read(checkBuffer);
+ String expected = CONTENT.substring(0, 10) + "test"
+ + CONTENT.substring(10 + "test".length());
+ assertEquals(expected, new String(checkBuffer.array(), "iso8859-1"));
+ }
+
+ /**
+ * Tests map() method for the value of positions exceeding memory
+ * page size and allocation granularity size.
+ *
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_LargePosition() throws IOException {
+ // Regression test for HARMONY-3085
+ int[] sizes = {
+ 4096, // 4K size (normal page size for Linux & Windows)
+ 65536, // 64K size (alocation granularity size for Windows)
+ Platform.getFileSystem().getAllocGranularity() // alloc granularity
+ };
+ final int CONTENT_LEN = 10;
+
+ for (int i = 0; i < sizes.length; ++i) {
+ // reset the file and the channel for the iterations
+ // (for the first iteration it was done by setUp()
+ if (i > 0 ) {
+ fileOfReadOnlyFileChannel = File.createTempFile(
+ "File_of_readOnlyFileChannel", "tmp");
+ fileOfReadOnlyFileChannel.deleteOnExit();
+ readOnlyFileChannel = new FileInputStream(fileOfReadOnlyFileChannel)
+ .getChannel();
+ }
+
+ writeLargeDataToFile(fileOfReadOnlyFileChannel, sizes[i] + 2 * CONTENT_LEN);
+ MappedByteBuffer mapped = readOnlyFileChannel.map(MapMode.READ_ONLY,
+ sizes[i], CONTENT_LEN);
+ assertEquals("Incorrectly mapped file channel for " + sizes[i]
+ + " position (capacity)", CONTENT_LEN, mapped.capacity());
+ assertEquals("Incorrectly mapped file channel for " + sizes[i]
+ + " position (limit)", CONTENT_LEN, mapped.limit());
+ assertEquals("Incorrectly mapped file channel for " + sizes[i]
+ + " position (position)", 0, mapped.position());
+
+ // map not change channel's position
+ assertEquals(0, readOnlyFileChannel.position());
+
+ // Close the file and the channel before the next iteration
+ readOnlyFileChannel.close();
+ fileOfReadOnlyFileChannel.delete();
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+ */
+ public void test_writeLByteBuffer_Null() throws Exception {
+ ByteBuffer writeBuffer = null;
+
+ try {
+ writeOnlyFileChannel.write(writeBuffer);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.write(writeBuffer);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+ */
+ public void test_writeLByteBuffer_Closed() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.write(writeBuffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.write(writeBuffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.write(writeBuffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // should throw ClosedChannelException first
+ writeBuffer = null;
+ try {
+ readWriteFileChannel.read(writeBuffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+ */
+ public void test_writeLByteBuffer_ReadOnly() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ readOnlyFileChannel.write(writeBuffer);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ // first throws NonWriteableChannelException
+ writeBuffer = null;
+ try {
+ readOnlyFileChannel.write(writeBuffer);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+ */
+ public void test_writeLByteBuffer() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+
+ int result = writeOnlyFileChannel.write(writeBuffer);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffer.position());
+ writeOnlyFileChannel.close();
+
+ assertEquals(CONTENT_AS_BYTES_LENGTH, fileOfWriteOnlyFileChannel
+ .length());
+
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] inputBuffer = new byte[CONTENT_AS_BYTES_LENGTH];
+ fis.read(inputBuffer);
+ assertTrue(Arrays.equals(CONTENT_AS_BYTES, inputBuffer));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+ */
+ public void test_writeLByteBuffer_positioned() throws Exception {
+ final int pos = 5;
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ writeBuffer.position(pos);
+ int result = writeOnlyFileChannel.write(writeBuffer);
+ assertEquals(CONTENT_AS_BYTES_LENGTH - pos, result);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffer.position());
+ writeOnlyFileChannel.close();
+
+ assertEquals(CONTENT_AS_BYTES_LENGTH - pos, fileOfWriteOnlyFileChannel
+ .length());
+
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] inputBuffer = new byte[CONTENT_AS_BYTES_LENGTH - pos];
+ fis.read(inputBuffer);
+ String test = CONTENT.substring(pos);
+ assertTrue(Arrays.equals(test.getBytes(), inputBuffer));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer, long)
+ */
+ public void test_writeLByteBufferJ_Null() throws Exception {
+ ByteBuffer writeBuffer = null;
+
+ try {
+ readOnlyFileChannel.write(writeBuffer, 0);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.write(writeBuffer, 0);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // first throws NullPointerException
+ try {
+ readOnlyFileChannel.write(writeBuffer, -1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.write(writeBuffer, 0);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // first throws NullPointerException
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.write(writeBuffer, 0);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer, long)
+ */
+ public void test_writeLByteBufferJ_Closed() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.write(writeBuffer, 0);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.write(writeBuffer, 0);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer, long)
+ */
+ public void test_writeLByteBufferJ_ReadOnly() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ readOnlyFileChannel.write(writeBuffer, 10);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ // regression test for Harmony-903
+
+ // read-only file channel never throws ClosedChannelException even if
+ // the channel is closed.
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.write(writeBuffer, 10);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ try {
+ readOnlyFileChannel.write(writeBuffer, -1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ writeBuffer = null;
+ try {
+ readOnlyFileChannel.write(writeBuffer, -1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer, long)
+ */
+ public void test_writeLByteBufferJ_IllegalArgument() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ readOnlyFileChannel.write(writeBuffer, -1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.write(writeBuffer, -1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.write(writeBuffer, -1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ // throws IllegalArgumentException first.
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.write(writeBuffer, -1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer,long)
+ */
+ public void test_writeLByteBufferJ() throws Exception {
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ final int POSITION = 4;
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ int result = writeOnlyFileChannel.write(writeBuffer, POSITION);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffer.position());
+ writeOnlyFileChannel.close();
+
+ assertEquals(POSITION + CONTENT_AS_BYTES_LENGTH,
+ fileOfWriteOnlyFileChannel.length());
+
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] inputBuffer = new byte[POSITION + CONTENT_AS_BYTES_LENGTH];
+ fis.read(inputBuffer);
+ byte[] expectedResult = new byte[POSITION + CONTENT_AS_BYTES_LENGTH];
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, 0, POSITION);
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, POSITION,
+ CONTENT_AS_BYTES_LENGTH);
+ assertTrue(Arrays.equals(expectedResult, inputBuffer));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer[])
+ */
+ public void test_write$LByteBuffer() throws Exception {
+ ByteBuffer[] writeBuffers = new ByteBuffer[2];
+ MockFileChannel mockFileChannel = new MockFileChannel();
+ mockFileChannel.write(writeBuffers);
+ // verify that calling write(ByteBuffer[] srcs) leads to the method
+ // write(srcs, 0, srcs.length)
+ assertTrue(mockFileChannel.isWriteCalled);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII_Null() throws Exception {
+ ByteBuffer[] writeBuffers = null;
+
+ try {
+ readOnlyFileChannel.write(writeBuffers, 1, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.write(writeBuffers, 1, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.write(writeBuffers, 1, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // first throws NullPointerException
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.write(writeBuffers, 0, 0);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII_Closed() throws Exception {
+ ByteBuffer[] writeBuffers = new ByteBuffer[2];
+ writeBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ writeBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // throws ClosedChannelException first
+ writeBuffers[0] = null;
+ try {
+ readWriteFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII_ReadOnly() throws Exception {
+ ByteBuffer[] writeBuffers = new ByteBuffer[2];
+ writeBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ writeBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ readOnlyFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ // throw NonWritableChannelException first although buffer array is
+ // empty.
+ writeBuffers = new ByteBuffer[2];
+ try {
+ readOnlyFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ readOnlyFileChannel.close();
+ writeBuffers = null;
+ try {
+ readOnlyFileChannel.write(writeBuffers, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ readOnlyFileChannel.write(writeBuffers, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII_EmptyBuffers() throws Exception {
+ ByteBuffer[] writeBuffers = new ByteBuffer[2];
+ try {
+ writeOnlyFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII() throws Exception {
+ ByteBuffer[] writeBuffers = new ByteBuffer[2];
+ writeBuffers[0] = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ writeBuffers[1] = ByteBuffer.wrap(CONTENT_AS_BYTES);
+
+ long result = writeOnlyFileChannel.write(writeBuffers, 0, 2);
+ assertEquals(CONTENT_AS_BYTES_LENGTH * 2, result);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffers[0].position());
+ assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffers[1].position());
+ writeOnlyFileChannel.close();
+
+ assertEquals(CONTENT_AS_BYTES_LENGTH * 2, fileOfWriteOnlyFileChannel
+ .length());
+
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] inputBuffer = new byte[CONTENT_AS_BYTES_LENGTH];
+ fis.read(inputBuffer);
+ byte[] expectedResult = new byte[CONTENT_AS_BYTES_LENGTH * 2];
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, 0,
+ CONTENT_AS_BYTES_LENGTH);
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult,
+ CONTENT_AS_BYTES_LENGTH, CONTENT_AS_BYTES_LENGTH);
+ assertTrue(Arrays.equals(CONTENT_AS_BYTES, inputBuffer));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_Closed()
+ throws Exception {
+ readByteChannel = DatagramChannel.open();
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.transferFrom(readByteChannel, 0, 0);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.transferFrom(readByteChannel, 0, 10);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.transferFrom(readByteChannel, 0, 0);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // should throw ClosedChannelException first.
+ try {
+ readWriteFileChannel.transferFrom(readByteChannel, 0, -1);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_SourceClosed()
+ throws Exception {
+ readByteChannel = DatagramChannel.open();
+ readByteChannel.close();
+
+ try {
+ readOnlyFileChannel.transferFrom(readByteChannel, 0, 10);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.transferFrom(readByteChannel, 0, 10);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.transferFrom(readByteChannel, 0, 10);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // should throw ClosedChannelException first.
+ try {
+ readWriteFileChannel.transferFrom(readByteChannel, 0, -1);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_IllegalArgument()
+ throws Exception {
+ readByteChannel = DatagramChannel.open();
+ try {
+ writeOnlyFileChannel.transferFrom(readByteChannel, 10, -1);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.transferFrom(readByteChannel, -1, -10);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_NonWritable()
+ throws Exception {
+ readByteChannel = DatagramChannel.open();
+ try {
+ readOnlyFileChannel.transferFrom(readByteChannel, 0, 0);
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_SourceNonReadable()
+ throws Exception {
+ try {
+ readWriteFileChannel.transferFrom(writeOnlyFileChannel, 0, 0);
+ fail("should throw NonReadableChannelException.");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+
+ // not throws NonReadableChannelException first if position beyond file
+ // size.
+ readWriteFileChannel.transferFrom(writeOnlyFileChannel, 10, 10);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_PositionBeyondSize()
+ throws Exception {
+ // init data to file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ final int READONLYFILECHANNELPOSITION = 2;
+ readOnlyFileChannel.position(READONLYFILECHANNELPOSITION);
+
+ final int POSITION = CONTENT_AS_BYTES_LENGTH * 2;
+ final int LENGTH = 5;
+ long result = writeOnlyFileChannel.transferFrom(readOnlyFileChannel,
+ POSITION, LENGTH);
+ assertEquals(0, result);
+ assertEquals(0, writeOnlyFileChannel.position());
+ assertEquals(READONLYFILECHANNELPOSITION, readOnlyFileChannel
+ .position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_FileChannel()
+ throws Exception {
+ // init data to file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ final int READONLYFILECHANNELPOSITION = 2;
+ final int WRITEONLYFILECHANNELPOSITION = 4;
+ readOnlyFileChannel.position(READONLYFILECHANNELPOSITION);
+ writeOnlyFileChannel.position(WRITEONLYFILECHANNELPOSITION);
+
+ final int POSITION = 3;
+ final int LENGTH = 5;
+ long result = writeOnlyFileChannel.transferFrom(readOnlyFileChannel,
+ POSITION, LENGTH);
+ assertEquals(LENGTH, result);
+ assertEquals(WRITEONLYFILECHANNELPOSITION, writeOnlyFileChannel
+ .position());
+ assertEquals(READONLYFILECHANNELPOSITION + LENGTH, readOnlyFileChannel
+ .position());
+ writeOnlyFileChannel.close();
+
+ final int EXPECTED_LENGTH = POSITION + LENGTH;
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] resultContent = new byte[EXPECTED_LENGTH];
+ fis.read(resultContent);
+
+ byte[] expectedContent = new byte[EXPECTED_LENGTH];
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedContent, 0, POSITION);
+ System.arraycopy(CONTENT_AS_BYTES, READONLYFILECHANNELPOSITION,
+ expectedContent, POSITION, LENGTH);
+ assertTrue(Arrays.equals(expectedContent, resultContent));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_DatagramChannel()
+ throws Exception {
+ // connects two datagramChannels.
+ datagramChannelReceiver = DatagramChannel.open();
+ datagramChannelReceiver.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ datagramChannelSender = DatagramChannel.open();
+ datagramChannelSender.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ datagramChannelReceiver.socket().setSoTimeout(TIME_OUT);
+ datagramChannelReceiver.connect(datagramChannelSender.socket()
+ .getLocalSocketAddress());
+ datagramChannelSender.socket().setSoTimeout(TIME_OUT);
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ datagramChannelSender.socket().setSoTimeout(TIME_OUT);
+ // sends data from datagramChannelSender to datagramChannelReceiver.
+ datagramChannelSender.send(writeBuffer, datagramChannelReceiver
+ .socket().getLocalSocketAddress());
+ datagramChannelReceiver.socket().setSoTimeout(TIME_OUT);
+
+ // transfers data from datagramChannelReceiver to fileChannel.
+ long result = writeOnlyFileChannel.transferFrom(
+ datagramChannelReceiver, 0, CONTENT_AS_BYTES_LENGTH);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ assertEquals(0, writeOnlyFileChannel.position());
+ writeOnlyFileChannel.close();
+
+ // gets content from file.
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, fileOfWriteOnlyFileChannel
+ .length());
+ byte[] resultContent = new byte[CONTENT_AS_BYTES_LENGTH];
+ fis.read(resultContent);
+
+ // compares contents.
+ assertTrue(Arrays.equals(CONTENT_AS_BYTES, resultContent));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_SocketChannel()
+ throws Exception {
+ // connects two socketChannels.
+ socketChannelReceiver = SocketChannel.open();
+ serverSocketChannel = ServerSocketChannel.open();
+ serverSocketChannel.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ socketChannelReceiver.socket().setSoTimeout(TIME_OUT);
+ socketChannelReceiver.connect(serverSocketChannel.socket()
+ .getLocalSocketAddress());
+ serverSocketChannel.socket().setSoTimeout(TIME_OUT);
+ socketChannelSender = serverSocketChannel.accept();
+ socketChannelSender.socket().setSoTimeout(TIME_OUT);
+
+ // sends data from socketChannelSender to socketChannelReceiver.
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ socketChannelSender.write(writeBuffer);
+
+ // transfers data from socketChannelReceiver to fileChannel.
+ long result = readWriteFileChannel.transferFrom(socketChannelReceiver,
+ 0, CONTENT_AS_BYTES_LENGTH);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ assertEquals(0, readWriteFileChannel.position());
+ readWriteFileChannel.close();
+
+ // gets content from file.
+ fis = new FileInputStream(fileOfReadWriteFileChannel);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, fileOfReadWriteFileChannel
+ .length());
+ byte[] resultContent = new byte[CONTENT_AS_BYTES_LENGTH];
+ fis.read(resultContent);
+
+ // compares content.
+ assertTrue(Arrays.equals(CONTENT_AS_BYTES, resultContent));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_Pipe() throws Exception {
+ // inits data in file.
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ // inits pipe.
+ pipe = Pipe.open();
+
+ // writes content to pipe.
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ pipe.sink().write(writeBuffer);
+
+ // transfers data from pipe to fileChannel.
+ final int OFFSET = 2;
+ final int LENGTH = 4;
+ long result = writeOnlyFileChannel.transferFrom(pipe.source(), OFFSET,
+ LENGTH);
+ assertEquals(LENGTH, result);
+ writeOnlyFileChannel.close();
+
+ // gets content from file.
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] resultBytes = new byte[OFFSET + LENGTH];
+ fis.read(resultBytes);
+
+ // compares content.
+ byte[] expectedBytes = new byte[OFFSET + LENGTH];
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedBytes, 0, OFFSET);
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedBytes, OFFSET, LENGTH);
+
+ assertTrue(Arrays.equals(expectedBytes, resultBytes));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_Null() throws Exception {
+ writableByteChannel = null;
+ try {
+ readOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+ fail("should throw NullPointerException.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+ fail("should throw NullPointerException.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.transferTo(0, 10, writableByteChannel);
+ fail("should throw NullPointerException.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // should throw NullPointerException first.
+ readOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.transferTo(-1, 0, writableByteChannel);
+ fail("should throw NullPointerException.");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_Closed() throws Exception {
+ writableByteChannel = DatagramChannel.open();
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.transferTo(0, 10, writableByteChannel);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // should throw ClosedChannelException first.
+ try {
+ readWriteFileChannel.transferTo(0, -1, writableByteChannel);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_SourceClosed()
+ throws Exception {
+ writableByteChannel = DatagramChannel.open();
+ writableByteChannel.close();
+
+ try {
+ readOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.transferTo(0, 10, writableByteChannel);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // should throw ClosedChannelException first.
+ try {
+ readWriteFileChannel.transferTo(0, -1, writableByteChannel);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_IllegalArgument()
+ throws Exception {
+ writableByteChannel = DatagramChannel.open();
+ try {
+ readOnlyFileChannel.transferTo(10, -1, writableByteChannel);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.transferTo(-1, -10, writableByteChannel);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_NonReadable()
+ throws Exception {
+ writableByteChannel = DatagramChannel.open();
+ try {
+ writeOnlyFileChannel.transferTo(-1, 10, writableByteChannel);
+ fail("should throw NonReadableChannelException.");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_TargetNonWritable()
+ throws Exception {
+ try {
+ readWriteFileChannel.transferTo(0, 0, readOnlyFileChannel);
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ // first throws NonWritableChannelException even position out of file
+ // size.
+ try {
+ readWriteFileChannel.transferTo(10, 10, readOnlyFileChannel);
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ // regression test for Harmony-941
+ // first throws NonWritableChannelException even arguments are illegal.
+ try {
+ readWriteFileChannel.transferTo(-1, 10, readOnlyFileChannel);
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.transferTo(0, -1, readOnlyFileChannel);
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_PositionBeyondSize()
+ throws Exception {
+ // init data to file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ final int WRITEONLYFILECHANNELPOSITION = 2;
+ writeOnlyFileChannel.position(WRITEONLYFILECHANNELPOSITION);
+
+ final int POSITION = CONTENT_AS_BYTES_LENGTH * 2;
+ final int LENGTH = 5;
+ long result = readOnlyFileChannel.transferTo(POSITION, LENGTH,
+ writeOnlyFileChannel);
+ assertEquals(0, result);
+ assertEquals(0, readOnlyFileChannel.position());
+ assertEquals(WRITEONLYFILECHANNELPOSITION, writeOnlyFileChannel
+ .position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_FileChannel()
+ throws Exception {
+ // init data to file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ final int READONLYFILECHANNELPOSITION = 2;
+ final int WRITEONLYFILECHANNELPOSITION = 4;
+ readOnlyFileChannel.position(READONLYFILECHANNELPOSITION);
+ writeOnlyFileChannel.position(WRITEONLYFILECHANNELPOSITION);
+
+ final int POSITION = 3;
+ final int LENGTH = 5;
+ long result = readOnlyFileChannel.transferTo(POSITION, LENGTH,
+ writeOnlyFileChannel);
+ assertEquals(LENGTH, result);
+ assertEquals(READONLYFILECHANNELPOSITION, readOnlyFileChannel
+ .position());
+ assertEquals(WRITEONLYFILECHANNELPOSITION + LENGTH,
+ writeOnlyFileChannel.position());
+ writeOnlyFileChannel.close();
+
+ final int EXPECTED_LENGTH = WRITEONLYFILECHANNELPOSITION + LENGTH;
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] resultContent = new byte[EXPECTED_LENGTH];
+ fis.read(resultContent);
+
+ byte[] expectedContent = new byte[EXPECTED_LENGTH];
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedContent, 0,
+ WRITEONLYFILECHANNELPOSITION);
+ System.arraycopy(CONTENT_AS_BYTES, POSITION, expectedContent,
+ WRITEONLYFILECHANNELPOSITION, LENGTH);
+ assertTrue(Arrays.equals(expectedContent, resultContent));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_SocketChannel()
+ throws Exception {
+ // inits data into file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ // connects two socketChannels.
+ socketChannelReceiver = SocketChannel.open();
+ socketChannelReceiver.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ serverSocketChannel = ServerSocketChannel.open();
+ serverSocketChannel.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ socketChannelReceiver.socket().setSoTimeout(TIME_OUT);
+ socketChannelReceiver.connect(serverSocketChannel.socket()
+ .getLocalSocketAddress());
+ serverSocketChannel.socket().setSoTimeout(TIME_OUT);
+ socketChannelSender = serverSocketChannel.accept();
+ socketChannelSender.socket().setSoTimeout(TIME_OUT);
+
+ // position here should have no effect on transferTo since it uses
+ // offset from file_begin
+ final int POSITION = 10;
+ readOnlyFileChannel.position(POSITION);
+
+ // transfers data from file to socketChannelSender.
+ final int OFFSET = 2;
+ long result = readOnlyFileChannel.transferTo(OFFSET,
+ CONTENT_AS_BYTES_LENGTH * 2, socketChannelSender);
+ final int LENGTH = CONTENT_AS_BYTES_LENGTH - OFFSET;
+ assertEquals(LENGTH, result);
+ assertEquals(POSITION, readOnlyFileChannel.position());
+ readOnlyFileChannel.close();
+ socketChannelSender.close();
+
+ // gets contents from socketChannelReceiver.
+ ByteBuffer readBuffer = ByteBuffer.allocate(LENGTH + 1);
+ int totalRead = 0;
+ int countRead = 0;
+ long beginTime = System.currentTimeMillis();
+ while ((countRead = socketChannelReceiver.read(readBuffer)) != -1) {
+ totalRead += countRead;
+ // TIMEOUT
+ if (System.currentTimeMillis() - beginTime > TIME_OUT) {
+ break;
+ }
+ }
+ assertEquals(LENGTH, totalRead);
+
+ // compares contents.
+ readBuffer.flip();
+ for (int i = OFFSET; i < CONTENT_AS_BYTES_LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_DatagramChannel()
+ throws Exception {
+ // inits data to file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ // connects two datagramChannel
+ datagramChannelReceiver = DatagramChannel.open();
+ datagramChannelReceiver.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ datagramChannelSender = DatagramChannel.open();
+ datagramChannelSender.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ datagramChannelSender.socket().setSoTimeout(TIME_OUT);
+ datagramChannelSender.connect(datagramChannelReceiver.socket()
+ .getLocalSocketAddress());
+ datagramChannelReceiver.socket().setSoTimeout(TIME_OUT);
+ datagramChannelReceiver.connect(datagramChannelSender.socket()
+ .getLocalSocketAddress());
+
+ // transfers data from fileChannel to datagramChannelSender
+ long result = readOnlyFileChannel.transferTo(0,
+ CONTENT_AS_BYTES_LENGTH, datagramChannelSender);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ assertEquals(0, readOnlyFileChannel.position());
+ readOnlyFileChannel.close();
+ datagramChannelSender.close();
+
+ // gets contents from datagramChannelReceiver
+ ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_AS_BYTES_LENGTH);
+ long beginTime = System.currentTimeMillis();
+ int totalRead = 0;
+ while (totalRead < CONTENT_AS_BYTES_LENGTH) {
+ totalRead += datagramChannelReceiver.read(readBuffer);
+ if (System.currentTimeMillis() - beginTime > TIME_OUT) {
+ break;
+ }
+ }
+ assertEquals(CONTENT_AS_BYTES_LENGTH, totalRead);
+
+ // compares contents.
+ readBuffer.flip();
+ for (int i = 0; i < CONTENT_AS_BYTES_LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_Pipe() throws Exception {
+ // inits data in file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ // inits pipe.
+ pipe = Pipe.open();
+
+ // transfers data from fileChannel to pipe.
+ final int OFFSET = 2;
+ final int LENGTH = 4;
+ long result = readOnlyFileChannel.transferTo(OFFSET, LENGTH, pipe
+ .sink());
+ assertEquals(LENGTH, result);
+ assertEquals(0, readOnlyFileChannel.position());
+ readOnlyFileChannel.close();
+
+ // gets content from pipe.
+ ByteBuffer readBuffer = ByteBuffer.allocate(LENGTH);
+ result = pipe.source().read(readBuffer);
+ assertEquals(LENGTH, result);
+
+ // compares content.
+ readBuffer.flip();
+ for (int i = OFFSET; i < OFFSET + LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ }
+ }
+
+ private class MockFileChannel extends FileChannel {
+
+ private boolean isLockCalled = false;
+
+ private boolean isTryLockCalled = false;
+
+ private boolean isReadCalled = false;
+
+ private boolean isWriteCalled = false;
+
+ public void force(boolean arg0) throws IOException {
+ // do nothing
+ }
+
+ public FileLock lock(long position, long size, boolean shared)
+ throws IOException {
+ // verify that calling lock() leads to the method
+ // lock(0, Long.MAX_VALUE, false).
+ if (0 == position && Long.MAX_VALUE == size && false == shared) {
+ isLockCalled = true;
+ }
+ return null;
+ }
+
+ public MappedByteBuffer map(MapMode arg0, long arg1, long arg2)
+ throws IOException {
+ return null;
+ }
+
+ public long position() throws IOException {
+ return 0;
+ }
+
+ public FileChannel position(long arg0) throws IOException {
+ return null;
+ }
+
+ public int read(ByteBuffer arg0) throws IOException {
+ return 0;
+ }
+
+ public int read(ByteBuffer arg0, long arg1) throws IOException {
+ return 0;
+ }
+
+ public long read(ByteBuffer[] srcs, int offset, int length)
+ throws IOException {
+ // verify that calling read(ByteBuffer[] srcs) leads to the method
+ // read(srcs, 0, srcs.length)
+ if (0 == offset && length == srcs.length) {
+ isReadCalled = true;
+ }
+ return 0;
+ }
+
+ public long size() throws IOException {
+ return 0;
+ }
+
+ public long transferFrom(ReadableByteChannel arg0, long arg1, long arg2)
+ throws IOException {
+ return 0;
+ }
+
+ public long transferTo(long arg0, long arg1, WritableByteChannel arg2)
+ throws IOException {
+ return 0;
+ }
+
+ public FileChannel truncate(long arg0) throws IOException {
+ return null;
+ }
+
+ public FileLock tryLock(long position, long size, boolean shared)
+ throws IOException {
+ // verify that calling tryLock() leads to the method
+ // tryLock(0, Long.MAX_VALUE, false).
+ if (0 == position && Long.MAX_VALUE == size && false == shared) {
+ isTryLockCalled = true;
+ }
+ return null;
+ }
+
+ public int write(ByteBuffer arg0) throws IOException {
+ return 0;
+ }
+
+ public int write(ByteBuffer arg0, long arg1) throws IOException {
+ return 0;
+ }
+
+ public long write(ByteBuffer[] srcs, int offset, int length)
+ throws IOException {
+ // verify that calling write(ByteBuffer[] srcs) leads to the method
+ // write(srcs, 0, srcs.length)
+ if(0 == offset && length == srcs.length){
+ isWriteCalled = true;
+ }
+ return 0;
+ }
+
+ protected void implCloseChannel() throws IOException {
+
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java
new file mode 100644
index 0000000..a6d60d5
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java
@@ -0,0 +1,45 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.FileLockInterruptionException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for FileLockInterruptionException
+ */
+public class FileLockInterruptionExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new FileLockInterruptionException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this,
+ new FileLockInterruptionException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java
new file mode 100644
index 0000000..d13c521
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java
@@ -0,0 +1,193 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests class FileLock.
+ */
+public class FileLockTest extends TestCase {
+
+ private FileChannel readWriteChannel;
+
+ private MockFileLock mockLock;
+
+ class MockFileLock extends FileLock {
+
+ boolean isValid = true;
+
+ protected MockFileLock(FileChannel channel, long position, long size,
+ boolean shared) {
+ super(channel, position, size, shared);
+ }
+
+ public boolean isValid() {
+ return isValid;
+ }
+
+ public void release() throws IOException {
+ isValid = false;
+ }
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ File tempFile = File.createTempFile("testing", "tmp");
+ tempFile.deleteOnExit();
+ RandomAccessFile randomAccessFile = new RandomAccessFile(tempFile, "rw");
+ readWriteChannel = randomAccessFile.getChannel();
+ mockLock = new MockFileLock(readWriteChannel, 10, 100, false);
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#FileLock(FileChannel, long, long,
+ * boolean)
+ */
+ public void test_Constructor_Ljava_nio_channels_FileChannelJJZ() {
+ FileLock fileLock1 = new MockFileLock(null, 0, 0, false);
+ assertNull(fileLock1.channel());
+
+ try {
+ new MockFileLock(readWriteChannel, -1, 0, false);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ try {
+ new MockFileLock(readWriteChannel, 0, -1, false);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ // Harmony-682 regression test
+ try {
+ new MockFileLock(readWriteChannel, Long.MAX_VALUE, 1, false);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#channel()
+ */
+ public void test_channel() {
+ assertSame(readWriteChannel, mockLock.channel());
+ FileLock lock = new MockFileLock(null, 0, 10, true);
+ assertNull(lock.channel());
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#position()
+ */
+ public void test_position() {
+ FileLock fileLock1 = new MockFileLock(readWriteChannel, 20, 100, true);
+ assertEquals(20, fileLock1.position());
+
+ final long position = ((long) Integer.MAX_VALUE + 1);
+ FileLock fileLock2 = new MockFileLock(readWriteChannel, position, 100,
+ true);
+ assertEquals(position, fileLock2.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#size()
+ */
+ public void test_size() {
+ FileLock fileLock1 = new MockFileLock(readWriteChannel, 20, 100, true);
+ assertEquals(100, fileLock1.size());
+
+ final long position = 0x0FFFFFFFFFFFFFFFL;
+ final long size = ((long) Integer.MAX_VALUE + 1);
+ FileLock fileLock2 = new MockFileLock(readWriteChannel, position, size,
+ true);
+ assertEquals(size, fileLock2.size());
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#isShared()
+ */
+ public void test_isShared() {
+ assertFalse(mockLock.isShared());
+ FileLock lock = new MockFileLock(null, 0, 10, true);
+ assertTrue(lock.isShared());
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#overlaps(long, long)
+ */
+ public void test_overlaps_JJ() {
+ assertTrue(mockLock.overlaps(0, 11));
+ assertFalse(mockLock.overlaps(0, 10));
+ assertTrue(mockLock.overlaps(100, 110));
+ assertTrue(mockLock.overlaps(99, 110));
+ assertFalse(mockLock.overlaps(-1, 10));
+ //Harmony-671 regression test
+ assertTrue(mockLock.overlaps(1, 120));
+ assertTrue(mockLock.overlaps(20, 50));
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#isValid()
+ */
+ public void test_isValid() throws IOException {
+ FileLock fileLock = readWriteChannel.lock();
+ assertTrue(fileLock.isValid());
+ fileLock.release();
+ assertFalse(fileLock.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#release()
+ */
+ public void test_release() throws Exception {
+ File file = File.createTempFile("test", "tmp");
+ file.deleteOnExit();
+ FileOutputStream fout = new FileOutputStream(file);
+ FileChannel fileChannel = fout.getChannel();
+ FileLock fileLock = fileChannel.lock();
+ fileChannel.close();
+ try {
+ fileLock.release();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // release after release
+ fout = new FileOutputStream(file);
+ fileChannel = fout.getChannel();
+ fileLock = fileChannel.lock();
+ fileLock.release();
+ fileChannel.close();
+ try {
+ fileLock.release();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ //expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java
new file mode 100644
index 0000000..1e26eb0
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java
@@ -0,0 +1,45 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.IllegalBlockingModeException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for IllegalBlockingModeException
+ */
+public class IllegalBlockingModeExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new IllegalBlockingModeException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest
+ .verifyGolden(this, new IllegalBlockingModeException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java
new file mode 100644
index 0000000..3d80375
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.IllegalSelectorException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for IllegalSelectorException
+ */
+public class IllegalSelectorExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new IllegalSelectorException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new IllegalSelectorException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MapModeTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MapModeTest.java
new file mode 100644
index 0000000..33234eb
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MapModeTest.java
@@ -0,0 +1,52 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.FileChannel;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for FileChannel.MapMode
+ */
+public class MapModeTest extends TestCase {
+
+ /**
+ * java.nio.channels.FileChannel.MapMode#PRIVATE,READONLY,READWRITE
+ */
+ public void test_PRIVATE_READONLY_READWRITE() {
+ assertNotNull(FileChannel.MapMode.PRIVATE);
+ assertNotNull(FileChannel.MapMode.READ_ONLY);
+ assertNotNull(FileChannel.MapMode.READ_WRITE);
+
+ assertFalse(FileChannel.MapMode.PRIVATE
+ .equals(FileChannel.MapMode.READ_ONLY));
+ assertFalse(FileChannel.MapMode.PRIVATE
+ .equals(FileChannel.MapMode.READ_WRITE));
+ assertFalse(FileChannel.MapMode.READ_ONLY
+ .equals(FileChannel.MapMode.READ_WRITE));
+ }
+
+ /**
+ * java.nio.channels.FileChannel.MapMode#toString()
+ */
+ public void test_toString() {
+ assertNotNull(FileChannel.MapMode.PRIVATE.toString());
+ assertNotNull(FileChannel.MapMode.READ_ONLY.toString());
+ assertNotNull(FileChannel.MapMode.READ_WRITE.toString());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockDatagramChannel.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockDatagramChannel.java
new file mode 100644
index 0000000..c8dc2af
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockDatagramChannel.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+class MockDatagramChannel extends DatagramChannel {
+
+ public MockDatagramChannel(SelectorProvider arg0) {
+ super(arg0);
+ }
+
+ public DatagramSocket socket() {
+ return null;
+ }
+
+ public boolean isConnected() {
+ return false;
+ }
+
+ public DatagramChannel connect(SocketAddress arg0) throws IOException {
+ return null;
+ }
+
+ public DatagramChannel disconnect() throws IOException {
+ return null;
+ }
+
+ public SocketAddress receive(ByteBuffer arg0) throws IOException {
+ return null;
+ }
+
+ public int send(ByteBuffer arg0, SocketAddress arg1) throws IOException {
+ return 0;
+ }
+
+ public int read(ByteBuffer arg0) throws IOException {
+ return 0;
+ }
+
+ public long read(ByteBuffer[] arg0, int arg1, int arg2) throws IOException {
+ return 0;
+ }
+
+ public int write(ByteBuffer arg0) throws IOException {
+ return 0;
+ }
+
+ public long write(ByteBuffer[] arg0, int arg1, int arg2) throws IOException {
+ return 0;
+ }
+
+ protected void implCloseSelectableChannel() throws IOException {
+ // empty
+ }
+
+ protected void implConfigureBlocking(boolean arg0) throws IOException {
+ // empty
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockServerSocketChannel.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockServerSocketChannel.java
new file mode 100644
index 0000000..2058a7a
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockServerSocketChannel.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+class MockServerSocketChannel extends ServerSocketChannel {
+
+ protected MockServerSocketChannel(SelectorProvider arg0) {
+ super(arg0);
+ }
+
+ public ServerSocket socket() {
+ return null;
+ }
+
+ public SocketChannel accept() throws IOException {
+ return null;
+ }
+
+ protected void implCloseSelectableChannel() throws IOException {
+ }
+
+ protected void implConfigureBlocking(boolean arg0) throws IOException {
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockSocketChannel.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockSocketChannel.java
new file mode 100644
index 0000000..9d130ca
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockSocketChannel.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+class MockSocketChannel extends SocketChannel {
+
+ protected MockSocketChannel(SelectorProvider arg0) {
+ super(arg0);
+ }
+
+ public Socket socket() {
+ return null;
+ }
+
+ public boolean isConnected() {
+ return false;
+ }
+
+ public boolean isConnectionPending() {
+ return false;
+ }
+
+ public boolean connect(SocketAddress arg0) throws IOException {
+ return false;
+ }
+
+ public boolean finishConnect() throws IOException {
+ return false;
+ }
+
+ public int read(ByteBuffer arg0) throws IOException {
+ return 0;
+ }
+
+ public long read(ByteBuffer[] arg0, int arg1, int arg2) throws IOException {
+ return 0;
+ }
+
+ public int write(ByteBuffer arg0) throws IOException {
+ return 0;
+ }
+
+ public long write(ByteBuffer[] arg0, int arg1, int arg2) throws IOException {
+ return 0;
+ }
+
+ protected void implCloseSelectableChannel() throws IOException {
+ }
+
+ protected void implConfigureBlocking(boolean arg0) throws IOException {
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java
new file mode 100644
index 0000000..6fcc71f
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java
@@ -0,0 +1,45 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.NoConnectionPendingException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NoConnectionPendingException
+ */
+public class NoConnectionPendingExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new NoConnectionPendingException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest
+ .verifyGolden(this, new NoConnectionPendingException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java
new file mode 100644
index 0000000..e287e2f
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.NonReadableChannelException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NonReadableChannelException
+ */
+public class NonReadableChannelExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new NonReadableChannelException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new NonReadableChannelException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java
new file mode 100644
index 0000000..c145354
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.NonWritableChannelException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NonWritableChannelException
+ */
+public class NonWritableChannelExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new NonWritableChannelException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new NonWritableChannelException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java
new file mode 100644
index 0000000..35fd7df
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.NotYetBoundException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NotYetBoundException
+ */
+public class NotYetBoundExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new NotYetBoundException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new NotYetBoundException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java
new file mode 100644
index 0000000..6cfb0af
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.NotYetConnectedException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NotYetConnectedException
+ */
+public class NotYetConnectedExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new NotYetConnectedException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new NotYetConnectedException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java
new file mode 100644
index 0000000..9d3a786
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java
@@ -0,0 +1,45 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.OverlappingFileLockException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for OverlappingFileLockException
+ */
+public class OverlappingFileLockExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new OverlappingFileLockException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest
+ .verifyGolden(this, new OverlappingFileLockException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/PipeTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/PipeTest.java
new file mode 100644
index 0000000..c1b2111
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/PipeTest.java
@@ -0,0 +1,57 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.nio.channels.Pipe;
+import java.nio.channels.Pipe.SinkChannel;
+import java.nio.channels.Pipe.SourceChannel;
+
+import junit.framework.TestCase;
+
+/*
+ * Tests for Pipe and its default implementation
+ */
+public class PipeTest extends TestCase {
+
+ /**
+ * @tests java.nio.channels.Pipe#open()
+ */
+ public void test_open() throws IOException{
+ Pipe pipe = Pipe.open();
+ assertNotNull(pipe);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe#sink()
+ */
+ public void test_sink() throws IOException {
+ Pipe pipe = Pipe.open();
+ SinkChannel sink = pipe.sink();
+ assertTrue(sink.isBlocking());
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe#source()
+ */
+ public void test_source() throws IOException {
+ Pipe pipe = Pipe.open();
+ SourceChannel source = pipe.source();
+ assertTrue(source.isBlocking());
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectableChannelTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectableChannelTest.java
new file mode 100644
index 0000000..25b5f00
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectableChannelTest.java
@@ -0,0 +1,89 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.SelectorProvider;
+import junit.framework.TestCase;
+
+/*
+ * Tests for SelectableChannel
+ */
+public class SelectableChannelTest extends TestCase {
+
+ /**
+ * @tests SelectableChannel#register(Selector, int)
+ */
+ public void test_register_LSelectorI() throws IOException {
+ MockSelectableChannel msc = new MockSelectableChannel();
+ // Verify that calling register(Selector, int) leads to the method
+ // register(Selector, int, Object) being called with a null value
+ // for the third argument.
+ msc.register(Selector.open(), SelectionKey.OP_ACCEPT);
+ assertTrue(msc.isCalled);
+ }
+
+ private class MockSelectableChannel extends SelectableChannel {
+
+ private boolean isCalled = false;
+
+ public Object blockingLock() {
+ return null;
+ }
+
+ public SelectableChannel configureBlocking(boolean block)
+ throws IOException {
+ return null;
+ }
+
+ public boolean isBlocking() {
+ return false;
+ }
+
+ public boolean isRegistered() {
+ return false;
+ }
+
+ public SelectionKey keyFor(Selector sel) {
+ return null;
+ }
+
+ public SelectorProvider provider() {
+ return null;
+ }
+
+ public SelectionKey register(Selector sel, int ops, Object att)
+ throws ClosedChannelException {
+ if (null == att) {
+ isCalled = true;
+ }
+ return null;
+ }
+
+ public int validOps() {
+ return 0;
+ }
+
+ protected void implCloseChannel() throws IOException {
+ // empty
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectionKeyTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectionKeyTest.java
new file mode 100644
index 0000000..ed33752
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectionKeyTest.java
@@ -0,0 +1,321 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.nio.channels.CancelledKeyException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/*
+ * Tests for SelectionKey and its default implementation
+ */
+public class SelectionKeyTest extends TestCase {
+
+ Selector selector;
+
+ SocketChannel sc;
+
+ SelectionKey selectionKey;
+
+ private static String LOCAL_ADDR = "127.0.0.1";
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ selector = Selector.open();
+ sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ selectionKey = sc.register(selector, SelectionKey.OP_CONNECT);
+ }
+
+ protected void tearDown() throws Exception {
+ selectionKey.cancel();
+ selectionKey = null;
+ selector.close();
+ selector = null;
+ super.tearDown();
+ }
+
+ static class MockSelectionKey extends SelectionKey {
+ private int interestOps;
+
+ MockSelectionKey(int ops) {
+ interestOps = ops;
+ }
+
+ public void cancel() {
+ // do nothing
+ }
+
+ public SelectableChannel channel() {
+ return null;
+ }
+
+ public int interestOps() {
+ return 0;
+ }
+
+ public SelectionKey interestOps(int operations) {
+ return null;
+ }
+
+ public boolean isValid() {
+ return true;
+ }
+
+ public int readyOps() {
+ return interestOps;
+ }
+
+ public Selector selector() {
+ return null;
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#attach(Object)
+ */
+ public void test_attach() {
+ MockSelectionKey mockSelectionKey = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+ // no previous, return null
+ Object o = new Object();
+ Object check = mockSelectionKey.attach(o);
+ assertNull(check);
+
+ // null parameter is ok
+ check = mockSelectionKey.attach(null);
+ assertSame(o, check);
+
+ check = mockSelectionKey.attach(o);
+ assertNull(check);
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#attachment()
+ */
+ public void test_attachment() {
+ MockSelectionKey mockSelectionKey = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+ assertNull(mockSelectionKey.attachment());
+ Object o = new Object();
+ mockSelectionKey.attach(o);
+ assertSame(o, mockSelectionKey.attachment());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#channel()
+ */
+ public void test_channel() {
+ assertSame(sc, selectionKey.channel());
+ // can be invoked even canceled
+ selectionKey.cancel();
+ assertSame(sc, selectionKey.channel());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#interestOps()
+ */
+ public void test_interestOps() {
+ assertEquals(SelectionKey.OP_CONNECT, selectionKey.interestOps());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#interestOps(int)
+ */
+ public void test_interestOpsI() {
+ selectionKey.interestOps(SelectionKey.OP_WRITE);
+ assertEquals(SelectionKey.OP_WRITE, selectionKey.interestOps());
+
+ try {
+ selectionKey.interestOps(SelectionKey.OP_ACCEPT);
+ fail("should throw IAE.");
+ } catch (IllegalArgumentException ex) {
+ // expected;
+ }
+
+ try {
+ selectionKey.interestOps(~sc.validOps());
+ fail("should throw IAE.");
+ } catch (IllegalArgumentException ex) {
+ // expected;
+ }
+ try {
+ selectionKey.interestOps(-1);
+ fail("should throw IAE.");
+ } catch (IllegalArgumentException ex) {
+ // expected;
+ }
+
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isValid()
+ */
+ public void test_isValid() {
+ assertTrue(selectionKey.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isValid()
+ */
+ public void test_isValid_KeyCancelled() {
+ selectionKey.cancel();
+ assertFalse(selectionKey.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isValid()
+ */
+ public void test_isValid_ChannelColsed() throws IOException {
+ sc.close();
+ assertFalse(selectionKey.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isValid()
+ */
+ public void test_isValid_SelectorClosed() throws IOException {
+ selector.close();
+ assertFalse(selectionKey.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isAcceptable()
+ */
+ public void test_isAcceptable() throws IOException {
+ MockSelectionKey mockSelectionKey1 = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+ assertTrue(mockSelectionKey1.isAcceptable());
+ MockSelectionKey mockSelectionKey2 = new MockSelectionKey(SelectionKey.OP_CONNECT);
+ assertFalse(mockSelectionKey2.isAcceptable());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isConnectable()
+ */
+ public void test_isConnectable() {
+ MockSelectionKey mockSelectionKey1 = new MockSelectionKey(SelectionKey.OP_CONNECT);
+ assertTrue(mockSelectionKey1.isConnectable());
+ MockSelectionKey mockSelectionKey2 = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+ assertFalse(mockSelectionKey2.isConnectable());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isReadable()
+ */
+ public void test_isReadable() {
+ MockSelectionKey mockSelectionKey1 = new MockSelectionKey(SelectionKey.OP_READ);
+ assertTrue(mockSelectionKey1.isReadable());
+ MockSelectionKey mockSelectionKey2 = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+ assertFalse(mockSelectionKey2.isReadable());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isWritable()
+ */
+ public void test_isWritable() {
+ MockSelectionKey mockSelectionKey1 = new MockSelectionKey(SelectionKey.OP_WRITE);
+ assertTrue(mockSelectionKey1.isWritable());
+ MockSelectionKey mockSelectionKey2 = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+ assertFalse(mockSelectionKey2.isWritable());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#cancel()
+ */
+ public void test_cancel() {
+ selectionKey.cancel();
+ try {
+ selectionKey.isAcceptable();
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+ try {
+ selectionKey.isConnectable();
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+ try {
+ selectionKey.isReadable();
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+ try {
+ selectionKey.isWritable();
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+
+ try {
+ selectionKey.readyOps();
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+
+ try {
+ selectionKey.interestOps(SelectionKey.OP_CONNECT);
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+
+ try {
+ selectionKey.interestOps();
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#readyOps()
+ */
+ public void test_readyOps() throws IOException {
+ int port = Support_PortManager.getNextPort();
+ ServerSocket ss = new ServerSocket(port);
+ try {
+ sc.connect(new InetSocketAddress(LOCAL_ADDR, port));
+ assertEquals(0, selectionKey.readyOps());
+ assertFalse(selectionKey.isConnectable());
+ selector.select();
+ assertEquals(SelectionKey.OP_CONNECT, selectionKey.readyOps());
+ } finally {
+ ss.close();
+ ss = null;
+ }
+
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#selector()
+ */
+ public void test_selector() {
+ assertSame(selector, selectionKey.selector());
+ selectionKey.cancel();
+ assertSame(selector, selectionKey.selector());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java
new file mode 100644
index 0000000..9f73172
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java
@@ -0,0 +1,544 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Set;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/*
+ * Tests for Selector and its default implementation
+ */
+public class SelectorTest extends TestCase {
+
+ private static final int WAIT_TIME = 100;
+
+ private static final int PORT = Support_PortManager.getNextPort();
+
+ private static final InetSocketAddress LOCAL_ADDRESS = new InetSocketAddress(
+ "127.0.0.1", PORT);
+
+ Selector selector;
+
+ ServerSocketChannel ssc;
+
+ enum SelectType {
+ NULL, TIMEOUT, NOW
+ };
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ ssc = ServerSocketChannel.open();
+ ssc.configureBlocking(false);
+ ServerSocket ss = ssc.socket();
+ InetSocketAddress address = new InetSocketAddress(PORT);
+ ss.bind(address);
+ selector = Selector.open();
+ }
+
+ protected void tearDown() throws Exception {
+ try {
+ ssc.close();
+ } catch (Exception e) {
+ // do nothing
+ }
+ try {
+ selector.close();
+ } catch (Exception e) {
+ // do nothing
+ }
+ super.tearDown();
+ }
+
+ /**
+ * @tests java.nio.channels.Selector#open()
+ */
+ public void test_open() throws IOException {
+ assertNotNull(selector);
+ }
+
+ /**
+ * @tests Selector#isOpen()
+ */
+ public void test_isOpen() throws IOException {
+ assertTrue(selector.isOpen());
+ selector.close();
+ assertFalse(selector.isOpen());
+ }
+
+ /**
+ * @tests java.nio.channels.Selector#provider()
+ */
+ public void test_provider() throws IOException {
+ // should be system default provider
+ assertNotNull(selector.provider());
+ assertSame(SelectorProvider.provider(), selector.provider());
+ }
+
+ /**
+ * @tests java.nio.channels.Selector#keys()
+ */
+ public void test_keys() throws IOException {
+ SelectionKey key = ssc.register(selector, SelectionKey.OP_ACCEPT);
+
+ Set<SelectionKey> keySet = selector.keys();
+ Set<SelectionKey> keySet2 = selector.keys();
+
+ assertSame(keySet, keySet2);
+ assertEquals(1,keySet.size());
+ SelectionKey key2 = keySet.iterator().next();
+ assertEquals(key,key2);
+
+ // Any attempt to modify keys will cause UnsupportedOperationException
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ SelectionKey key3 = sc.register(selector, SelectionKey.OP_READ);
+ try {
+ keySet2.add(key3);
+ fail("should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ keySet2.remove(key3);
+ fail("should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ keySet2.clear();
+ fail("should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ selector.close();
+ try {
+ selector.keys();
+ fail("should throw ClosedSelectorException");
+ } catch (ClosedSelectorException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Selector#keys()
+ */
+ public void test_selectedKeys() throws IOException {
+ SocketChannel sc = SocketChannel.open();
+ ssc.register(selector, SelectionKey.OP_ACCEPT);
+ try {
+ int count = 0;
+ sc.connect(LOCAL_ADDRESS);
+ count = blockingSelect(SelectType.NULL, 0);
+ assertEquals(1, count);
+ Set<SelectionKey> selectedKeys = selector.selectedKeys();
+ Set<SelectionKey> selectedKeys2 = selector.selectedKeys();
+ assertSame(selectedKeys, selectedKeys2);
+
+ assertEquals(1, selectedKeys.size());
+ assertEquals(ssc.keyFor(selector), selectedKeys.iterator().next());
+ // add one key into selectedKeys
+ try {
+ selectedKeys.add(ssc.keyFor(selector));
+ fail("Should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ // no exception should be thrown
+ selectedKeys.clear();
+
+ Set<SelectionKey> selectedKeys3 = selector.selectedKeys();
+ assertSame(selectedKeys, selectedKeys3);
+
+ ssc.keyFor(selector).cancel();
+ assertEquals(0, selectedKeys.size());
+ selector.close();
+ try {
+ selector.selectedKeys();
+ fail("should throw ClosedSelectorException");
+ } catch (ClosedSelectorException e) {
+ // expected
+ }
+ } finally {
+ sc.close();
+ }
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#selectNow()
+ */
+ public void test_selectNow() throws IOException {
+ assert_select_OP_ACCEPT(SelectType.NOW, 0);
+ assert_select_OP_CONNECT(SelectType.NOW, 0);
+ assert_select_OP_READ(SelectType.NOW, 0);
+ assert_select_OP_WRITE(SelectType.NOW, 0);
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#selectNow()
+ */
+ public void test_selectNow_SelectorClosed() throws IOException {
+ assert_select_SelectorClosed(SelectType.NOW, 0);
+ }
+
+ /**
+ * @test java.nio.channels.Selector#selectNow()
+ */
+ public void test_selectNow_Timeout() throws IOException {
+ // make sure selectNow doesn't block
+ selector.selectNow();
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#select()
+ */
+ public void test_select() throws IOException {
+ assert_select_OP_ACCEPT(SelectType.NULL, 0);
+ assert_select_OP_CONNECT(SelectType.NULL, 0);
+ assert_select_OP_READ(SelectType.NULL, 0);
+ assert_select_OP_WRITE(SelectType.NULL, 0);
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#select()
+ */
+ public void test_select_SelectorClosed() throws IOException {
+ assert_select_SelectorClosed(SelectType.NULL, 0);
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#select(long)
+ */
+ public void test_selectJ() throws IOException {
+ assert_select_OP_ACCEPT(SelectType.TIMEOUT, 0);
+ assert_select_OP_CONNECT(SelectType.TIMEOUT, 0);
+ assert_select_OP_READ(SelectType.TIMEOUT, 0);
+ assert_select_OP_WRITE(SelectType.TIMEOUT, 0);
+
+ assert_select_OP_ACCEPT(SelectType.TIMEOUT, WAIT_TIME);
+ assert_select_OP_CONNECT(SelectType.TIMEOUT, WAIT_TIME);
+ assert_select_OP_READ(SelectType.TIMEOUT, WAIT_TIME);
+ assert_select_OP_WRITE(SelectType.TIMEOUT, WAIT_TIME);
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#select(long)
+ */
+ public void test_selectJ_SelectorClosed() throws IOException {
+ assert_select_SelectorClosed(SelectType.TIMEOUT, 0);
+ selector = Selector.open();
+ assert_select_SelectorClosed(SelectType.TIMEOUT, WAIT_TIME);
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#select(long)
+ */
+ public void test_selectJ_Exception() throws IOException {
+ try {
+ selector.select(-1);
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @test java.nio.channels.Selector#select(long)
+ */
+ public void test_selectJ_Timeout() throws IOException {
+ // make sure select(timeout) doesn't block
+ selector.select(WAIT_TIME);
+ }
+
+ /**
+ * @tests java.nio.channels.Selector#wakeup()
+ */
+ public void test_wakeup() throws IOException {
+ /*
+ * make sure the test does not block on select
+ */
+ selector.wakeup();
+ selectOnce(SelectType.NULL, 0);
+ selector.wakeup();
+ selectOnce(SelectType.TIMEOUT, 0);
+
+ // try to wakeup select. The invocation sequence of wakeup and select
+ // doesn't affect test result.
+ new Thread() {
+ public void run() {
+
+ try {
+ Thread.sleep(WAIT_TIME);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ selector.wakeup();
+ }
+ }.start();
+ selectOnce(SelectType.NULL, 0);
+
+ // try to wakeup select. The invocation sequence of wakeup and select
+ // doesn't affect test result.
+ new Thread() {
+ public void run() {
+
+ try {
+ Thread.sleep(WAIT_TIME);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ selector.wakeup();
+ }
+ }.start();
+ selectOnce(SelectType.TIMEOUT, 0);
+ }
+
+ private void assert_select_SelectorClosed(SelectType type, int timeout)
+ throws IOException {
+ // selector is closed
+ selector.close();
+ try {
+ selectOnce(type, timeout);
+ fail("should throw ClosedSelectorException");
+ } catch (ClosedSelectorException e) {
+ // expected
+ }
+ }
+
+ private void assert_select_OP_ACCEPT(SelectType type, int timeout)
+ throws IOException, ClosedChannelException {
+ SocketChannel sc = SocketChannel.open();
+ SocketChannel client = null;
+ try {
+ ssc.register(selector, SelectionKey.OP_ACCEPT);
+ sc.connect(LOCAL_ADDRESS);
+ int count = blockingSelect(type, timeout);
+ assertEquals(1, count);
+ Set<SelectionKey> selectedKeys = selector.selectedKeys();
+ assertEquals(1, selectedKeys.size());
+ SelectionKey key = selectedKeys.iterator().next();
+ assertEquals(ssc.keyFor(selector), key);
+ assertEquals(SelectionKey.OP_ACCEPT, key.readyOps());
+ // select again, it should return 0
+ count = selectOnce(type, timeout);
+ assertEquals(0,count);
+ // but selectedKeys remains the same as previous
+ assertSame(selectedKeys, selector.selectedKeys());
+ client = ssc.accept();
+ selectedKeys.clear();
+ } finally {
+ try {
+ sc.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ if (null != client) {
+ client.close();
+ }
+ }
+ ssc.keyFor(selector).cancel();
+ }
+
+ private void assert_select_OP_CONNECT(SelectType type, int timeout)
+ throws IOException, ClosedChannelException {
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ sc.register(selector, SelectionKey.OP_CONNECT);
+ try {
+ sc.connect(LOCAL_ADDRESS);
+ int count = blockingSelect(type, timeout);
+ assertEquals(1, count);
+ Set<SelectionKey> selectedKeys = selector.selectedKeys();
+ assertEquals(1, selectedKeys.size());
+ SelectionKey key = selectedKeys.iterator().next();
+ assertEquals(sc.keyFor(selector), key);
+ assertEquals(SelectionKey.OP_CONNECT, key.readyOps());
+ // select again, it should return 0
+ count = selectOnce(type, timeout);
+ assertEquals(0, count);
+ // but selectedKeys remains the same as previous
+ assertSame(selectedKeys, selector.selectedKeys());
+ sc.finishConnect();
+ selectedKeys.clear();
+ } finally {
+ try {
+ ssc.accept().close();
+ } catch (Exception e) {
+ // do nothing
+ }
+
+ try {
+ sc.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ }
+
+ private void assert_select_OP_READ(SelectType type, int timeout)
+ throws IOException {
+ SocketChannel sc = SocketChannel.open();
+ SocketChannel client = null;
+ SocketChannel sc2 = SocketChannel.open();
+ SocketChannel client2 = null;
+ try {
+ ssc.configureBlocking(true);
+ sc.connect(LOCAL_ADDRESS);
+ client = ssc.accept();
+ sc.configureBlocking(false);
+ sc.register(selector, SelectionKey.OP_READ);
+ client.configureBlocking(true);
+
+ sc2.connect(LOCAL_ADDRESS);
+ client2 = ssc.accept();
+ sc2.configureBlocking(false);
+ sc2.register(selector, SelectionKey.OP_READ);
+ client2.configureBlocking(true);
+
+ client.write(ByteBuffer.wrap("a".getBytes()));
+ int count = blockingSelect(type, timeout);
+ assertEquals(1, count);
+ Set<SelectionKey> selectedKeys = selector.selectedKeys();
+ assertEquals(1, selectedKeys.size());
+ SelectionKey key = selectedKeys.iterator().next();
+ assertEquals(sc.keyFor(selector), key);
+ assertEquals(SelectionKey.OP_READ, key.readyOps());
+ // select again, it should return 0
+ count = selectOnce(type, timeout);
+ assertEquals(0, count);
+ // but selectedKeys remains the same as previous
+ assertSame(selectedKeys, selector.selectedKeys());
+
+ sc.read(ByteBuffer.allocate(8));
+
+ // the second SocketChannel should be selected this time
+ client2.write(ByteBuffer.wrap("a".getBytes()));
+ count = blockingSelect(type, timeout);
+ assertEquals(1, count);
+ // selectedKeys still includes the key of sc, because the key of sc
+ // is not removed last time.
+ selectedKeys = selector.selectedKeys();
+ assertEquals(2, selectedKeys.size());
+ } finally {
+ if (null != client) {
+ try {
+ client.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ if (null != client2) {
+ try {
+ client2.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ try {
+ sc.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ try {
+ sc2.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ ssc.configureBlocking(false);
+ }
+ }
+
+ private void assert_select_OP_WRITE(SelectType type, int timeout)
+ throws IOException {
+ SocketChannel sc = SocketChannel.open();
+ SocketChannel client = null;
+ try {
+ sc.connect(LOCAL_ADDRESS);
+ ssc.configureBlocking(true);
+ client = ssc.accept();
+ sc.configureBlocking(false);
+ sc.register(selector, SelectionKey.OP_WRITE);
+ int count = blockingSelect(type, timeout);
+ assertEquals(1, count);
+ Set<SelectionKey> selectedKeys = selector.selectedKeys();
+ assertEquals(1, selectedKeys.size());
+ SelectionKey key = selectedKeys.iterator().next();
+ assertEquals(sc.keyFor(selector), key);
+ assertEquals(SelectionKey.OP_WRITE, key.readyOps());
+ // select again, it should return 0
+ count = selectOnce(type, timeout);
+ assertEquals(0, count);
+ // but selectedKeys remains the same as previous
+ assertSame(selectedKeys, selector.selectedKeys());
+ } finally {
+ if (null != client) {
+ client.close();
+ }
+ try {
+ sc.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ ssc.configureBlocking(false);
+ }
+ }
+
+ private int blockingSelect(SelectType type, int timeout) throws IOException {
+ int ret = 0;
+ do {
+ ret = selectOnce(type, timeout);
+ if (ret > 0) {
+ return ret;
+ }
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ } while (true);
+ }
+
+ private int selectOnce(SelectType type, int timeout) throws IOException {
+ int ret = 0;
+ switch (type) {
+ case NULL:
+ ret = selector.select();
+ break;
+ case TIMEOUT:
+ ret = selector.select(timeout);
+ break;
+ case NOW:
+ ret = selector.selectNow();
+ break;
+ }
+ return ret;
+ }
+
+} \ No newline at end of file
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ServerSocketChannelTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ServerSocketChannelTest.java
new file mode 100644
index 0000000..1c45e6c
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ServerSocketChannelTest.java
@@ -0,0 +1,575 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NotYetBoundException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/*
+ * test for ServerSocketChannel
+ */
+public class ServerSocketChannelTest extends TestCase {
+
+ private static final int CAPACITY_NORMAL = 200;
+
+ private static final int CAPACITY_64KB = 65536;
+
+ private static final int TIME_UNIT = 200;
+
+ private InetSocketAddress localAddr1;
+
+ private ServerSocketChannel serverChannel;
+
+ private SocketChannel clientChannel;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.localAddr1 = new InetSocketAddress(
+ "127.0.0.1", Support_PortManager
+ .getNextPort());
+ this.serverChannel = ServerSocketChannel.open();
+ this.clientChannel = SocketChannel.open();
+ }
+
+ protected void tearDown() throws Exception {
+ if (null != this.serverChannel) {
+ try {
+ this.serverChannel.close();
+ } catch (Exception e) {
+ //ignore
+ }
+
+ }
+ if (null != this.clientChannel) {
+ try {
+ this.clientChannel.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ super.tearDown();
+ }
+
+ // -------------------------------------------------------------------
+ // Test for methods in abstract class.
+ // -------------------------------------------------------------------
+
+ /*
+ * Test method for 'java.nio.channels.ServerSocketChannel.validOps()'
+ */
+ public void testValidOps() {
+ MockServerSocketChannel testMSChnlnull = new MockServerSocketChannel(
+ null);
+ MockServerSocketChannel testMSChnl = new MockServerSocketChannel(
+ SelectorProvider.provider());
+ assertEquals(SelectionKey.OP_ACCEPT, this.serverChannel.validOps());
+ assertEquals(SelectionKey.OP_ACCEPT, testMSChnl.validOps());
+ assertEquals(SelectionKey.OP_ACCEPT, testMSChnlnull.validOps());
+
+ }
+
+ /*
+ * Test method for 'java.nio.channels.ServerSocketChannel.open()'
+ */
+ public void testOpen() {
+ MockServerSocketChannel testMSChnl = new MockServerSocketChannel(null);
+ MockServerSocketChannel testMSChnlnotnull = new MockServerSocketChannel(
+ SelectorProvider.provider());
+ assertEquals(SelectionKey.OP_ACCEPT, testMSChnlnotnull.validOps());
+ assertNull(testMSChnl.provider());
+ assertNotNull(testMSChnlnotnull.provider());
+ assertNotNull(this.serverChannel.provider());
+ assertEquals(testMSChnlnotnull.provider(), this.serverChannel
+ .provider());
+ }
+
+ // -------------------------------------------------------------------
+ // Test for socket()
+ // -------------------------------------------------------------------
+
+ /*
+ * Test method for 'com.ibm.io.nio.ServerSocketChannelImpl.socket()'
+ */
+ public void testSocket_Block_BeforeClose() throws Exception {
+ assertTrue(this.serverChannel.isOpen());
+ assertTrue(this.serverChannel.isBlocking());
+ ServerSocket s1 = this.serverChannel.socket();
+ assertFalse(s1.isClosed());
+ assertSocketNotAccepted(s1);
+ ServerSocket s2 = this.serverChannel.socket();
+ // same
+ assertSame(s1, s2);
+
+ // socket close makes the channel close
+ s1.close();
+ assertFalse(this.serverChannel.isOpen());
+
+ }
+
+ public void testSocket_NonBlock_BeforeClose() throws Exception {
+ assertTrue(this.serverChannel.isOpen());
+ this.serverChannel.configureBlocking(false);
+ ServerSocket s1 = this.serverChannel.socket();
+ assertFalse(s1.isClosed());
+ assertSocketNotAccepted(s1);
+ ServerSocket s2 = this.serverChannel.socket();
+ // same
+ assertSame(s1, s2);
+
+ // socket close makes the channel close
+ s1.close();
+ assertFalse(this.serverChannel.isOpen());
+
+ }
+
+ public void testSocket_Block_Closed() throws Exception {
+ this.serverChannel.close();
+ assertFalse(this.serverChannel.isOpen());
+ assertTrue(this.serverChannel.isBlocking());
+ ServerSocket s1 = this.serverChannel.socket();
+ assertTrue(s1.isClosed());
+ assertSocketNotAccepted(s1);
+ ServerSocket s2 = this.serverChannel.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ public void testSocket_NonBlock_Closed() throws Exception {
+ this.serverChannel.configureBlocking(false);
+ this.serverChannel.close();
+ assertFalse(this.serverChannel.isBlocking());
+ assertFalse(this.serverChannel.isOpen());
+ ServerSocket s1 = this.serverChannel.socket();
+ assertTrue(s1.isClosed());
+ assertSocketNotAccepted(s1);
+ ServerSocket s2 = this.serverChannel.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ private void assertSocketNotAccepted(ServerSocket s) throws IOException {
+ assertFalse(s.isBound());
+ assertNull(s.getInetAddress());
+ assertEquals(-1, s.getLocalPort());
+ assertNull(s.getLocalSocketAddress());
+ assertEquals(0, s.getSoTimeout());
+ }
+
+ public void testChannelBasicStatus() {
+ ServerSocket gotSocket = this.serverChannel.socket();
+ assertFalse(gotSocket.isClosed());
+ assertTrue(this.serverChannel.isBlocking());
+ assertFalse(this.serverChannel.isRegistered());
+ assertEquals(SelectionKey.OP_ACCEPT, this.serverChannel.validOps());
+ assertEquals(SelectorProvider.provider(), this.serverChannel.provider());
+ }
+
+ // -------------------------------------------------------------------
+ // Test for accept()
+ // -------------------------------------------------------------------
+
+ /*
+ * Test method for 'com.ibm.io.nio.ServerSocketChannelImpl.accept()'
+ */
+
+ public void testAccept_Block_NotYetBound() throws IOException {
+ assertTrue(this.serverChannel.isOpen());
+ assertTrue(this.serverChannel.isBlocking());
+ try {
+ this.serverChannel.accept();
+ fail("Should throw NotYetBoundException");
+ } catch (NotYetBoundException e) {
+ // correct
+ }
+ }
+
+ public void testAccept_NonBlock_NotYetBound() throws IOException {
+ assertTrue(this.serverChannel.isOpen());
+ this.serverChannel.configureBlocking(false);
+ try {
+ this.serverChannel.accept();
+ fail("Should throw NotYetBoundException");
+ } catch (NotYetBoundException e) {
+ // correct
+ }
+ }
+
+ public void testAccept_ClosedChannel() throws Exception {
+ this.serverChannel.close();
+ assertFalse(this.serverChannel.isOpen());
+ try {
+ this.serverChannel.accept();
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ public void testAccept_Block_NoConnect() throws IOException {
+ assertTrue(this.serverChannel.isBlocking());
+ ServerSocket gotSocket = this.serverChannel.socket();
+ gotSocket.bind(localAddr1);
+ // blocking mode , will block and wait for ever...
+ // so must close the server channel with another thread.
+ new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(TIME_UNIT);
+ ServerSocketChannelTest.this.serverChannel.close();
+ } catch (Exception e) {
+ fail("Fail to close the server channel because of"
+ + e.getClass().getName());
+ }
+ }
+ }.start();
+ try {
+ this.serverChannel.accept();
+ fail("Should throw a AsynchronousCloseException");
+ } catch (AsynchronousCloseException e) {
+ // OK.
+ }
+ }
+
+ public void testAccept_NonBlock_NoConnect() throws IOException {
+ ServerSocket gotSocket = this.serverChannel.socket();
+ gotSocket.bind(localAddr1);
+ this.serverChannel.configureBlocking(false);
+ // non-blocking mode , will immediately return
+ assertNull(this.serverChannel.accept());
+ }
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_read_Blocking_RealData() throws IOException {
+ serverChannel.socket().bind(localAddr1);
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ buf.put((byte) i);
+ }
+ clientChannel.connect(localAddr1);
+ Socket serverSocket = serverChannel.accept().socket();
+ InputStream in = serverSocket.getInputStream();
+ buf.flip();
+ clientChannel.write(buf);
+ clientChannel.close();
+ assertReadResult(in,CAPACITY_NORMAL);
+ }
+
+ /**
+ * Asserts read content. The read content should contain <code>size</code>
+ * bytes, and the value should be a sequence from 0 to size-1
+ * ([0,1,...size-1]). Otherwise, the method throws Exception.
+ *
+ */
+ private void assertReadResult(InputStream in, int size) throws IOException{
+ byte[] readContent = new byte[size + 1];
+ int count = 0;
+ int total = 0;
+ while ((count = in.read(readContent, total, size + 1 - total)) != -1) {
+ total = total + count;
+ }
+ assertEquals(size, total);
+ for (int i = 0; i < size; i++) {
+ assertEquals((byte) i, readContent[i]);
+ }
+ }
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_read_NonBlocking_RealData() throws Exception {
+ serverChannel.configureBlocking(false);
+ serverChannel.socket().bind(localAddr1);
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ buf.put((byte) i);
+ }
+ buf.flip();
+ clientChannel.connect(localAddr1);
+ Socket serverSocket = serverChannel.accept().socket();
+ InputStream in = serverSocket.getInputStream();
+ clientChannel.write(buf);
+ clientChannel.close();
+ assertReadResult(in,CAPACITY_NORMAL);
+ }
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_write_Blocking_RealData() throws IOException {
+ assertTrue(serverChannel.isBlocking());
+ ServerSocket serverSocket = serverChannel.socket();
+ serverSocket.bind(localAddr1);
+
+ byte[] writeContent = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < writeContent.length; i++) {
+ writeContent[i] = (byte) i;
+ }
+ clientChannel.connect(localAddr1);
+ Socket socket = serverChannel.accept().socket();
+ OutputStream out = socket.getOutputStream();
+ out.write(writeContent);
+ out.flush();
+ socket.close();
+ assertWriteResult(CAPACITY_NORMAL);
+ }
+
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_write_NonBlocking_RealData() throws Exception {
+ serverChannel.configureBlocking(false);
+ ServerSocket serverSocket = serverChannel.socket();
+ serverSocket.bind(localAddr1);
+
+ byte[] writeContent = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ writeContent[i] = (byte) i;
+ }
+ clientChannel.connect(localAddr1);
+ Socket clientSocket = serverChannel.accept().socket();
+ OutputStream out = clientSocket.getOutputStream();
+ out.write(writeContent);
+ clientSocket.close();
+ assertWriteResult(CAPACITY_NORMAL);
+ }
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_read_LByteBuffer_Blocking_ReadWriteRealLargeData()
+ throws IOException {
+ serverChannel.socket().bind(localAddr1);
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_64KB);
+ for (int i = 0; i < CAPACITY_64KB; i++) {
+ buf.put((byte) i);
+ }
+ buf.flip();
+ clientChannel.connect(localAddr1);
+ clientChannel.write(buf);
+ clientChannel.close();
+ Socket socket = serverChannel.accept().socket();
+ InputStream in = socket.getInputStream();
+ assertReadResult(in,CAPACITY_64KB);
+ }
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_read_LByteBuffer_NonBlocking_ReadWriteRealLargeData()
+ throws Exception {
+ serverChannel.configureBlocking(false);
+ serverChannel.socket().bind(localAddr1);
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_64KB);
+ for (int i = 0; i < CAPACITY_64KB; i++) {
+ buf.put((byte) i);
+ }
+ buf.flip();
+ clientChannel.connect(localAddr1);
+ clientChannel.write(buf);
+ clientChannel.close();
+ Socket socket = serverChannel.accept().socket();
+ InputStream in = socket.getInputStream();
+ assertReadResult(in,CAPACITY_64KB);
+ }
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_write_LByteBuffer_NonBlocking_ReadWriteRealLargeData()
+ throws Exception {
+ serverChannel.configureBlocking(false);
+ serverChannel.socket().bind(localAddr1);
+ byte[] writeContent = new byte[CAPACITY_64KB];
+ for (int i = 0; i < writeContent.length; i++) {
+ writeContent[i] = (byte) i;
+ }
+ clientChannel.connect(localAddr1);
+ Socket socket = serverChannel.accept().socket();
+ OutputStream out = socket.getOutputStream();
+ out.write(writeContent);
+ socket.close();
+ assertWriteResult(CAPACITY_64KB);
+ }
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_write_LByteBuffer_Blocking_ReadWriteRealLargeData()
+ throws Exception {
+ serverChannel.socket().bind(localAddr1);
+ byte[] writeContent = new byte[CAPACITY_64KB];
+ for (int i = 0; i < writeContent.length; i++) {
+ writeContent[i] = (byte) i;
+ }
+ clientChannel.connect(localAddr1);
+ Socket socket = serverChannel.accept().socket();
+ OutputStream out = socket.getOutputStream();
+ out.write(writeContent);
+ socket.close();
+ assertWriteResult(CAPACITY_64KB);
+ }
+
+ /**
+ * Uses SocketChannel.read(ByteBuffer) to verify write result.
+ */
+ private void assertWriteResult(int size) throws IOException{
+ ByteBuffer buf = ByteBuffer.allocate(size + 1);
+ int count = 0;
+ int total = 0;
+ long beginTime = System.currentTimeMillis();
+ while ((count = clientChannel.read(buf)) != -1) {
+ total = total + count;
+ // 10s timeout to avoid dead loop
+ if (System.currentTimeMillis() - beginTime > 10000){
+ break;
+ }
+ }
+ assertEquals(total, size);
+ buf.flip();
+ for (int i = 0; i < count; i++) {
+ assertEquals((byte) i, buf.get(i));
+ }
+ }
+
+ /**
+ * @tests ServerSocketChannel#socket().getSoTimeout()
+ */
+ public void test_accept_SOTIMEOUT() throws IOException {
+ // regression test for Harmony-707
+ final int SO_TIMEOUT = 10;
+ ServerSocketChannel sc = ServerSocketChannel.open();
+ try {
+ ServerSocket ss = sc.socket();
+ ss.bind(localAddr1);
+ sc.configureBlocking(false);
+ ss.setSoTimeout(SO_TIMEOUT);
+ SocketChannel client = sc.accept();
+ // non blocking mode, returns null since there are no pending connections.
+ assertNull(client);
+ int soTimeout = ss.getSoTimeout();
+ // Harmony fails here.
+ assertEquals(SO_TIMEOUT, soTimeout);
+ } finally {
+ sc.close();
+ }
+ }
+
+ /**
+ * @tests ServerSocket#socket().accept()
+ */
+ public void test_socket_accept_Blocking_NotBound() throws IOException {
+ // regression test for Harmony-748
+ ServerSocket gotSocket = serverChannel.socket();
+ serverChannel.configureBlocking(true);
+ try {
+ gotSocket.accept();
+ fail("Should throw an IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ serverChannel.close();
+ try {
+ gotSocket.accept();
+ fail("Should throw an IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests ServerSocket#socket().accept()
+ */
+ public void test_socket_accept_Nonblocking_NotBound() throws IOException {
+ // regression test for Harmony-748
+ ServerSocket gotSocket = serverChannel.socket();
+ serverChannel.configureBlocking(false);
+ try {
+ gotSocket.accept();
+ fail("Should throw an IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ serverChannel.close();
+ try {
+ gotSocket.accept();
+ fail("Should throw an IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests ServerSocket#socket().accept()
+ */
+ public void test_socket_accept_Nonblocking_Bound() throws IOException {
+ // regression test for Harmony-748
+ serverChannel.configureBlocking(false);
+ ServerSocket gotSocket = serverChannel.socket();
+ gotSocket.bind(localAddr1);
+ try {
+ gotSocket.accept();
+ fail("Should throw an IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ serverChannel.close();
+ try {
+ gotSocket.accept();
+ fail("Should throw a ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests ServerSocket#socket().accept()
+ */
+ public void test_socket_accept_Blocking_Bound() throws IOException {
+ // regression test for Harmony-748
+ serverChannel.configureBlocking(true);
+ ServerSocket gotSocket = serverChannel.socket();
+ gotSocket.bind(localAddr1);
+ serverChannel.close();
+ try {
+ gotSocket.accept();
+ fail("Should throw a ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SinkChannelTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SinkChannelTest.java
new file mode 100644
index 0000000..97c4c4d
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SinkChannelTest.java
@@ -0,0 +1,537 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.Pipe;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for Pipe.SinkChannel class
+ */
+public class SinkChannelTest extends TestCase {
+
+ private static final int BUFFER_SIZE = 5;
+
+ private static final String ISO8859_1 = "ISO8859-1";
+
+ private Pipe pipe;
+
+ private Pipe.SinkChannel sink;
+
+ private Pipe.SourceChannel source;
+
+ private ByteBuffer buffer;
+
+ private ByteBuffer positionedBuffer;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ pipe = Pipe.open();
+ sink = pipe.sink();
+ source = pipe.source();
+ buffer = ByteBuffer.wrap("bytes".getBytes(ISO8859_1));
+ positionedBuffer = ByteBuffer.wrap("12345bytes".getBytes(ISO8859_1));
+ positionedBuffer.position(BUFFER_SIZE);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#validOps()
+ */
+ public void test_validOps() {
+ assertEquals(SelectionKey.OP_WRITE, sink.validOps());
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
+ */
+ public void test_write_LByteBuffer() throws IOException {
+ ByteBuffer[] bufArray = { buffer, positionedBuffer };
+ boolean[] sinkBlockingMode = { true, true, false, false };
+ boolean[] sourceBlockingMode = { true, false, true, false };
+ int oldPosition;
+ int currentPosition;
+ for (int i = 0; i < sinkBlockingMode.length; ++i) {
+ sink.configureBlocking(sinkBlockingMode[i]);
+ source.configureBlocking(sourceBlockingMode[i]);
+ // if sink and source both are blocking mode, source only needs read
+ // once to get what sink write.
+ boolean isBlocking = sinkBlockingMode[i] && sourceBlockingMode[i];
+ for (ByteBuffer buf : bufArray) {
+ buf.mark();
+ oldPosition = buf.position();
+ sink.write(buf);
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ int totalCount = 0;
+ do {
+ int count = source.read(readBuf);
+ if (count > 0) {
+ totalCount += count;
+ }
+ } while (totalCount != BUFFER_SIZE && !isBlocking);
+ currentPosition = buf.position();
+ assertEquals(BUFFER_SIZE, currentPosition - oldPosition);
+ assertEquals("bytes", new String(readBuf.array(), ISO8859_1));
+ buf.reset();
+ }
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
+ */
+ public void test_write_LByteBuffer_mutliThread() throws IOException,
+ InterruptedException {
+ final int THREAD_NUM = 20;
+ final byte[] strbytes = "bytes".getBytes(ISO8859_1);
+ Thread[] thread = new Thread[THREAD_NUM];
+ for (int i = 0; i < THREAD_NUM; i++) {
+ thread[i] = new Thread() {
+ public void run() {
+ try {
+ sink.write(ByteBuffer.wrap(strbytes));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+ for (int i = 0; i < THREAD_NUM; i++) {
+ thread[i].start();
+ }
+ for (int i = 0; i < THREAD_NUM; i++) {
+ thread[i].join();
+ }
+ ByteBuffer readBuf = ByteBuffer.allocate(THREAD_NUM * BUFFER_SIZE);
+
+ long totalCount = 0;
+ do {
+ long count = source.read(readBuf);
+ if (count < 0) {
+ break;
+ }
+ totalCount += count;
+ } while (totalCount != (THREAD_NUM * BUFFER_SIZE));
+
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < THREAD_NUM; i++) {
+ buf.append("bytes");
+ }
+ String readString = buf.toString();
+ assertEquals(readString, new String(readBuf.array(), ISO8859_1));
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
+ */
+ public void test_write_LByteBuffer_Exception() throws IOException {
+ // write null ByteBuffer
+ ByteBuffer nullBuf = null;
+ try {
+ sink.write(nullBuf);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
+ */
+ public void test_write_LByteBuffer_SourceClosed() throws IOException {
+ source.close();
+ int written = sink.write(buffer);
+ assertEquals(BUFFER_SIZE, written);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
+ */
+ public void test_write_LByteBuffer_SinkClosed() throws IOException {
+ sink.close();
+ try {
+ sink.write(buffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // write null ByteBuffer
+ ByteBuffer nullBuf = null;
+ try {
+ sink.write(nullBuf);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[])
+ */
+ public void test_write_$LByteBuffer() throws IOException {
+ ByteBuffer[] bufArray = { buffer, positionedBuffer };
+ boolean[] sinkBlockingMode = { true, true, false, false };
+ boolean[] sourceBlockingMode = { true, false, true, false };
+ for (int i = 0; i < sinkBlockingMode.length; ++i) {
+ sink.configureBlocking(sinkBlockingMode[i]);
+ source.configureBlocking(sourceBlockingMode[i]);
+ buffer.position(0);
+ positionedBuffer.position(BUFFER_SIZE);
+ sink.write(bufArray);
+ // if sink and source both are blocking mode, source only needs read
+ // once to get what sink write.
+ boolean isBlocking = sinkBlockingMode[i] && sourceBlockingMode[i];
+ for (int j = 0; j < bufArray.length; ++j) {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ int totalCount = 0;
+ do {
+ int count = source.read(readBuf);
+ if (count < 0) {
+ break;
+ }
+ totalCount += count;
+ } while (totalCount != BUFFER_SIZE && !isBlocking);
+ assertEquals("bytes", new String(readBuf.array(), ISO8859_1));
+ }
+ assertEquals(BUFFER_SIZE, buffer.position());
+ assertEquals(10, positionedBuffer.position());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[])
+ */
+ public void test_write_$LByteBuffer_Exception() throws IOException {
+ // write null ByteBuffer[]
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ sink.write(nullBufArrayRef);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // write ByteBuffer[] contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray = { buffer, nullBuf };
+ try {
+ sink.write(nullBufArray);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[])
+ */
+ public void test_write_$LByteBuffer_SourceClosed() throws IOException {
+ ByteBuffer[] bufArray = { buffer };
+ source.close();
+ long written = sink.write(bufArray);
+ assertEquals(BUFFER_SIZE, written);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[])
+ */
+ public void test_write_$LByteBuffer_SinkClosed() throws IOException {
+ ByteBuffer[] bufArray = { buffer };
+ sink.close();
+ try {
+ sink.write(bufArray);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ sink.write(nullBufArrayRef);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray = { nullBuf };
+ // write ByteBuffer[] contains null element
+ try {
+ sink.write(nullBufArray);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[], int, int)
+ */
+ public void test_write_$LByteBufferII() throws IOException {
+ ByteBuffer[] bufArray = { buffer, positionedBuffer };
+ boolean[] sinkBlockingMode = { true, true, false, false };
+ boolean[] sourceBlockingMode = { true, false, true, false };
+ for (int i = 0; i < sinkBlockingMode.length; ++i) {
+ sink.configureBlocking(sinkBlockingMode[i]);
+ source.configureBlocking(sourceBlockingMode[i]);
+ positionedBuffer.position(BUFFER_SIZE);
+ sink.write(bufArray, 1, 1);
+ // if sink and source both are blocking mode, source only needs read
+ // once to get what sink write.
+ boolean isBlocking = sinkBlockingMode[i] && sourceBlockingMode[i];
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ int totalCount = 0;
+ do {
+ int count = source.read(readBuf);
+ if (count < 0) {
+ break;
+ }
+ totalCount += count;
+ } while (totalCount != BUFFER_SIZE && !isBlocking);
+ assertEquals("bytes", new String(readBuf.array(), ISO8859_1));
+ assertEquals(10, positionedBuffer.position());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[], int, int)
+ */
+ public void test_write_$LByteBufferII_Exception() throws IOException {
+ // write null ByteBuffer[]
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ sink.write(nullBufArrayRef, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ sink.write(nullBufArrayRef, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // write ByteBuffer[] contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray = { nullBuf };
+ try {
+ sink.write(nullBufArray, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ sink.write(nullBufArray, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ ByteBuffer[] bufArray = { buffer, nullBuf };
+ try {
+ sink.write(bufArray, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray, -1, 0);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray, 0, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[], int, int)
+ */
+ public void test_write_$LByteBufferII_SourceClosed() throws IOException {
+ ByteBuffer[] bufArray = { buffer };
+ source.close();
+ long written = sink.write(bufArray, 0, 1);
+ assertEquals(BUFFER_SIZE, written);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[], int, int)
+ */
+ public void test_write_$LByteBufferII_SinkClosed() throws IOException {
+ ByteBuffer[] bufArray = { buffer };
+ sink.close();
+ try {
+ sink.write(bufArray, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // write null ByteBuffer[]
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ sink.write(nullBufArrayRef, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ // illegal array index
+ try {
+ sink.write(nullBufArrayRef, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // write ByteBuffer[] contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray = { nullBuf };
+ try {
+ sink.write(nullBufArray, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ // illegal array index
+ try {
+ sink.write(nullBufArray, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ ByteBuffer[] bufArray2 = { buffer, nullBuf };
+ // illegal array index
+ try {
+ sink.write(bufArray2, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray2, -1, 0);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray2, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray2, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray2, 0, 2);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#close()
+ */
+ public void test_close() throws IOException {
+ sink.close();
+ assertFalse(sink.isOpen());
+ }
+
+ public void test_socketChannel_read_close() throws Exception {
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+ SocketChannel sc = SocketChannel.open();
+ ByteBuffer buf = null;
+ try{
+ sc.write(buf);
+ fail("should throw NPE");
+ }catch (NullPointerException e){
+ // expected
+ }
+ sc.connect(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+ SocketChannel sock = ssc.accept();
+ ssc.close();
+ sc.close();
+ try{
+ sc.write(buf);
+ fail("should throw NPE");
+ }catch (NullPointerException e){
+ // expected
+ }
+ sock.close();
+ }
+
+ public void test_socketChannel_read_write() throws Exception {
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+ SocketChannel sock = ssc.accept();
+ ByteBuffer[] buf = {ByteBuffer.allocate(10),null};
+ try{
+ sc.write(buf,0,2);
+ fail("should throw NPE");
+ }catch (NullPointerException e){
+ // expected
+ }
+ ssc.close();
+ sc.close();
+ ByteBuffer target = ByteBuffer.allocate(10);
+ assertEquals(-1, sock.read(target));
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java
new file mode 100755
index 0000000..0d48c62
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java
@@ -0,0 +1,3118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.BindException;
+import java.net.ConnectException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ConnectionPendingException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NoConnectionPendingException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.UnresolvedAddressException;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.nio.channels.spi.SelectorProvider;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/**
+ * Tests for SocketChannel and its default implementation.
+ */
+public class SocketChannelTest extends TestCase {
+
+ private static final int CAPACITY_NORMAL = 200;
+
+ private InetSocketAddress localAddr1;
+
+ private InetSocketAddress localAddr2;
+
+ private SocketChannel channel1;
+
+ private SocketChannel channel2;
+
+ private ServerSocket server1;
+
+ private ServerSocket server2;
+
+ private final static int TIMEOUT = 60000;
+
+ private final static int EOF = -1;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.localAddr1 = new InetSocketAddress("127.0.0.1",
+ Support_PortManager.getNextPort());
+ this.localAddr2 = new InetSocketAddress("127.0.0.1",
+ Support_PortManager.getNextPort());
+ this.channel1 = SocketChannel.open();
+ this.channel2 = SocketChannel.open();
+ this.server1 = new ServerSocket(localAddr1.getPort());
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (null != this.channel1) {
+ try {
+ this.channel1.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ if (null != this.channel2) {
+ try {
+ this.channel2.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ if (null != this.server1) {
+ try {
+ this.server1.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ if (null != this.server2) {
+ try {
+ this.server2.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Test for methods in abstract class.
+ // -------------------------------------------------------------------
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.validOps()'
+ */
+ public void testValidOps() {
+ MockSocketChannel testMSChannel = new MockSocketChannel(null);
+ assertEquals(13, this.channel1.validOps());
+ assertEquals(13, testMSChannel.validOps());
+ }
+
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.open()'
+ */
+ public void testOpen() throws IOException {
+ java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[1];
+ buf[0] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ MockSocketChannel testMSChannel = new MockSocketChannel(null);
+ MockSocketChannel testMSChannelnotnull = new MockSocketChannel(
+ SelectorProvider.provider());
+ assertNull(testMSChannel.provider());
+ assertNotNull(testMSChannelnotnull.provider());
+ assertNotNull(this.channel1);
+ assertEquals(this.channel1.provider(), testMSChannelnotnull.provider());
+ try {
+ this.channel1.write(buf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.open(SocketAddress)'
+ */
+ public void testOpenSocketAddress_Null() throws IOException {
+ SocketChannel channel1IP = null;
+ try {
+ channel1IP = SocketChannel.open(null);
+ fail("Should throw an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // correct
+ }
+ assertNull(channel1IP);
+ }
+
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.read(ByteBuffer[])'
+ */
+ public void testReadByteBufferArray() throws IOException {
+ java.nio.ByteBuffer[] byteBuf = null;
+ MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+ MockSocketChannel testMSChannel = new MockSocketChannel(
+ SelectorProvider.provider());
+ ServerSocket testServer = new ServerSocket(Support_PortManager
+ .getNextPort());
+ try {
+ try {
+ this.channel1.read(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ byteBuf = new java.nio.ByteBuffer[CAPACITY_NORMAL];
+ try {
+ this.channel1.read(byteBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ long readNum = CAPACITY_NORMAL;
+ readNum = testMSChannel.read(byteBuf);
+ assertEquals(0, readNum);
+ readNum = CAPACITY_NORMAL;
+ readNum = testMSChannelnull.read(byteBuf);
+ assertEquals(0, readNum);
+ } finally {
+ testServer.close();
+ }
+ }
+
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.read(ByteBuffer[])'
+ */
+ public void testReadByteBufferArray_BufNull() throws IOException {
+ java.nio.ByteBuffer[] byteBuf = null;
+ MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+ MockSocketChannel testMSChannel = new MockSocketChannel(
+ SelectorProvider.provider());
+ try {
+ this.channel1.read(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMSChannel.read(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMSChannelnull.read(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.write(ByteBuffer[])'
+ */
+ public void testWriteByteBufferArray() throws IOException {
+ java.nio.ByteBuffer[] byteBuf = null;
+ MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+ MockSocketChannel testMSChannel = new MockSocketChannel(
+ SelectorProvider.provider());
+ try {
+ this.channel1.write(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ byteBuf = new java.nio.ByteBuffer[CAPACITY_NORMAL];
+ try {
+ this.channel1.write(byteBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ testMSChannel.write(byteBuf);
+ testMSChannelnull.write(byteBuf);
+ }
+
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.write(ByteBuffer[])'
+ */
+ public void testWriteByteBufferArray_BufNull() throws IOException {
+ java.nio.ByteBuffer[] byteBuf = null;
+ MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+ MockSocketChannel testMSChannel = new MockSocketChannel(
+ SelectorProvider.provider());
+ try {
+ this.channel1.write(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMSChannel.write(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMSChannelnull.write(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testSocket_BasicStatusBeforeConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ Socket s1 = this.channel1.socket();
+ assertSocketBeforeConnect(s1);
+ Socket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ public void testSocket_Block_BasicStatusAfterConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ assertTrue(this.channel1.connect(localAddr1));
+
+ assertTrue(this.channel1.isConnected());
+ Socket s1 = this.channel1.socket();
+
+ assertSocketAfterConnect(s1, localAddr1);
+ Socket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ public void testSocket_NonBlock_BasicStatusAfterConnect() throws Exception {
+ assertFalse(this.channel1.isConnected());// not connected
+ this.channel1.configureBlocking(false);
+ assertFalse(this.channel1.connect(localAddr1));
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.channel1.isConnectionPending());
+ Socket s1 = this.channel1.socket();
+ // status of not connected
+ assertSocketBeforeConnect(s1);
+ Socket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+
+ if (tryFinish()) {
+ assertTrue(this.channel1.isConnected());
+ s1 = this.channel1.socket();
+ assertSocketAfterConnect(s1, localAddr1);
+ s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+ }
+
+ public void testSocket_Block_ActionsBeforeConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ Socket s = this.channel1.socket();
+ assertSocketAction_Block_BeforeConnect(s);
+ }
+
+ public void testSocket_Block_ActionsAfterConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ assertTrue(this.channel1.connect(localAddr1));
+ assertTrue(this.channel1.isConnected());
+ Socket s = this.channel1.socket();
+ assertSocketAction_Block_AfterConnect(s);
+
+ }
+
+ public void testSocket_NonBlock_ActionsAfterConnectBeforeFinish()
+ throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ this.channel1.configureBlocking(false);
+ assertFalse(this.channel1.connect(localAddr1));
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.channel1.isConnectionPending());
+ Socket s1 = this.channel1.socket();
+ // Action of not connected
+ assertSocketAction_NonBlock_BeforeConnect(s1);
+ Socket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ public void testSocket_NonBlock_ActionsAfterConnectAfterFinish()
+ throws Exception {
+ assertFalse(this.channel1.isConnected());// not connected
+ this.channel1.configureBlocking(false);
+ assertFalse(this.channel1.connect(localAddr1));
+ if (tryFinish()) {
+ Socket s1 = this.channel1.socket();
+ assertSocketAction_NonBlock_AfterConnect(s1);
+ Socket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+ }
+
+ private void assertSocketBeforeConnect(Socket s) throws IOException {
+ assertFalse(s.isBound());
+ assertFalse(s.isClosed());
+ assertFalse(s.isConnected());
+ assertFalse(s.getKeepAlive());
+ try {
+ s.getInputStream();
+ fail("Should throw SocketException.");
+ } catch (SocketException e) {
+ // OK.
+ }
+ assertFalse(s.getOOBInline());
+ try {
+ s.getOutputStream();
+ fail("Should throw SocketException.");
+ } catch (SocketException e) {
+ // OK.
+ }
+ assertEquals(-1, s.getSoLinger());
+ assertFalse(s.getTcpNoDelay());
+
+ assertFalse(s.isInputShutdown());
+ assertFalse(s.isOutputShutdown());
+
+ assertNull(s.getInetAddress());
+ assertEquals(s.getLocalAddress().getHostAddress(), "0.0.0.0");
+ // RI fails here. RI returns 0 while spec says unbound socket should
+ // return -1.
+ assertEquals(s.getLocalPort(), -1);
+ assertFalse(s.getReuseAddress());
+ assertNull(s.getLocalSocketAddress());
+
+ // not connected
+ assertEquals(s.getPort(), 0);
+ assertTrue(s.getReceiveBufferSize() >= 8192);
+ assertNull(s.getRemoteSocketAddress());
+ assertTrue(s.getSendBufferSize() >= 8192);
+ assertEquals(s.getSoTimeout(), 0);
+ assertEquals(s.getTrafficClass(), 0);
+
+ }
+
+ private void assertSocketAfterConnect(Socket s, InetSocketAddress address)
+ throws IOException {
+ assertTrue(s.isBound());
+ assertFalse(s.isClosed());
+ assertTrue(s.isConnected());
+ assertFalse(s.getKeepAlive());
+
+ assertNotNull(s.getInputStream());
+ assertNotNull(s.getOutputStream());
+
+ assertFalse(s.getOOBInline());
+ assertEquals(-1, s.getSoLinger());
+ assertFalse(s.getTcpNoDelay());
+
+ assertFalse(s.isInputShutdown());
+ assertFalse(s.isOutputShutdown());
+
+ assertSame(s.getInetAddress(), address.getAddress());
+
+ assertEquals(s.getLocalAddress(), this.localAddr1.getAddress());
+ assertEquals(s.getPort(), address.getPort());
+ assertNotNull(s.getLocalSocketAddress());
+ assertTrue(s.getReceiveBufferSize() >= 8192);
+ // equal , not same
+ assertNotSame(s.getRemoteSocketAddress(), (SocketAddress) address);
+ assertEquals(s.getRemoteSocketAddress(), (SocketAddress) address);
+ // assertFalse(s.getReuseAddress());
+ assertTrue(s.getSendBufferSize() >= 8192);
+ assertEquals(s.getSoTimeout(), 0);
+ assertEquals(s.getTrafficClass(), 0);
+ }
+
+ private void assertSocketAction_Block_BeforeConnect(Socket s)
+ throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.server2 = new ServerSocket(localAddr2.getPort());
+ s.connect(localAddr2);
+ assertTrue(this.channel1.isConnected());
+ assertTrue(s.isConnected());
+
+ assertSocketAfterConnect(s, localAddr2);
+
+ try {
+ s.bind(localAddr2);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+
+ s.close();
+ assertTrue(s.isClosed());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ private void assertSocketAction_NonBlock_BeforeConnect(Socket s)
+ throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.server2 = new ServerSocket(localAddr2.getPort());
+ try {
+ s.connect(localAddr2);
+ fail("Should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e1) {
+ // OK.
+ }
+
+ if (this.channel1.isConnectionPending()) {
+ try {
+ s.bind(localAddr2);
+ fail("Should throw ConnectionPendingException");
+ } catch (ConnectionPendingException e1) {
+ // OK.
+ }
+ } else {
+ try {
+ s.bind(localAddr2);
+ fail("Should throw BindException");
+ } catch (BindException e1) {
+ // OK.
+ }
+ }
+
+ assertFalse(this.channel1.isConnected());
+ assertFalse(s.isConnected());
+
+ s.close();
+ assertTrue(s.isClosed());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ private void assertSocketAction_Block_AfterConnect(Socket s)
+ throws IOException {
+ assertEquals(s.getPort(), localAddr1.getPort());
+ assertTrue(this.channel1.isConnected());
+ assertTrue(s.isConnected());
+ try {
+ s.connect(localAddr2);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+
+ try {
+ s.bind(localAddr2);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+
+ s.close();
+ assertTrue(s.isClosed());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ private void assertSocketAction_NonBlock_AfterConnect(Socket s)
+ throws IOException {
+ assertEquals(s.getPort(), localAddr1.getPort());
+ assertTrue(this.channel1.isConnected());
+ assertTrue(s.isConnected());
+
+ if (this.channel1.isConnectionPending()) {
+ try {
+ s.connect(localAddr2);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ } else {
+ try {
+ s.connect(localAddr2);
+ fail("Should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // OK.
+ }
+ }
+
+ try {
+ s.bind(localAddr2);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+
+ s.close();
+ assertTrue(s.isClosed());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ // -------------------------------------------------------------------
+ // Tests for connect(), finishConnect(),isConnected(),isConnectionPending()
+ // These methods are very close, so we test them together, call them "CFII".
+ // -------------------------------------------------------------------
+ /**
+ * connect-->finish-->close
+ */
+ public void testCFII_Norml_NoServer_Block() throws Exception {
+ // ensure
+ ensureServerClosed();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // connect
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectException here.");
+ } catch (ConnectException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw a ClosedChannelException here.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * connect-->finish-->close
+ */
+ public void testCFII_Norml_NoServer_NonBlock() throws Exception {
+ connectNoServerNonBlock();
+
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->finish-->close
+ */
+ public void testCFII_Norml_Server_Block() throws Exception {
+ connectServerBlock();
+
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * connect-->finish-->close
+ */
+ public void testCFII_Norml_Server_NonBlock() throws Exception {
+ connectServerNonBlock();
+
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->server closed-->finish-->close
+ */
+ public void testCFII_ServerClosed_Block() throws Exception {
+ // ensure
+ ensureServerOpen();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // connect
+ assertTrue(this.channel1.connect(localAddr1));
+ statusConnected_NotPending();
+
+ ensureServerClosed();
+
+ tryFinish();
+
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * connect-->server closed-->finish-->close
+ */
+ public void testCFII_ServerClosed_NonBlock() throws Exception {
+ // ensure
+ ensureServerOpen();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+
+ ensureServerClosed();
+
+ tryFinish();
+
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->finish-->server closed-->close
+ */
+ public void testCFII_ServerClosedAfterFinish_Block() throws Exception {
+ connectServerBlock();
+
+ ensureServerClosed();
+ assertTrue(this.channel1.isOpen());
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * connect-->finish-->server closed-->close
+ */
+ public void testCFII_ServerClosedAfterFinish_NonBlock() throws Exception {
+ connectServerNonBlock();
+
+ ensureServerClosed();
+ assertTrue(this.channel1.isOpen());
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * no server-->connect-->server open-->finish-->close
+ */
+ public void testCFII_ServerStartLater_Block() throws Exception {
+ // ensure
+ ensureServerClosed();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // connect
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectException here.");
+ } catch (ConnectException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ ensureServerOpen();
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw a ClosedChannelException here.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * no server-->connect-->server open-->finish-->close
+ */
+ public void testCFII_ServerStartLater_NonBlock() throws Exception {
+ // ensure
+ ensureServerClosed();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+
+ ensureServerOpen();
+
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ this.channel1.close();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+ }
+
+ /**
+ * connect-->finish-->finish-->close
+ */
+ public void testCFII_FinishTwice_NoServer_NonBlock() throws Exception {
+ // ensure
+ ensureServerClosed();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ this.channel1.close();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->finish-->finish-->close
+ */
+ public void testCFII_FinishTwice_Server_Block() throws Exception {
+ connectServerBlock();
+ tryFinish();
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * connect-->finish-->finish-->close
+ */
+ public void testCFII_FinishTwice_Server_NonBlock() throws Exception {
+ connectServerNonBlock();
+ tryFinish();
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->finish-->connect-->close
+ */
+ public void testCFII_ConnectAfterFinish_NoServer_Block() throws Exception {
+ // ensure
+ ensureServerClosed();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // connect
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectException here.");
+ } catch (ConnectException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw a ClosedChannelException here.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ClosedChannelException here.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->finish-->connect-->close
+ */
+ public void testCFII_ConnectAfterFinish_NoServer_NonBlock()
+ throws Exception {
+ // ensure
+ ensureServerClosed();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+
+ if (this.channel1.isOpen()) {
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ // connect another addr
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ // connect if server closed
+ ensureServerClosed();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ this.channel1.close();
+ }
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->finish-->connect-->close
+ */
+ public void testCFII_ConnectAfterFinish_Server_Block() throws Exception {
+ connectServerBlock();
+
+ if (!this.channel1.isConnected()) {
+ System.err
+ .println("Connection fail, testCFII_ConnectAfterFinish_Server_Block is not finished.");
+ return;
+ }
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ // connect another addr
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ // connect if server closed
+ ensureServerClosed();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * connect-->finish-->connect-->close
+ */
+ public void testCFII_ConnectAfterFinish_Server_NonBlock() throws Exception {
+ connectServerNonBlock();
+
+ if (!this.channel1.isConnected()) {
+ System.err
+ .println("Connection fail, testCFII_ConnectAfterFinish_Server_Block is not finished.");
+ return;
+ }
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw an AlreadyConnectedException or a ConnectionPendingException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+
+ statusConnected_NotPending();
+
+ // connect another addr
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ // connect if server closed
+ ensureServerClosed();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->connect-->finish-->close
+ */
+ public void testCFII_ConnectTwice_NoServer_NonBlock() throws Exception {
+ // ensure
+ ensureServerClosed();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ // connect another addr
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ // connect if server closed
+ ensureServerClosed();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ this.channel1.close();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->connect-->finish-->close
+ */
+ public void testCFII_ConnectTwice_Server_Block() throws Exception {
+ // ensure
+ ensureServerOpen();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // connect
+ assertTrue(this.channel1.connect(localAddr1));
+ statusConnected_NotPending();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ // connect another addr
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ // connect if server closed
+ ensureServerClosed();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ tryFinish();
+
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * connect-->connect-->finish-->close
+ */
+ public void testCFII_ConnectTwice_Server_NonBlock() throws Exception {
+ // ensure
+ ensureServerOpen();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ // connect another addr
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ // connect if server closed
+ ensureServerClosed();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ tryFinish();
+
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * finish-->connect-->finish-->close
+ */
+ public void testCFII_FinishFirst_NoServer_Block() throws Exception {
+ // ensure
+ ensureServerClosed();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // finish
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_NotPending();
+ // connect
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectException here.");
+ } catch (ConnectException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw a ClosedChannelException here.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ }
+
+ /**
+ * finish-->connect-->finish-->close
+ */
+ public void testCFII_FinishFirst_NoServer_NonBlock() throws Exception {
+ // ensure
+ ensureServerClosed();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // finish
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ this.channel1.close();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+
+ statusChannelClosed();
+ }
+
+ /**
+ * finish-->connect-->finish-->close
+ */
+ public void testCFII_FinishFirst_Server_Block() throws Exception {
+ // ensure
+ ensureServerOpen();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // finish
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_NotPending();
+ // connect
+ assertTrue(this.channel1.connect(localAddr1));
+ statusConnected_NotPending();
+
+ tryFinish();
+
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * finish-->connect-->finish-->close
+ */
+ public void testCFII_FinishFirst_Server_NonBlock() throws Exception {
+ // ensure
+ ensureServerOpen();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // finish
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+
+ tryFinish();
+
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ public void testCFII_Null() throws Exception {
+ statusNotConnected_NotPending();
+ try {
+ this.channel1.connect(null);
+ fail("Should throw an IllegalArgumentException here.");
+ } catch (IllegalArgumentException e) {
+ // OK.
+ }
+ }
+
+ public void testCFII_UnsupportedType() throws Exception {
+ class SubSocketAddress extends SocketAddress {
+ private static final long serialVersionUID = 1L;
+
+ //empty
+ public SubSocketAddress() {
+ super();
+ }
+ }
+ statusNotConnected_NotPending();
+ SocketAddress newTypeAddress = new SubSocketAddress();
+ try {
+ this.channel1.connect(newTypeAddress);
+ fail("Should throw an UnsupportedAddressTypeException here.");
+ } catch (UnsupportedAddressTypeException e) {
+ // OK.
+ }
+ }
+
+ public void testCFII_Unresolved() throws IOException {
+ statusNotConnected_NotPending();
+ InetSocketAddress unresolved = new InetSocketAddress(
+ "unresolved address", 1080);
+ try {
+ this.channel1.connect(unresolved);
+ fail("Should throw an UnresolvedAddressException here.");
+ } catch (UnresolvedAddressException e) {
+ // OK.
+ }
+ }
+
+ public void testCFII_EmptyHost() throws Exception {
+ statusNotConnected_NotPending();
+ ServerSocket server = new ServerSocket(0);
+ int port = server.getLocalPort();
+ server.close();
+ try {
+ this.channel1.connect(new InetSocketAddress("", port));
+ fail("Should throw ConnectException");
+ } catch (ConnectException e) {
+ // correct
+ }
+ }
+
+ public void testCFII_CloseFirst() throws Exception {
+ this.channel1.close();
+ statusChannelClosed();
+ ensureServerOpen();
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ try {
+ this.channel1.configureBlocking(false);
+ fail("Should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ }
+
+ public void testCFII_StatusAfterFinish() throws Exception {
+ // 1. close server, finish must return false, check the status
+ ensureServerClosed();
+
+ // 1.1 block mode
+ assertTrue(this.channel1.isBlocking());
+ try {
+ channel1.connect(localAddr1);
+ fail("Should throw ConnectException");
+ } catch (ConnectException e) {
+ // OK.
+ }
+ assertFalse(this.channel1.isOpen());
+
+ assertFalse(this.channel1.isOpen());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnectionPending());
+
+ // 1.2 non block mode
+ this.channel1 = SocketChannel.open();
+ this.channel1.configureBlocking(false);
+ assertFalse(this.channel1.connect(localAddr1));
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ this.channel1.close();
+ } catch (ConnectException e) {
+ System.out.println(e.getMessage());
+ }
+
+ // 2. start server, finish usually return true, check the status
+ ensureServerOpen();
+
+ // 2.1 block mode
+ this.channel1 = SocketChannel.open();
+ assertTrue(this.channel1.isBlocking());
+ assertTrue(this.channel1.connect(localAddr1));
+ assertTrue(this.channel1.finishConnect());
+ statusConnected_NotPending();
+ this.channel1.close();
+
+ // 2.2 non block mode
+ this.channel1 = SocketChannel.open();
+ this.channel1.configureBlocking(false);
+ assertFalse(this.channel1.connect(localAddr1));
+ tryFinish();
+ this.channel1.close();
+ }
+
+ private void ensureServerClosed() throws IOException {
+ if (null != this.server1) {
+ this.server1.close();
+ assertTrue(this.server1.isClosed());
+ }
+ if (null != this.server2) {
+ this.server2.close();
+ assertTrue(this.server2.isClosed());
+ }
+ }
+
+ private void ensureServerOpen() throws IOException {
+ ensureServerClosed();
+ this.server1 = new ServerSocket(localAddr1.getPort());
+ this.server2 = new ServerSocket(localAddr2.getPort());
+ assertTrue(this.server1.isBound());
+ assertTrue(this.server2.isBound());
+ }
+
+ private void connectNoServerNonBlock() throws Exception {
+ // ensure
+ ensureServerClosed();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+ }
+
+ private void connectServerNonBlock() throws Exception {
+ // ensure
+ ensureServerOpen();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+
+ tryFinish();
+ }
+
+ private void connectServerBlock() throws Exception {
+ // ensure
+ ensureServerOpen();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // connect
+ assertTrue(this.channel1.connect(localAddr1));
+ statusConnected_NotPending();
+ tryFinish();
+ }
+
+ private void statusChannelClosed() {
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ private void statusNotConnected_NotPending() {
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ }
+
+ private void statusNotConnected_Pending() {
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ }
+
+ private void statusConnected_NotPending() {
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ }
+
+ private boolean tryFinish() throws IOException {
+ /*
+ * the result of finish will be asserted in multi-thread tests.
+ */
+ boolean connected = false;
+ assertTrue(this.channel1.isOpen());
+ try {
+ connected = this.channel1.finishConnect();
+ } catch (SocketException e) {
+ // Finish connection failed, probably due to reset by peer error.
+ }
+ if (connected) {
+ statusConnected_NotPending();
+ }
+ return connected;
+ }
+
+ // -------------------------------------------------------------------
+ // Original tests. Test method for CFII with real data.
+ // -------------------------------------------------------------------
+
+ /**
+ *
+ * 'SocketChannelImpl.connect(SocketAddress)'
+ */
+ public void testCFII_Data_ConnectWithServer() throws Exception {
+ ensureServerOpen();
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL);
+ java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+ writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+
+ this.channel1.connect(localAddr1);
+
+ assertTrue(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBufArr, 0, 1));
+
+ this.channel1.configureBlocking(false);
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // correct
+ }
+
+ assertFalse(this.channel1.isRegistered());
+ tryFinish();
+ }
+
+ /*
+ * Test method for 'SocketChannelImpl.connect(SocketAddress)'
+ */
+ public void testCFII_Data_ConnectWithServer_nonBlocking() throws Exception {
+ ensureServerOpen();
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL);
+ java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+ writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ this.channel1.configureBlocking(false);
+ this.channel1.connect(localAddr1);
+
+ assertFalse(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ if (tryFinish()) {
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBufArr, 0, 1));
+
+ this.channel1.configureBlocking(false);
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // correct
+ }
+ }
+
+ assertFalse(this.channel1.isRegistered());
+ tryFinish();
+ }
+
+ /*
+ * Test method for 'SocketChannelImpl.finishConnect()'
+ */
+ public void testCFII_Data_FinishConnect_nonBlocking() throws IOException {
+ ensureServerOpen();
+
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL);
+ java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+ writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+
+ this.channel1.configureBlocking(false);
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertFalse(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ this.server1.accept();
+ if (tryFinish()) {
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBufArr, 0, 1));
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // correct
+ }
+ }
+ assertFalse(this.channel1.isRegistered());
+ tryFinish();
+ }
+
+ public void testCFII_Data_FinishConnect_AddrSetServerStartLater()
+ throws IOException, InterruptedException {
+ ensureServerClosed();
+ java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+ writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ this.channel1.configureBlocking(false);
+ try {
+ SocketChannel.open(localAddr1);
+ fail("Should throw ConnectException");
+ } catch (ConnectException e) {
+ // correct
+ }
+ assertTrue(this.channel1.isOpen());
+ assertFalse(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnectionPending());
+ this.channel1.configureBlocking(true);
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // correct
+ }
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw ConnectException");
+ } catch (ConnectException e) {
+ // correct
+ }
+
+ assertTrue(this.channel1.isBlocking());
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ assertFalse(this.channel1.isConnected());
+ // finish after finish OK
+ assertFalse(this.channel1.isConnectionPending());
+ this.channel1 = SocketChannel.open();
+ this.channel1.configureBlocking(false);
+ this.channel1.connect(localAddr1);
+ assertFalse(this.channel1.isConnected());
+ ensureServerOpen();
+ // cannot connect?
+ try {
+ assertFalse(this.channel1.finishConnect());
+ assertFalse(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ConnectionPendingException");
+ } catch (ConnectionPendingException e) {
+ // correct
+ }
+ this.channel1.configureBlocking(true);
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ConnectionPendingException");
+ } catch (ConnectionPendingException e) {
+ // correct
+ }
+ tryFinish();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+ }
+
+ public void testCFII_Data_FinishConnect_ServerStartLater()
+ throws IOException {
+ ensureServerClosed();
+ java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+ writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ this.channel1.configureBlocking(true);
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // correct
+ }
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ConnectException");
+ } catch (ConnectException e) {
+ // correct
+ }
+
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ assertFalse(this.channel1.isConnected());
+ // finish after finish OK
+ assertFalse(this.channel1.isConnectionPending());
+ this.channel1 = SocketChannel.open();
+ this.channel1.configureBlocking(false);
+ this.channel1.connect(localAddr1);
+ assertFalse(this.channel1.isConnected());
+ ensureServerOpen();
+ // cannot connect?
+ try {
+ assertFalse(this.channel1.finishConnect());
+ assertFalse(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ConnectionPendingException");
+ } catch (ConnectionPendingException e) {
+ // correct
+ }
+ this.channel1.configureBlocking(true);
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ConnectionPendingException");
+ } catch (ConnectionPendingException e) {
+ // correct
+ }
+ tryFinish();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+ }
+
+ public void testCFII_Data_FinishConnect_Blocking() throws IOException {
+ ensureServerOpen();
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL);
+ java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+ writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ this.channel1.configureBlocking(true);
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // correct
+ }
+
+ this.channel1.connect(localAddr1);
+
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ if (tryFinish()) {
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBufArr, 0, 1));
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // correct
+ }
+ }
+ assertFalse(this.channel1.isRegistered());
+ tryFinish();
+ }
+
+ /**
+ * Regression test for Harmony-1947.
+ */
+ public void test_finishConnect() throws Exception {
+ SocketAddress address = new InetSocketAddress("localhost", 2046);
+
+ ServerSocketChannel theServerChannel = ServerSocketChannel.open();
+ ServerSocket serversocket = theServerChannel.socket();
+ serversocket.setReuseAddress(true);
+ // Bind the socket
+ serversocket.bind(address);
+
+ boolean doneNonBlockingConnect = false;
+ // Loop so that we make sure we're definitely testing finishConnect()
+ while (!doneNonBlockingConnect) {
+ channel1 = SocketChannel.open();
+
+ // Set the SocketChannel to non-blocking so that connect(..) does
+ // not block
+ channel1.configureBlocking(false);
+ boolean connected = channel1.connect(address);
+ if (!connected) {
+ // Now set the SocketChannel back to blocking so that
+ // finishConnect() blocks.
+ channel1.configureBlocking(true);
+ doneNonBlockingConnect = channel1.finishConnect();
+ }
+ if (doneNonBlockingConnect) {
+ tryFinish();
+ }
+ channel1.close();
+ }
+ if (!serversocket.isClosed()) {
+ serversocket.close();
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // End of original tests. Test method for CFII with real data.
+ // -------------------------------------------------------------------
+
+ /**
+ * @tests java.nio.channels.SocketChannel#read(ByteBuffer)
+ */
+ public void test_readLjava_nio_ByteBuffer_Blocking() throws IOException {
+ // initialize write content
+ byte[] writeContent = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < writeContent.length; i++) {
+ writeContent[i] = (byte) i;
+ }
+ // establish connection
+ channel1.connect(localAddr1);
+ Socket acceptedSocket = server1.accept();
+
+ // use OutputStream.write to send CAPACITY_NORMAL bytes data
+ OutputStream out = acceptedSocket.getOutputStream();
+ out.write(writeContent);
+ // use close to guarantee all data is sent
+ acceptedSocket.close();
+
+ ByteBuffer readContent = ByteBuffer.allocate(CAPACITY_NORMAL + 1);
+ int totalCount = 0;
+ int count = 0;
+ long startTime = System.currentTimeMillis();
+ // use SocketChannel.read to read data
+ while (totalCount <= CAPACITY_NORMAL) {
+ count = channel1.read(readContent);
+ if (EOF == count) {
+ break;
+ }
+ totalCount += count;
+ // if the channel could not finish reading in TIMEOUT ms, the
+ // test fails. It is used to guarantee the test never hangs even
+ // if there are bugs of SocketChannel implementation. For
+ // blocking read, it possibly returns 0 in some cases.
+ assertTimeout(startTime, TIMEOUT);
+ }
+ assertEquals(CAPACITY_NORMAL, totalCount);
+ readContent.flip();
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ assertEquals(writeContent[i], readContent.get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#read(ByteBuffer)
+ */
+ public void test_readLjava_nio_ByteBuffer_Nonblocking() throws IOException {
+ // initialize write content
+ byte[] writeContent = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < writeContent.length; i++) {
+ writeContent[i] = (byte) i;
+ }
+
+ // establish connection
+ channel1.connect(localAddr1);
+ Socket acceptedSocket = server1.accept();
+ // use OutputStream.write to write CAPACITY_NORMAL bytes data.
+ OutputStream out = acceptedSocket.getOutputStream();
+ out.write(writeContent);
+ // use close to guarantee all data is sent
+ acceptedSocket.close();
+
+ channel1.configureBlocking(false);
+ ByteBuffer readContent = ByteBuffer.allocate(CAPACITY_NORMAL + 1);
+ int totalCount = 0;
+ int count = 0;
+ long startTime = System.currentTimeMillis();
+ // use SocketChannel.read to read data
+ while (totalCount <= CAPACITY_NORMAL) {
+ count = channel1.read(readContent);
+ if (EOF == count) {
+ break;
+ }
+ totalCount += count;
+ // if the channel could not finish reading in TIMEOUT ms, the
+ // test fails. It is used to guarantee the test never hangs even
+ // if there are bugs of SocketChannel implementation.
+ assertTimeout(startTime, TIMEOUT);
+ }
+
+ // assert read content
+ assertEquals(CAPACITY_NORMAL, totalCount);
+ assertEquals(CAPACITY_NORMAL, readContent.position());
+ readContent.flip();
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ assertEquals(writeContent[i], readContent.get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer)
+ */
+ public void test_wrtieLjava_nio_ByteBuffer_Blocking() throws IOException {
+ // initialize write content
+ ByteBuffer writeContent = ByteBuffer.allocate(CAPACITY_NORMAL);
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ writeContent.put((byte) i);
+ }
+ writeContent.flip();
+ // establish connection
+ channel1.connect(localAddr1);
+ Socket acceptedSocket = server1.accept();
+
+ // use SocketChannel.write(ByteBuffer) to write CAPACITY_NORMAL bytes
+ // data
+ int writtenCount = channel1.write(writeContent);
+ // assert written count and ByteBuffer position
+ assertEquals(CAPACITY_NORMAL, writtenCount);
+ assertEquals(CAPACITY_NORMAL, writeContent.position());
+ // use close to guarantee all data is sent
+ channel1.close();
+
+ InputStream in = acceptedSocket.getInputStream();
+ int totalCount = 0;
+ int count = 0;
+ byte[] readContent = new byte[CAPACITY_NORMAL + 1];
+ // if the channel could not finish reading in TIMEOUT ms, the test
+ // fails. It is used to guarantee the test never hangs even if there
+ // are bugs of SocketChannel implementation.
+ acceptedSocket.setSoTimeout(TIMEOUT);
+
+ // use InputStream.read to read data.
+ while (totalCount <= CAPACITY_NORMAL) {
+ count = in.read(readContent, totalCount, readContent.length
+ - totalCount);
+ if (EOF == count) {
+ break;
+ }
+ totalCount += count;
+ }
+
+ // assert read content
+ assertEquals(CAPACITY_NORMAL, totalCount);
+ writeContent.flip();
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ assertEquals(writeContent.get(), readContent[i]);
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer)
+ */
+ public void test_wrtieLjava_nio_ByteBuffer_NonBlocking() throws Exception {
+ // initialize write content
+ ByteBuffer writeContent = ByteBuffer.allocate(CAPACITY_NORMAL);
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ writeContent.put((byte) i);
+ }
+ writeContent.flip();
+
+ // establish connection
+ channel1.connect(localAddr1);
+ Socket acceptedSocket = server1.accept();
+
+ channel1.configureBlocking(false);
+ int writtenTotalCount = 0;
+ int writtenCount = 0;
+ long startTime = System.currentTimeMillis();
+ // use SocketChannel.write(ByteBuffer) to write CAPACITY_NORMAL bytes
+ while (writtenTotalCount < CAPACITY_NORMAL) {
+ writtenCount = channel1.write(writeContent);
+ writtenTotalCount += writtenCount;
+ // if the channel could not finish writing in TIMEOUT ms, the
+ // test fails. It is used to guarantee the test never hangs even
+ // if there are bugs of SocketChannel implementation.
+ assertTimeout(startTime, TIMEOUT);
+ }
+ // assert written count and ByteBuffer position
+ assertEquals(CAPACITY_NORMAL, writtenTotalCount);
+ assertEquals(CAPACITY_NORMAL, writeContent.position());
+ // use close to guarantee all data is sent
+ channel1.close();
+
+ InputStream in = acceptedSocket.getInputStream();
+ byte[] readContent = new byte[CAPACITY_NORMAL + 1];
+ int totalCount = 0;
+ int count = 0;
+ // if the channel could not finish reading in TIMEOUT ms, the test
+ // fails. It is used to guarantee the test never hangs even if there
+ // are bugs of SocketChannel implementation.
+ acceptedSocket.setSoTimeout(TIMEOUT);
+ // use InputStream.read to read data.
+ while (totalCount <= CAPACITY_NORMAL) {
+ count = in.read(readContent, totalCount, readContent.length
+ - totalCount);
+ if (EOF == count) {
+ break;
+ }
+ totalCount += count;
+ }
+ // assert read content
+ assertEquals(CAPACITY_NORMAL, totalCount);
+ writeContent.flip();
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ assertEquals(writeContent.get(), readContent[i]);
+ }
+ }
+
+ /*
+ * Fails if the difference between current time and start time is greater
+ * than timeout.
+ */
+ private void assertTimeout(long startTime, long timeout) {
+ long currentTime = System.currentTimeMillis();
+ if ((currentTime - startTime) > timeout) {
+ fail("Timeout");
+ }
+ }
+
+ // -------------------------------------------------
+ // Test for read/write but no real data expressed
+ // -------------------------------------------------
+
+ public void testReadByteBuffer() throws Exception {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer readBuf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ // note: blocking-mode will make the read process endless!
+ this.channel1.configureBlocking(false);
+ try {
+ channel1.read(readBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertFalse(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnectionPending());
+ assertFalse(this.channel1.isConnected());
+ if (tryFinish()) {
+ assertEquals(0, this.channel1.read(readBuf));
+ }
+
+ this.channel1.close();
+ try {
+ channel1.read(readBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testReadByteBuffer_Direct() throws Exception {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer readBuf = java.nio.ByteBuffer
+ .allocateDirect(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ // note: blocking-mode will make the read process endless!
+ this.channel1.configureBlocking(false);
+ try {
+ channel1.read(readBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertFalse(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnectionPending());
+ assertFalse(this.channel1.isConnected());
+ if (tryFinish()) {
+ assertEquals(0, this.channel1.read(readBuf));
+ }
+
+ this.channel1.close();
+ try {
+ channel1.read(readBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testReadByteBuffer_BufNull() throws Exception {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer readBuf = java.nio.ByteBuffer.allocate(0);
+ // note: blocking-mode will make the read process endless!
+ this.channel1.configureBlocking(false);
+ try {
+ channel1.read((java.nio.ByteBuffer) null);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ if (tryFinish()) {
+ try {
+ this.channel1.read((java.nio.ByteBuffer) null);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, this.channel1.read(readBuf));
+ }
+ this.server1.close();
+ try {
+ channel1.read((java.nio.ByteBuffer) null);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * SocketChannelImpl.read(ByteBuffer[], int, int)'
+ */
+ public void testReadByteBufferArrayIntInt() throws Exception {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[2];
+ readBuf[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ readBuf[1] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ // note: blocking-mode will make the read process endless!
+ this.channel1.configureBlocking(false);
+ try {
+ channel1.read(readBuf, 0, 1);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertFalse(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnectionPending());
+ assertFalse(this.channel1.isConnected());
+ if (tryFinish()) {
+ assertEquals(0, this.channel1.read(readBuf, 0, 1));
+ assertEquals(0, this.channel1.read(readBuf, 0, 2));
+ }
+
+ this.channel1.close();
+ try {
+ channel1.read(readBuf, 0, 1);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ /*
+ * SocketChannelImpl.read(ByteBuffer[], int, int)'
+ */
+ public void testReadByteBufferArrayIntInt_Direct() throws Exception {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[2];
+ readBuf[0] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ readBuf[1] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ // note: blocking-mode will make the read process endless!
+ this.channel1.configureBlocking(false);
+ try {
+ channel1.read(readBuf, 0, 1);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertFalse(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnectionPending());
+ assertFalse(this.channel1.isConnected());
+ if (tryFinish()) {
+ assertEquals(0, this.channel1.read(readBuf, 0, 1));
+ assertEquals(0, this.channel1.read(readBuf, 0, 2));
+ }
+
+ this.channel1.close();
+ try {
+ channel1.read(readBuf, 0, 1);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testReadByteBufferArrayIntInt_BufNull() throws Exception {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[2];
+ readBuf[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ // note: blocking-mode will make the read process endless!
+ this.channel1.configureBlocking(false);
+ try {
+ channel1.read(null, 0, 0);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ if (tryFinish()) {
+
+ try {
+ channel1.read(null, 0, 0);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ channel1.read(readBuf, 0, 2);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+
+ assertEquals(0, this.channel1.read(readBuf, 0, 1));
+ }
+ this.channel1.close();
+ try {
+ channel1.read(null, 0, 1);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBuffer() throws IOException {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ try {
+ channel1.write(writeBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+
+ this.channel1.close();
+ try {
+ channel1.write(writeBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBuffer_Direct() throws IOException {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+ .allocateDirect(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ try {
+ channel1.write(writeBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+
+ this.channel1.close();
+ try {
+ channel1.write(writeBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBuffer_BufNull() throws IOException {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer.allocate(0);
+ this.channel1.connect(localAddr1);
+ assertEquals(this.channel1.write(writeBuf), 0);
+ try {
+ this.channel1.write((java.nio.ByteBuffer) null);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * SocketChannelImpl.write(ByteBuffer[], int, int)'
+ */
+ public void testWriteByteBufferArrayIntInt() throws IOException {
+ java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[2];
+ writeBuf[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ writeBuf[1] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ try {
+ channel1.write(writeBuf, 0, 1);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 1));
+ // still writes the same size as above
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 2));
+ writeBuf[0].flip();
+ writeBuf[1].flip();
+ assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+ this.channel1.close();
+ try {
+ channel1.write(writeBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ /*
+ * SocketChannelImpl.write(ByteBuffer[], int, int)'
+ */
+ public void testWriteByteBufferArrayIntInt_Direct() throws IOException {
+ java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[2];
+ writeBuf[0] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ writeBuf[1] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ try {
+ channel1.write(writeBuf, 0, 1);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 1));
+ // still writes the same size as above
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 2));
+ writeBuf[0].flip();
+ writeBuf[1].flip();
+ assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+ this.channel1.close();
+ try {
+ channel1.write(writeBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBufferArrayIntInt_BufNull() throws IOException {
+ java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[0];
+
+ this.channel1.connect(localAddr1);
+ try {
+ this.channel1.write(null, 0, 1);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, this.channel1.write(writeBuf, 0, 0));
+ try {
+ this.channel1.write(writeBuf, 0, 1);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ writeBuf = new java.nio.ByteBuffer[1];
+ try {
+ this.channel1.write(writeBuf, 0, 1);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ this.channel1.write(writeBuf, 0, 2);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ this.server1.close();
+ try {
+ channel1.read(null, 0, 1);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBufferArrayIntInt_SizeError() throws IOException {
+ java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[0];
+
+ this.channel1.connect(localAddr1);
+ try {
+ this.channel1.write(null, -1, 1);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ assertEquals(0, this.channel1.write(writeBuf, 0, 0));
+ try {
+ this.channel1.write(writeBuf, 0, -1);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ writeBuf = new java.nio.ByteBuffer[1];
+ try {
+ this.channel1.write(writeBuf, 2, 1);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ try {
+ this.channel1.write(writeBuf, 2, -1);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ this.server1.close();
+ try {
+ channel1.read(null, -1, -1);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ }
+
+ public void testReadByteBufferArrayIntInt_SizeError() throws IOException {
+ java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[0];
+
+ this.channel1.connect(localAddr1);
+ try {
+ this.channel1.read(null, -1, 1);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ assertEquals(0, this.channel1.read(readBuf, 0, 0));
+ try {
+ this.channel1.read(readBuf, 0, -1);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ readBuf = new java.nio.ByteBuffer[1];
+ try {
+ this.channel1.read(readBuf, 2, 1);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ try {
+ this.channel1.read(readBuf, 2, -1);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ this.server1.close();
+ try {
+ assertEquals(CAPACITY_NORMAL, this.channel1.read(null, -1, -1));
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ }
+
+ /*
+ * ==========================================================================
+ * Tests for read/write real data
+ * ==========================================================================
+ */
+
+
+ /**
+ * @tests java.nio.channels.SocketChannel#read(ByteBuffer[])
+ */
+ public void test_read$LByteBuffer() throws IOException {
+ MockSocketChannel sc = new MockSocketChannel(null);
+ ByteBuffer [] byteBufferArray = { ByteBuffer.allocate(1), ByteBuffer.allocate(1)};
+ // Verify that calling read(ByteBuffer[]) leads to the method
+ // read(ByteBuffer[], int, int) being called with a 0 for the
+ // second parameter and targets.length as the third parameter.
+ sc.read(byteBufferArray);
+ assertTrue(sc.isReadCalled);
+ }
+ /**
+ * @tests java.nio.channels.SocketChannel#read(ByteBuffer[],int,int)
+ */
+ public void test_read$LByteBufferII_blocking() throws Exception {
+ assert_read$LByteBuffer(true);
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#read(ByteBuffer[],int,int)
+ */
+ public void test_read$LByteBufferII_nonblocking() throws Exception {
+ assert_read$LByteBuffer(false);
+ }
+
+ private void assert_read$LByteBuffer(boolean isBlocking) throws IOException {
+ // initialize write content
+ byte[] writeContent = new byte[CAPACITY_NORMAL * 2];
+ for (int i = 0; i < CAPACITY_NORMAL * 2; i++) {
+ writeContent[i] = (byte) i;
+ }
+ ByteBuffer[] readContents = new ByteBuffer[2];
+ readContents[0] = ByteBuffer.allocate(CAPACITY_NORMAL);
+ readContents[1] = ByteBuffer.allocate(CAPACITY_NORMAL + 1);
+ // establish connection
+ channel1.connect(localAddr1);
+ Socket acceptedSocket = server1.accept();
+ // use OutputStream.write to send CAPACITY_NORMAL * 2 bytes data
+ OutputStream out = acceptedSocket.getOutputStream();
+ out.write(writeContent);
+ // use close to guarantee all data is sent
+ acceptedSocket.close();
+ // configure block/nonblock mode
+ channel1.configureBlocking(isBlocking);
+ long startTime = System.currentTimeMillis();
+ long totalRead = 0;
+ long countRead = 0;
+
+ while (totalRead <= CAPACITY_NORMAL * 2) {
+ countRead = channel1.read(readContents, 0, 2);
+ if (0 == countRead && !readContents[1].hasRemaining()) {
+ // read returns 0 because readContents is full
+ break;
+ }
+ if (EOF == countRead) {
+ break;
+ }
+ totalRead += countRead;
+ // if the channel could not finish reading in TIMEOUT ms, the
+ // test fails. It is used to guarantee the test never hangs even
+ // if there are bugs of SocketChannel implementation. For
+ // blocking read, it possibly returns 0 in some cases.
+ assertTimeout(startTime, TIMEOUT);
+ }
+
+ // assert total bytes read and the position of ByteBuffers
+ assertEquals(CAPACITY_NORMAL * 2, totalRead);
+ assertEquals(CAPACITY_NORMAL, readContents[0].position());
+ assertEquals(CAPACITY_NORMAL, readContents[1].position());
+ // assert read content
+ readContents[0].flip();
+ readContents[1].flip();
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ assertEquals(writeContent[i], readContents[0].get());
+ }
+ for (int i = CAPACITY_NORMAL; i < CAPACITY_NORMAL * 2; i++) {
+ assertEquals(writeContent[i], readContents[1].get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII_blocking() throws Exception {
+ assert_write$LByteBuffer(true);
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII_nonblocking()
+ throws Exception {
+ assert_write$LByteBuffer(false);
+ }
+
+ private void assert_write$LByteBuffer(boolean isBlocking)
+ throws IOException {
+ // initialize write contents
+ ByteBuffer writeContents[] = new ByteBuffer[2];
+ writeContents[0] = ByteBuffer.allocate(CAPACITY_NORMAL);
+ writeContents[1] = ByteBuffer.allocate(CAPACITY_NORMAL);
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ writeContents[0].put((byte) i);
+ }
+ for (int i = CAPACITY_NORMAL; i < CAPACITY_NORMAL * 2; i++) {
+ writeContents[1].put((byte) i);
+ }
+ writeContents[0].flip();
+ writeContents[1].flip();
+ // establish connection
+ channel1.connect(localAddr1);
+ Socket acceptedSocket = server1.accept();
+ // set blocking/nonblocking mode
+ channel1.configureBlocking(isBlocking);
+
+ assertEquals(CAPACITY_NORMAL, channel1.write(writeContents, 0, 1));
+ assertEquals(CAPACITY_NORMAL, channel1.write(writeContents, 1, 1));
+
+ // assert written count and ByteBuffer position
+ assertEquals(CAPACITY_NORMAL, writeContents[0].position());
+ assertEquals(CAPACITY_NORMAL, writeContents[1].position());
+ // use close to guarantee all data is sent
+ channel1.close();
+ InputStream in = acceptedSocket.getInputStream();
+ byte[] readContent = new byte[CAPACITY_NORMAL * 2 + 1];
+ int totalCount = 0;
+ int count = 0;
+ // if the channel could not finish reading in TIMEOUT ms, the test
+ // fails. It is used to guarantee the test never hangs even if there
+ // are bugs of SocketChannel implementation.
+ acceptedSocket.setSoTimeout(TIMEOUT);
+ // use InputStream.read to read data.
+ while (totalCount <= CAPACITY_NORMAL) {
+ count = in.read(readContent, totalCount, readContent.length
+ - totalCount);
+ if (EOF == count) {
+ break;
+ }
+ totalCount += count;
+ }
+ // assert read content
+ assertEquals(CAPACITY_NORMAL * 2, totalCount);
+ writeContents[0].flip();
+ writeContents[1].flip();
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ assertEquals(writeContents[0].get(), readContent[i]);
+ }
+ for (int i = CAPACITY_NORMAL; i < CAPACITY_NORMAL * 2; i++) {
+ assertEquals(writeContents[1].get(), readContent[i]);
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+ */
+ public void test_write$LByteBuffer() throws IOException {
+ MockSocketChannel sc = new MockSocketChannel(null);
+ ByteBuffer [] byteBufferArray = { ByteBuffer.allocate(1), ByteBuffer.allocate(1)};
+ // Verify that calling write(ByteBuffer[]) leads to the method
+ // write(ByteBuffer[], int, int) being called with a 0 for the
+ // second parameter and sources.length as the third parameter.
+ sc.write(byteBufferArray);
+ assertTrue(sc.isWriteCalled);
+ }
+
+ public void testSocket_configureblocking() throws IOException {
+ byte[] serverWBuf = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < serverWBuf.length; i++) {
+ serverWBuf[i] = (byte) i;
+ }
+ java.nio.ByteBuffer buf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL + 1);
+ channel1.connect(localAddr1);
+ server1.accept();
+ Socket sock = this.channel1.socket();
+ channel1.configureBlocking(false);
+ assertFalse(channel1.isBlocking());
+ OutputStream channelSocketOut = sock.getOutputStream();
+ try {
+ // write operation is not allowed in non-blocking mode
+ channelSocketOut.write(buf.array());
+ fail("Non-Blocking mode should cause IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // correct
+ }
+ channel1.configureBlocking(true);
+ assertTrue(channel1.isBlocking());
+ // write operation is allowed in blocking mode
+ channelSocketOut.write(buf.array());
+ }
+
+ /**
+ * @tests SocketChannel#read(ByteBuffer[], int, int) when remote server
+ * closed
+ */
+ public void test_socketChannel_read_ByteBufferII_remoteClosed()
+ throws Exception {
+ // regression 1 for HARMONY-549
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(localAddr2);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(localAddr2);
+ ssc.accept().close();
+ ByteBuffer[] buf = { ByteBuffer.allocate(10) };
+ assertEquals(-1, sc.read(buf, 0, 1));
+ ssc.close();
+ sc.close();
+ }
+
+ /**
+ * @tests SocketChannel#write(ByteBuffer[], int, int)
+ */
+ public void test_socketChannel_write_ByteBufferII() throws Exception {
+ // regression 2 for HARMONY-549
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(localAddr2);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(localAddr2);
+ SocketChannel sock = ssc.accept();
+ ByteBuffer[] buf = { ByteBuffer.allocate(10), null };
+ try {
+ sc.write(buf, 0, 2);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ ssc.close();
+ sc.close();
+ ByteBuffer target = ByteBuffer.allocate(10);
+ assertEquals(-1, sock.read(target));
+ }
+
+ /**
+ * @tests SocketChannel#read(ByteBuffer[], int, int) with a null ByteBuffer
+ */
+ public void test_socketChannel_read_ByteBufferII_bufNULL() throws Exception {
+ // regression 3 for HARMONY-549
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(localAddr2);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(localAddr2);
+ ssc.accept();
+ ByteBuffer[] buf = new ByteBuffer[2];
+ buf[0] = ByteBuffer.allocate(1);
+ // let buf[1] be null
+ try {
+ sc.read(buf, 0, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ ssc.close();
+ sc.close();
+ }
+
+ /**
+ * @tests SocketChannel#write(ByteBuffer) after close
+ */
+ public void test_socketChannel_write_close() throws Exception {
+ // regression 4 for HARMONY-549
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(localAddr2);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(localAddr2);
+ SocketChannel sock = ssc.accept();
+ ByteBuffer buf = null;
+ ssc.close();
+ sc.close();
+ try {
+ sc.write(buf);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ sock.close();
+ }
+
+ /**
+ * @tests SocketChannel#write(ByteBuffer) if position is not zero
+ */
+ public void test_socketChannel_write_ByteBuffer_posNotZero()
+ throws Exception {
+ // regression 5 for HARMONY-549
+ final String testStr = "Hello World";
+ ByteBuffer readBuf = ByteBuffer.allocate(11);
+ ByteBuffer buf = ByteBuffer.wrap(testStr.getBytes());
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(localAddr2);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(localAddr2);
+ buf.position(2);
+ ssc.accept().write(buf);
+ assertEquals(9, sc.read(readBuf));
+ buf.flip();
+ readBuf.flip();
+ byte[] read = new byte[9];
+ byte[] write = new byte[11];
+ buf.get(write);
+ readBuf.get(read);
+ for (int i = 0; i < 9; i++) {
+ assertEquals(read[i], write[i + 2]);
+ }
+ }
+
+ /**
+ * @tests SocketChannelImpl#read(ByteBuffer[])
+ */
+ public void test_read_$ByteBuffer_Blocking() throws IOException {
+ // regression test for Harmony-728
+ byte[] data = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ data[i] = (byte) i;
+ }
+ ByteBuffer[] buf = new ByteBuffer[2];
+ buf[0] = ByteBuffer.allocate(CAPACITY_NORMAL);
+ buf[1] = ByteBuffer.allocate(CAPACITY_NORMAL);
+ channel1.connect(localAddr1);
+ Socket socket = null;
+ try {
+ socket = server1.accept();
+ OutputStream out = socket.getOutputStream();
+ out.write(data);
+ // should not block here
+ channel1.read(buf);
+ } finally {
+ if (null != socket) {
+ socket.close();
+ }
+ }
+ }
+
+ /**
+ * @tests SocketChannelImpl#socket().getOutputStream().read
+ */
+ public void test_socket_getOutputStream_nonBlocking_read_Exception()
+ throws IOException {
+ channel1.connect(this.localAddr1);
+ InputStream is = channel1.socket().getInputStream();
+ channel1.configureBlocking(false);
+ try {
+ is.read();
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ try {
+ is.read(null, 1, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ is.read(null, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ // closed
+ is.close();
+ try {
+ is.read(null);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ is.read();
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ try {
+ is.read(null, 1, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ is.read(null, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests SocketChannelImpl#socket().getOutputStream().read
+ */
+ public void test_socket_getOutputStream_blocking_read_Exception()
+ throws IOException {
+ channel1.connect(this.localAddr1);
+ InputStream is = channel1.socket().getInputStream();
+ try {
+ is.read(null);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ is.read(null, 1, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ is.read(null, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ // closed
+ is.close();
+ try {
+ is.read(null);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ is.read();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ try {
+ is.read(null, 1, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ is.read(null, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests SocketChannelImpl#socket().getOutputStream().write
+ */
+ public void test_socket_getOutputStream_nonBlocking_write_Exception()
+ throws IOException {
+ channel1.connect(this.localAddr1);
+ OutputStream os = channel1.socket().getOutputStream();
+ channel1.configureBlocking(false);
+ try {
+ os.write(null);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ os.write(1);
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ try {
+ os.write(1);
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ try {
+ os.write(null, 1, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ os.write(null, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ // closed
+ os.close();
+ try {
+ os.write(null);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ os.write(1);
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ try {
+ os.write(null, 1, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ os.write(null, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests SocketChannelImpl#socket().getOutputStream().write
+ */
+ public void test_socket_getOutputStream_blocking_write_Exception()
+ throws IOException {
+ channel1.connect(this.localAddr1);
+ OutputStream os = channel1.socket().getOutputStream();
+ try {
+ os.write(null);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ os.write(null, 1, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ os.write(null, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ // closed
+ os.close();
+ try {
+ os.write(null);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ os.write(1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ try {
+ os.write(null, 1, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ os.write(null, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests SocketChannelImpl#socket().getOutputStream().write(int)
+ */
+ public void test_socket_getOutputStream_write_oneByte()
+ throws IOException {
+
+ // Regression test for Harmony-3475
+
+ int MAGIC = 123;
+
+ channel1.connect(this.localAddr1);
+
+ OutputStream os = channel1.socket().getOutputStream();
+
+ Socket acceptedSocket = server1.accept();
+
+ InputStream in = acceptedSocket.getInputStream();
+
+ os.write(MAGIC);
+ channel1.close();
+
+ int lastByte = in.read();
+ if (lastByte == -1) {
+ fail("Server received nothing. Expected 1 byte.");
+ } else if (lastByte != MAGIC) {
+ fail("Server received wrong single byte: " + lastByte +
+ ", expected: " + MAGIC);
+ }
+
+ lastByte = in.read();
+ if (lastByte != -1) {
+ fail("Server received too long sequence. Expected 1 byte.");
+ }
+ }
+
+ class MockSocketChannel extends SocketChannel{
+
+ private boolean isWriteCalled = false;
+
+ private boolean isReadCalled = false;
+
+ public MockSocketChannel(SelectorProvider provider){
+ super(provider);
+ }
+
+ public Socket socket() {
+ return null;
+ }
+
+ public boolean isConnected() {
+ return false;
+ }
+
+ public boolean isConnectionPending() {
+ return false;
+ }
+
+ public boolean connect(SocketAddress address) throws IOException {
+ return false;
+ }
+
+ public boolean finishConnect() throws IOException {
+ return false;
+ }
+
+ public int read(ByteBuffer target) throws IOException {
+ return 0;
+ }
+
+ public long read(ByteBuffer[] targets, int offset, int length) throws IOException {
+ // Verify that calling read(ByteBuffer[]) leads to the method
+ // read(ByteBuffer[], int, int) being called with a 0 for the
+ // second parameter and targets.length as the third parameter.
+ if(0 == offset && length == targets.length){
+ isReadCalled = true;
+ }
+ return 0;
+ }
+
+ public int write(ByteBuffer source) throws IOException {
+ return 0;
+ }
+
+ public long write(ByteBuffer[] sources, int offset, int length) throws IOException {
+ // Verify that calling write(ByteBuffer[]) leads to the method
+ // write(ByteBuffer[], int, int) being called with a 0 for the
+ // second parameter and sources.length as the third parameter.
+ if(0 == offset && length == sources.length){
+ isWriteCalled = true;
+ }
+ return 0;
+ }
+
+ protected void implCloseSelectableChannel() throws IOException {
+ // empty
+ }
+
+ protected void implConfigureBlocking(boolean blockingMode) throws IOException {
+ // empty
+ }
+
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SourceChannelTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SourceChannelTest.java
new file mode 100644
index 0000000..05dca90
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SourceChannelTest.java
@@ -0,0 +1,532 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.Pipe;
+import java.nio.channels.SelectionKey;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for java.nio.channels.Pipe.SourceChannel
+ */
+public class SourceChannelTest extends TestCase {
+
+ private static final int BUFFER_SIZE = 5;
+
+ private static final String ISO8859_1 = "ISO8859-1";
+
+ private Pipe pipe;
+
+ private Pipe.SinkChannel sink;
+
+ private Pipe.SourceChannel source;
+
+ private ByteBuffer buffer;
+
+ private ByteBuffer positionedBuffer;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ pipe = Pipe.open();
+ sink = pipe.sink();
+ source = pipe.source();
+ buffer = ByteBuffer.wrap("bytes".getBytes(ISO8859_1));
+ positionedBuffer = ByteBuffer.wrap("12345bytes".getBytes(ISO8859_1));
+ positionedBuffer.position(BUFFER_SIZE);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#validOps()
+ */
+ public void test_validOps() {
+ assertEquals(SelectionKey.OP_READ, source.validOps());
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_DataAvailable() throws IOException {
+ // if anything can read, read method will not block
+ sink.write(ByteBuffer.allocate(1));
+ int count = source.read(ByteBuffer.allocate(10));
+ assertEquals(1, count);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_Exception() throws IOException {
+ ByteBuffer nullBuf = null;
+ try {
+ source.read(nullBuf);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_SinkClosed() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ sink.write(buffer);
+ sink.close();
+ long count = source.read(readBuf);
+ assertEquals(BUFFER_SIZE, count);
+ // readBuf is full, read 0 byte expected
+ count = source.read(readBuf);
+ assertEquals(0, count);
+ // readBuf is not null, -1 is expected
+ readBuf.position(0);
+ count = source.read(readBuf);
+ assertEquals(-1, count);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_SourceClosed() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ source.close();
+ try {
+ source.read(readBuf);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ readBuf.position(BUFFER_SIZE);
+ try {
+ // readBuf is full
+ source.read(readBuf);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ ByteBuffer nullBuf = null;
+ try {
+ source.read(nullBuf);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ ByteBuffer[] bufArray = null;
+ try {
+ source.read(bufArray);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArray = {nullBuf};
+ try {
+ source.read(nullBufArray);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer[])
+ */
+ public void test_read_$LByteBuffer() throws IOException {
+ ByteBuffer[] bufArray = { buffer, positionedBuffer };
+ boolean[] sinkBlockingMode = { true, true, false, false };
+ boolean[] sourceBlockingMode = { true, false, true, false };
+ for (int i = 0; i < sinkBlockingMode.length; ++i) {
+ // open new pipe everytime, will be closed in finally block
+ pipe = Pipe.open();
+ sink = pipe.sink();
+ source = pipe.source();
+ sink.configureBlocking(sinkBlockingMode[i]);
+ source.configureBlocking(sourceBlockingMode[i]);
+ buffer.position(0);
+ positionedBuffer.position(BUFFER_SIZE);
+ try {
+ long writeCount = sink.write(bufArray);
+ assertEquals(10, writeCount);
+ // invoke close to ensure all data will be sent out
+ sink.close();
+ // read until EOF is meet or readBufArray is full.
+ ByteBuffer[] readBufArray = { ByteBuffer.allocate(BUFFER_SIZE),
+ ByteBuffer.allocate(BUFFER_SIZE) };
+ long totalCount = 0;
+ do {
+ long count = source.read(readBufArray);
+ if (count < 0) {
+ break;
+ }
+ if (0 == count && BUFFER_SIZE == readBufArray[1].position()) {
+ // source.read returns 0 because readBufArray is full
+ break;
+ }
+ totalCount += count;
+ } while (totalCount <= 10);
+ // assert read result
+ for (ByteBuffer readBuf : readBufArray) {
+ // RI may fail because of its bug implementation
+ assertEquals(BUFFER_SIZE, readBuf.position());
+ assertEquals("bytes",
+ new String(readBuf.array(), ISO8859_1));
+ }
+ } finally {
+ // close pipe everytime
+ sink.close();
+ source.close();
+ }
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_$LByteBuffer_Exception() throws IOException {
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ source.read(nullBufArrayRef);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // ByteBuffer array contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray1 = { nullBuf };
+ try {
+ source.read(nullBufArray1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArray2 = { buffer, nullBuf };
+ try {
+ source.read(nullBufArray2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_$LByteBuffer_SinkClosed() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ ByteBuffer[] readBufArray = { readBuf };
+ sink.write(buffer);
+ sink.close();
+ long count = source.read(readBufArray);
+ assertEquals(BUFFER_SIZE, count);
+ // readBuf is full, read 0 byte expected
+ count = source.read(readBufArray);
+ assertEquals(0, count);
+ // readBuf is not null, -1 is expected
+ readBuf.position(0);
+ assertTrue(readBuf.hasRemaining());
+ count = source.read(readBufArray);
+ assertEquals(-1, count);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_$LByteBuffer_SourceClosed() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ ByteBuffer[] readBufArray = { readBuf };
+ source.close();
+ try {
+ source.read(readBufArray);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ readBuf.position(BUFFER_SIZE);
+ try {
+ // readBuf is full
+ source.read(readBufArray);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ source.read(nullBufArrayRef);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // ByteBuffer array contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray1 = { nullBuf };
+ try {
+ source.read(nullBufArray1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read_$LByteBufferII() throws IOException {
+ ByteBuffer[] bufArray = { buffer, positionedBuffer };
+ boolean[] sinkBlockingMode = { true, true, false, false };
+ boolean[] sourceBlockingMode = { true, false, true, false };
+ for (int i = 0; i < sinkBlockingMode.length; ++i) {
+ Pipe pipe = Pipe.open();
+ sink = pipe.sink();
+ source = pipe.source();
+
+ sink.configureBlocking(sinkBlockingMode[i]);
+ source.configureBlocking(sourceBlockingMode[i]);
+
+ buffer.position(0);
+ positionedBuffer.position(BUFFER_SIZE);
+ try {
+ sink.write(bufArray);
+ // invoke close to ensure all data will be sent out
+ sink.close();
+ // read until EOF is meet or readBufArray is full.
+ ByteBuffer[] readBufArray = { ByteBuffer.allocate(BUFFER_SIZE),
+ ByteBuffer.allocate(BUFFER_SIZE) };
+ long totalCount = 0;
+ do {
+ long count = source.read(readBufArray, 0, 2);
+ if (count < 0) {
+ break;
+ }
+ if (0 == count && BUFFER_SIZE == readBufArray[1].position()) {
+ // source.read returns 0 because readBufArray is full
+ break;
+ }
+ totalCount += count;
+ } while (totalCount != 10);
+
+ // assert read result
+ for (ByteBuffer readBuf : readBufArray) {
+ // RI may fail because of its bug implementation
+ assertEquals(BUFFER_SIZE, readBuf.position());
+ assertEquals("bytes",
+ new String(readBuf.array(), ISO8859_1));
+ }
+ } finally {
+ sink.close();
+ source.close();
+ }
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_$LByteBufferII_Exception() throws IOException {
+
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ source.read(nullBufArrayRef, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ source.read(nullBufArrayRef, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // ByteBuffer array contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray1 = { nullBuf };
+ try {
+ source.read(nullBufArray1, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ source.read(nullBufArray1, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ source.read(nullBufArray1, -1, 0);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ source.read(nullBufArray1, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArray2 = { buffer, nullBuf };
+
+ try {
+ source.read(nullBufArray1, 1, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ source.read(nullBufArray2, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ source.read(nullBufArray2, 0, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_$LByteBufferII_SinkClosed() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ ByteBuffer[] readBufArray = { readBuf };
+ sink.write(buffer);
+ sink.close();
+ long count = source.read(readBufArray, 0, 1);
+ assertEquals(BUFFER_SIZE, count);
+ // readBuf is full, read 0 byte expected
+ count = source.read(readBufArray);
+ assertEquals(0, count);
+ // readBuf is not null, -1 is expected
+ readBuf.position(0);
+ count = source.read(readBufArray, 0, 1);
+ assertEquals(-1, count);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_$LByteBufferII_SourceClosed() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ ByteBuffer[] readBufArray = { readBuf };
+ source.close();
+ try {
+ source.read(readBufArray, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ readBuf.position(BUFFER_SIZE);
+ try {
+ // readBuf is full
+ source.read(readBufArray, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ source.read(nullBufArrayRef, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ source.read(nullBufArrayRef, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ // ByteBuffer array contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray1 = { nullBuf };
+ try {
+ source.read(nullBufArray1, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ try {
+ source.read(nullBufArray1, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ source.read(nullBufArray1, -1, 0);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ source.read(nullBufArray1, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArray2 = { buffer, nullBuf };
+
+ try {
+ source.read(nullBufArray1, 1, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ source.read(nullBufArray2, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ source.read(nullBufArray2, 0, 2);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#close()
+ */
+ public void test_close() throws IOException {
+ sink.close();
+ assertFalse(sink.isOpen());
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java
new file mode 100644
index 0000000..3157f3b
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java
@@ -0,0 +1,44 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.UnresolvedAddressException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for UnresolvedAddressException
+ */
+public class UnresolvedAddressExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new UnresolvedAddressException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new UnresolvedAddressException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java
new file mode 100644
index 0000000..eb8baba
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java
@@ -0,0 +1,45 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.tests.java.nio.channels;
+
+import java.nio.channels.UnsupportedAddressTypeException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for UnsupportedAddressTypeException
+ */
+public class UnsupportedAddressTypeExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new UnsupportedAddressTypeException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this,
+ new UnsupportedAddressTypeException());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractInterruptibleChannelTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractInterruptibleChannelTest.java
new file mode 100644
index 0000000..e8c24ed
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractInterruptibleChannelTest.java
@@ -0,0 +1,136 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.spi.AbstractInterruptibleChannel;
+
+import junit.framework.TestCase;
+
+public class AbstractInterruptibleChannelTest extends TestCase {
+
+ /**
+ * @tests AbstractInterruptibleChannel#close()
+ */
+ public void test_close() throws IOException {
+ MockInterruptibleChannel testMiChannel = new MockInterruptibleChannel();
+ assertTrue(testMiChannel.isOpen());
+ testMiChannel.isImplCloseCalled = false;
+ testMiChannel.close();
+ assertTrue(testMiChannel.isImplCloseCalled);
+ assertFalse(testMiChannel.isOpen());
+ }
+
+ /**
+ * @tests AbstractInterruptibleChannel#begin/end()
+ */
+ public void test_begin_end() throws IOException {
+ boolean complete = false;
+ MockInterruptibleChannel testChannel = new MockInterruptibleChannel();
+ try {
+ testChannel.superBegin();
+ complete = true;
+ } finally {
+ testChannel.superEnd(complete);
+ }
+
+ try {
+ testChannel.superBegin();
+ complete = false;
+ } finally {
+ testChannel.superEnd(complete);
+ }
+
+ try {
+ testChannel.superBegin();
+ complete = true;
+ } finally {
+ testChannel.superEnd(complete);
+ }
+ testChannel.superEnd(complete);
+
+ testChannel.superBegin();
+ try {
+ testChannel.superBegin();
+ complete = true;
+ } finally {
+ testChannel.superEnd(complete);
+ }
+ assertTrue(testChannel.isOpen());
+ testChannel.close();
+ }
+
+ /**
+ * @tests AbstractInterruptibleChannel#close/begin/end()
+ */
+ public void test_close_begin_end() throws IOException {
+ boolean complete = false;
+ MockInterruptibleChannel testChannel = new MockInterruptibleChannel();
+ assertTrue(testChannel.isOpen());
+ try {
+ testChannel.superBegin();
+ complete = true;
+ } finally {
+ testChannel.superEnd(complete);
+ }
+ assertTrue(testChannel.isOpen());
+ testChannel.close();
+ try {
+ testChannel.superBegin();
+ complete = false;
+ } finally {
+ try {
+ testChannel.superEnd(complete);
+ fail("should throw AsynchronousCloseException");
+ } catch (AsynchronousCloseException e) {
+ // expected
+ }
+ }
+ assertFalse(testChannel.isOpen());
+ try {
+ testChannel.superBegin();
+ complete = true;
+ } finally {
+ testChannel.superEnd(complete);
+ }
+ assertFalse(testChannel.isOpen());
+ }
+
+ private class MockInterruptibleChannel extends AbstractInterruptibleChannel {
+
+ private boolean isImplCloseCalled = false;
+
+ public MockInterruptibleChannel() {
+ super();
+ }
+
+ protected void implCloseChannel() throws IOException {
+ isImplCloseCalled = true;
+ }
+
+ // call super.begin() for test
+ void superBegin() {
+ super.begin();
+ }
+
+ // call super.end() for test
+ void superEnd(boolean completed) throws AsynchronousCloseException {
+ super.end(completed);
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java
new file mode 100644
index 0000000..d6e0e08
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java
@@ -0,0 +1,304 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.IllegalSelectorException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for AbstractSelectableChannel
+ */
+public class AbstractSelectableChannelTest extends TestCase {
+
+ private MockSelectableChannel testChannel;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ testChannel = new MockSelectableChannel(SelectorProvider.provider());
+ }
+
+ protected void tearDown() throws Exception {
+ if (testChannel.isOpen()) {
+ testChannel.close();
+ }
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#implCloseChannel()
+ */
+ public void test_implClose() throws IOException {
+ testChannel.isImplCloseSelectableChannelCalled = false;
+ testChannel.implCloseSelectableChannelCount = 0;
+ testChannel.close();
+ assertFalse(testChannel.isOpen());
+ assertTrue(testChannel.isImplCloseSelectableChannelCalled);
+ assertEquals(1, testChannel.implCloseSelectableChannelCount);
+
+ testChannel = new MockSelectableChannel(SelectorProvider.provider());
+ testChannel.isImplCloseSelectableChannelCalled = false;
+ testChannel.implCloseSelectableChannelCount = 0;
+ // close twice.
+ // make sure implCloseSelectableChannelCount is called only once.
+ testChannel.close();
+ testChannel.close();
+ assertFalse(testChannel.isOpen());
+ assertTrue(testChannel.isImplCloseSelectableChannelCalled);
+ assertEquals(1, testChannel.implCloseSelectableChannelCount);
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#provider()
+ */
+ public void test_provider() {
+ SelectorProvider provider = testChannel.provider();
+ assertSame(SelectorProvider.provider(), provider);
+ testChannel = new MockSelectableChannel(null);
+ provider = testChannel.provider();
+ assertNull(provider);
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#isBlocking()
+ */
+ public void test_isBlocking() throws IOException {
+ assertTrue(testChannel.isBlocking());
+ testChannel.configureBlocking(false);
+ assertFalse(testChannel.isBlocking());
+ testChannel.configureBlocking(true);
+ assertTrue(testChannel.isBlocking());
+ }
+
+ /**
+ *
+ * @tests AbstractSelectableChannel#blockingLock()
+ */
+ public void test_blockingLock() {
+ Object gotObj = testChannel.blockingLock();
+ assertNotNull(gotObj);
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#register(Selector, int, Object)
+ */
+ public void test_register_LSelectorILObject() throws IOException {
+ assertFalse(testChannel.isRegistered());
+ Selector acceptSelector1 = SelectorProvider.provider().openSelector();
+ Selector acceptSelector2 = new MockAbstractSelector(SelectorProvider
+ .provider());
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ SelectionKey acceptKey = sc.register(acceptSelector1,
+ SelectionKey.OP_READ, null);
+ assertNotNull(acceptKey);
+ assertTrue(acceptKey.isValid());
+ assertSame(sc, acceptKey.channel());
+
+ //test that sc.register invokes Selector.register()
+ acceptKey = sc.register(acceptSelector2, SelectionKey.OP_READ, null);
+ assertNull(acceptKey);
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#register(Selector, int, Object)
+ */
+ public void test_register_LSelectorILObject_IllegalArgument()
+ throws IOException {
+ Selector acceptSelector = SelectorProvider.provider().openSelector();
+ assertTrue(acceptSelector.isOpen());
+ MockSelectableChannel msc = new MockSelectableChannel(SelectorProvider
+ .provider());
+ msc.configureBlocking(false);
+ // in nonblocking mode
+ try {
+ //different SelectionKey with validOps
+ msc.register(acceptSelector, SelectionKey.OP_READ, null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ msc.register(null, 0, null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ // in nonblocking mode, if selector closed
+ acceptSelector.close();
+ try {
+ msc.register(acceptSelector, SelectionKey.OP_READ, null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ msc.register(null, 0, null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ msc.register(acceptSelector, 0, null);
+ fail("Should throw IllegalSelectorException");
+ } catch (IllegalSelectorException e) {
+ // expected
+ }
+
+ acceptSelector = SelectorProvider.provider().openSelector();
+ // test in blocking mode
+ msc.configureBlocking(true);
+ try {
+ msc.register(acceptSelector, SelectionKey.OP_READ, null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ msc.register(null, 0, null);
+ fail("Should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ acceptSelector.close();
+ // in blocking mode, if selector closed
+ try {
+ msc.register(acceptSelector, SelectionKey.OP_READ, null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ msc.register(null, 0, null);
+ fail("Should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+
+ // register with an object
+ Object argObj = new Object();
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ try {
+ sc.register(null, SelectionKey.OP_READ, argObj);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // if channel closed
+ msc.close();
+ try {
+ msc.register(acceptSelector, SelectionKey.OP_READ, null);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#keyFor(Selector)
+ */
+ public void test_keyfor_LSelector() throws Exception {
+ SocketChannel sc = SocketChannel.open();
+ Object argObj = new Object();
+ sc.configureBlocking(false);
+ Selector acceptSelector = SelectorProvider.provider().openSelector();
+ Selector acceptSelectorOther = SelectorProvider.provider()
+ .openSelector();
+ SelectionKey acceptKey = sc.register(acceptSelector,
+ SelectionKey.OP_READ, argObj);
+ assertEquals(sc.keyFor(acceptSelector), acceptKey);
+ SelectionKey acceptKeyObjNull = sc.register(acceptSelector,
+ SelectionKey.OP_READ, null);
+ assertSame(sc.keyFor(acceptSelector), acceptKeyObjNull);
+ assertSame(acceptKeyObjNull, acceptKey);
+ SelectionKey acceptKeyOther = sc.register(acceptSelectorOther,
+ SelectionKey.OP_READ, null);
+ assertSame(sc.keyFor(acceptSelectorOther), acceptKeyOther);
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#configureBlocking(boolean)
+ */
+ public void test_configureBlocking_Z_IllegalBlockingMode() throws Exception {
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ Selector acceptSelector = SelectorProvider.provider().openSelector();
+ SelectionKey acceptKey = sc.register(acceptSelector,
+ SelectionKey.OP_READ, null);
+ assertEquals(sc.keyFor(acceptSelector), acceptKey);
+ SelectableChannel getChannel = sc.configureBlocking(false);
+ assertEquals(getChannel, sc);
+ try {
+ sc.configureBlocking(true);
+ fail("Should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#configureBlocking(boolean)
+ */
+ public void test_configureBlocking_Z() throws Exception {
+ MockSelectableChannel mock = new MockSelectableChannel(SelectorProvider
+ .provider());
+ //default blocking mode is true
+ //the implConfigureBlocking is only invoked if the given mode is different with current one
+ mock.configureBlocking(true);
+ assertFalse(mock.implConfigureBlockingCalled);
+ mock.configureBlocking(false);
+ assertTrue(mock.implConfigureBlockingCalled);
+ }
+
+ private class MockSelectableChannel extends AbstractSelectableChannel {
+
+ private boolean isImplCloseSelectableChannelCalled = false;
+
+ private int implCloseSelectableChannelCount = 0;
+
+ private boolean implConfigureBlockingCalled = false;
+
+ public MockSelectableChannel(SelectorProvider arg0) {
+ super(arg0);
+ }
+
+ protected void implCloseSelectableChannel() throws IOException {
+ isImplCloseSelectableChannelCalled = true;
+ ++implCloseSelectableChannelCount;
+ }
+
+ protected void implConfigureBlocking(boolean arg0) throws IOException {
+ implConfigureBlockingCalled = true;
+ }
+
+ public int validOps() {
+ return SelectionKey.OP_ACCEPT;
+ }
+
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectionKeyTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectionKeyTest.java
new file mode 100644
index 0000000..1404fc1
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectionKeyTest.java
@@ -0,0 +1,76 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels.spi;
+
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectionKey;
+
+import junit.framework.TestCase;
+
+public class AbstractSelectionKeyTest extends TestCase {
+
+ /**
+ * @tests AbstractSelectionKey#isValid() without selector
+ */
+ public void test_isValid() throws Exception {
+ MockSelectionKey testKey = new MockSelectionKey();
+ assertTrue(testKey.isValid());
+ }
+
+ /**
+ * @tests AbstractSelectionKey#cancel
+ */
+ public void test_cancel() throws Exception {
+ MockSelectionKey testKey = new MockSelectionKey();
+ try {
+ testKey.cancel();
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected: no selector available
+ }
+ assertFalse(testKey.isValid());
+ }
+
+ private class MockSelectionKey extends AbstractSelectionKey {
+
+ MockSelectionKey() {
+ super();
+ }
+
+ public SelectableChannel channel() {
+ return null;
+ }
+
+ public Selector selector() {
+ return null;
+ }
+
+ public int interestOps() {
+ return 0;
+ }
+
+ public SelectionKey interestOps(int arg0) {
+ return null;
+ }
+
+ public int readyOps() {
+ return 0;
+ }
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectorTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectorTest.java
new file mode 100644
index 0000000..4b39001
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectorTest.java
@@ -0,0 +1,160 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for AbstractSelector and register of its default implementation
+ */
+public class AbstractSelectorTest extends TestCase {
+
+ /**
+ * @tests AbstractSelector#provider()
+ */
+ public void test_provider() throws IOException {
+ Selector mockSelector = new MockAbstractSelector(SelectorProvider
+ .provider());
+ assertTrue(mockSelector.isOpen());
+ assertSame(SelectorProvider.provider(), mockSelector.provider());
+ mockSelector = new MockAbstractSelector(null);
+ assertNull(mockSelector.provider());
+ }
+
+ /**
+ * @tests AbstractSelector#close()
+ */
+ public void test_close() throws IOException {
+ MockAbstractSelector mockSelector = new MockAbstractSelector(
+ SelectorProvider.provider());
+ mockSelector.close();
+ assertTrue(mockSelector.isImplCloseSelectorCalled);
+ }
+
+ /**
+ *
+ * @tests AbstractSelector#begin/end()
+ */
+ public void test_begin_end() throws IOException {
+ MockAbstractSelector mockSelector = new MockAbstractSelector(
+ SelectorProvider.provider());
+ try {
+ mockSelector.superBegin();
+ } finally {
+ mockSelector.superEnd();
+ }
+
+ mockSelector = new MockAbstractSelector(SelectorProvider.provider());
+ try {
+ mockSelector.superBegin();
+ mockSelector.close();
+ } finally {
+ mockSelector.superEnd();
+ }
+
+ try {
+ // begin twice
+ mockSelector.superBegin();
+ mockSelector.superBegin();
+ } finally {
+ mockSelector.superEnd();
+ }
+
+ try {
+ mockSelector.superBegin();
+ } finally {
+ // end twice
+ mockSelector.superEnd();
+ mockSelector.superEnd();
+ }
+
+ mockSelector.close();
+ try {
+ mockSelector.superBegin();
+ } finally {
+ mockSelector.superEnd();
+ }
+ }
+
+ /**
+ * @tests AbstractSelector#isOpen()
+ */
+ public void test_isOpen() throws Exception {
+ Selector acceptSelector = SelectorProvider.provider().openSelector();
+ assertTrue(acceptSelector.isOpen());
+ acceptSelector.close();
+ assertFalse(acceptSelector.isOpen());
+ }
+
+ /**
+ * @tests AbstractSelector#register(Selector,int)
+ */
+ public void test_register_LSelectorI() throws Exception {
+ Selector acceptSelector = SelectorProvider.provider().openSelector();
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.configureBlocking(false);
+
+ assertFalse(ssc.isRegistered());
+ SelectionKey acceptKey = ssc.register(acceptSelector,
+ SelectionKey.OP_ACCEPT);
+ assertTrue(ssc.isRegistered());
+ assertNotNull(acceptKey);
+ assertTrue(acceptSelector.keys().contains(acceptKey));
+ }
+
+ /**
+ * @tests AbstractSelector#register(Selector,int)
+ */
+ public void test_register_LSelectorI_error() throws IOException {
+ Selector acceptSelector = SelectorProvider.provider().openSelector();
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.configureBlocking(false);
+ acceptSelector.close();
+
+ assertFalse(acceptSelector.isOpen());
+ try {
+ ssc.register(acceptSelector, SelectionKey.OP_ACCEPT);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ assertFalse(ssc.isRegistered());
+
+ acceptSelector = Selector.open();
+ ssc.configureBlocking(true);
+ try {
+ ssc.register(acceptSelector, SelectionKey.OP_ACCEPT);
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ assertFalse(ssc.isRegistered());
+ ssc.configureBlocking(false);
+ SelectionKey acceptKey = ssc.register(acceptSelector,
+ SelectionKey.OP_ACCEPT);
+ assertNotNull(acceptKey);
+ assertTrue(acceptSelector.keys().contains(acceptKey));
+ assertTrue(ssc.isRegistered());
+ }
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AllTests.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AllTests.java
new file mode 100644
index 0000000..4febb4b
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AllTests.java
@@ -0,0 +1,37 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels.spi;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(
+ "Test for tests.api.java.nio.channels.spi");
+ //$JUnit-BEGIN$
+ suite.addTestSuite(AbstractInterruptibleChannelTest.class);
+ suite.addTestSuite(AbstractSelectorTest.class);
+ suite.addTestSuite(AbstractSelectableChannelTest.class);
+ suite.addTestSuite(SelectorProviderTest.class);
+ suite.addTestSuite(AbstractSelectionKeyTest.class);
+ //$JUnit-END$
+ return suite;
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/MockAbstractSelector.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/MockAbstractSelector.java
new file mode 100644
index 0000000..eb6e53f
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/MockAbstractSelector.java
@@ -0,0 +1,89 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.AbstractSelectionKey;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Set;
+
+public class MockAbstractSelector extends AbstractSelector {
+
+ public boolean isImplCloseSelectorCalled = false;
+
+ public MockAbstractSelector(SelectorProvider arg0) {
+ super(arg0);
+ }
+
+ public static MockAbstractSelector openSelector() {
+ return new MockAbstractSelector(SelectorProvider.provider());
+ }
+
+ public Set getCancelledKeys() {
+ return super.cancelledKeys();
+ }
+
+ protected void implCloseSelector() throws IOException {
+ isImplCloseSelectorCalled = true;
+ }
+
+ protected SelectionKey register(AbstractSelectableChannel arg0, int arg1,
+ Object arg2) {
+ return null;
+ }
+
+ public void superBegin() {
+ super.begin();
+ }
+
+ public void superEnd() {
+ super.end();
+ }
+
+ protected void mockDeregister(AbstractSelectionKey key) {
+ super.deregister(key);
+ }
+
+ public Set<SelectionKey> keys() {
+ return null;
+ }
+
+ public Set<SelectionKey> selectedKeys() {
+ return null;
+ }
+
+ public int selectNow() throws IOException {
+ return 0;
+ }
+
+ public int select(long arg0) throws IOException {
+ return 0;
+ }
+
+ public int select() throws IOException {
+ return 0;
+ }
+
+ public Selector wakeup() {
+ return null;
+ }
+
+}
diff --git a/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/SelectorProviderTest.java b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/SelectorProviderTest.java
new file mode 100644
index 0000000..305e9e2
--- /dev/null
+++ b/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/SelectorProviderTest.java
@@ -0,0 +1,115 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.nio.tests.java.nio.channels.spi;
+
+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;
+import java.security.Permission;
+
+import junit.framework.TestCase;
+
+public class SelectorProviderTest extends TestCase {
+
+ /**
+ * @tests SelectorProvider#provider() using security manager
+ */
+ public void test_provider_security() {
+ SecurityManager originalSecuirtyManager = System.getSecurityManager();
+ System.setSecurityManager(new MockSelectorProviderSecurityManager());
+ try {
+ new MockSelectorProvider();
+ fail("should throw SecurityException");
+ } catch (SecurityException e) {
+ // expected
+ } finally {
+ System.setSecurityManager(originalSecuirtyManager);
+ }
+ }
+
+ /**
+ * @tests SelectorProvider#provider() using security manager
+ */
+ public void test_provider_security_twice() {
+ SelectorProvider.provider();
+ SecurityManager originalSecuirtyManager = System.getSecurityManager();
+ System.setSecurityManager(new MockSelectorProviderSecurityManager());
+ try {
+ // should not throw SecurityException since it has been initialized
+ // in the beginning of this method.
+ SelectorProvider testProvider = SelectorProvider.provider();
+ assertNotNull(testProvider);
+ } finally {
+ System.setSecurityManager(originalSecuirtyManager);
+ }
+ }
+
+ private static class MockSelectorProviderSecurityManager extends
+ SecurityManager {
+
+ public MockSelectorProviderSecurityManager() {
+ super();
+ }
+
+ public void checkPermission(Permission perm) {
+ if (perm instanceof RuntimePermission) {
+ if ("selectorProvider".equals(perm.getName())) {
+ throw new SecurityException();
+ }
+ }
+ }
+
+ public void checkPermission(Permission perm, Object context) {
+ if (perm instanceof RuntimePermission) {
+ if ("selectorProvider".equals(perm.getName())) {
+ throw new SecurityException();
+ }
+ }
+ }
+ }
+
+ private class MockSelectorProvider extends SelectorProvider {
+
+ public MockSelectorProvider() {
+ super();
+ }
+
+ public DatagramChannel openDatagramChannel() throws IOException {
+ return null;
+ }
+
+ public Pipe openPipe() throws IOException {
+ return null;
+ }
+
+ public AbstractSelector openSelector() throws IOException {
+ return MockAbstractSelector.openSelector();
+ }
+
+ public ServerSocketChannel openServerSocketChannel() throws IOException {
+ return null;
+ }
+
+ public SocketChannel openSocketChannel() throws IOException {
+ return null;
+ }
+ }
+} \ No newline at end of file
diff --git a/nio/src/test/java/tests/nio/AllTests.java b/nio/src/test/java/tests/nio/AllTests.java
new file mode 100644
index 0000000..1abe67a
--- /dev/null
+++ b/nio/src/test/java/tests/nio/AllTests.java
@@ -0,0 +1,40 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.nio;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes all tests for the Math project.
+ */
+public class AllTests {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(AllTests.suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite("All Math test suites");
+ // $JUnit-BEGIN$
+ suite.addTest(org.apache.harmony.nio.tests.java.nio.AllTests.suite());
+ suite.addTest(org.apache.harmony.nio.tests.java.nio.channels.AllTests.suite());
+ suite.addTest(org.apache.harmony.nio.tests.java.nio.channels.spi.AllTests.suite());
+ // $JUnit-END$
+ return suite;
+ }
+}
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.golden.ser
new file mode 100644
index 0000000..80e8f7c
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.golden.ser
new file mode 100644
index 0000000..2e0fc6d
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.golden.ser
new file mode 100644
index 0000000..c29debf
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.golden.ser
new file mode 100644
index 0000000..fbbc876
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.golden.ser
new file mode 100644
index 0000000..9bd539c
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.golden.ser
new file mode 100644
index 0000000..6dbac7d
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.golden.ser
new file mode 100644
index 0000000..40288df
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.golden.ser
new file mode 100644
index 0000000..1f1e73b
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.golden.ser
new file mode 100644
index 0000000..ea5b80a
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.golden.ser
new file mode 100644
index 0000000..1831746
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.golden.ser
new file mode 100644
index 0000000..9e17263
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.golden.ser
new file mode 100644
index 0000000..4024191
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.golden.ser
new file mode 100644
index 0000000..c15c66b
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.golden.ser
new file mode 100644
index 0000000..89ed091
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.golden.ser
new file mode 100644
index 0000000..022d3bc
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.golden.ser
new file mode 100644
index 0000000..5cf767c
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.golden.ser
new file mode 100644
index 0000000..34a42e9
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.golden.ser
new file mode 100644
index 0000000..69d1a57
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.golden.ser
new file mode 100644
index 0000000..b5cc027
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.golden.ser
new file mode 100644
index 0000000..9c0e175
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.golden.ser
new file mode 100644
index 0000000..2a24deb
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.golden.ser
Binary files differ
diff --git a/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.golden.ser b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.golden.ser
new file mode 100644
index 0000000..1dd6a01
--- /dev/null
+++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.golden.ser
Binary files differ