1. /*
  2. * Copyright 2002-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant.filters.util;
  18. import java.io.FilterReader;
  19. import java.io.IOException;
  20. import java.io.Reader;
  21. import java.lang.reflect.Constructor;
  22. import java.lang.reflect.InvocationTargetException;
  23. import java.util.Vector;
  24. import org.apache.tools.ant.AntClassLoader;
  25. import org.apache.tools.ant.BuildException;
  26. import org.apache.tools.ant.Project;
  27. import org.apache.tools.ant.filters.BaseFilterReader;
  28. import org.apache.tools.ant.filters.ChainableReader;
  29. import org.apache.tools.ant.types.AntFilterReader;
  30. import org.apache.tools.ant.types.FilterChain;
  31. import org.apache.tools.ant.types.Parameter;
  32. import org.apache.tools.ant.types.Parameterizable;
  33. import org.apache.tools.ant.types.Path;
  34. import org.apache.tools.ant.util.FileUtils;
  35. /**
  36. * Process a FilterReader chain.
  37. *
  38. */
  39. public final class ChainReaderHelper {
  40. // default buffer size
  41. private static final int DEFAULT_BUFFER_SIZE = 8192;
  42. /**
  43. * The primary reader to which the reader chain is to be attached.
  44. */
  45. public Reader primaryReader;
  46. /**
  47. * The size of the buffer to be used.
  48. */
  49. public int bufferSize = DEFAULT_BUFFER_SIZE;
  50. /**
  51. * Chain of filters
  52. */
  53. public Vector filterChains = new Vector();
  54. /** The Ant project */
  55. private Project project = null;
  56. /**
  57. * Sets the primary reader
  58. * @param rdr the reader object
  59. */
  60. public final void setPrimaryReader(Reader rdr) {
  61. primaryReader = rdr;
  62. }
  63. /**
  64. * Set the project to work with
  65. * @param project the current project
  66. */
  67. public final void setProject(final Project project) {
  68. this.project = project;
  69. }
  70. /**
  71. * Get the project
  72. *
  73. * @return the current project
  74. */
  75. public final Project getProject() {
  76. return project;
  77. }
  78. /**
  79. * Sets the buffer size to be used. Defaults to 4096,
  80. * if this method is not invoked.
  81. * @param size the buffer size to use
  82. */
  83. public final void setBufferSize(int size) {
  84. bufferSize = size;
  85. }
  86. /**
  87. * Sets the collection of filter reader sets
  88. *
  89. * @param fchain the filter chains collection
  90. */
  91. public final void setFilterChains(Vector fchain) {
  92. filterChains = fchain;
  93. }
  94. /**
  95. * Assemble the reader
  96. * @return the assembled reader
  97. * @exception BuildException if an error occurs
  98. */
  99. public final Reader getAssembledReader() throws BuildException {
  100. if (primaryReader == null) {
  101. throw new BuildException("primaryReader must not be null.");
  102. }
  103. Reader instream = primaryReader;
  104. final int filterReadersCount = filterChains.size();
  105. final Vector finalFilters = new Vector();
  106. for (int i = 0; i < filterReadersCount; i++) {
  107. final FilterChain filterchain =
  108. (FilterChain) filterChains.elementAt(i);
  109. final Vector filterReaders = filterchain.getFilterReaders();
  110. final int readerCount = filterReaders.size();
  111. for (int j = 0; j < readerCount; j++) {
  112. finalFilters.addElement(filterReaders.elementAt(j));
  113. }
  114. }
  115. final int filtersCount = finalFilters.size();
  116. if (filtersCount > 0) {
  117. for (int i = 0; i < filtersCount; i++) {
  118. Object o = finalFilters.elementAt(i);
  119. if (o instanceof AntFilterReader) {
  120. final AntFilterReader filter
  121. = (AntFilterReader) finalFilters.elementAt(i);
  122. final String className = filter.getClassName();
  123. final Path classpath = filter.getClasspath();
  124. final Project project = filter.getProject();
  125. if (className != null) {
  126. try {
  127. Class clazz = null;
  128. if (classpath == null) {
  129. clazz = Class.forName(className);
  130. } else {
  131. AntClassLoader al
  132. = project.createClassLoader(classpath);
  133. clazz = Class.forName(className, true, al);
  134. }
  135. if (clazz != null) {
  136. if (!FilterReader.class.isAssignableFrom(clazz)) {
  137. throw new BuildException(className
  138. + " does not extend java.io.FilterReader");
  139. }
  140. final Constructor[] constructors =
  141. clazz.getConstructors();
  142. int j = 0;
  143. boolean consPresent = false;
  144. for (; j < constructors.length; j++) {
  145. Class[] types = constructors[j]
  146. .getParameterTypes();
  147. if (types.length == 1
  148. && types[0].isAssignableFrom(Reader.class)) {
  149. consPresent = true;
  150. break;
  151. }
  152. }
  153. if (!consPresent) {
  154. throw new BuildException(className
  155. + " does not define a public constructor"
  156. + " that takes in a Reader as its "
  157. + "single argument.");
  158. }
  159. final Reader[] rdr = {instream};
  160. instream =
  161. (Reader) constructors[j].newInstance(rdr);
  162. setProjectOnObject(instream);
  163. if (Parameterizable.class.isAssignableFrom(clazz)) {
  164. final Parameter[] params = filter.getParams();
  165. ((Parameterizable)
  166. instream).setParameters(params);
  167. }
  168. }
  169. } catch (final ClassNotFoundException cnfe) {
  170. throw new BuildException(cnfe);
  171. } catch (final InstantiationException ie) {
  172. throw new BuildException(ie);
  173. } catch (final IllegalAccessException iae) {
  174. throw new BuildException(iae);
  175. } catch (final InvocationTargetException ite) {
  176. throw new BuildException(ite);
  177. }
  178. }
  179. } else if (o instanceof ChainableReader) {
  180. setProjectOnObject(o);
  181. instream = ((ChainableReader) o).chain(instream);
  182. setProjectOnObject(instream);
  183. }
  184. }
  185. }
  186. return instream;
  187. }
  188. /**
  189. * helper method to set the project on an object.
  190. * the reflection setProject does not work for anonymous/protected/private
  191. * classes, even if they have public methods.
  192. */
  193. private void setProjectOnObject(Object obj) {
  194. if (project == null) {
  195. return;
  196. }
  197. if (obj instanceof BaseFilterReader) {
  198. ((BaseFilterReader) obj).setProject(project);
  199. return;
  200. }
  201. project.setProjectReference(obj);
  202. }
  203. /**
  204. * Read data from the reader and return the
  205. * contents as a string.
  206. * @param rdr the reader object
  207. * @return the contents of the file as a string
  208. * @exception IOException if an error occurs
  209. */
  210. public final String readFully(Reader rdr)
  211. throws IOException {
  212. return FileUtils.readFully(rdr, bufferSize);
  213. }
  214. }