View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one or more
3    *  contributor license agreements.  See the NOTICE file distributed with
4    *  this work for additional information regarding copyright ownership.
5    *  The ASF licenses this file to You under the Apache License, Version 2.0
6    *  (the "License"); you may not use this file except in compliance with
7    *  the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.commons.io.input;
19  
20  import static org.apache.commons.io.IOUtils.EOF;
21  
22  import java.io.IOException;
23  import java.io.Reader;
24  
25  import org.apache.commons.io.IOUtils;
26  
27  /**
28   * A {@link Reader} without any of the superclass' synchronization.
29   *
30   * @since 2.17.0
31   */
32  public abstract class UnsynchronizedReader extends Reader {
33  
34      /**
35       * The maximum skip-buffer size.
36       */
37      private static final int MAX_SKIP_BUFFER_SIZE = IOUtils.DEFAULT_BUFFER_SIZE;
38  
39      /**
40       * Whether {@link #close()} completed successfully.
41       */
42      private boolean closed;
43  
44      /**
45       * The skip buffer, defaults to null until allocated in {@link UnsynchronizedReader#skip(long)}.
46       */
47      private char skipBuffer[];
48  
49      /**
50       * Constructs a new instance.
51       */
52      public UnsynchronizedReader() {
53          // empty
54      }
55  
56      /**
57       * Checks if this instance is closed and throws an IOException if so.
58       *
59       * @throws IOException if this instance is closed.
60       */
61      void checkOpen() throws IOException {
62          Input.checkOpen(!isClosed());
63      }
64  
65      @Override
66      public void close() throws IOException {
67          closed = true;
68      }
69  
70      /**
71       * Tests whether this instance is closed; if {@link #close()} completed successfully.
72       *
73       * @return whether this instance is closed.
74       */
75      public boolean isClosed() {
76          return closed;
77      }
78  
79      /**
80       * Sets whether this instance is closed.
81       *
82       * @param closed whether this instance is closed.
83       */
84      public void setClosed(final boolean closed) {
85          this.closed = closed;
86      }
87  
88      /**
89       * Skips characters by reading from this instance.
90       *
91       * This method will <em>block</em> until:
92       * <ul>
93       * <li>some characters are available,</li>
94       * <li>an I/O error occurs, or</li>
95       * <li>the end of the stream is reached.</li>
96       * </ul>
97       *
98       * @param n The number of characters to skip.
99       * @return The number of characters actually skipped.
100      * @throws IllegalArgumentException If {@code n} is negative.
101      * @throws IOException              If an I/O error occurs.
102      */
103     @Override
104     public long skip(final long n) throws IOException {
105         if (n < 0L) {
106             throw new IllegalArgumentException("skip value < 0");
107         }
108         final int bufSize = (int) Math.min(n, MAX_SKIP_BUFFER_SIZE);
109         if (skipBuffer == null || skipBuffer.length < bufSize) {
110             skipBuffer = new char[bufSize];
111         }
112         long remaining = n;
113         while (remaining > 0) {
114             final int countOrEof = read(skipBuffer, 0, (int) Math.min(remaining, bufSize));
115             if (countOrEof == EOF) {
116                 break;
117             }
118             remaining -= countOrEof;
119         }
120         return n - remaining;
121     }
122 }