001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.nio.internal;
019:
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.io.OutputStream;
023: import java.nio.ByteBuffer;
024: import java.nio.CharBuffer;
025: import java.nio.charset.CharsetDecoder;
026: import java.nio.charset.CharsetEncoder;
027: import java.nio.charset.CoderResult;
028:
029: import org.apache.harmony.nio.Util;
030: import org.apache.harmony.nio.internal.nls.Messages;
031:
032: /**
033: * Static methods for I/O util. Used by io package and nio package.
034: */
035: public final class IOUtil {
036:
037: private static final int DEFAULT_BUFFER_SIZE = 8192;
038:
039: /*
040: * Not designed to be instantiated.
041: */
042: private IOUtil() {
043: super ();
044: }
045:
046: /*
047: * Read method for InputStreamReader and Channels.
048: */
049: public static int readInputStreamReader(InputStream in,
050: ByteBuffer bytes, CharBuffer chars, CharsetDecoder decoder,
051: Object lock) throws IOException {
052: synchronized (lock) {
053: if (in != null) {
054: if (chars.limit() == chars.position()) {
055: fillBuf(in, bytes, chars, decoder);
056: }
057: if (chars.limit() == 0) {
058: return -1;
059: }
060: return chars.get();
061: }
062: // nio.06=InputStreamReader is closed.
063: throw new IOException(Messages.getString("nio.06")); //$NON-NLS-1$
064: }
065: }
066:
067: /*
068: * Read method for InputStreamReader and Channels.
069: */
070: public static int readInputStreamReader(char[] buf, int offset,
071: int length, InputStream in, ByteBuffer bytes,
072: CharBuffer chars, CharsetDecoder decoder, Object lock)
073: throws IOException {
074: synchronized (lock) {
075: if (in != null) {
076: if (length == 0) {
077: return 0;
078: }
079: Util.assertArrayIndex(buf, offset, length);
080: // read at least once
081: if (chars.limit() == chars.position()) {
082: fillBuf(in, bytes, chars, decoder);
083: }
084: int position = chars.position();
085: int availableChars = chars.limit() - position;
086: // read at least once for one byte
087: int needChars = length;
088: while (availableChars < needChars) {
089: System.arraycopy(chars.array(), position, buf,
090: offset, availableChars);
091: chars.position(position + availableChars);
092: needChars -= availableChars;
093: offset += availableChars;
094: if (in.available() <= 0) {
095: return needChars == length ? -1 : length
096: - needChars;
097: }
098: fillBuf(in, bytes, chars, decoder);
099: position = chars.position();
100: availableChars = chars.limit();
101: if (availableChars == 0) {
102: return needChars == length ? -1 : length
103: - needChars;
104: }
105: }
106: System.arraycopy(chars.array(), position, buf, offset,
107: needChars);
108: chars.position(chars.position() + needChars);
109: return length;
110: }
111: // nio.06=InputStreamReader is closed.
112: throw new IOException(Messages.getString("nio.06")); //$NON-NLS-1$
113: }
114: }
115:
116: /*
117: * Refill the buffer from wrapped InputStream.
118: */
119: private static void fillBuf(InputStream in, ByteBuffer bytes,
120: CharBuffer chars, CharsetDecoder decoder)
121: throws IOException {
122: chars.clear();
123: int read = 0;
124: try {
125: read = in.read(bytes.array());
126: } catch (IOException e) {
127: chars.limit(0);
128: throw e;
129: }
130: if (read == -1) {
131: chars.limit(0);
132: return;
133: }
134: bytes.limit(read);
135: boolean endOfInput = read < DEFAULT_BUFFER_SIZE;
136: CoderResult result = decoder.decode(bytes, chars, endOfInput);
137: if (result.isError()) {
138: throw new IOException(result.toString());
139: }
140: bytes.clear();
141: chars.flip();
142: }
143:
144: /*
145: * Write method for OutputStreamWriter and Channels.
146: */
147: public static void writeOutputStreamWriter(String str, int offset,
148: int count, OutputStream out, ByteBuffer bytes,
149: CharsetEncoder encoder, Object lock) throws IOException {
150: Util.assertArrayIndex(str.length(), offset, count);
151: CharBuffer chars = CharBuffer.wrap(str, offset, count + offset);
152: convert(lock, encoder, bytes, chars, out);
153: }
154:
155: /*
156: * Write method for OutputStreamWriter and Channels.
157: */
158: public static void writeOutputStreamWriter(int oneChar,
159: OutputStream out, ByteBuffer bytes, CharsetEncoder encoder,
160: Object lock) throws IOException {
161: synchronized (lock) {
162: if (encoder == null) {
163: // nio.07=Writer is closed.
164: throw new IOException(Messages.getString("nio.07")); //$NON-NLS-1$
165: }
166: CharBuffer chars = CharBuffer
167: .wrap(new char[] { (char) oneChar });
168: convert(lock, encoder, bytes, chars, out);
169: }
170: }
171:
172: /*
173: * Write method for OutputStreamWriter and Channels.
174: */
175: public static void writeOutputStreamWriter(char[] buf, int offset,
176: int count, OutputStream out, ByteBuffer bytes,
177: CharsetEncoder encoder, Object lock) throws IOException {
178: Util.assertArrayIndex(buf, offset, count);
179: CharBuffer chars = CharBuffer.wrap(buf, offset, count);
180: convert(lock, encoder, bytes, chars, out);
181: }
182:
183: /*
184: * Flush method for OutputStreamWriter and Channels.
185: */
186: public static void flushOutputStreamWriter(OutputStream out,
187: ByteBuffer bytes, CharsetEncoder encoder, Object lock)
188: throws IOException {
189: synchronized (lock) {
190: if (encoder == null) {
191: // nio.07=Writer is closed.
192: throw new IOException(Messages.getString("nio.07")); //$NON-NLS-1$
193: }
194: int position;
195: if ((position = bytes.position()) > 0) {
196: bytes.flip();
197: out.write(bytes.array(), 0, position);
198: bytes.clear();
199: }
200: out.flush();
201: }
202: }
203:
204: /*
205: * Convert function used in write.
206: */
207: private static void convert(Object lock, CharsetEncoder encoder,
208: ByteBuffer bytes, CharBuffer chars, OutputStream out)
209: throws IOException {
210: synchronized (lock) {
211: if (encoder == null) {
212: // nio.07=Writer is closed.
213: throw new IOException(Messages.getString("nio.07")); //$NON-NLS-1$
214: }
215: CoderResult result = encoder.encode(chars, bytes, true);
216: while (true) {
217: if (result.isError()) {
218: throw new IOException(result.toString());
219: } else if (result.isOverflow()) {
220: // flush the output buffer
221: flushOutputStreamWriter(out, bytes, encoder, lock);
222: result = encoder.encode(chars, bytes, true);
223: continue;
224: }
225: break;
226: }
227: }
228: }
229: }
|