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.tools.ant.filters;
019:
020: import java.io.FilterReader;
021: import java.io.IOException;
022: import java.io.Reader;
023: import java.io.StringReader;
024: import org.apache.tools.ant.Project;
025: import org.apache.tools.ant.util.FileUtils;
026:
027: /**
028: * Base class for core filter readers.
029: *
030: */
031: public abstract class BaseFilterReader extends FilterReader {
032: /** Buffer size used when reading */
033: private static final int BUFFER_SIZE = 8192;
034:
035: /** Have the parameters passed been interpreted? */
036: private boolean initialized = false;
037:
038: /** The Ant project this filter is part of. */
039: private Project project = null;
040:
041: /**
042: * Constructor used by Ant's introspection mechanism.
043: * The original filter reader is only used for chaining
044: * purposes, never for filtering purposes (and indeed
045: * it would be useless for filtering purposes, as it has
046: * no real data to filter). ChainedReaderHelper uses
047: * this placeholder instance to create a chain of real filters.
048: */
049: public BaseFilterReader() {
050: super (new StringReader(""));
051: FileUtils.close(this );
052: }
053:
054: /**
055: * Creates a new filtered reader.
056: *
057: * @param in A Reader object providing the underlying stream.
058: * Must not be <code>null</code>.
059: *
060: */
061: public BaseFilterReader(final Reader in) {
062: super (in);
063: }
064:
065: /**
066: * Reads characters into a portion of an array. This method will block
067: * until some input is available, an I/O error occurs, or the end of the
068: * stream is reached.
069: *
070: * @param cbuf Destination buffer to write characters to.
071: * Must not be <code>null</code>.
072: * @param off Offset at which to start storing characters.
073: * @param len Maximum number of characters to read.
074: *
075: * @return the number of characters read, or -1 if the end of the
076: * stream has been reached
077: *
078: * @exception IOException If an I/O error occurs
079: */
080: public final int read(final char[] cbuf, final int off,
081: final int len) throws IOException {
082: for (int i = 0; i < len; i++) {
083: final int ch = read();
084: if (ch == -1) {
085: if (i == 0) {
086: return -1;
087: } else {
088: return i;
089: }
090: }
091: cbuf[off + i] = (char) ch;
092: }
093: return len;
094: }
095:
096: /**
097: * Skips characters. This method will block until some characters are
098: * available, an I/O error occurs, or the end of the stream is reached.
099: *
100: * @param n The number of characters to skip
101: *
102: * @return the number of characters actually skipped
103: *
104: * @exception IllegalArgumentException If <code>n</code> is negative.
105: * @exception IOException If an I/O error occurs
106: */
107: public final long skip(final long n) throws IOException,
108: IllegalArgumentException {
109: if (n < 0L) {
110: throw new IllegalArgumentException("skip value is negative");
111: }
112:
113: for (long i = 0; i < n; i++) {
114: if (read() == -1) {
115: return i;
116: }
117: }
118: return n;
119: }
120:
121: /**
122: * Sets the initialized status.
123: *
124: * @param initialized Whether or not the filter is initialized.
125: */
126: protected final void setInitialized(final boolean initialized) {
127: this .initialized = initialized;
128: }
129:
130: /**
131: * Returns the initialized status.
132: *
133: * @return whether or not the filter is initialized
134: */
135: protected final boolean getInitialized() {
136: return initialized;
137: }
138:
139: /**
140: * Sets the project to work with.
141: *
142: * @param project The project this filter is part of.
143: * Should not be <code>null</code>.
144: */
145: public final void setProject(final Project project) {
146: this .project = project;
147: }
148:
149: /**
150: * Returns the project this filter is part of.
151: *
152: * @return the project this filter is part of
153: */
154: protected final Project getProject() {
155: return project;
156: }
157:
158: /**
159: * Reads a line of text ending with '\n' (or until the end of the stream).
160: * The returned String retains the '\n'.
161: *
162: * @return the line read, or <code>null</code> if the end of the stream
163: * has already been reached
164: *
165: * @exception IOException if the underlying reader throws one during
166: * reading
167: */
168: protected final String readLine() throws IOException {
169: int ch = in.read();
170:
171: if (ch == -1) {
172: return null;
173: }
174:
175: StringBuffer line = new StringBuffer();
176:
177: while (ch != -1) {
178: line.append((char) ch);
179: if (ch == '\n') {
180: break;
181: }
182: ch = in.read();
183: }
184: return line.toString();
185: }
186:
187: /**
188: * Reads to the end of the stream, returning the contents as a String.
189: *
190: * @return the remaining contents of the reader, as a String
191: *
192: * @exception IOException if the underlying reader throws one during
193: * reading
194: */
195: protected final String readFully() throws IOException {
196: return FileUtils.readFully(in, BUFFER_SIZE);
197: }
198: }
|