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;
  18. import java.io.IOException;
  19. import java.io.Reader;
  20. import org.apache.tools.ant.Project;
  21. /**
  22. * Expands Ant properties, if any, in the data.
  23. * <p>
  24. * Example:<br>
  25. * <pre><expandproperties/></pre>
  26. * Or:
  27. * <pre><filterreader
  28. * classname="org.apache.tools.ant.filters.ExpandProperties"/></pre>
  29. *
  30. */
  31. public final class ExpandProperties
  32. extends BaseFilterReader
  33. implements ChainableReader {
  34. /** Data that must be read from, if not null. */
  35. private String queuedData = null;
  36. /**
  37. * Constructor for "dummy" instances.
  38. *
  39. * @see BaseFilterReader#BaseFilterReader()
  40. */
  41. public ExpandProperties() {
  42. super();
  43. }
  44. /**
  45. * Creates a new filtered reader.
  46. *
  47. * @param in A Reader object providing the underlying stream.
  48. * Must not be <code>null</code>.
  49. */
  50. public ExpandProperties(final Reader in) {
  51. super(in);
  52. }
  53. /**
  54. * Returns the next character in the filtered stream. The original
  55. * stream is first read in fully, and the Ant properties are expanded.
  56. * The results of this expansion are then queued so they can be read
  57. * character-by-character.
  58. *
  59. * @return the next character in the resulting stream, or -1
  60. * if the end of the resulting stream has been reached
  61. *
  62. * @exception IOException if the underlying stream throws an IOException
  63. * during reading
  64. */
  65. public final int read() throws IOException {
  66. int ch = -1;
  67. if (queuedData != null && queuedData.length() == 0) {
  68. queuedData = null;
  69. }
  70. if (queuedData != null) {
  71. ch = queuedData.charAt(0);
  72. queuedData = queuedData.substring(1);
  73. if (queuedData.length() == 0) {
  74. queuedData = null;
  75. }
  76. } else {
  77. queuedData = readFully();
  78. if (queuedData == null) {
  79. ch = -1;
  80. } else {
  81. Project project = getProject();
  82. queuedData = project.replaceProperties(queuedData);
  83. return read();
  84. }
  85. }
  86. return ch;
  87. }
  88. /**
  89. * Creates a new ExpandProperties filter using the passed in
  90. * Reader for instantiation.
  91. *
  92. * @param rdr A Reader object providing the underlying stream.
  93. * Must not be <code>null</code>.
  94. *
  95. * @return a new filter based on this configuration, but filtering
  96. * the specified reader
  97. */
  98. public final Reader chain(final Reader rdr) {
  99. ExpandProperties newFilter = new ExpandProperties(rdr);
  100. newFilter.setProject(getProject());
  101. return newFilter;
  102. }
  103. }