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 
24 package convwatch;
25 
26 import java.io.File;
27 import java.io.RandomAccessFile;
28 import java.util.ArrayList;
29 
30 /**
31    Helper class to give a simple API to read/write windows like ini files
32  */
33 /* public */ // is only need, if we need this class outside package convwatch
34 class IniFile
35 {
36     /**
37      * internal representation of the ini file content.
38      * Problem, if ini file changed why other write something difference, we don't realise this.
39      */
40     String m_sFilename;
41     ArrayList m_aList;
42     boolean m_bListContainUnsavedChanges = false;
43 
44     /**
45        open a ini file by it's name
46        @param _sFilename string a filename, if the file doesn't exist, a new empty ini file will create.
47        write back to disk only if there are really changes.
48      */
IniFile(String _sFilename)49     public IniFile(String _sFilename)
50         {
51             m_sFilename = _sFilename;
52             m_aList = loadLines();
53         }
54 
loadLines()55     ArrayList loadLines()
56         {
57             File aFile = new File(m_sFilename);
58             ArrayList aLines = new ArrayList();
59             if (! aFile.exists())
60             {
61                 GlobalLogWriter.get().println("couldn't find file " + m_sFilename);
62                 // DebugHelper.exception(BasicErrorCode.SbERR_FILE_NOT_FOUND, "");
63                 // m_bListContainUnsavedChanges = false;
64                 return aLines;
65             }
66             RandomAccessFile aReader = null;
67             try
68             {
69                 aReader = new RandomAccessFile(aFile,"r");
70                 String aLine = "";
71                 while (aLine != null)
72                 {
73                     aLine = aReader.readLine();
74                     if (aLine != null)
75                     {
76                         aLines.add(aLine);
77                         }
78                     }
79                 }
80             catch (java.io.FileNotFoundException fne)
81             {
82                 GlobalLogWriter.get().println("couldn't open file " + m_sFilename);
83                 GlobalLogWriter.get().println("Message: " + fne.getMessage());
84                 // DebugHelper.exception(BasicErrorCode.SbERR_FILE_NOT_FOUND, "");
85             }
86             catch (java.io.IOException ie)
87             {
88                 GlobalLogWriter.get().println("Exception occurs while reading from file " + m_sFilename);
89                 GlobalLogWriter.get().println("Message: " + ie.getMessage());
90                 // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, ie.getMessage());
91             }
92             try
93             {
94                 aReader.close();
95             }
96             catch (java.io.IOException ie)
97             {
98                 GlobalLogWriter.get().println("Couldn't close file " + m_sFilename);
99                 GlobalLogWriter.get().println("Message: " + ie.getMessage());
100                 // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, ie.getMessage());
101             }
102             return aLines;
103         }
104 
105     /**
106      * @return true, if the ini file contain some readable data
107      */
is()108     public boolean is()
109         {
110             return m_aList.size() > 1 ? true : false;
111         }
112 
113     // -----------------------------------------------------------------------------
114 
isRemark(String _sLine)115     boolean isRemark(String _sLine)
116         {
117             if ( ((_sLine.length() < 2) ) ||
118                  ( _sLine.startsWith("#")) ||
119                  ( _sLine.startsWith(";")) )
120             {
121                 return true;
122             }
123             return false;
124         }
125 
getItem(int i)126     String getItem(int i)
127         {
128             return (String)m_aList.get(i);
129         }
130 
buildSectionName(String _sSectionName)131     String buildSectionName(String _sSectionName)
132         {
133             String sFindSection = "[" + _sSectionName + "]";
134             return sFindSection;
135         }
toLowerIfNeed(String _sName)136     String toLowerIfNeed(String _sName)
137         {
138             return _sName.toLowerCase();
139         }
140 
141     // return the number where this section starts
findSection(String _sSection)142     int findSection(String _sSection)
143         {
144             String sFindSection = toLowerIfNeed(buildSectionName(_sSection));
145             // ----------- find _sSection ---------------
146             int i;
147             for (i=0; i<m_aList.size();i++)
148             {
149                 String sLine = toLowerIfNeed(getItem(i).trim());
150                 if (isRemark(sLine))
151             {
152                     continue;
153                 }
154                 if (sFindSection.equals("[]"))
155                 {
156                     // special case, empty Section.
157                     return i - 1;
158                 }
159                 if (sLine.startsWith(sFindSection))
160                 {
161                     return i;
162                 }
163             }
164             return -1;
165         }
166 
167     // return the line number, where the key is found.
findKey(String _sSection, String _sKey)168     int findKey(String _sSection, String _sKey)
169         {
170             int i = findSection(_sSection);
171             if (i == -1)
172             {
173                 // Section not found, therefore the value can't exist
174                 return -1;
175             }
176             return findKeyFromKnownSection(i, _sKey);
177         }
178 
179     // i must be the index in the list, where the well known section starts
findKeyFromKnownSection(int _nSectionIndex, String _sKey)180     int findKeyFromKnownSection(int _nSectionIndex, String _sKey)
181         {
182             _sKey = toLowerIfNeed(_sKey);
183             for (int j=_nSectionIndex + 1; j<m_aList.size();j++)
184             {
185                 String sLine = getItem(j).trim();
186 
187                 if (isRemark(sLine))
188                 {
189                     continue;
190                 }
191 
192                 if (sLine.startsWith("[") /* && sLine.endsWith("]") */)
193                 {
194                     // found end.
195                     break;
196                 }
197 
198                 int nEqual = sLine.indexOf("=");
199                 if (nEqual >= 0)
200                 {
201                     String sKey = toLowerIfNeed(sLine.substring(0, nEqual).trim());
202                     if (sKey.equals(_sKey))
203                     {
204                         return j;
205                     }
206             }
207             }
208             return -1;
209         }
210 
211     // i must be the index in the list, where the well known section starts
findLastKnownKeyIndex(int _nSectionIndex, String _sKey)212     int findLastKnownKeyIndex(int _nSectionIndex, String _sKey)
213         {
214             _sKey = toLowerIfNeed(_sKey);
215             int i = _nSectionIndex + 1;
216             for (int j=i; j<m_aList.size();j++)
217             {
218                 String sLine = getItem(j).trim();
219 
220                 if (isRemark(sLine))
221                 {
222                     continue;
223                 }
224 
225                 if (sLine.startsWith("[") /* && sLine.endsWith("]") */)
226                 {
227                     // found end.
228                     return j;
229                 }
230 
231                 int nEqual = sLine.indexOf("=");
232                 if (nEqual >= 0)
233                 {
234                     String sKey = toLowerIfNeed(sLine.substring(0, nEqual).trim());
235                     if (sKey.equals(_sKey))
236                     {
237                         return j;
238                     }
239                 }
240             }
241             return i;
242         }
243 
getValue(int _nIndex)244     String getValue(int _nIndex)
245         {
246             String sLine = getItem(_nIndex).trim();
247             if (isRemark(sLine))
248             {
249                 return "";
250             }
251             int nEqual = sLine.indexOf("=");
252             if (nEqual >= 0)
253             {
254                 String sKey =   sLine.substring(0, nEqual).trim();
255                 String sValue = sLine.substring(nEqual + 1).trim();
256                 return sValue;
257                     }
258             return "";
259                 }
260 
261     /**
262        @param _sSection string
263        @param _sKey string
264        @return the value found in the inifile which is given by the section and key parameter
265     */
getValue(String _sSection, String _sKey)266     public String getValue(String _sSection, String _sKey)
267         {
268             String sValue = "";
269             int i = findKey(_sSection, _sKey);
270             if (i == -1)
271             {
272                 // Section not found, therefore the value can't exist
273                 return "";
274             }
275 
276             sValue = getValue(i);
277 
278             return sValue;
279         }
280 
281     /**
282        write back the ini file to the disk, only if there exist changes
283     */
store()284     public void store()
285         {
286             if (m_bListContainUnsavedChanges == false)
287             {
288                 // nothing has changed, so no need to store
289                 return;
290             }
291 
292             File aFile = new File(m_sFilename);
293             if (aFile.exists())
294             {
295                 // System.out.println("couldn't find file " + m_sFilename);
296                 aFile.delete();
297                 if (aFile.exists())
298                 {
299                     GlobalLogWriter.get().println("Couldn't delete the file " + m_sFilename);
300                     return;
301                     // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, "Couldn't delete the file " + m_sFilename);
302                 }
303             }
304             // if (! aFile.canWrite())
305             // {
306             //    System.out.println("Couldn't write to file " + m_sFilename);
307             //    DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, "");
308             // }
309             try
310             {
311                 RandomAccessFile aWriter = new RandomAccessFile(aFile, "rw");
312                 for (int i=0; i<m_aList.size();i++)
313                 {
314                     String sLine = getItem(i);
315                     aWriter.writeBytes(sLine);
316                     aWriter.writeByte((int)'\n');
317                 }
318                 aWriter.close();
319             }
320 
321             catch (java.io.FileNotFoundException fne)
322             {
323                 GlobalLogWriter.get().println("couldn't open file for writing " + m_sFilename);
324                 GlobalLogWriter.get().println("Message: " + fne.getMessage());
325                 // DebugHelper.exception(BasicErrorCode.SbERR_FILE_NOT_FOUND, "");
326             }
327             catch(java.io.IOException ie)
328             {
329                 GlobalLogWriter.get().println("Exception occurs while writing to file " + m_sFilename);
330                 GlobalLogWriter.get().println("Message: " + ie.getMessage());
331                 // DebugHelper.exception(BasicErrorCode.SbERR_INTERNAL_ERROR, ie.getMessage());
332             }
333         }
334 
335 
336 
337     /**
338        insert a value
339        there are 3 cases
340        1. section doesn't exist, goto end and insert a new section, insert a new key value pair
341        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
342        3. section exist and key exist, remove the old key and insert the key value pair at the same position
343     */
insertValue(String _sSection, String _sKey, String _sValue)344     public void insertValue(String _sSection, String _sKey, String _sValue)
345         {
346             int i = findSection(_sSection);
347             if (i == -1)
348             {
349                 // case 1: section doesn't exist
350                 String sFindSection = buildSectionName(_sSection);
351 
352                 m_aList.add(sFindSection);
353                 String sKeyValuePair = _sKey + "=" + _sValue;
354                 m_aList.add(sKeyValuePair);
355                 m_bListContainUnsavedChanges = true;
356                 return;
357             }
358             int j = findKeyFromKnownSection(i, _sKey);
359             if (j == -1)
360             {
361                 // case 2: section exist, but not the key
362                 j = findLastKnownKeyIndex(i, _sKey);
363                 String sKeyValuePair = _sKey + "=" + _sValue;
364                 m_aList.add(j, sKeyValuePair);
365                 m_bListContainUnsavedChanges = true;
366                 return;
367             }
368             else
369             {
370                 // case 3: section exist, and also the key
371                 String sKeyValuePair = _sKey + "=" + _sValue;
372                 m_aList.set(j, sKeyValuePair);
373                 m_bListContainUnsavedChanges = true;
374             }
375         }
376     // -----------------------------------------------------------------------------
377     // String replaceEvaluatedValue(String _sSection, String _sValue)
378     //     {
379     //         String sValue = _sValue;
380     //         int nIndex = 0;
381     //         while (( nIndex = sValue.indexOf("$(", nIndex)) >= 0)
382     //         {
383     //             int nNextIndex = sValue.indexOf(")", nIndex);
384     //             if (nNextIndex >= 0)
385     //             {
386     //                 String sKey = sValue.substring(nIndex + 2, nNextIndex);
387     //                 String sNewValue = getValue(_sSection, sKey);
388     //                 if (sNewValue != null && sNewValue.length() > 0)
389     //                 {
390     //                     String sRegexpKey = "\\$\\(" + sKey + "\\)";
391     //                     sValue = sValue.replaceAll(sRegexpKey, sNewValue);
392     //                 }
393     //                 nIndex = nNextIndex;
394     //             }
395     //             else
396     //             {
397     //                 nIndex += 2;
398     //             }
399     //         }
400     //         return sValue;
401     //     }
402     // -----------------------------------------------------------------------------
403 
404     // public String getLocalEvaluatedValue(String _sSection, String _sKey)
405     //     {
406     //         String sValue = getValue(_sSection, _sKey);
407     //         sValue = replaceEvaluatedValue(_sSection, sValue);
408     //         return sValue;
409     //     }
410 
411     // -----------------------------------------------------------------------------
412 
413     // this is a special behaviour.
414     // public String getGlobalLocalEvaluatedValue(String _sSection, String _sKey)
415     //     {
416     //         String sGlobalValue = getKey("global", _sKey);
417     //         String sLocalValue = getKey(_sSection, _sKey);
418     //         if (sLocalValue.length() == 0)
419     //         {
420     //             sGlobalValue = replaceEvaluatedKey(_sSection, sGlobalValue);
421     //             sGlobalValue = replaceEvaluatedKey("global", sGlobalValue);
422     //             return sGlobalValue;
423     //         }
424     //         sLocalValue = replaceEvaluatedKey(_sSection, sLocalValue);
425     //         sLocalValue = replaceEvaluatedKey("global", sLocalValue);
426     //
427     //         return sLocalValue;
428     //     }
429 
430 
431     /**
432      * some tests for this class
433      */
434 //    public static void main(String[] args)
435 //        {
436 //            IniFile aIniFile = new IniFile("/tmp/inifile");
437 //            String sValue = aIniFile.getValue("Section","Key");
438 //            // insert a new value to a already exist section
439 //            aIniFile.insertValue("Section","Key2","a new value in a existing section");
440 //            // replace a value
441 //            aIniFile.insertValue("Section","Key","replaced value");
442 //            // create a new value
443 //            aIniFile.insertValue("New Section", "Key", "a new key value pair");
444 //
445 //            String sValue2 = aIniFile.getValue("Section2","Key");
446 //            aIniFile.store();
447 //        }
448 }
449