You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by gh...@apache.org on 2006/04/28 17:38:02 UTC

svn commit: r397925 - in /incubator/harmony/enhanced/classlib/trunk/modules/nio/src: main/java/java/nio/channels/ main/java/org/apache/harmony/nio/internal/ test/java/org/apache/harmony/tests/java/nio/channels/

Author: gharley
Date: Fri Apr 28 08:38:01 2006
New Revision: 397925

URL: http://svn.apache.org/viewcvs?rev=397925&view=rev
Log:
HARMONY 41 : NIO - java.nio.channels.spi and java.nio.channels.Channels, Pipe, Selector have not been implemented

Added:
    incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java   (with props)
    incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/ChannelsTest.java   (with props)
Modified:
    incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/Channels.java
    incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/AllTests.java

Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/Channels.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/Channels.java?rev=397925&r1=397924&r2=397925&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/Channels.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/java/nio/channels/Channels.java Fri Apr 28 08:38:01 2006
@@ -1,4 +1,4 @@
-/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -12,94 +12,514 @@
  * 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.luni.util.NotYetImplementedException;
+import org.apache.harmony.nio.internal.IOUtil;
 
 /**
- * Provides convenience methods to java.io package streams.
+ * This class provides several utilities to get I/O streams from channels.
  * 
  */
 public final class Channels {
 
-	/*
-	 * Not intended to be instantiated. 
-	 */
-	private Channels() {
-		super();
-	}
-
-	/**
-	 * Answers 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) {
-		// TODO
-		throw new NotYetImplementedException();
-	}
-
-	/**
-	 * Answers 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) {
-		// TODO
-		throw new NotYetImplementedException();
-	}
-
-	/**
-	 * Answers 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) {
-		//TODO
-		throw new NotYetImplementedException();
-	}
-
-	/**
-	 * Answers 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) {
-		//TODO
-		throw new NotYetImplementedException();
-	}
-
-	public static Reader newReader(ReadableByteChannel channel,
-			CharsetDecoder decoder, int minBufferCapacity) {
-		//TODO
-		throw new NotYetImplementedException();
-	}
-
-	public static Reader newReader(ReadableByteChannel channel,
-			String charsetName) {
-		return newReader(channel, Charset.forName(charsetName).newDecoder(), -1);
-	}
-
-	public static Writer newWriter(WritableByteChannel channel,
-			CharsetEncoder encoder, int minBufferCapacity) {
-		// TODO
-		throw new NotYetImplementedException();
-	}
-
-	public static Writer newWriter(WritableByteChannel channel,
-			String charsetName) {
-		return newWriter(channel, Charset.forName(charsetName).newEncoder(), -1);
-	}
+    // -------------------------------------------------------------------
+    // Constructor
+    // -------------------------------------------------------------------
+    /*
+     * Not intended to be instantiated.
+     */
+    private Channels() {
+        super();
+    }
+
+    // -------------------------------------------------------------------
+    // Public Methods
+    // -------------------------------------------------------------------
+
+    /**
+     * Answers 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);
+    }
+
+    /**
+     * Answers 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);
+    }
+
+    /**
+     * Answers 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);
+    }
+
+    /**
+     * Answers 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);
+    }
+
+    /**
+     * Answers 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 ReadableByteChannelInputStream(channel), decoder,
+                minBufferCapacity);
+    }
+
+    /**
+     * Answers 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);
+    }
+
+    /**
+     * Answers 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);
+    }
+
+    /**
+     * Answers 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
+    // -------------------------------------------------------------------
+
+    /*
+     * Wrapper class used for newInputStream(ReadableByteChannel channel)
+     */
+    private static class ReadableByteChannelInputStream extends InputStream {
+
+        private ReadableByteChannel channel;
+
+        /*
+         * @param someChannel
+         */
+        public ReadableByteChannelInputStream(ReadableByteChannel aChannel) {
+            super();
+            channel = aChannel;
+        }
+
+        /*
+         * @see java.io.InputStream#read()
+         */
+        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#read(byte[], int, int)
+         */
+        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);
+
+        }
+
+        /*
+         * @see java.io.InputStream#close()
+         */
+        public synchronized void close() throws IOException {
+            channel.close();
+        }
+    }
+
+    /*
+     * 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);
+        }
+    }
+
 }

Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java?rev=397925&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java Fri Apr 28 08:38:01 2006
@@ -0,0 +1,236 @@
+/* Copyright 2005, 2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.nio.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+
+import org.apache.harmony.luni.util.Msg;
+
+
+/*
+ * Static methods for I/O util. Used by io package and nio package.
+ * 
+ */
+public final class IOUtil {
+
+	// -------------------------------------------------------------------
+	// Class variables
+	// -------------------------------------------------------------------
+
+	private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+	// -------------------------------------------------------------------
+	// Constructor
+	// -------------------------------------------------------------------
+
+	/*
+	 * No instance.
+	 */
+	private IOUtil() {
+		super();
+	}
+
+	// -------------------------------------------------------------------
+	// Routine methods.
+	// -------------------------------------------------------------------
+
+	/*
+	 * Read method for InputStreamReader and Channels.
+	 */
+	public static int readInputStreamReader(InputStream in, ByteBuffer bytes,
+			CharBuffer chars, CharsetDecoder decoder, Object lock)
+			throws IOException {
+		synchronized (lock) {
+			if (in != null) {
+				if (chars.limit() == chars.position()) {
+					fillBuf(in, bytes, chars, decoder);
+				}
+				if (chars.limit() == 0) {
+					return -1;
+				}
+				return chars.get();
+			}
+			throw new IOException(Msg.getString("K0070")); //$NON-NLS-1$
+		}
+	}
+
+	/*
+	 * Read method for InputStreamReader and Channels.
+	 */
+	public static int readInputStreamReader(char[] buf, int offset, int length,
+			InputStream in, ByteBuffer bytes, CharBuffer chars,
+			CharsetDecoder decoder, Object lock) throws IOException {
+		synchronized (lock) {
+			if (in != null) {
+				if (length == 0) {
+					return 0;
+				}
+				if (offset < 0 || length < 0 || offset + length > buf.length) {
+					throw new IndexOutOfBoundsException();
+				}
+				// read at least once
+				if (chars.limit() == chars.position()) {
+					fillBuf(in, bytes, chars, decoder);
+				}
+				int position = chars.position();
+				int availableChars = chars.limit() - position;
+				// read at least once for one byte
+				int needChars = length;
+				while (availableChars < needChars) {
+					System.arraycopy(chars.array(), position, buf, offset,
+							availableChars);
+					chars.position(position + availableChars);
+					needChars -= availableChars;
+					offset += availableChars;
+					if (in.available() <= 0) {
+						return needChars == length ? -1 : length - needChars;
+					}
+					fillBuf(in, bytes, chars, decoder);
+					position = chars.position();
+					availableChars = chars.limit();
+					if (availableChars == 0) {
+						return needChars == length ? -1 : length - needChars;
+					}
+				}
+				System.arraycopy(chars.array(), position, buf, offset,
+						needChars);
+				chars.position(chars.position() + needChars);
+				return length;
+			}
+            throw new IOException(Msg.getString("K0070")); //$NON-NLS-1$
+		}
+	}
+
+	/*
+	 * refill the buffer from wrapped InputStream
+	 */
+	private static void fillBuf(InputStream in, ByteBuffer bytes,
+			CharBuffer chars, CharsetDecoder decoder) throws IOException {
+		chars.clear();
+		int read = 0;
+		try {
+			read = in.read(bytes.array());
+		} catch (IOException e) {
+			chars.limit(0);
+			throw e;
+		}
+		if (read == -1) {
+			chars.limit(0);
+			return;
+		}
+		bytes.limit(read);
+		boolean endOfInput = read < DEFAULT_BUFFER_SIZE;
+		CoderResult result = decoder.decode(bytes, chars, endOfInput);
+		if (result.isError()) {
+			throw new IOException(result.toString());
+		}
+		bytes.clear();
+		chars.flip();
+	}
+
+	/*
+	 * Write method for OutputStreamWriter and Channels.
+	 */
+	public static void writeOutputStreamWriter(String str, int offset,
+			int count, OutputStream out, ByteBuffer bytes,
+			CharsetEncoder encoder, Object lock) throws IOException {
+		// avoid int overflow
+		if (offset < 0 || count < 0 || offset + count > str.length()) {
+			throw new StringIndexOutOfBoundsException();
+		}
+		CharBuffer chars = CharBuffer.wrap(str, offset, count + offset);
+		convert(lock, encoder, bytes, chars, out);
+	}
+
+	/*
+	 * Write method for OutputStreamWriter and Channels.
+	 */
+	public static void writeOutputStreamWriter(int oneChar, OutputStream out,
+			ByteBuffer bytes, CharsetEncoder encoder, Object lock)
+			throws IOException {
+		synchronized (lock) {
+			if (encoder == null) {
+                throw new IOException(Msg.getString("K005d")); //$NON-NLS-1$
+			}
+			CharBuffer chars = CharBuffer.wrap(new char[] { (char) oneChar });
+			convert(lock, encoder, bytes, chars, out);
+		}
+	}
+
+	/*
+	 * Write method for OutputStreamWriter and Channels.
+	 */
+	public static void writeOutputStreamWriter(char[] buf, int offset,
+			int count, OutputStream out, ByteBuffer bytes,
+			CharsetEncoder encoder, Object lock) throws IOException {
+		if (offset < 0 || count < 0 || offset + count > buf.length) {
+			throw new ArrayIndexOutOfBoundsException();
+		}
+		CharBuffer chars = CharBuffer.wrap(buf, offset, count);
+		convert(lock, encoder, bytes, chars, out);
+	}
+
+	/*
+	 * Flush method for OutputStreamWriter and Channels.
+	 */
+	public static void flushOutputStreamWriter(OutputStream out,
+			ByteBuffer bytes, CharsetEncoder encoder, Object lock)
+			throws IOException {
+		synchronized (lock) {
+			if (encoder == null) {
+                throw new IOException(Msg.getString("K005d")); //$NON-NLS-1$
+			}
+			int position;
+			if ((position = bytes.position()) > 0) {
+				bytes.flip();
+				out.write(bytes.array(), 0, position);
+				bytes.clear();
+			}
+			out.flush();
+		}
+	}
+
+    /*
+	 * convert function used in write.
+	 */
+	private static void convert(Object lock, CharsetEncoder encoder,
+			ByteBuffer bytes, CharBuffer chars, OutputStream out)
+			throws IOException {
+		synchronized (lock) {
+			if (encoder == null) {
+                throw new IOException(Msg.getString("K005d")); //$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;
+			}
+		}
+	}
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/main/java/org/apache/harmony/nio/internal/IOUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/AllTests.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/AllTests.java?rev=397925&r1=397924&r2=397925&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/AllTests.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/AllTests.java Fri Apr 28 08:38:01 2006
@@ -29,6 +29,7 @@
 		suite.addTestSuite(FileChannelTest.class);
 		suite.addTestSuite(FileChannelLockingTest.class);
 		suite.addTestSuite(DatagramChannelTest.class);
+        suite.addTestSuite(ChannelsTest.class);
 		//$JUnit-END$
 		return suite;
 	}

