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 18package java.io; 19 20/** 21 * Wraps an existing {@link Reader} and performs some transformation on the 22 * input data while it is being read. Transformations can be anything from a 23 * simple byte-wise filtering input data to an on-the-fly compression or 24 * decompression of the underlying reader. Readers that wrap another reader and 25 * provide some additional functionality on top of it usually inherit from this 26 * class. 27 * 28 * @see FilterWriter 29 */ 30public abstract class FilterReader extends Reader { 31 32 /** 33 * The target Reader which is being filtered. 34 */ 35 protected Reader in; 36 37 /** 38 * Constructs a new FilterReader on the Reader {@code in}. 39 * 40 * @param in 41 * The non-null Reader to filter reads on. 42 */ 43 protected FilterReader(Reader in) { 44 super(in); 45 this.in = in; 46 } 47 48 /** 49 * Closes this reader. This implementation closes the filtered reader. 50 * 51 * @throws IOException 52 * if an error occurs while closing this reader. 53 */ 54 @Override 55 public void close() throws IOException { 56 synchronized (lock) { 57 in.close(); 58 } 59 } 60 61 /** 62 * Sets a mark position in this reader. The parameter {@code readlimit} 63 * indicates how many bytes can be read before the mark is invalidated. 64 * Sending {@code reset()} will reposition this reader back to the marked 65 * position, provided that {@code readlimit} has not been surpassed. 66 * <p> 67 * This implementation sets a mark in the filtered reader. 68 * 69 * @param readlimit 70 * the number of bytes that can be read from this reader before 71 * the mark is invalidated. 72 * @throws IOException 73 * if an error occurs while marking this reader. 74 * @see #markSupported() 75 * @see #reset() 76 */ 77 @Override 78 public synchronized void mark(int readlimit) throws IOException { 79 synchronized (lock) { 80 in.mark(readlimit); 81 } 82 } 83 84 /** 85 * Indicates whether this reader supports {@code mark()} and {@code reset()}. 86 * This implementation returns whether the filtered reader supports marking. 87 * 88 * @return {@code true} if {@code mark()} and {@code reset()} are supported 89 * by the filtered reader, {@code false} otherwise. 90 * @see #mark(int) 91 * @see #reset() 92 * @see #skip(long) 93 */ 94 @Override 95 public boolean markSupported() { 96 synchronized (lock) { 97 return in.markSupported(); 98 } 99 } 100 101 /** 102 * Reads a single character from the filtered reader and returns it as an 103 * integer with the two higher-order bytes set to 0. Returns -1 if the end 104 * of the filtered reader has been reached. 105 * 106 * @return The character read or -1 if the end of the filtered reader has 107 * been reached. 108 * @throws IOException 109 * if an error occurs while reading from this reader. 110 */ 111 @Override 112 public int read() throws IOException { 113 synchronized (lock) { 114 return in.read(); 115 } 116 } 117 118 /** 119 * Reads up to {@code count} characters from the filtered reader and stores them 120 * in the byte array {@code buffer} starting at {@code offset}. Returns the 121 * number of characters actually read or -1 if no characters were read and 122 * the end of the filtered reader was encountered. 123 * 124 * @throws IOException 125 * if an error occurs while reading from this reader. 126 */ 127 @Override 128 public int read(char[] buffer, int offset, int count) throws IOException { 129 synchronized (lock) { 130 return in.read(buffer, offset, count); 131 } 132 } 133 134 /** 135 * Indicates whether this reader is ready to be read without blocking. If 136 * the result is {@code true}, the next {@code read()} will not block. If 137 * the result is {@code false}, this reader may or may not block when 138 * {@code read()} is sent. 139 * 140 * @return {@code true} if this reader will not block when {@code read()} 141 * is called, {@code false} if unknown or blocking will occur. 142 * @throws IOException 143 * if the reader is closed or some other I/O error occurs. 144 */ 145 @Override 146 public boolean ready() throws IOException { 147 synchronized (lock) { 148 return in.ready(); 149 } 150 } 151 152 /** 153 * Resets this reader's position to the last marked location. Invocations of 154 * {@code read()} and {@code skip()} will occur from this new location. If 155 * this reader was not marked, the behavior depends on the implementation of 156 * {@code reset()} in the Reader subclass that is filtered by this reader. 157 * The default behavior for Reader is to throw an {@code IOException}. 158 * 159 * @throws IOException 160 * if a problem occurred or the filtered reader does not support 161 * {@code mark()} and {@code reset()}. 162 * @see #mark(int) 163 * @see #markSupported() 164 */ 165 @Override 166 public void reset() throws IOException { 167 synchronized (lock) { 168 in.reset(); 169 } 170 } 171 172 /** 173 * Skips {@code charCount} characters in this reader. Subsequent calls to {@code read} 174 * will not return these characters unless {@code reset} is used. The 175 * default implementation is to skip characters in the filtered reader. 176 * 177 * @return the number of characters actually skipped. 178 * @throws IOException 179 * if the filtered reader is closed or some other I/O error 180 * occurs. 181 * @see #mark(int) 182 * @see #markSupported() 183 * @see #reset() 184 */ 185 @Override 186 public long skip(long charCount) throws IOException { 187 synchronized (lock) { 188 return in.skip(charCount); 189 } 190 } 191} 192