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.util;
019:
020: import java.io.FilterReader;
021: import java.io.IOException;
022: import java.io.Reader;
023: import java.lang.reflect.Constructor;
024: import java.lang.reflect.InvocationTargetException;
025: import java.util.Vector;
026: import org.apache.tools.ant.AntClassLoader;
027: import org.apache.tools.ant.BuildException;
028: import org.apache.tools.ant.Project;
029: import org.apache.tools.ant.filters.BaseFilterReader;
030: import org.apache.tools.ant.filters.ChainableReader;
031: import org.apache.tools.ant.types.AntFilterReader;
032: import org.apache.tools.ant.types.FilterChain;
033: import org.apache.tools.ant.types.Parameter;
034: import org.apache.tools.ant.types.Parameterizable;
035: import org.apache.tools.ant.types.Path;
036: import org.apache.tools.ant.util.FileUtils;
037:
038: /**
039: * Process a FilterReader chain.
040: *
041: */
042: public final class ChainReaderHelper {
043:
044: // default buffer size
045: private static final int DEFAULT_BUFFER_SIZE = 8192;
046: // CheckStyle:VisibilityModifier OFF - bc
047: /**
048: * The primary reader to which the reader chain is to be attached.
049: */
050: public Reader primaryReader;
051:
052: /**
053: * The size of the buffer to be used.
054: */
055: public int bufferSize = DEFAULT_BUFFER_SIZE;
056:
057: /**
058: * Chain of filters
059: */
060: public Vector filterChains = new Vector();
061:
062: /** The Ant project */
063: private Project project = null;
064:
065: // CheckStyle:VisibilityModifier ON
066:
067: /**
068: * Sets the primary reader
069: * @param rdr the reader object
070: */
071: public void setPrimaryReader(Reader rdr) {
072: primaryReader = rdr;
073: }
074:
075: /**
076: * Set the project to work with
077: * @param project the current project
078: */
079: public void setProject(final Project project) {
080: this .project = project;
081: }
082:
083: /**
084: * Get the project
085: *
086: * @return the current project
087: */
088: public Project getProject() {
089: return project;
090: }
091:
092: /**
093: * Sets the buffer size to be used. Defaults to 8192,
094: * if this method is not invoked.
095: * @param size the buffer size to use
096: */
097: public void setBufferSize(int size) {
098: bufferSize = size;
099: }
100:
101: /**
102: * Sets the collection of filter reader sets
103: *
104: * @param fchain the filter chains collection
105: */
106: public void setFilterChains(Vector fchain) {
107: filterChains = fchain;
108: }
109:
110: /**
111: * Assemble the reader
112: * @return the assembled reader
113: * @exception BuildException if an error occurs
114: */
115: public Reader getAssembledReader() throws BuildException {
116: if (primaryReader == null) {
117: throw new BuildException("primaryReader must not be null.");
118: }
119:
120: Reader instream = primaryReader;
121: final int filterReadersCount = filterChains.size();
122: final Vector finalFilters = new Vector();
123:
124: for (int i = 0; i < filterReadersCount; i++) {
125: final FilterChain filterchain = (FilterChain) filterChains
126: .elementAt(i);
127: final Vector filterReaders = filterchain.getFilterReaders();
128: final int readerCount = filterReaders.size();
129: for (int j = 0; j < readerCount; j++) {
130: finalFilters.addElement(filterReaders.elementAt(j));
131: }
132: }
133:
134: final int filtersCount = finalFilters.size();
135:
136: if (filtersCount > 0) {
137: for (int i = 0; i < filtersCount; i++) {
138: Object o = finalFilters.elementAt(i);
139:
140: if (o instanceof AntFilterReader) {
141: final AntFilterReader filter = (AntFilterReader) finalFilters
142: .elementAt(i);
143: final String className = filter.getClassName();
144: final Path classpath = filter.getClasspath();
145: final Project pro = filter.getProject();
146: if (className != null) {
147: try {
148: Class clazz = null;
149: if (classpath == null) {
150: clazz = Class.forName(className);
151: } else {
152: AntClassLoader al = pro
153: .createClassLoader(classpath);
154: clazz = Class.forName(className, true,
155: al);
156: }
157: if (clazz != null) {
158: if (!FilterReader.class
159: .isAssignableFrom(clazz)) {
160: throw new BuildException(
161: className
162: + " does not extend java.io.FilterReader");
163: }
164: final Constructor[] constructors = clazz
165: .getConstructors();
166: int j = 0;
167: boolean consPresent = false;
168: for (; j < constructors.length; j++) {
169: Class[] types = constructors[j]
170: .getParameterTypes();
171: if (types.length == 1
172: && types[0]
173: .isAssignableFrom(Reader.class)) {
174: consPresent = true;
175: break;
176: }
177: }
178: if (!consPresent) {
179: throw new BuildException(
180: className
181: + " does not define a public constructor"
182: + " that takes in a Reader as its "
183: + "single argument.");
184: }
185: final Reader[] rdr = { instream };
186: instream = (Reader) constructors[j]
187: .newInstance((Object[]) rdr);
188: setProjectOnObject(instream);
189: if (Parameterizable.class
190: .isAssignableFrom(clazz)) {
191: final Parameter[] params = filter
192: .getParams();
193: ((Parameterizable) instream)
194: .setParameters(params);
195: }
196: }
197: } catch (final ClassNotFoundException cnfe) {
198: throw new BuildException(cnfe);
199: } catch (final InstantiationException ie) {
200: throw new BuildException(ie);
201: } catch (final IllegalAccessException iae) {
202: throw new BuildException(iae);
203: } catch (final InvocationTargetException ite) {
204: throw new BuildException(ite);
205: }
206: }
207: } else if (o instanceof ChainableReader) {
208: setProjectOnObject(o);
209: instream = ((ChainableReader) o).chain(instream);
210: setProjectOnObject(instream);
211: }
212: }
213: }
214: return instream;
215: }
216:
217: /**
218: * helper method to set the project on an object.
219: * the reflection setProject does not work for anonymous/protected/private
220: * classes, even if they have public methods.
221: */
222: private void setProjectOnObject(Object obj) {
223: if (project == null) {
224: return;
225: }
226: if (obj instanceof BaseFilterReader) {
227: ((BaseFilterReader) obj).setProject(project);
228: return;
229: }
230: project.setProjectReference(obj);
231: }
232:
233: /**
234: * Read data from the reader and return the
235: * contents as a string.
236: * @param rdr the reader object
237: * @return the contents of the file as a string
238: * @exception IOException if an error occurs
239: */
240: public String readFully(Reader rdr) throws IOException {
241: return FileUtils.readFully(rdr, bufferSize);
242: }
243: }
|