Added: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/ChannelsTest.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/ChannelsTest.java?rev=397925&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/ChannelsTest.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/ChannelsTest.java Fri Apr 28 08:38:01 2006
@@ -0,0 +1,639 @@
+/* Copyright 2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.harmony.tests.java.nio.channels;
+
+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.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+
+import junit.framework.TestCase;
+
+/**
+ * Note: the test case uses a txt file named "test.txt" which contains 31
+ * charactors : "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 static final String TEST_FILE = "test.txt"; //$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
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        // Make the test file same in every test
+        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;
+        }
+
+        // this.writeFileSame();
+        super.tearDown();
+
+    }
+
+    private void writeFileSame() throws IOException {
+        this.fouts = new FileOutputStream(TEST_FILE);
+        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(String FileName, int compareNumber)
+            throws IOException {
+        FileInputStream file = new FileInputStream(FileName);
+        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(TEST_FILE);
+        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(TEST_FILE);
+        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(TEST_FILE);
+        } 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(TEST_FILE);
+        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(TEST_FILE);
+        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(TEST_FILE);
+        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(TEST_FILE);
+        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(TEST_FILE);
+        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(TEST_FILE, this.testNum);
+        writebc.write(writebcbuf);
+        this.assertFileSizeSame(TEST_FILE, this.testNum * 2);
+        testouts.write(writebuf);
+        this.assertFileSizeSame(TEST_FILE, 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(TEST_FILE);
+
+        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(TEST_FILE);
+        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(TEST_FILE);
+        // 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(TEST_FILE);
+        // 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(TEST_FILE);
+        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(TEST_FILE);
+        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(TEST_FILE);
+        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(TEST_FILE, 1);
+
+        // writer continues to write after '1',what the fouts write
+        testWriter.write(writebuf);
+        testWriter.flush();
+        this.assertFileSizeSame(TEST_FILE, this.writebufSize / 2 + 1);
+        // testwriter_s does not know if testwrite writes
+        testWriter_s.write(writebuf);
+        testWriter.flush();
+        this.assertFileSizeSame(TEST_FILE, this.writebufSize / 2 + 1);
+        // testwriter_s even does not know if himself writes?
+        testWriter_s.write(writebuf);
+        testWriter.flush();
+        this.assertFileSizeSame(TEST_FILE, 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(TEST_FILE, this.writebufSize / 2 + 1);
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/nio/src/test/java/org/apache/harmony/tests/java/nio/channels/ChannelsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native