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:
023: /**
024: * This method converts non-latin characters to unicode escapes.
025: * Useful to load properties containing non latin
026: * Example:
027: *
028: * <pre><escapeunicode></pre>
029: *
030: * Or:
031: *
032: * <pre><filterreader
033: classname="org.apache.tools.ant.filters.EscapeUnicode"/>
034: * </pre>
035: *
036: * @since Ant 1.6
037: */
038: public class EscapeUnicode extends BaseParamFilterReader implements
039: ChainableReader {
040: //this field will hold unnnn right after reading a non latin character
041: //afterwards it will be truncated of one char every call to read
042: private StringBuffer unicodeBuf;
043:
044: /**
045: * Constructor for "dummy" instances.
046: *
047: * @see BaseFilterReader#BaseFilterReader()
048: */
049: public EscapeUnicode() {
050: super ();
051: unicodeBuf = new StringBuffer();
052: }
053:
054: /**
055: * Creates a new filtered reader.
056: *
057: * @param in A Reader object providing the underlying stream.
058: * Must not be <code>null</code>.
059: */
060: public EscapeUnicode(final Reader in) {
061: super (in);
062: unicodeBuf = new StringBuffer();
063: }
064:
065: /**
066: * Returns the next character in the filtered stream, converting non latin
067: * characters to unicode escapes.
068: *
069: * @return the next character in the resulting stream, or -1
070: * if the end of the resulting stream has been reached
071: *
072: * @exception IOException if the underlying stream throws
073: * an IOException during reading
074: */
075: public final int read() throws IOException {
076: if (!getInitialized()) {
077: initialize();
078: setInitialized(true);
079: }
080:
081: int ch = -1;
082: if (unicodeBuf.length() == 0) {
083: ch = in.read();
084: if (ch != -1) {
085: char achar = (char) ch;
086: if (achar >= '\u0080') {
087: unicodeBuf = new StringBuffer("u0000");
088: String s = Integer.toHexString(ch);
089: //replace the last 0s by the chars contained in s
090: for (int i = 0; i < s.length(); i++) {
091: unicodeBuf.setCharAt(unicodeBuf.length()
092: - s.length() + i, s.charAt(i));
093: }
094: ch = '\\';
095: }
096: }
097: } else {
098: ch = (int) unicodeBuf.charAt(0);
099: unicodeBuf.deleteCharAt(0);
100: }
101: return ch;
102: }
103:
104: /**
105: * Creates a new EscapeUnicode using the passed in
106: * Reader for instantiation.
107: *
108: * @param rdr A Reader object providing the underlying stream.
109: * Must not be <code>null</code>.
110: *
111: * @return a new filter based on this configuration, but filtering
112: * the specified reader
113: */
114: public final Reader chain(final Reader rdr) {
115: EscapeUnicode newFilter = new EscapeUnicode(rdr);
116: newFilter.setInitialized(true);
117: return newFilter;
118: }
119:
120: /**
121: * Parses the parameters (currently unused)
122: */
123: private void initialize() {
124: }
125: }
|