1 /*
  2  * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.io;
 27 
 28 import java.nio.CharBuffer;
 29 import java.nio.ReadOnlyBufferException;
 30 import java.util.Objects;
 31 import jdk.internal.misc.InternalLock;
 32 
 33 /**
 34  * Abstract class for reading character streams.  The only methods that a
 35  * subclass must implement are read(char[], int, int) and close().  Most
 36  * subclasses, however, will override some of the methods defined here in order
 37  * to provide higher efficiency, additional functionality, or both.
 38  *
 39  *
 40  * @see BufferedReader
 41  * @see   LineNumberReader
 42  * @see CharArrayReader
 43  * @see InputStreamReader
 44  * @see   FileReader
 45  * @see FilterReader
 46  * @see   PushbackReader
 47  * @see PipedReader
 48  * @see StringReader
 49  * @see Writer
 50  *
 51  * @author      Mark Reinhold
 52  * @since       1.1
 53  */
 54 
 55 public abstract class Reader implements Readable, Closeable {
 56 
 57     private static final int TRANSFER_BUFFER_SIZE = 8192;
 58 
 59     /**
 60      * Returns a new {@code Reader} that reads no characters. The returned
 61      * stream is initially open.  The stream is closed by calling the
 62      * {@code close()} method.  Subsequent calls to {@code close()} have no
 63      * effect.
 64      *
 65      * <p> While the stream is open, the {@code read()}, {@code read(char[])},
 66      * {@code read(char[], int, int)}, {@code read(CharBuffer)}, {@code
 67      * ready()}, {@code skip(long)}, and {@code transferTo()} methods all
 68      * behave as if end of stream has been reached. After the stream has been
 69      * closed, these methods all throw {@code IOException}.
 70      *
 71      * <p> The {@code markSupported()} method returns {@code false}.  The
 72      * {@code mark()} and {@code reset()} methods throw an {@code IOException}.
 73      *
 74      * <p> The {@link #lock object} used to synchronize operations on the
 75      * returned {@code Reader} is not specified.
 76      *
 77      * @return a {@code Reader} which reads no characters
 78      *
 79      * @since 11
 80      */
 81     public static Reader nullReader() {
 82         return new Reader() {
 83             private volatile boolean closed;
 84 
 85             private void ensureOpen() throws IOException {
 86                 if (closed) {
 87                     throw new IOException("Stream closed");
 88                 }
 89             }
 90 
 91             @Override
 92             public int read() throws IOException {
 93                 ensureOpen();
 94                 return -1;
 95             }
 96 
 97             @Override
 98             public int read(char[] cbuf, int off, int len) throws IOException {
 99                 Objects.checkFromIndexSize(off, len, cbuf.length);
100                 ensureOpen();
101                 if (len == 0) {
102                     return 0;
103                 }
104                 return -1;
105             }
106 
107             @Override
108             public int read(CharBuffer target) throws IOException {
109                 Objects.requireNonNull(target);
110                 ensureOpen();
111                 if (target.hasRemaining()) {
112                     return -1;
113                 }
114                 return 0;
115             }
116 
117             @Override
118             public boolean ready() throws IOException {
119                 ensureOpen();
120                 return false;
121             }
122 
123             @Override
124             public long skip(long n) throws IOException {
125                 ensureOpen();
126                 return 0L;
127             }
128 
129             @Override
130             public long transferTo(Writer out) throws IOException {
131                 Objects.requireNonNull(out);
132                 ensureOpen();
133                 return 0L;
134             }
135 
136             @Override
137             public void close() {
138                 closed = true;
139             }
140         };
141     }
142 
143     /**
144      * The object used to synchronize operations on this stream.  For
145      * efficiency, a character-stream object may use an object other than
146      * itself to protect critical sections.  A subclass should therefore use
147      * the object in this field rather than {@code this} or a synchronized
148      * method.
149      */
150     protected Object lock;
151 
152     /**
153      * Creates a new character-stream reader whose critical sections will
154      * synchronize on the reader itself.
155      */
156     protected Reader() {
157         // use InternalLock for trusted classes
158         Class<?> clazz = getClass();
159         if (clazz == InputStreamReader.class
160             || clazz == BufferedReader.class
161             || clazz == FileReader.class
162             || clazz == sun.nio.cs.StreamDecoder.class) {
163             this.lock = new InternalLock();
164         } else {
165             this.lock = this;
166         }
167     }
168 
169     /**
170      * Creates a new character-stream reader whose critical sections will
171      * synchronize on the given object.
172      *
173      * @param lock  The Object to synchronize on.
174      */
175     protected Reader(Object lock) {
176         this.lock = Objects.requireNonNull(lock);
177     }
178 
179     /**
180      * Attempts to read characters into the specified character buffer.
181      * The buffer is used as a repository of characters as-is: the only
182      * changes made are the results of a put operation. No flipping or
183      * rewinding of the buffer is performed.
184      *
185      * @param target the buffer to read characters into
186      * @return The number of characters added to the buffer, or
187      *         -1 if this source of characters is at its end
188      * @throws IOException if an I/O error occurs
189      * @throws NullPointerException if target is null
190      * @throws java.nio.ReadOnlyBufferException if target is a read only buffer
191      * @since 1.5
192      */
193     public int read(CharBuffer target) throws IOException {
194         if (target.isReadOnly())
195             throw new ReadOnlyBufferException();
196 
197         int nread;
198         if (target.hasArray()) {
199             char[] cbuf = target.array();
200             int pos = target.position();
201             int rem = Math.max(target.limit() - pos, 0);
202             int off = target.arrayOffset() + pos;
203             nread = this.read(cbuf, off, rem);
204             if (nread > 0)
205                 target.position(pos + nread);
206         } else {
207             int len = target.remaining();
208             char[] cbuf = new char[len];
209             nread = read(cbuf, 0, len);
210             if (nread > 0)
211                 target.put(cbuf, 0, nread);
212         }
213         return nread;
214     }
215 
216     /**
217      * Reads a single character.  This method will block until a character is
218      * available, an I/O error occurs, or the end of the stream is reached.
219      *
220      * <p> Subclasses that intend to support efficient single-character input
221      * should override this method.
222      *
223      * @return     The character read, as an integer in the range 0 to 65535
224      *             ({@code 0x00-0xffff}), or -1 if the end of the stream has
225      *             been reached
226      *
227      * @throws     IOException  If an I/O error occurs
228      */
229     public int read() throws IOException {
230         char[] cb = new char[1];
231         if (read(cb, 0, 1) == -1)
232             return -1;
233         else
234             return cb[0];
235     }
236 
237     /**
238      * Reads characters into an array.  This method will block until some input
239      * is available, an I/O error occurs, or the end of the stream is reached.
240      *
241      * <p> If the length of {@code cbuf} is zero, then no characters are read
242      * and {@code 0} is returned; otherwise, there is an attempt to read at
243      * least one character.  If no character is available because the stream is
244      * at its end, the value {@code -1} is returned; otherwise, at least one
245      * character is read and stored into {@code cbuf}.
246      *
247      * @param       cbuf  Destination buffer
248      *
249      * @return      The number of characters read, or -1
250      *              if the end of the stream
251      *              has been reached
252      *
253      * @throws      IOException  If an I/O error occurs
254      */
255     public int read(char[] cbuf) throws IOException {
256         return read(cbuf, 0, cbuf.length);
257     }
258 
259     /**
260      * Reads characters into a portion of an array.  This method will block
261      * until some input is available, an I/O error occurs, or the end of the
262      * stream is reached.
263      *
264      * <p> If {@code len} is zero, then no characters are read and {@code 0} is
265      * returned; otherwise, there is an attempt to read at least one character.
266      * If no character is available because the stream is at its end, the value
267      * {@code -1} is returned; otherwise, at least one character is read and
268      * stored into {@code cbuf}.
269      *
270      * @param      cbuf  Destination buffer
271      * @param      off   Offset at which to start storing characters
272      * @param      len   Maximum number of characters to read
273      *
274      * @return     The number of characters read, or -1 if the end of the
275      *             stream has been reached
276      *
277      * @throws     IndexOutOfBoundsException
278      *             If {@code off} is negative, or {@code len} is negative,
279      *             or {@code len} is greater than {@code cbuf.length - off}
280      * @throws     IOException  If an I/O error occurs
281      */
282     public abstract int read(char[] cbuf, int off, int len) throws IOException;
283 
284     /** Maximum skip-buffer size */
285     private static final int maxSkipBufferSize = 8192;
286 
287     /** Skip buffer, null until allocated */
288     private char[] skipBuffer = null;
289 
290     /**
291      * Skips characters.  This method will block until some characters are
292      * available, an I/O error occurs, or the end of the stream is reached.
293      * If the stream is already at its end before this method is invoked,
294      * then no characters are skipped and zero is returned.
295      *
296      * @param  n  The number of characters to skip
297      *
298      * @return    The number of characters actually skipped
299      *
300      * @throws     IllegalArgumentException  If {@code n} is negative.
301      * @throws     IOException  If an I/O error occurs
302      */
303     public long skip(long n) throws IOException {
304         if (n < 0L)
305             throw new IllegalArgumentException("skip value is negative");
306         Object lock = this.lock;
307         if (lock instanceof InternalLock locker) {
308             locker.lock();
309             try {
310                 return lockedSkip(n);
311             } finally {
312                 locker.unlock();
313             }
314         } else {
315             synchronized (lock) {
316                 return lockedSkip(n);
317             }
318         }
319     }
320 
321     private long lockedSkip(long n) throws IOException {
322         int nn = (int) Math.min(n, maxSkipBufferSize);
323         if ((skipBuffer == null) || (skipBuffer.length < nn))
324             skipBuffer = new char[nn];
325         long r = n;
326         while (r > 0) {
327             int nc = read(skipBuffer, 0, (int)Math.min(r, nn));
328             if (nc == -1)
329                 break;
330             r -= nc;
331         }
332         return n - r;
333     }
334 
335     /**
336      * Tells whether this stream is ready to be read.
337      *
338      * @return True if the next read() is guaranteed not to block for input,
339      * false otherwise.  Note that returning false does not guarantee that the
340      * next read will block.
341      *
342      * @throws     IOException  If an I/O error occurs
343      */
344     public boolean ready() throws IOException {
345         return false;
346     }
347 
348     /**
349      * Tells whether this stream supports the mark() operation. The default
350      * implementation always returns false. Subclasses should override this
351      * method.
352      *
353      * @return true if and only if this stream supports the mark operation.
354      */
355     public boolean markSupported() {
356         return false;
357     }
358 
359     /**
360      * Marks the present position in the stream.  Subsequent calls to reset()
361      * will attempt to reposition the stream to this point.  Not all
362      * character-input streams support the mark() operation.
363      *
364      * @param  readAheadLimit  Limit on the number of characters that may be
365      *                         read while still preserving the mark.  After
366      *                         reading this many characters, attempting to
367      *                         reset the stream may fail.
368      *
369      * @throws     IOException  If the stream does not support mark(),
370      *                          or if some other I/O error occurs
371      */
372     public void mark(int readAheadLimit) throws IOException {
373         throw new IOException("mark() not supported");
374     }
375 
376     /**
377      * Resets the stream.  If the stream has been marked, then attempt to
378      * reposition it at the mark.  If the stream has not been marked, then
379      * attempt to reset it in some way appropriate to the particular stream,
380      * for example by repositioning it to its starting point.  Not all
381      * character-input streams support the reset() operation, and some support
382      * reset() without supporting mark().
383      *
384      * @throws     IOException  If the stream has not been marked,
385      *                          or if the mark has been invalidated,
386      *                          or if the stream does not support reset(),
387      *                          or if some other I/O error occurs
388      */
389     public void reset() throws IOException {
390         throw new IOException("reset() not supported");
391     }
392 
393     /**
394      * Closes the stream and releases any system resources associated with
395      * it.  Once the stream has been closed, further read(), ready(),
396      * mark(), reset(), or skip() invocations will throw an IOException.
397      * Closing a previously closed stream has no effect.
398      *
399      * @throws     IOException  If an I/O error occurs
400      */
401      public abstract void close() throws IOException;
402 
403     /**
404      * Reads all characters from this reader and writes the characters to the
405      * given writer in the order that they are read. On return, this reader
406      * will be at end of the stream. This method does not close either reader
407      * or writer.
408      * <p>
409      * This method may block indefinitely reading from the reader, or
410      * writing to the writer. The behavior for the case where the reader
411      * and/or writer is <i>asynchronously closed</i>, or the thread
412      * interrupted during the transfer, is highly reader and writer
413      * specific, and therefore not specified.
414      * <p>
415      * If an I/O error occurs reading from the reader or writing to the
416      * writer, then it may do so after some characters have been read or
417      * written. Consequently the reader may not be at end of the stream and
418      * one, or both, streams may be in an inconsistent state. It is strongly
419      * recommended that both streams be promptly closed if an I/O error occurs.
420      *
421      * @param  out the writer, non-null
422      * @return the number of characters transferred
423      * @throws IOException if an I/O error occurs when reading or writing
424      * @throws NullPointerException if {@code out} is {@code null}
425      *
426      * @since 10
427      */
428     public long transferTo(Writer out) throws IOException {
429         Objects.requireNonNull(out, "out");
430         long transferred = 0;
431         char[] buffer = new char[TRANSFER_BUFFER_SIZE];
432         int nRead;
433         while ((nRead = read(buffer, 0, TRANSFER_BUFFER_SIZE)) >= 0) {
434             out.write(buffer, 0, nRead);
435             transferred += nRead;
436         }
437         return transferred;
438     }
439 
440 }