1 19 20 21 package org.netbeans.modules.properties; 22 23 24 import java.io.BufferedReader ; 25 import java.io.IOException ; 26 import java.io.Reader ; 27 import java.io.StringReader ; 28 import java.util.ArrayList ; 29 import java.util.Map ; 30 import java.util.HashMap ; 31 import java.util.List ; 32 import javax.swing.text.BadLocationException ; 33 import javax.swing.text.Document ; 34 import javax.swing.text.Position ; 35 import org.openide.text.PositionRef; 36 import org.openide.text.PositionBounds; 37 38 39 46 class PropertiesParser { 47 48 49 PropertiesFileEntry pfe; 50 51 52 PropertiesEditorSupport editor; 53 54 55 PropertiesReader propertiesReader; 56 57 58 private boolean stop = false; 59 60 61 65 public PropertiesParser(PropertiesFileEntry pfe) { 66 this.pfe = pfe; 67 } 68 69 70 72 void initParser() throws IOException { 73 editor = pfe.getPropertiesEditor(); 74 propertiesReader = createReader(); 75 } 76 77 82 private PropertiesReader createReader() throws IOException { 83 Document loadDoc = null; 85 86 if(editor.isDocumentLoaded()) { 87 loadDoc = editor.getDocument(); 88 } 89 90 if(loadDoc == null) { 91 loadDoc = editor.openDocument(); 92 } 93 94 final Document document = loadDoc; 95 final String [] str = new String [1]; 96 97 document.render(new Runnable () { 99 public void run() { 100 try { 101 str[0] = document.getText(0, document.getLength()); 102 } catch(BadLocationException ble) { 103 ble.printStackTrace(); 105 } 106 } 107 }); 108 109 return new PropertiesReader(str[0]); 110 } 111 112 116 public PropertiesStructure parseFile() { 117 try { 118 PropertiesStructure propStructure = parseFileMain(); 119 120 return propStructure; 121 } catch(IOException e) { 122 return null; 124 } 125 } 126 127 128 public void stop() { 129 stop = true; 130 clean(); 131 } 132 133 134 public void clean() { 135 if(propertiesReader != null) { 136 try { 137 propertiesReader.close(); 138 propertiesReader = null; 139 } catch(IOException ioe) { 140 org.openide.ErrorManager.getDefault().notify(org.openide.ErrorManager.INFORMATIONAL, ioe); 141 } 142 } 143 } 144 145 146 private PropertiesStructure parseFileMain() throws IOException { 147 148 Map <String ,Element.ItemElem> items = new HashMap <String ,Element.ItemElem>(25, 1.0F); 149 150 PropertiesReader reader = null; 151 152 while (true) { 153 if (stop) { 154 return null; 156 } 157 158 reader = propertiesReader; 159 if (reader == null) { 160 return null; 162 } 163 Element.ItemElem element = readNextElem(reader); 164 165 if (element == null) { 166 break; 167 } else { 168 items.put(element.getKey(), element); 170 } 171 } 172 173 return new PropertiesStructure(createBiasBounds(0, reader.position), items); 174 } 175 176 179 private Element.ItemElem readNextElem(PropertiesReader in) throws IOException { 180 Element.CommentElem commE; 181 Element.KeyElem keyE; 182 Element.ValueElem valueE; 183 184 int begPos = in.position; 185 186 int keyPos = begPos; 188 FlaggedLine fl = in.readLineExpectComment(); 189 StringBuffer comment = new StringBuffer (); 190 boolean firstNull = true; 191 while (fl != null) { 192 firstNull = false; 193 if(fl.flag) { 194 comment.append(trimComment(fl.line)); 196 comment.append(fl.lineSep); 197 keyPos = in.position; 198 } else 199 break; 201 fl = in.readLineExpectComment(); 202 } 203 204 if (firstNull) { 206 return null; 207 } 208 209 String comHelp; 210 comHelp = comment.toString(); 211 if(comment.length() > 0) 212 if(comment.charAt(comment.length() - 1) == '\n') 213 comHelp = comment.substring(0, comment.length() - 1); 214 215 commE = new Element.CommentElem(createBiasBounds(begPos, keyPos), UtilConvert.loadConvert(comHelp)); 216 218 219 if(fl == null) { 220 keyE = null; 221 valueE = null; 222 } else { 223 ArrayList <FlaggedLine> lines = new ArrayList <FlaggedLine>(2); 226 fl.startPosition = keyPos; 227 fl.stringValue = fl.line.toString(); 228 lines.add(fl); 229 int nowPos; 230 while (isPartialLine(fl.line)) { 231 fl.stringValue = fl.stringValue.substring(0, fl.stringValue.length() - 1); 233 nowPos = in.position; 235 fl = in.readLineNoFrills(); 236 if(fl == null) break; 237 int startIndex=0; 239 for(startIndex=0; startIndex < fl.line.length(); startIndex++) 240 if(UtilConvert.whiteSpaceChars.indexOf(fl.line.charAt(startIndex)) == -1) 241 break; 242 fl.stringValue = fl.line.substring(startIndex, fl.line.length()); 243 fl.startPosition = nowPos + startIndex; 244 lines.add(fl); 245 } 246 248 PositionMap positionMap = new PositionMap(lines); 249 String line = positionMap.getString(); 250 251 int len = line.length(); 253 int keyStart; 254 for(keyStart=0; keyStart<len; keyStart++) { 255 if(UtilConvert.whiteSpaceChars.indexOf(line.charAt(keyStart)) == -1) 256 break; 257 } 258 259 int separatorIndex; 261 for(separatorIndex=keyStart; separatorIndex<len; separatorIndex++) { 262 char currentChar = line.charAt(separatorIndex); 263 if(currentChar == '\\') 264 separatorIndex++; 265 else if(UtilConvert.keyValueSeparators.indexOf(currentChar) != -1) 266 break; 267 } 268 269 int valueIndex; 271 for (valueIndex=separatorIndex; valueIndex<len; valueIndex++) 272 if(UtilConvert.whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1) 273 break; 274 275 if(valueIndex < len) 277 if(UtilConvert.strictKeyValueSeparators.indexOf(line.charAt(valueIndex)) != -1) 278 valueIndex++; 279 280 while (valueIndex < len) { 282 if(UtilConvert.whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1) 283 break; 284 valueIndex++; 285 } 286 String key = line.substring(keyStart, separatorIndex); 287 String value = (separatorIndex < len) ? line.substring(valueIndex, len) : ""; 289 if(key == null) 290 ; 292 293 int currentPos = in.position; 294 int valuePosFile = 0; 295 296 try { 297 valuePosFile = positionMap.getFilePosition(valueIndex); 298 } catch (ArrayIndexOutOfBoundsException e) { 299 valuePosFile = currentPos; 300 } 301 302 keyE = new Element.KeyElem (createBiasBounds(keyPos, valuePosFile), UtilConvert.loadConvert(key)); 303 valueE = new Element.ValueElem(createBiasBounds(valuePosFile, currentPos), UtilConvert.loadConvert(value)); 304 } 305 306 return new Element.ItemElem(createBiasBounds(begPos, in.position), keyE, valueE, commE); 307 } 308 309 310 private StringBuffer trimComment(StringBuffer line) { 311 while (line.length() > 0) { 312 char lead = line.charAt(0); 313 if (lead == '#' || lead == '!') { 314 line.deleteCharAt(0); 315 } else { 316 break; 317 } 318 } 319 return line; 320 } 321 322 325 private static int position(long p) { 326 return (int)(p & 0xFFFFFFFFL); 327 } 328 329 335 private PositionBounds createBiasBounds(long begin, long end) { 336 PositionRef posBegin = editor.createPositionRef(position(begin), Position.Bias.Forward); 337 PositionRef posEnd = editor.createPositionRef(position(end), Position.Bias.Backward); 338 return new PositionBounds(posBegin, posEnd); 339 } 340 341 345 private static class PropertiesReader extends BufferedReader { 346 347 348 private static final String LINE_SEPARATOR = "line.separator"; 350 351 private int peekChar = -1; 352 353 354 public int position = 0; 355 356 357 358 private PropertiesReader(String buffer) { 359 super(new StringReader (buffer)); 360 } 361 362 363 private PropertiesReader(Reader reader) { 364 super(reader); 365 } 366 367 368 371 public int read() throws IOException { 372 int character = peek(); 373 peekChar = -1; 374 if(character != -1) 375 position++; 376 377 return character; 378 } 379 380 384 private int peek() throws IOException { 385 if(peekChar == -1) 386 peekChar = super.read(); 387 388 return peekChar; 389 } 390 391 395 public FlaggedLine readLineExpectComment() throws IOException { 396 int charRead = read(); 397 if(charRead == -1) 398 return null; 400 401 boolean decided = false; 402 FlaggedLine fl = new FlaggedLine(); 403 while (charRead != -1 && charRead != (int)'\n' && charRead != (int)'\r') { 404 if(!decided) 405 if(UtilConvert.whiteSpaceChars.indexOf((char)charRead) == -1) { 406 fl.flag = (((char)charRead == '!') || ((char)charRead == '#')); 408 decided = true; 409 } 410 fl.line.append((char)charRead); 411 charRead = read(); 412 } 413 414 if(!decided) 415 fl.flag = true; 417 418 if(charRead == (int)'\r') 420 if(peek() == (int)'\n') { 421 charRead = read(); 422 fl.lineSep = "\r\n"; } else 424 fl.lineSep = "\r"; else 426 if(charRead == (int)'\n') 427 fl.lineSep = "\n"; else 429 fl.lineSep = System.getProperty(LINE_SEPARATOR); 430 431 return fl; 432 } 433 434 436 public FlaggedLine readLineNoFrills() throws IOException { 437 int charRead = read(); 438 if(charRead == -1) 439 return null; 441 442 FlaggedLine fl = new FlaggedLine(); 443 while (charRead != -1 && charRead != (int)'\n' && charRead != (int)'\r') { 444 fl.line.append((char)charRead); 445 charRead = read(); 446 } 447 448 if(charRead == (int)'\r') 450 if(peek() == (int)'\n') { 451 charRead = read(); 452 fl.lineSep = "\r\n"; } else 454 fl.lineSep = "\r"; else 456 if(charRead == (int)'\n') fl.lineSep = "\n"; else 459 fl.lineSep = System.getProperty(LINE_SEPARATOR); 460 461 return fl; 462 } 463 464 } 466 470 private static boolean isPartialLine (StringBuffer line) { 471 int slashCount = 0; 472 int index = line.length() - 1; 473 while((index >= 0) && (line.charAt(index--) == '\\')) 474 slashCount++; 475 return (slashCount % 2 == 1); 476 } 477 478 480 private static class PositionMap { 481 482 483 private List <FlaggedLine> list; 484 485 486 487 PositionMap(List <FlaggedLine> lines) { 488 list = lines; 489 } 490 491 492 493 public String getString() { 494 String allLines = list.get(0).stringValue; 495 for (int part=1; part<list.size(); part++) { 496 allLines += list.get(part).stringValue; 497 } 498 return allLines; 499 } 500 501 507 public int getFilePosition(int posString) throws ArrayIndexOutOfBoundsException { 508 int part; 510 int lengthSoFar = 0; 511 int lastLengthSoFar = 0; 512 for (part=0; part < list.size(); part++) { 513 lastLengthSoFar = lengthSoFar; 514 lengthSoFar += list.get(part).stringValue.length(); 515 if (part == list.size() - 1) { 517 if (lengthSoFar >= posString) { 518 break; 519 } 520 } else { 521 if (lengthSoFar > posString) { 522 break; 523 } 524 } 525 } 526 if (posString > lengthSoFar) { 527 throw new ArrayIndexOutOfBoundsException ("not in scope"); } 529 return list.get(part).startPosition + posString - lastLengthSoFar; 530 } 531 } 533 534 535 private static class FlaggedLine { 536 537 538 StringBuffer line; 539 540 541 boolean flag; 542 543 544 String lineSep; 545 546 547 int startPosition; 548 549 550 String stringValue; 551 552 553 554 FlaggedLine() { 555 line = new StringBuffer (); 556 flag = false; 557 lineSep = "\n"; startPosition = 0; 559 } 560 } } 562 | Popular Tags |