1. /*
  2. * Copyright 2003-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. /**
  21. * This method converts non-latin characters to unicode escapes.
  22. * Useful to load properties containing non latin
  23. * Example:
  24. *
  25. * <pre><escapeunicode></pre>
  26. *
  27. * Or:
  28. *
  29. * <pre><filterreader
  30. classname="org.apache.tools.ant.filters.EscapeUnicode"/>
  31. * </pre>
  32. *
  33. * @since Ant 1.6
  34. */
  35. public class EscapeUnicode
  36. extends BaseParamFilterReader
  37. implements ChainableReader {
  38. //this field will hold unnnn right after reading a non latin character
  39. //afterwards it will be truncated of one char every call to read
  40. private StringBuffer unicodeBuf;
  41. /**
  42. * Constructor for "dummy" instances.
  43. *
  44. * @see BaseFilterReader#BaseFilterReader()
  45. */
  46. public EscapeUnicode() {
  47. super();
  48. unicodeBuf = new StringBuffer();
  49. }
  50. /**
  51. * Creates a new filtered reader.
  52. *
  53. * @param in A Reader object providing the underlying stream.
  54. * Must not be <code>null</code>.
  55. */
  56. public EscapeUnicode(final Reader in) {
  57. super(in);
  58. unicodeBuf = new StringBuffer();
  59. }
  60. /**
  61. * Returns the next character in the filtered stream, converting non latin
  62. * characters to unicode escapes.
  63. *
  64. * @return the next character in the resulting stream, or -1
  65. * if the end of the resulting stream has been reached
  66. *
  67. * @exception IOException if the underlying stream throws
  68. * an IOException during reading
  69. */
  70. public final int read() throws IOException {
  71. if (!getInitialized()) {
  72. initialize();
  73. setInitialized(true);
  74. }
  75. int ch = -1;
  76. if (unicodeBuf.length() == 0) {
  77. ch = in.read();
  78. if (ch != -1) {
  79. char achar = (char) ch;
  80. if (achar >= '\u0080') {
  81. unicodeBuf = new StringBuffer("u0000");
  82. String s = Integer.toHexString(ch);
  83. //replace the last 0s by the chars contained in s
  84. for (int i = 0; i < s.length(); i++) {
  85. unicodeBuf.setCharAt(unicodeBuf.length()
  86. - s.length() + i,
  87. s.charAt(i));
  88. }
  89. ch = '\\';
  90. }
  91. }
  92. } else {
  93. ch = (int) unicodeBuf.charAt(0);
  94. unicodeBuf.deleteCharAt(0);
  95. }
  96. return ch;
  97. }
  98. /**
  99. * Creates a new EscapeUnicode using the passed in
  100. * Reader for instantiation.
  101. *
  102. * @param rdr A Reader object providing the underlying stream.
  103. * Must not be <code>null</code>.
  104. *
  105. * @return a new filter based on this configuration, but filtering
  106. * the specified reader
  107. */
  108. public final Reader chain(final Reader rdr) {
  109. EscapeUnicode newFilter = new EscapeUnicode(rdr);
  110. newFilter.setInitialized(true);
  111. return newFilter;
  112. }
  113. /**
  114. * Parses the parameters (currently unused)
  115. */
  116. private final void initialize() {
  117. }
  118. }