diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
commit | fdb2704414a9ed92394ada0d1395e4db86889465 (patch) | |
tree | 9b591a4a50054274a197f02b3ccb51313681879f /nio | |
download | libcore-fdb2704414a9ed92394ada0d1395e4db86889465.zip libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.gz libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.bz2 |
Initial Contribution
Diffstat (limited to 'nio')
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 < 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 Binary files differnew file mode 100644 index 0000000..80e8f7c --- /dev/null +++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.golden.ser 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 Binary files differnew file mode 100644 index 0000000..2e0fc6d --- /dev/null +++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.golden.ser 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 Binary files differnew file mode 100644 index 0000000..c29debf --- /dev/null +++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.golden.ser 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 Binary files differnew file mode 100644 index 0000000..fbbc876 --- /dev/null +++ b/nio/src/test/resources/serialization/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.golden.ser 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 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 Binary files differnew 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 |