| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| import java.io.File; |
| import java.io.RandomAccessFile; |
| import java.util.ArrayList; |
| import java.util.Enumeration; |
| |
| |
| /** |
| * Simple implementation of a inifile manager |
| */ |
| class GlobalLogWriter |
| { |
| public static void println(String _s) |
| { |
| System.out.println(_s); |
| } |
| } |
| |
| /** |
| Helper class to give a simple API to read/write windows like ini files |
| */ |
| |
| /* public */ // is only need, if we need this class outside package convwatch |
| public class IniFile implements Enumeration |
| { |
| |
| /** |
| * internal representation of the ini file content. |
| * Problem, if ini file changed why other write something difference, we don't realise this. |
| */ |
| private String m_sFilename; |
| // private File m_aFile; |
| private ArrayList<String> m_aList; |
| boolean m_bListContainUnsavedChanges = false; |
| private int m_aEnumerationPos = 0; |
| |
| /** |
| open a ini file by it's name |
| @param _sFilename string a filename, if the file doesn't exist, a new empty ini file will create. |
| write back to disk only if there are really changes. |
| */ |
| public IniFile(String _sFilename) |
| { |
| m_sFilename = _sFilename; |
| // m_aFile = new File(_sFilename); |
| m_aList = loadLines(); |
| m_aEnumerationPos = findNextSection(0); |
| } |
| |
| /** |
| open a ini file by it's name |
| @param _aFile a java.io.File object, if the file doesn't exist, a new empty ini file will create. |
| write back to disk only if there are really changes. |
| */ |
| public IniFile(File _aFile) |
| { |
| m_sFilename = _aFile.getAbsolutePath(); |
| m_aList = loadLines(); |
| m_aEnumerationPos = findNextSection(0); |
| } |
| |
| public void insertFirstComment(String[] _aList) |
| { |
| if (m_aList.size() == 0) |
| { |
| // can only insert if there is nothing else already in the ini file |
| for (int i = 0; i < _aList.length; i++) |
| { |
| m_aList.add(_aList[i]); |
| } |
| } |
| } |
| |
| private ArrayList<String> loadLines() |
| { |
| ArrayList<String> aLines = new ArrayList<String>(); |
| File aFile = new File(m_sFilename); |
| if (!aFile.exists()) |
| { |
| // GlobalLogWriter.println("couldn't find file '" + m_sFilename + "', will be created."); |
| // DebugHelper.exception(BasicErrorCode.SbERR_FILE_NOT_FOUND, ""); |
| // m_bListContainUnsavedChanges = false; |
| return aLines; |
| } |
| RandomAccessFile aReader = null; |
| // BufferedReader aReader; |
| try |
| { |
| aReader = new RandomAccessFile(aFile, "r"); |
| String aLine = ""; |
| while (aLine != null) |
| { |
| aLine = aReader.readLine(); |
| if (aLine != null && aLine.length() > 0) |
| { |
| aLines.add(aLine); |
| } |
| } |
| } |
| catch (java.io.FileNotFoundException fne) |
| { |
| GlobalLogWriter.println("couldn't open file " + m_sFilename); |
| GlobalLogWriter.println("Message: " + fne.getMessage()); |
| // DebugHelper.exception(BasicErrorCode.SbERR_FILE_NOT_FOUND, ""); |
| } |
| catch (java.io.IOException ie) |
| { |
| GlobalLogWriter.println("Exception occurs while reading from file " + m_sFilename); |
| GlobalLogWriter.println("Message: " + ie.getMessage()); |
| // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, ie.getMessage()); |
| } |
| try |
| { |
| aReader.close(); |
| } |
| catch (java.io.IOException ie) |
| { |
| GlobalLogWriter.println("Couldn't close file " + m_sFilename); |
| GlobalLogWriter.println("Message: " + ie.getMessage()); |
| // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, ie.getMessage()); |
| } |
| return aLines; |
| } |
| |
| /** |
| * @return true, if the ini file contain some readable data |
| */ |
| public boolean is() |
| { |
| return m_aList.size() > 1 ? true : false; |
| } |
| |
| /** |
| * Check if a given Section and Key exists in the ini file |
| * @param _sSectionName |
| * @param _sKey |
| * @return true if the given Section, Key exists, now you can get the value |
| */ |
| public boolean hasValue(String _sSectionName, String _sKey) |
| { |
| int n = findKey(_sSectionName, _sKey); |
| if (n > 0) |
| { |
| return true; |
| } |
| return false; |
| } |
| // ----------------------------------------------------------------------------- |
| |
| private boolean isRemark(String _sLine) |
| { |
| if (((_sLine.length() < 2)) || |
| (_sLine.startsWith("#")) || |
| (_sLine.startsWith(";"))) |
| { |
| return true; |
| } |
| return false; |
| } |
| |
| private String getItem(int i) |
| { |
| return m_aList.get(i); |
| } |
| |
| private String buildSectionName(String _sSectionName) |
| { |
| String sFindSection = "[" + _sSectionName + "]"; |
| return sFindSection; |
| } |
| |
| private String sectionToString(String _sSectionName) |
| { |
| String sKeyName = _sSectionName; |
| if (sKeyName.startsWith("[") && |
| sKeyName.endsWith("]")) |
| { |
| sKeyName = sKeyName.substring(1, sKeyName.length() - 1); |
| } |
| return sKeyName; |
| } |
| |
| private String toLowerIfNeed(String _sName) |
| { |
| return _sName.toLowerCase(); |
| } |
| |
| // return the number where this section starts |
| private int findSection(String _sSection) |
| { |
| String sFindSection = toLowerIfNeed(buildSectionName(_sSection)); |
| // ----------- find _sSection --------------- |
| int i; |
| for (i = 0; i < m_aList.size(); i++) |
| { |
| String sLine = toLowerIfNeed(getItem(i).trim()); |
| if (isRemark(sLine)) |
| { |
| continue; |
| } |
| if (sFindSection.equals("[]")) |
| { |
| // special case, empty Section. |
| return i - 1; |
| } |
| if (sLine.startsWith(sFindSection)) |
| { |
| return i; |
| } |
| } |
| return -1; |
| } |
| |
| /** |
| * Checks if a given section exists in the ini file |
| * @param _sSection |
| * @return true if the given _sSection was found |
| */ |
| public boolean hasSection(String _sSection) |
| { |
| int i = findSection(_sSection); |
| if (i == -1) |
| { |
| return false; |
| } |
| return true; |
| } |
| |
| // return the line number, where the key is found. |
| private int findKey(String _sSection, String _sKey) |
| { |
| int i = findSection(_sSection); |
| if (i == -1) |
| { |
| // Section not found, therefore the value can't exist |
| return -1; |
| } |
| return findKeyFromKnownSection(i, _sKey); |
| } |
| |
| // i must be the index in the list, where the well known section starts |
| private int findKeyFromKnownSection(int _nSectionIndex, String _sKey) |
| { |
| _sKey = toLowerIfNeed(_sKey); |
| for (int j = _nSectionIndex + 1; j < m_aList.size(); j++) |
| { |
| String sLine = getItem(j).trim(); |
| |
| if (isRemark(sLine)) |
| { |
| continue; |
| } |
| if (sLine.startsWith("[") /* && sLine.endsWith("]") */) |
| { |
| // TODO: due to the fact we would like to insert an empty line before new sections |
| // TODO: we should check if we are in an empty line and if, go back one line. |
| |
| // found end. |
| break; |
| } |
| |
| int nEqual = sLine.indexOf("="); |
| if (nEqual >= 0) |
| { |
| String sKey = toLowerIfNeed(sLine.substring(0, nEqual).trim()); |
| if (sKey.equals(_sKey)) |
| { |
| return j; |
| } |
| } |
| } |
| return -1; |
| } |
| |
| // i must be the index in the list, where the well known section starts |
| private int findLastKnownKeyIndex(int _nSectionIndex, String _sKey) |
| { |
| _sKey = toLowerIfNeed(_sKey); |
| int i = _nSectionIndex + 1; |
| for (int j = i; j < m_aList.size(); j++) |
| { |
| String sLine = getItem(j).trim(); |
| |
| if (isRemark(sLine)) |
| { |
| continue; |
| } |
| |
| if (sLine.startsWith("[") /* && sLine.endsWith("]") */) |
| { |
| // found end. |
| return j; |
| } |
| |
| int nEqual = sLine.indexOf("="); |
| if (nEqual >= 0) |
| { |
| String sKey = toLowerIfNeed(sLine.substring(0, nEqual).trim()); |
| if (sKey.equals(_sKey)) |
| { |
| return j; |
| } |
| } |
| } |
| return i; |
| } |
| |
| private String getValue(int _nIndex) |
| { |
| String sLine = getItem(_nIndex).trim(); |
| if (isRemark(sLine)) |
| { |
| return ""; |
| } |
| int nEqual = sLine.indexOf("="); |
| if (nEqual >= 0) |
| { |
| String sKey = sLine.substring(0, nEqual).trim(); |
| String sValue = sLine.substring(nEqual + 1).trim(); |
| return sValue; |
| } |
| return ""; |
| } |
| |
| /** |
| @param _sSection string |
| @param _sKey string |
| @return the value found in the inifile which is given by the section and key parameter |
| */ |
| // private int m_nCurrentPosition; |
| // private String m_sOldKey; |
| public String getValue(String _sSection, String _sKey) |
| { |
| String sValue = ""; |
| int m_nCurrentPosition = findKey(_sSection, _sKey); |
| if (m_nCurrentPosition == -1) |
| { |
| // Section not found, therefore the value can't exist |
| return ""; |
| } |
| |
| // m_sOldKey = _sKey; |
| sValue = getValue(m_nCurrentPosition); |
| |
| return sValue; |
| } |
| |
| // private String getNextValue() |
| // { |
| // if (m_nCurrentPosition >= 0) |
| // { |
| // ++m_nCurrentPosition; |
| // String sValue = getValue(m_nCurrentPosition); |
| // return sValue; |
| // } |
| // return ""; |
| // } |
| /** |
| * Returns the value at Section, Key converted to an integer |
| * Check with hasValue(Section, Key) to check before you get into trouble. |
| * @param _sSection |
| * @param _sKey |
| * @param _nDefault if there is a problem, key not found... this value will return |
| * @return the value as integer if possible to convert, if not return default value. |
| */ |
| public int getIntValue(String _sSection, String _sKey, int _nDefault) |
| { |
| String sValue = getValue(_sSection, _sKey); |
| int nValue = _nDefault; |
| if (sValue.length() > 0) |
| { |
| try |
| { |
| nValue = Integer.valueOf(sValue).intValue(); |
| } |
| catch (java.lang.NumberFormatException e) |
| { |
| GlobalLogWriter.println("IniFile.getIntValue(): Caught a number format exception, return the default value."); |
| } |
| } |
| return nValue; |
| } |
| |
| /** |
| * close a open inifile. |
| * If there are changes, all changes will store back to disk. |
| */ |
| public void close() |
| { |
| store(); |
| } |
| |
| /** |
| write back the ini file to the disk, only if there exist changes |
| * @deprecated use close() instead! |
| */ |
| |
| // TODO: make private |
| private void store() |
| { |
| if (m_bListContainUnsavedChanges == false) |
| { |
| // nothing has changed, so no need to store |
| return; |
| } |
| |
| File aFile = new File(m_sFilename); |
| if (aFile.exists()) |
| { |
| // System.out.println("couldn't find file " + m_sFilename); |
| // TODO: little bit unsafe here, first rename, after write is complete, delete the old. |
| aFile.delete(); |
| if (aFile.exists()) |
| { |
| GlobalLogWriter.println("Couldn't delete the file " + m_sFilename); |
| return; |
| // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, "Couldn't delete the file " + m_sFilename); |
| } |
| } |
| // if (! aFile.canWrite()) |
| // { |
| // System.out.println("Couldn't write to file " + m_sFilename); |
| // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, ""); |
| // } |
| try |
| { |
| RandomAccessFile aWriter = new RandomAccessFile(aFile, "rw"); |
| for (int i = 0; i < m_aList.size(); i++) |
| { |
| String sLine = getItem(i); |
| if (sLine.startsWith("[")) |
| { |
| // write an extra empty line before next section. |
| aWriter.writeByte((int) '\n'); |
| } |
| aWriter.writeBytes(sLine); |
| aWriter.writeByte((int) '\n'); |
| } |
| aWriter.close(); |
| } |
| catch (java.io.FileNotFoundException fne) |
| { |
| GlobalLogWriter.println("couldn't open file for writing " + m_sFilename); |
| GlobalLogWriter.println("Message: " + fne.getMessage()); |
| // DebugHelper.exception(BasicErrorCode.SbERR_FILE_NOT_FOUND, ""); |
| } |
| catch (java.io.IOException ie) |
| { |
| GlobalLogWriter.println("Exception occurs while writing to file " + m_sFilename); |
| GlobalLogWriter.println("Message: " + ie.getMessage()); |
| // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, ie.getMessage()); |
| } |
| } |
| |
| public void insertValue(String _sSection, String _sKey, int _nValue) |
| { |
| insertValue(_sSection, _sKey, String.valueOf(_nValue)); |
| } |
| |
| public void insertValue(String _sSection, String _sKey, long _nValue) |
| { |
| insertValue(_sSection, _sKey, String.valueOf(_nValue)); |
| } |
| |
| /** |
| insert a value |
| there are 3 cases |
| 1. section doesn't exist, goto end and insert a new section, insert a new key value pair |
| 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 |
| 3. section exist and key exist, remove the old key and insert the key value pair at the same position |
| * @param _sSection |
| * @param _sKey |
| * @param _sValue |
| */ |
| public void insertValue(String _sSection, String _sKey, String _sValue) |
| { |
| int i = findSection(_sSection); |
| if (i == -1) |
| { |
| // case 1: section doesn't exist |
| String sFindSection = buildSectionName(_sSection); |
| |
| // TODO: before create a new Section, insert a empty line |
| m_aList.add(sFindSection); |
| if (_sKey.length() > 0) |
| { |
| String sKeyValuePair = _sKey + "=" + _sValue; |
| m_aList.add(sKeyValuePair); |
| } |
| m_bListContainUnsavedChanges = true; |
| return; |
| } |
| int j = findKeyFromKnownSection(i, _sKey); |
| if (j == -1) |
| { |
| // case 2: section exist, but not the key |
| j = findLastKnownKeyIndex(i, _sKey); |
| if (_sKey.length() > 0) |
| { |
| String sKeyValuePair = _sKey + "=" + _sValue; |
| m_aList.add(j, sKeyValuePair); |
| m_bListContainUnsavedChanges = true; |
| } |
| return; |
| } |
| else |
| { |
| // case 3: section exist, and also the key |
| String sKeyValuePair = _sKey + "=" + _sValue; |
| m_aList.set(j, sKeyValuePair); |
| m_bListContainUnsavedChanges = true; |
| } |
| } |
| // ----------------------------------------------------------------------------- |
| // String replaceEvaluatedValue(String _sSection, String _sValue) |
| // { |
| // String sValue = _sValue; |
| // int nIndex = 0; |
| // while (( nIndex = sValue.indexOf("$(", nIndex)) >= 0) |
| // { |
| // int nNextIndex = sValue.indexOf(")", nIndex); |
| // if (nNextIndex >= 0) |
| // { |
| // String sKey = sValue.substring(nIndex + 2, nNextIndex); |
| // String sNewValue = getValue(_sSection, sKey); |
| // if (sNewValue != null && sNewValue.length() > 0) |
| // { |
| // String sRegexpKey = "\\$\\(" + sKey + "\\)"; |
| // sValue = sValue.replaceAll(sRegexpKey, sNewValue); |
| // } |
| // nIndex = nNextIndex; |
| // } |
| // else |
| // { |
| // nIndex += 2; |
| // } |
| // } |
| // return sValue; |
| // } |
| // ----------------------------------------------------------------------------- |
| |
| // public String getLocalEvaluatedValue(String _sSection, String _sKey) |
| // { |
| // String sValue = getValue(_sSection, _sKey); |
| // sValue = replaceEvaluatedValue(_sSection, sValue); |
| // return sValue; |
| // } |
| |
| // ----------------------------------------------------------------------------- |
| |
| // this is a special behaviour. |
| // public String getGlobalLocalEvaluatedValue(String _sSection, String _sKey) |
| // { |
| // String sGlobalValue = getKey("global", _sKey); |
| // String sLocalValue = getKey(_sSection, _sKey); |
| // if (sLocalValue.length() == 0) |
| // { |
| // sGlobalValue = replaceEvaluatedKey(_sSection, sGlobalValue); |
| // sGlobalValue = replaceEvaluatedKey("global", sGlobalValue); |
| // return sGlobalValue; |
| // } |
| // sLocalValue = replaceEvaluatedKey(_sSection, sLocalValue); |
| // sLocalValue = replaceEvaluatedKey("global", sLocalValue); |
| // |
| // return sLocalValue; |
| // } |
| public void removeSection(String _sSectionToRemove) |
| { |
| // first, search for the name |
| int i = findSection(_sSectionToRemove); |
| if (i == -1) |
| { |
| // Section to remove not found, do nothing. |
| return; |
| } |
| // second, find the next section |
| int j = findNextSection(i + 1); |
| if (j == -1) |
| { |
| // if we are at the end, use size() as second section |
| j = m_aList.size(); |
| } |
| // remove all between first and second section |
| for (int k = i; k < j; k++) |
| { |
| m_aList.remove(i); |
| } |
| // mark the list as changed |
| m_bListContainUnsavedChanges = true; |
| } |
| |
| /** |
| * some tests for this class |
| */ |
| // public static void main(String[] args) |
| // { |
| // String sTempFile = System.getProperty("java.io.tmpdir"); |
| // sTempFile += "inifile"; |
| // |
| // |
| // IniFile aIniFile = new IniFile(sTempFile); |
| // String sValue = aIniFile.getValue("Section", "Key"); |
| // // insert a new value to a already exist section |
| // aIniFile.insertValue("Section", "Key2", "a new value in a existing section"); |
| // // replace a value |
| // aIniFile.insertValue("Section", "Key", "replaced value"); |
| // // create a new value |
| // aIniFile.insertValue("New Section", "Key", "a new key value pair"); |
| // aIniFile.insertValue("New Section", "Key2", "a new second key value pair"); |
| // |
| // String sValue2 = aIniFile.getValue("Section2", "Key"); |
| // |
| // aIniFile.removeSection("Section"); |
| // aIniFile.removeSection("New Section"); |
| // |
| // aIniFile.close(); |
| // } |
| |
| /** |
| * Enumeration Interface |
| * @return true, if there are more Key values |
| */ |
| public boolean hasMoreElements() |
| { |
| if (m_aEnumerationPos >= 0 && |
| m_aEnumerationPos < m_aList.size()) |
| { |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Find the next line, which starts with '[' |
| * @param i start position |
| * @return the line where '[' found or -1 |
| */ |
| private int findNextSection(int i) |
| { |
| if (i >= 0) |
| { |
| while (i < m_aList.size()) |
| { |
| String sLine = m_aList.get(i); |
| if (sLine.startsWith("[")) |
| { |
| return i; |
| } |
| i++; |
| } |
| } |
| return -1; |
| } |
| |
| /** |
| * Enumeration Interface |
| * @return a key without the enveloped '[' ']' |
| */ |
| public Object nextElement() |
| { |
| int nLineWithSection = findNextSection(m_aEnumerationPos); |
| if (nLineWithSection != -1) |
| { |
| String sSection = m_aList.get(nLineWithSection); |
| m_aEnumerationPos = findNextSection(nLineWithSection + 1); |
| sSection = sectionToString(sSection); |
| return sSection; |
| } |
| else |
| { |
| m_aEnumerationPos = m_aList.size(); |
| } |
| return null; |
| } |
| |
| /** |
| * Helper to count the occurence of Sections |
| * @return returns the count of '^['.*']$' Elements |
| */ |
| public int getElementCount() |
| { |
| int nCount = 0; |
| int nPosition = 0; |
| while ((nPosition = findNextSection(nPosition)) != -1) |
| { |
| nCount++; |
| nPosition++; |
| } |
| return nCount; |
| } |
| } |
| |