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.IOException;
021: import java.io.Reader;
022: import java.util.Vector;
023: import org.apache.tools.ant.Project;
024: import org.apache.tools.ant.types.Parameter;
025: import org.apache.tools.ant.types.RegularExpression;
026: import org.apache.tools.ant.util.regexp.Regexp;
027:
028: /**
029: * Filter which includes only those lines that contain the user-specified
030: * regular expression matching strings.
031: *
032: * Example:
033: * <pre><linecontainsregexp>
034: * <regexp pattern="foo*">
035: * </linecontainsregexp></pre>
036: *
037: * Or:
038: *
039: * <pre><filterreader classname="org.apache.tools.ant.filters.LineContainsRegExp">
040: * <param type="regexp" value="foo*"/>
041: * </filterreader></pre>
042: *
043: * This will fetch all those lines that contain the pattern <code>foo</code>
044: *
045: */
046: public final class LineContainsRegExp extends BaseParamFilterReader
047: implements ChainableReader {
048: /** Parameter name for the regular expression to filter on. */
049: private static final String REGEXP_KEY = "regexp";
050:
051: /** Parameter name for the words to filter on. */
052: private static final String NEGATE_KEY = "negate";
053:
054: /** Vector that holds the expressions that input lines must contain. */
055: private Vector regexps = new Vector();
056:
057: /**
058: * Remaining line to be read from this filter, or <code>null</code> if
059: * the next call to <code>read()</code> should read the original stream
060: * to find the next matching line.
061: */
062: private String line = null;
063:
064: private boolean negate = false;
065:
066: /**
067: * Constructor for "dummy" instances.
068: *
069: * @see BaseFilterReader#BaseFilterReader()
070: */
071: public LineContainsRegExp() {
072: super ();
073: }
074:
075: /**
076: * Creates a new filtered reader.
077: *
078: * @param in A Reader object providing the underlying stream.
079: * Must not be <code>null</code>.
080: */
081: public LineContainsRegExp(final Reader in) {
082: super (in);
083: }
084:
085: /**
086: * Returns the next character in the filtered stream, only including
087: * lines from the original stream which match all of the specified
088: * regular expressions.
089: *
090: * @return the next character in the resulting stream, or -1
091: * if the end of the resulting stream has been reached
092: *
093: * @exception IOException if the underlying stream throws an IOException
094: * during reading
095: */
096: public int read() throws IOException {
097: if (!getInitialized()) {
098: initialize();
099: setInitialized(true);
100: }
101:
102: int ch = -1;
103:
104: if (line != null) {
105: ch = line.charAt(0);
106: if (line.length() == 1) {
107: line = null;
108: } else {
109: line = line.substring(1);
110: }
111: } else {
112: final int regexpsSize = regexps.size();
113:
114: for (line = readLine(); line != null; line = readLine()) {
115: boolean matches = true;
116: for (int i = 0; matches && i < regexpsSize; i++) {
117: RegularExpression regexp = (RegularExpression) regexps
118: .elementAt(i);
119: Regexp re = regexp.getRegexp(getProject());
120: matches = re.matches(line);
121: }
122: if (matches ^ isNegated()) {
123: break;
124: }
125: }
126: if (line != null) {
127: return read();
128: }
129: }
130: return ch;
131: }
132:
133: /**
134: * Adds a <code>regexp</code> element.
135: *
136: * @param regExp The <code>regexp</code> element to add.
137: * Must not be <code>null</code>.
138: */
139: public void addConfiguredRegexp(final RegularExpression regExp) {
140: this .regexps.addElement(regExp);
141: }
142:
143: /**
144: * Sets the vector of regular expressions which must be contained within
145: * a line read from the original stream in order for it to match this
146: * filter.
147: *
148: * @param regexps A vector of regular expressions which must be contained
149: * within a line in order for it to match in this filter. Must not be
150: * <code>null</code>.
151: */
152: private void setRegexps(final Vector regexps) {
153: this .regexps = regexps;
154: }
155:
156: /**
157: * Returns the vector of regular expressions which must be contained within
158: * a line read from the original stream in order for it to match this
159: * filter.
160: *
161: * @return the vector of regular expressions which must be contained within
162: * a line read from the original stream in order for it to match this
163: * filter. The returned object is "live" - in other words, changes made to
164: * the returned object are mirrored in the filter.
165: */
166: private Vector getRegexps() {
167: return regexps;
168: }
169:
170: /**
171: * Creates a new LineContainsRegExp using the passed in
172: * Reader for instantiation.
173: *
174: * @param rdr A Reader object providing the underlying stream.
175: * Must not be <code>null</code>.
176: *
177: * @return a new filter based on this configuration, but filtering
178: * the specified reader
179: */
180: public Reader chain(final Reader rdr) {
181: LineContainsRegExp newFilter = new LineContainsRegExp(rdr);
182: newFilter.setRegexps(getRegexps());
183: newFilter.setNegate(isNegated());
184: return newFilter;
185: }
186:
187: /**
188: * Set the negation mode. Default false (no negation).
189: * @param b the boolean negation mode to set.
190: */
191: public void setNegate(boolean b) {
192: negate = b;
193: }
194:
195: /**
196: * Find out whether we have been negated.
197: * @return boolean negation flag.
198: */
199: public boolean isNegated() {
200: return negate;
201: }
202:
203: /**
204: * Parses parameters to add user defined regular expressions.
205: */
206: private void initialize() {
207: Parameter[] params = getParameters();
208: if (params != null) {
209: for (int i = 0; i < params.length; i++) {
210: if (REGEXP_KEY.equals(params[i].getType())) {
211: String pattern = params[i].getValue();
212: RegularExpression regexp = new RegularExpression();
213: regexp.setPattern(pattern);
214: regexps.addElement(regexp);
215: } else if (NEGATE_KEY.equals(params[i].getType())) {
216: setNegate(Project.toBoolean(params[i].getValue()));
217: }
218: }
219: }
220: }
221: }
|