1 15 package org.apache.tapestry.util.text; 16 17 import java.io.BufferedReader ; 18 import java.io.IOException ; 19 import java.io.InputStream ; 20 import java.io.InputStreamReader ; 21 import java.io.Reader ; 22 import java.io.UnsupportedEncodingException ; 23 import java.util.Map ; 24 25 35 public class LocalizedPropertiesLoader 36 { 37 private static final String HEX_DIGITS = "0123456789ABCDEF"; 38 39 private static final ICharacterMatcher WHITESPACE = new WhitespaceMatcher(false); 40 private static final ICharacterMatcher LINE_SEPARATOR = new AsciiCharacterMatcher("\n\r"); 41 private static final ICharacterMatcher NOT_LINE_SEPARATOR = new InverseMatcher(LINE_SEPARATOR); 42 private static final ICharacterMatcher KEY_VALUE_SEPARATOR = new AsciiCharacterMatcher("=:"); 43 private static final ICharacterMatcher SEPARATOR = new AsciiCharacterMatcher("=:\r\n"); 44 private static final ICharacterMatcher COMMENT = new AsciiCharacterMatcher("#!"); 45 private static final ICharacterMatcher WHITESPACE_OR_SEPARATOR = 46 new CompoundMatcher(new ICharacterMatcher[] { WHITESPACE, SEPARATOR }); 47 48 private ExtendedReader _extendedReader; 49 50 56 public LocalizedPropertiesLoader(InputStream ins) 57 { 58 this(new InputStreamReader (ins)); 59 } 60 61 69 public LocalizedPropertiesLoader(InputStream ins, String encoding) throws UnsupportedEncodingException 70 { 71 this(new InputStreamReader (ins, encoding)); 72 } 73 74 79 public LocalizedPropertiesLoader(Reader reader) 80 { 81 _extendedReader = new ExtendedReader(new BufferedReader (reader)); 82 } 83 84 90 public void load(Map properties) throws IOException 91 { 92 while (!isAtEndOfStream()) { 93 int nextChar = _extendedReader.peek(); 96 if (COMMENT.matches((char) nextChar)) { 97 _extendedReader.skipCharacters(NOT_LINE_SEPARATOR); 98 continue; 99 } 100 101 _extendedReader.skipCharacters(WHITESPACE); 102 if (!isAtEndOfLine()) { 103 String key = readQuotedLine(WHITESPACE_OR_SEPARATOR); 105 _extendedReader.skipCharacters(WHITESPACE); 106 107 nextChar = _extendedReader.peek(); 109 if (nextChar > 0 && KEY_VALUE_SEPARATOR.matches((char) nextChar)) { 110 _extendedReader.read(); 111 _extendedReader.skipCharacters(WHITESPACE); 112 } 113 114 String value = readQuotedLine(LINE_SEPARATOR); 116 117 properties.put(key, value); 118 } 119 _extendedReader.skipCharacters(LINE_SEPARATOR); 120 } 121 } 122 123 124 private boolean isAtEndOfStream() throws IOException 125 { 126 int nextChar = _extendedReader.peek(); 127 return (nextChar < 0); 128 } 129 130 131 private boolean isAtEndOfLine() throws IOException 132 { 133 int nextChar = _extendedReader.peek(); 134 if (nextChar < 0) 135 return true; 136 return LINE_SEPARATOR.matches((char) nextChar); 137 } 138 139 140 private String readQuotedLine(ICharacterMatcher terminators) throws IOException 141 { 142 StringBuffer buf = new StringBuffer (); 143 144 while (true) { 145 int nextChar = _extendedReader.peek(); 147 148 if (nextChar < 0 || terminators.matches((char) nextChar)) 150 break; 151 152 try { 153 char ch = readQuotedChar(); 155 buf.append(ch); 156 } catch (IgnoreCharacterException e) { 157 } 159 } 160 161 return buf.toString(); 162 } 163 164 165 private char readQuotedChar() throws IOException , IgnoreCharacterException 166 { 167 int nextChar = _extendedReader.read(); 168 if (nextChar < 0) 169 throw new IgnoreCharacterException(); 170 char ch = (char) nextChar; 171 172 if (ch != '\\') 174 return ch; 175 176 nextChar = _extendedReader.read(); 178 179 if (nextChar < 0) 181 throw new IgnoreCharacterException(); 182 183 ch = (char) nextChar; 184 switch (ch) { 185 case 'u' : 186 char res = 0; 187 for (int i = 0; i < 4; i++) { 188 nextChar = _extendedReader.read(); 189 if (nextChar < 0) 190 throw new IllegalArgumentException ("Malformed \\uxxxx encoding."); 191 char digitChar = (char) nextChar; 192 int digit = HEX_DIGITS.indexOf(Character.toUpperCase(digitChar)); 193 if (digit < 0) 194 throw new IllegalArgumentException ("Malformed \\uxxxx encoding."); 195 res = (char) (res * 16 + digit); 196 } 197 return res; 198 199 case '\r' : 200 nextChar = _extendedReader.peek(); 202 if (nextChar == '\n') 203 _extendedReader.read(); 204 case '\n' : 205 _extendedReader.skipCharacters(WHITESPACE); 206 throw new IgnoreCharacterException(); 207 208 case 't' : return '\t'; 209 case 'n' : return '\n'; 210 case 'r' : return '\r'; 211 default: return ch; 212 } 213 } 214 215 216 private static class IgnoreCharacterException extends Exception 217 { 218 } 219 } 220 | Popular Tags |