001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.io;
028:
029: import java.io.*;
030:
031: /**
032: * This class adds read buffering to the
033: * <code>ConnectionBaseAdapter</code>.
034: * <p>
035: * Implements {@link InputStream#available()}, however a subclass must
036: * specify a buffer size greater than 0 and override
037: * {@link #readBytesNonBlocking(byte[], int, int)} in order to for available
038: * to work properly.
039: */
040: public abstract class BufferedConnectionAdapter extends
041: ConnectionBaseAdapter {
042:
043: /**
044: * The end of file flag.
045: */
046: protected boolean eof;
047:
048: /**
049: * The internal buffer array where the data is stored.
050: * When necessary, it may be replaced by another array
051: * of a different size.
052: */
053: protected byte buf[];
054:
055: /**
056: * The index one greater than the index of the last valid
057: * byte in the buffer.
058: * This value is always in the range
059: * <code>0</code> through <code>buf.length</code>;
060: * elements <code>buf[0]</code> through <code>buf[count-1]
061: * </code>contain buffered input data obtained
062: * from the underlying input stream.
063: */
064: protected int count;
065:
066: /**
067: * The current position in the buffer. This is the index
068: * of the next character to be read from the
069: * <code>buf</code> array.
070: * <p>
071: * This value is always in the range <code>0</code>
072: * through <code>count</code>. If it is less
073: * than <code>count</code>, then <code>buf[pos]</code>
074: * is the next byte to be supplied as input;
075: * if it is equal to <code>count</code>, then
076: * the next <code>read</code> or <code>skip</code>
077: * operation will require more bytes to be
078: * read from the contained input stream.
079: */
080: protected int pos;
081:
082: /**
083: * Initializes the connection.
084: *
085: * @param sizeOfBuffer size of the internal buffer or 0 for no buffer
086: */
087: protected BufferedConnectionAdapter(int sizeOfBuffer) {
088: if (sizeOfBuffer > 0) {
089: buf = new byte[sizeOfBuffer];
090: }
091: }
092:
093: /**
094: * Reads up to <code>len</code> bytes of data from the input stream into
095: * an array of bytes, blocks until at least one byte is available.
096: * <p>
097: * Do not use this method if <code>openInputStream</code> has been called
098: * since the input stream may be buffering data.
099: *
100: * @param b the buffer into which the data is read.
101: * @param off the start offset in array <code>b</code>
102: * at which the data is written.
103: * @param len the maximum number of bytes to read.
104: * @return the total number of bytes read into the buffer, or
105: * <code>-1</code> if there is no more data because the end of
106: * the stream has been reached.
107: * @exception IOException if an I/O error occurs.
108: */
109: public int readBytes(byte b[], int off, int len) throws IOException {
110: int bytesRead;
111:
112: if (count == 0) {
113: if (eof) {
114: return -1;
115: }
116:
117: if (buf == null || len >= buf.length) {
118: return nonBufferedRead(b, off, len);
119: } else {
120: int res = nonBufferedRead(buf, 0, buf.length);
121:
122: pos = 0;
123:
124: if (res <= 0) {
125: return res;
126: } else {
127: count = res;
128: }
129: }
130: }
131:
132: if (len > count) {
133: len = count;
134: }
135:
136: System.arraycopy(buf, pos, b, off, len);
137: count -= len;
138: pos += len;
139: return len;
140: };
141:
142: /**
143: * Reads up to <code>len</code> bytes of data from the input stream into
144: * an array of bytes, but does not block if no bytes available. A subclass
145: * should implement this to so the available method on the InputStream
146: * will be useful.
147: * Sets the <code>eof</code> field of the connection when the native read
148: * returns -1.
149: * <p>
150: * The <code>readBytesNonBlocking</code> method of
151: * <code>ConnectionBaseAdapter</code> does nothing and returns 0.
152: *
153: * @param b the buffer into which the data is read.
154: * @param off the start offset in array <code>b</code>
155: * at which the data is written.
156: * @param len the maximum number of bytes to read.
157: * @return the total number of bytes read into the buffer, or
158: * <code>-1</code> if there is no more data because the end of
159: * the stream has been reached.
160: * @exception IOException if an I/O error occurs.
161: */
162: protected int readBytesNonBlocking(byte b[], int off, int len)
163: throws IOException {
164: return 0;
165: }
166:
167: /**
168: * Returns the number of bytes that can be read (or skipped over) from
169: * this input stream without blocking by the next caller of a method for
170: * this input stream. The next caller might be the same thread or
171: * another thread.
172: *
173: * <p>The <code>available</code> method always returns <code>0</code> if
174: * {@link #readBytesNonBlocking(byte[], int, int)} is
175: * not overridden by the subclass or there is not buffer.
176: *
177: * @return the number of bytes that can be read from this input stream
178: * without blocking.
179: * @exception IOException if an I/O error occurs.
180: */
181: public int available() throws IOException {
182: int bytesRead;
183:
184: if (buf == null) {
185: return 0;
186: }
187:
188: if (count > 0) {
189: return count;
190: }
191:
192: bytesRead = readBytesNonBlocking(buf, 0, buf.length);
193:
194: if (bytesRead == -1) {
195: return 0;
196: }
197:
198: /*
199: * Reset the current buffer position and count of bytes
200: * available. These variables must be reset to match
201: * the processing in readBytes.
202: */
203: pos = 0;
204: count = bytesRead;
205:
206: return count;
207: }
208:
209: /**
210: * Reads up to <code>len</code> bytes of data from the input stream into
211: * an array of bytes, blocks until at least one byte is available.
212: * Sets the <code>eof</code> field of the connection when there is
213: * no more data in the stream to read.
214: *
215: * @param b the buffer into which the data is read.
216: * @param off the start offset in array <code>b</code>
217: * at which the data is written.
218: * @param len the maximum number of bytes to read.
219: * @return the total number of bytes read into the buffer, or
220: * <code>-1</code> if there is no more data because the end of
221: * the stream has been reached.
222: * @exception IOException if an I/O error occurs.
223: */
224: protected abstract int nonBufferedRead(byte b[], int off, int len)
225: throws IOException;
226: }
|