1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 package graphical; 24 25 // import java.io.BufferedReader; 26 import java.io.File; 27 import java.io.RandomAccessFile; 28 import java.util.ArrayList; 29 import java.util.Enumeration; 30 31 /** 32 Helper class to give a simple API to read/write windows like ini files 33 */ 34 /* public */ // is only need, if we need this class outside package convwatch 35 public class IniFile implements Enumeration 36 { 37 38 /** 39 * internal representation of the ini file content. 40 * Problem, if ini file changed why other write something difference, we don't realise this. 41 */ 42 private String m_sFilename; 43 private ArrayList<String> m_aList; 44 boolean m_bListContainUnsavedChanges = false; 45 private int m_aEnumerationPos = 0; 46 47 /** 48 open a ini file by it's name 49 @param _sFilename string a filename, if the file doesn't exist, a new empty ini file will create. 50 write back to disk only if there are really changes. 51 */ IniFile(String _sFilename)52 public IniFile(String _sFilename) 53 { 54 m_sFilename = _sFilename; 55 m_aList = loadLines(); 56 m_aEnumerationPos = findNextSection(0); 57 // if (_sFilename.endsWith(".odb.ps.ini")) 58 // { 59 // int dummy = 0; 60 // } 61 } 62 insertFirstComment(String[] _aList)63 public void insertFirstComment(String[] _aList) 64 { 65 if (m_aList.size() == 0) 66 { 67 // can only insert if there is nothing else already in the ini file 68 for (int i = 0; i < _aList.length; i++) 69 { 70 m_aList.add(_aList[i]); 71 } 72 } 73 } 74 loadLines()75 private ArrayList<String> loadLines() 76 { 77 File aFile = new File(m_sFilename); 78 ArrayList<String> aLines = new ArrayList<String>(); 79 if (!aFile.exists()) 80 { 81 // GlobalLogWriter.println("couldn't find file '" + m_sFilename + "', will be created."); 82 // DebugHelper.exception(BasicErrorCode.SbERR_FILE_NOT_FOUND, ""); 83 // m_bListContainUnsavedChanges = false; 84 return aLines; 85 } 86 RandomAccessFile aReader = null; 87 // BufferedReader aReader; 88 try 89 { 90 aReader = new RandomAccessFile(aFile, "r"); 91 String aLine = ""; 92 while (aLine != null) 93 { 94 aLine = aReader.readLine(); 95 if (aLine != null && aLine.length() > 0) 96 { 97 aLines.add(aLine); 98 } 99 } 100 } 101 catch (java.io.FileNotFoundException fne) 102 { 103 GlobalLogWriter.println("couldn't open file " + m_sFilename); 104 GlobalLogWriter.println("Message: " + fne.getMessage()); 105 // DebugHelper.exception(BasicErrorCode.SbERR_FILE_NOT_FOUND, ""); 106 } 107 catch (java.io.IOException ie) 108 { 109 GlobalLogWriter.println("Exception occurs while reading from file " + m_sFilename); 110 GlobalLogWriter.println("Message: " + ie.getMessage()); 111 // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, ie.getMessage()); 112 } 113 try 114 { 115 aReader.close(); 116 } 117 catch (java.io.IOException ie) 118 { 119 GlobalLogWriter.println("Couldn't close file " + m_sFilename); 120 GlobalLogWriter.println("Message: " + ie.getMessage()); 121 // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, ie.getMessage()); 122 } 123 return aLines; 124 } 125 126 /** 127 * @return true, if the ini file contain some readable data 128 */ is()129 public boolean is() 130 { 131 return m_aList.size() > 1 ? true : false; 132 } 133 134 /** 135 * Check if a given Section and Key exists in the ini file 136 * @param _sSectionName 137 * @param _sKey 138 * @return true if the given Section, Key exists, now you can get the value 139 */ hasValue(String _sSectionName, String _sKey)140 public boolean hasValue(String _sSectionName, String _sKey) 141 { 142 int n = findKey(_sSectionName, _sKey); 143 if (n > 0) 144 { 145 return true; 146 } 147 return false; 148 } 149 // ----------------------------------------------------------------------------- 150 isRemark(String _sLine)151 private boolean isRemark(String _sLine) 152 { 153 if (((_sLine.length() < 2)) || 154 (_sLine.startsWith("#")) || 155 (_sLine.startsWith(";"))) 156 { 157 return true; 158 } 159 return false; 160 } 161 getItem(int i)162 private String getItem(int i) 163 { 164 return m_aList.get(i); 165 } 166 buildSectionName(String _sSectionName)167 private String buildSectionName(String _sSectionName) 168 { 169 String sFindSection = "[" + _sSectionName + "]"; 170 return sFindSection; 171 } 172 sectionToString(String _sSectionName)173 private String sectionToString(String _sSectionName) 174 { 175 String sKeyName = _sSectionName; 176 if (sKeyName.startsWith("[") && 177 sKeyName.endsWith("]")) 178 { 179 sKeyName = sKeyName.substring(1, sKeyName.length() - 1); 180 } 181 return sKeyName; 182 } 183 toLowerIfNeed(String _sName)184 private String toLowerIfNeed(String _sName) 185 { 186 return _sName.toLowerCase(); 187 } 188 189 // return the number where this section starts findSection(String _sSection)190 private int findSection(String _sSection) 191 { 192 String sFindSection = toLowerIfNeed(buildSectionName(_sSection)); 193 // ----------- find _sSection --------------- 194 int i; 195 for (i = 0; i < m_aList.size(); i++) 196 { 197 String sLine = toLowerIfNeed(getItem(i).trim()); 198 if (isRemark(sLine)) 199 { 200 continue; 201 } 202 if (sFindSection.equals("[]")) 203 { 204 // special case, empty Section. 205 return i - 1; 206 } 207 if (sLine.startsWith(sFindSection)) 208 { 209 return i; 210 } 211 } 212 return -1; 213 } 214 215 /** 216 * Checks if a given section exists in the ini file 217 * @param _sSection 218 * @return true if the given _sSection was found 219 */ hasSection(String _sSection)220 public boolean hasSection(String _sSection) 221 { 222 int i = findSection(_sSection); 223 if (i == -1) 224 { 225 return false; 226 } 227 return true; 228 } 229 230 // return the line number, where the key is found. findKey(String _sSection, String _sKey)231 private int findKey(String _sSection, String _sKey) 232 { 233 int i = findSection(_sSection); 234 if (i == -1) 235 { 236 // Section not found, therefore the value can't exist 237 return -1; 238 } 239 return findKeyFromKnownSection(i, _sKey); 240 } 241 242 // i must be the index in the list, where the well known section starts findKeyFromKnownSection(int _nSectionIndex, String _sKey)243 private int findKeyFromKnownSection(int _nSectionIndex, String _sKey) 244 { 245 _sKey = toLowerIfNeed(_sKey); 246 for (int j = _nSectionIndex + 1; j < m_aList.size(); j++) 247 { 248 String sLine = getItem(j).trim(); 249 250 if (isRemark(sLine)) 251 { 252 continue; 253 } 254 if (sLine.startsWith("[") /* && sLine.endsWith("]") */) 255 { 256 // TODO: due to the fact we would like to insert an empty line before new sections 257 // TODO: we should check if we are in an empty line and if, go back one line. 258 259 // found end. 260 break; 261 } 262 263 int nEqual = sLine.indexOf("="); 264 if (nEqual >= 0) 265 { 266 String sKey = toLowerIfNeed(sLine.substring(0, nEqual).trim()); 267 if (sKey.equals(_sKey)) 268 { 269 return j; 270 } 271 } 272 } 273 return -1; 274 } 275 276 // i must be the index in the list, where the well known section starts findLastKnownKeyIndex(int _nSectionIndex, String _sKey)277 private int findLastKnownKeyIndex(int _nSectionIndex, String _sKey) 278 { 279 _sKey = toLowerIfNeed(_sKey); 280 int i = _nSectionIndex + 1; 281 for (int j = i; j < m_aList.size(); j++) 282 { 283 String sLine = getItem(j).trim(); 284 285 if (isRemark(sLine)) 286 { 287 continue; 288 } 289 290 if (sLine.startsWith("[") /* && sLine.endsWith("]") */) 291 { 292 // found end. 293 return j; 294 } 295 296 int nEqual = sLine.indexOf("="); 297 if (nEqual >= 0) 298 { 299 String sKey = toLowerIfNeed(sLine.substring(0, nEqual).trim()); 300 if (sKey.equals(_sKey)) 301 { 302 return j; 303 } 304 } 305 } 306 return i; 307 } 308 getValue(int _nIndex)309 private String getValue(int _nIndex) 310 { 311 String sLine = getItem(_nIndex).trim(); 312 if (isRemark(sLine)) 313 { 314 return ""; 315 } 316 int nEqual = sLine.indexOf("="); 317 if (nEqual >= 0) 318 { 319 String sKey = sLine.substring(0, nEqual).trim(); 320 String sValue = sLine.substring(nEqual + 1).trim(); 321 return sValue; 322 } 323 return ""; 324 } 325 326 /** 327 @param _sSection string 328 @param _sKey string 329 @return the value found in the inifile which is given by the section and key parameter 330 */ 331 // private int m_nCurrentPosition; 332 // private String m_sOldKey; getValue(String _sSection, String _sKey)333 public String getValue(String _sSection, String _sKey) 334 { 335 String sValue = ""; 336 int m_nCurrentPosition = findKey(_sSection, _sKey); 337 if (m_nCurrentPosition == -1) 338 { 339 // Section not found, therefore the value can't exist 340 return ""; 341 } 342 343 // m_sOldKey = _sKey; 344 sValue = getValue(m_nCurrentPosition); 345 346 return sValue; 347 } 348 349 // private String getNextValue() 350 // { 351 // if (m_nCurrentPosition >= 0) 352 // { 353 // ++m_nCurrentPosition; 354 // String sValue = getValue(m_nCurrentPosition); 355 // return sValue; 356 // } 357 // return ""; 358 // } 359 /** 360 * Returns the value at Section, Key converted to an integer 361 * Check with hasValue(Section, Key) to check before you get into trouble. 362 * @param _sSection 363 * @param _sKey 364 * @param _nDefault if there is a problem, key not found... this value will return 365 * @return 366 */ getIntValue(String _sSection, String _sKey, int _nDefault)367 public int getIntValue(String _sSection, String _sKey, int _nDefault) 368 { 369 String sValue = getValue(_sSection, _sKey); 370 int nValue = _nDefault; 371 if (sValue.length() > 0) 372 { 373 try 374 { 375 nValue = Integer.valueOf(sValue).intValue(); 376 } 377 catch (java.lang.NumberFormatException e) 378 { 379 GlobalLogWriter.println("IniFile.getIntValue(): Caught a number format exception, return the default value."); 380 } 381 } 382 return nValue; 383 } 384 close()385 public void close() 386 { 387 store(); 388 } 389 390 /** 391 write back the ini file to the disk, only if there exist changes 392 * @deprecated use close() instead! 393 */ 394 395 // TODO: make private store()396 public void store() 397 { 398 if (m_bListContainUnsavedChanges == false) 399 { 400 // nothing has changed, so no need to store 401 return; 402 } 403 404 File aFile = new File(m_sFilename); 405 if (aFile.exists()) 406 { 407 // System.out.println("couldn't find file " + m_sFilename); 408 // TODO: little bit unsafe here, first rename, after write is complete, delete the old. 409 aFile.delete(); 410 if (aFile.exists()) 411 { 412 GlobalLogWriter.println("Couldn't delete the file " + m_sFilename); 413 return; 414 // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, "Couldn't delete the file " + m_sFilename); 415 } 416 } 417 // if (! aFile.canWrite()) 418 // { 419 // System.out.println("Couldn't write to file " + m_sFilename); 420 // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, ""); 421 // } 422 try 423 { 424 RandomAccessFile aWriter = new RandomAccessFile(aFile, "rw"); 425 for (int i = 0; i < m_aList.size(); i++) 426 { 427 String sLine = getItem(i); 428 if (sLine.startsWith("[")) 429 { 430 // write an extra empty line before next section. 431 aWriter.writeByte((int) '\n'); 432 } 433 aWriter.writeBytes(sLine); 434 aWriter.writeByte((int) '\n'); 435 } 436 aWriter.close(); 437 } 438 catch (java.io.FileNotFoundException fne) 439 { 440 GlobalLogWriter.println("couldn't open file for writing " + m_sFilename); 441 GlobalLogWriter.println("Message: " + fne.getMessage()); 442 // DebugHelper.exception(BasicErrorCode.SbERR_FILE_NOT_FOUND, ""); 443 } 444 catch (java.io.IOException ie) 445 { 446 GlobalLogWriter.println("Exception occurs while writing to file " + m_sFilename); 447 GlobalLogWriter.println("Message: " + ie.getMessage()); 448 // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, ie.getMessage()); 449 } 450 } 451 insertValue(String _sSection, String _sKey, int _nValue)452 public void insertValue(String _sSection, String _sKey, int _nValue) 453 { 454 insertValue(_sSection, _sKey, String.valueOf(_nValue)); 455 } 456 insertValue(String _sSection, String _sKey, long _nValue)457 public void insertValue(String _sSection, String _sKey, long _nValue) 458 { 459 insertValue(_sSection, _sKey, String.valueOf(_nValue)); 460 } 461 462 /** 463 insert a value 464 there are 3 cases 465 1. section doesn't exist, goto end and insert a new section, insert a new key value pair 466 2. section exist but key not, search section, search key, if key is -1 get last known key position and insert new key value pair there 467 3. section exist and key exist, remove the old key and insert the key value pair at the same position 468 * @param _sSection 469 * @param _sKey 470 * @param _sValue 471 */ insertValue(String _sSection, String _sKey, String _sValue)472 public void insertValue(String _sSection, String _sKey, String _sValue) 473 { 474 int i = findSection(_sSection); 475 if (i == -1) 476 { 477 // case 1: section doesn't exist 478 String sFindSection = buildSectionName(_sSection); 479 480 // TODO: before create a new Section, insert a empty line 481 m_aList.add(sFindSection); 482 if (_sKey.length() > 0) 483 { 484 String sKeyValuePair = _sKey + "=" + _sValue; 485 m_aList.add(sKeyValuePair); 486 } 487 m_bListContainUnsavedChanges = true; 488 return; 489 } 490 int j = findKeyFromKnownSection(i, _sKey); 491 if (j == -1) 492 { 493 // case 2: section exist, but not the key 494 j = findLastKnownKeyIndex(i, _sKey); 495 if (_sKey.length() > 0) 496 { 497 String sKeyValuePair = _sKey + "=" + _sValue; 498 m_aList.add(j, sKeyValuePair); 499 m_bListContainUnsavedChanges = true; 500 } 501 return; 502 } 503 else 504 { 505 // case 3: section exist, and also the key 506 String sKeyValuePair = _sKey + "=" + _sValue; 507 m_aList.set(j, sKeyValuePair); 508 m_bListContainUnsavedChanges = true; 509 } 510 } 511 // ----------------------------------------------------------------------------- 512 // String replaceEvaluatedValue(String _sSection, String _sValue) 513 // { 514 // String sValue = _sValue; 515 // int nIndex = 0; 516 // while (( nIndex = sValue.indexOf("$(", nIndex)) >= 0) 517 // { 518 // int nNextIndex = sValue.indexOf(")", nIndex); 519 // if (nNextIndex >= 0) 520 // { 521 // String sKey = sValue.substring(nIndex + 2, nNextIndex); 522 // String sNewValue = getValue(_sSection, sKey); 523 // if (sNewValue != null && sNewValue.length() > 0) 524 // { 525 // String sRegexpKey = "\\$\\(" + sKey + "\\)"; 526 // sValue = sValue.replaceAll(sRegexpKey, sNewValue); 527 // } 528 // nIndex = nNextIndex; 529 // } 530 // else 531 // { 532 // nIndex += 2; 533 // } 534 // } 535 // return sValue; 536 // } 537 // ----------------------------------------------------------------------------- 538 539 // public String getLocalEvaluatedValue(String _sSection, String _sKey) 540 // { 541 // String sValue = getValue(_sSection, _sKey); 542 // sValue = replaceEvaluatedValue(_sSection, sValue); 543 // return sValue; 544 // } 545 546 // ----------------------------------------------------------------------------- 547 548 // this is a special behaviour. 549 // public String getGlobalLocalEvaluatedValue(String _sSection, String _sKey) 550 // { 551 // String sGlobalValue = getKey("global", _sKey); 552 // String sLocalValue = getKey(_sSection, _sKey); 553 // if (sLocalValue.length() == 0) 554 // { 555 // sGlobalValue = replaceEvaluatedKey(_sSection, sGlobalValue); 556 // sGlobalValue = replaceEvaluatedKey("global", sGlobalValue); 557 // return sGlobalValue; 558 // } 559 // sLocalValue = replaceEvaluatedKey(_sSection, sLocalValue); 560 // sLocalValue = replaceEvaluatedKey("global", sLocalValue); 561 // 562 // return sLocalValue; 563 // } removeSection(String _sSectionToRemove)564 public void removeSection(String _sSectionToRemove) 565 { 566 // first, search for the name 567 int i = findSection(_sSectionToRemove); 568 if (i == -1) 569 { 570 // Section to remove not found, do nothing. 571 return; 572 } 573 // second, find the next section 574 int j = findNextSection(i + 1); 575 if (j == -1) 576 { 577 // if we are at the end, use size() as second section 578 j = m_aList.size(); 579 } 580 // remove all between first and second section 581 for (int k = i; k < j; k++) 582 { 583 m_aList.remove(i); 584 } 585 // mark the list as changed 586 m_bListContainUnsavedChanges = true; 587 } 588 589 /** 590 * some tests for this class 591 */ 592 // public static void main(String[] args) 593 // { 594 // String sTempFile = System.getProperty("java.io.tmpdir"); 595 // sTempFile += "inifile"; 596 // 597 // 598 // IniFile aIniFile = new IniFile(sTempFile); 599 // String sValue = aIniFile.getValue("Section", "Key"); 600 // // insert a new value to a already exist section 601 // aIniFile.insertValue("Section", "Key2", "a new value in a existing section"); 602 // // replace a value 603 // aIniFile.insertValue("Section", "Key", "replaced value"); 604 // // create a new value 605 // aIniFile.insertValue("New Section", "Key", "a new key value pair"); 606 // aIniFile.insertValue("New Section", "Key2", "a new second key value pair"); 607 // 608 // String sValue2 = aIniFile.getValue("Section2", "Key"); 609 // 610 // aIniFile.removeSection("Section"); 611 // aIniFile.removeSection("New Section"); 612 // 613 // aIniFile.close(); 614 // } 615 616 /** 617 * Enumeration Interface 618 * @return true, if there are more Key values 619 */ hasMoreElements()620 public boolean hasMoreElements() 621 { 622 if (m_aEnumerationPos >= 0 && 623 m_aEnumerationPos < m_aList.size()) 624 { 625 return true; 626 } 627 return false; 628 } 629 630 /** 631 * Find the next line, which starts with '[' 632 * @param i start position 633 * @return the line where '[' found or -1 634 */ findNextSection(int i)635 private int findNextSection(int i) 636 { 637 if (i >= 0) 638 { 639 while (i < m_aList.size()) 640 { 641 String sLine = m_aList.get(i); 642 if (sLine.startsWith("[")) 643 { 644 return i; 645 } 646 i++; 647 } 648 } 649 return -1; 650 } 651 652 /** 653 * Enumeration Interface 654 * @return a key without the enveloped '[' ']' 655 */ nextElement()656 public Object nextElement() 657 { 658 int nLineWithSection = findNextSection(m_aEnumerationPos); 659 if (nLineWithSection != -1) 660 { 661 String sSection = m_aList.get(nLineWithSection); 662 m_aEnumerationPos = findNextSection(nLineWithSection + 1); 663 sSection = sectionToString(sSection); 664 return sSection; 665 } 666 else 667 { 668 m_aEnumerationPos = m_aList.size(); 669 } 670 return null; 671 } 672 673 /** 674 * Helper to count the occurrence of Sections 675 * @return returns the count of '^['.*']$' Elements 676 */ getElementCount()677 public int getElementCount() 678 { 679 int nCount = 0; 680 int nPosition = 0; 681 while ((nPosition = findNextSection(nPosition)) != -1) 682 { 683 nCount++; 684 nPosition++; 685 } 686 return nCount; 687 } 688 } 689 690