KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > util > ExtendedProperties


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10 package org.mmbase.util;
11
12 import java.io.BufferedInputStream JavaDoc;
13 import java.io.BufferedOutputStream JavaDoc;
14 import java.io.File JavaDoc;
15 import java.io.FileInputStream JavaDoc;
16 import java.io.FileNotFoundException JavaDoc;
17 import java.io.FileOutputStream JavaDoc;
18 import java.io.IOException JavaDoc;
19 import java.io.InputStream JavaDoc;
20 import java.io.RandomAccessFile JavaDoc;
21 import java.util.Date JavaDoc;
22 import java.util.Enumeration JavaDoc;
23 import java.util.Hashtable JavaDoc;
24 import java.util.Properties JavaDoc;
25 import java.util.StringTokenizer JavaDoc;
26 import java.util.Vector JavaDoc;
27
28 import org.mmbase.util.logging.Logger;
29 import org.mmbase.util.logging.Logging;
30
31 /**
32  * This is a flexible Properties version, it can handle saving of Properties with
33  * the comments that will stay in your file.
34  * @author Jan van Oosterom
35  * @version $Id: ExtendedProperties.java,v 1.9 2005/11/30 15:58:04 pierre Exp $
36  */

37 public class ExtendedProperties extends Properties JavaDoc {
38     // logger
39
private static Logger log = Logging.getLoggerInstance(ExtendedProperties.class.getName());
40
41     /**
42      * A table of hex digits
43      */

44     private static char[] hexDigit = {
45         '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
46     };
47
48     /**
49     * The prefix of the comment in the Properties file.
50     * Everything after it will be treaded as comment
51     */

52     protected String JavaDoc commentPrefix = "#";
53
54     /**
55      * Extended Properties constructor
56      */

57     public ExtendedProperties() {
58     }
59
60     /**
61     * Create and read an ExtendedProperty from file.
62     * @param filename The file from were to read.
63     */

64     public ExtendedProperties(String JavaDoc filename) {
65         try {
66             getProps(filename);
67         } catch (IOException JavaDoc e) {
68             log.error("Failed to load the ExtendedProperties for: "+ filename);
69         }
70     }
71
72     /**
73     * Create an ExtendedProperties with a Allready filled ExtendedProperty list.
74     * @param exProp The list that will be put in this ExtendedProperty.
75     */

76     public ExtendedProperties(ExtendedProperties exProp) {
77 // super((Properties) exProp);
78
super(exProp);
79     }
80
81
82     /**
83     * Read from Properties and return them.
84     * @param filename The file from were to read the Properties.
85     */

86     public Hashtable JavaDoc readProperties(String JavaDoc filename) {
87         clear();
88         try {
89             getProps(filename);
90         } catch (IOException JavaDoc e) {
91             log.debug("Failed to load the ExtendedProperties from: "+ filename, e);
92         }
93         ExtendedProperties propsToReturn = new ExtendedProperties();
94         Enumeration JavaDoc e = keys();
95         while (e.hasMoreElements()) {
96             String JavaDoc s = (String JavaDoc) e.nextElement();
97             propsToReturn.put(s,get(s));
98         }
99         return propsToReturn;
100     }
101
102     /**
103     * save Properties to file.
104     * @param filename The File were to save them
105     * @param propsToSave The Properties which to save.
106     */

107     public synchronized void saveProperties(String JavaDoc filename, Hashtable JavaDoc propsToSave) {
108         clear();
109         Enumeration JavaDoc e = propsToSave.keys();
110         while (e.hasMoreElements()) {
111             String JavaDoc s = (String JavaDoc) e.nextElement();
112             put(s,propsToSave.get(s));//ROB
113
}
114         try {
115             save(filename);
116         } catch (IOException JavaDoc ioe) {
117             log.error("Fail to save the ExtendedProperties to: " + filename+" : "+ioe);
118         }
119     }
120
121     /**
122     * return a Vector of Strings which is parsed from a specified Property.
123     * @param whichProp The Property to get the list from.
124     * @param delimeter The delimeter to split wichProp's value with.
125     */

126     public Vector JavaDoc getPropertyValues(String JavaDoc whichProp, String JavaDoc delimeter) {
127         Vector JavaDoc parsedPropsToReturn = new Vector JavaDoc();
128         if (containsKey(whichProp)) {
129             //whichProp is available in this Property list
130
String JavaDoc value = (String JavaDoc) get(whichProp);
131             StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(value,delimeter);
132             while (tok.hasMoreTokens()) {
133                 parsedPropsToReturn.addElement(tok.nextToken());
134             }
135             return parsedPropsToReturn;
136         } else {
137             //whichProp is not available in this Property list
138
//log.debug("ExtendedProperties.getParsedProperty: " + whichProp + " not found." );
139
return null;
140         }
141     }
142
143     /**
144     * Read to this Property, the Properties from a file.
145     * @param filename The file were to read from
146     */

147     public void getProps(String JavaDoc filename) throws IOException JavaDoc {
148         try {
149             FileInputStream JavaDoc fileInputStream = new FileInputStream JavaDoc(filename);
150             BufferedInputStream JavaDoc bufferedInputStream = new BufferedInputStream JavaDoc (fileInputStream);
151             load(bufferedInputStream);
152             bufferedInputStream.close();
153         } catch (FileNotFoundException JavaDoc e ) {
154             log.debug("ExtendedProperties:: file " + filename + " not found");
155         }
156     }
157
158
159     /**
160      * Loads properties from an InputStream.
161      * Uses "=" as delimeter between key and value.
162      * Does <B> not </B> uses a ":" as delimiter!
163      * @param in the input stream
164      * @exception IOException Error when reading from input stream.
165      */

166     public synchronized void load(InputStream JavaDoc in) throws IOException JavaDoc {
167         in = Runtime.getRuntime().getLocalizedInputStream(in);
168
169         int ch = in.read();
170         while (ch != -1) {
171             switch (ch) {
172               case '#':
173               case '!':
174                 do {
175                     ch = in.read();
176                 } while ((ch >= 0) && (ch != '\n') && (ch != '\r'));
177                 continue;
178
179               case '\n':
180               case '\r':
181               case ' ':
182               case '\t':
183                 ch = in.read();
184                 continue;
185             }
186
187             // Read the key
188
StringBuffer JavaDoc key = new StringBuffer JavaDoc();
189
190             while ((ch >= 0) && (ch != '=') && (ch != ' ') && (ch != '\t') && (ch != '\n') && (ch != '\r')) {
191                 key.append((char)ch);
192                 ch = in.read();
193             }
194             while ((ch == ' ') && (ch == '\t')) {
195                 ch = in.read();
196             }
197             if ((ch == '=') || (ch == ':')) {
198                 ch = in.read();
199             }
200             while ((ch == ' ') && (ch == '\t')) {
201                 ch = in.read();
202             }
203
204             // Read the value
205
StringBuffer JavaDoc val = new StringBuffer JavaDoc();
206             while ((ch >= 0) && (ch != '\n') && (ch != '\r')) {
207                 if (ch == '\\') {
208                     switch (ch = in.read()) {
209                       case '\r':
210                     if (((ch = in.read()) == '\n') ||
211                         (ch == ' ') || (ch == '\t')) {
212                       // fall thru to '\n' case
213
} else continue;
214                       case '\n':
215                     while (((ch = in.read()) == ' ') || (ch == '\t'));
216                     continue;
217                       case 't': ch = '\t'; break;
218                       case 'n': ch = '\n'; break;
219                       case 'r': ch = '\r'; break;
220                       case 'u': {
221                     while ((ch = in.read()) == 'u');
222                     int d = 0;
223                       loop:
224                     for (int i = 0 ; i < 4 ; i++, ch = in.read()) {
225                         switch (ch) {
226                           case '0': case '1': case '2': case '3': case '4':
227                           case '5': case '6': case '7': case '8': case '9':
228                         d = (d << 4) + ch - '0';
229                         break;
230                           case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
231                         d = (d << 4) + 10 + ch - 'a';
232                         break;
233                           case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
234                         d = (d << 4) + 10 + ch - 'A';
235                         break;
236                           default:
237                         break loop;
238                         }
239                     }
240                     ch = d;
241                       }
242                     }
243                 }
244                 val.append((char)ch);
245                 ch = in.read();
246             }
247             put(key.toString(), val.toString());
248         }
249     }
250
251     /**
252     * Warning: this routine destroys your comments in your properties file.
253     * But it save's your Properties (If that is all that U want :-)
254     * @param filename The File were to save your Properties
255     * @param header If you want you can speciefy a header (on top of you file)
256     */

257      private void write (String JavaDoc filename, String JavaDoc header) throws IOException JavaDoc {
258         FileOutputStream JavaDoc fileOutputStream = new FileOutputStream JavaDoc(filename);
259         BufferedOutputStream JavaDoc bufferedOutputStream = new BufferedOutputStream JavaDoc(fileOutputStream);
260         save(bufferedOutputStream, header);
261         bufferedOutputStream.close();
262     }
263
264
265     /**
266     * This routine does not only saves your Properties but also
267     * merges your comments if the file already exists
268     * if the file doesn't exists the will call the "normal" write routine.
269     * @param filename The file were to save to.
270     */

271     public synchronized void save(String JavaDoc filename) throws IOException JavaDoc {
272         File JavaDoc file = new File JavaDoc (filename);
273         boolean des = false; // for skipping enters when destroying some info
274
if (file.exists()) {
275             ExtendedProperties copyOfProps = (ExtendedProperties) this.clone();
276             //the file exists so we have to merge
277
String JavaDoc newlines = "";
278             String JavaDoc lines = readOldProps(file);
279
280             StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(lines,"\n",true);
281             while(tok.hasMoreTokens()) {
282                 String JavaDoc line =(String JavaDoc) tok.nextElement();
283                 // Is it a comment
284
if (line.startsWith(commentPrefix)) {
285                     newlines = newlines + line;
286                 } else {
287                     int index = line.indexOf('=');
288                     if (index == -1) {
289                         //assuming a empty line ....
290
if (!des) {
291                             newlines = newlines + "\n";
292                         } else {
293                             des = false;
294                         }
295                     } else {
296                         //we found a new property value in the props file
297
String JavaDoc name = line.substring(0,index);
298
299                         if (containsKey(name)) {
300                             //this Property is in memory so get this one from memory
301
newlines = newlines + name + "=" + getProperty(name);
302                             //remove it from the copy
303
copyOfProps.remove(name);
304                         } else {
305                             //Thats odd, this one is not in memory
306
//Well we didn't used it so leave it there and use the old one
307
des = true;
308                     /* newlines = newlines + line;*/
309                         }
310
311                     }
312                 }
313             }
314
315             //everything that is left in the copy should be written also:
316
Enumeration JavaDoc e = copyOfProps.keys();
317             while (e.hasMoreElements()) {
318                 String JavaDoc name = (String JavaDoc) e.nextElement();
319                 newlines = newlines + "\n" + name + "=" + copyOfProps.getProperty(name);
320             }
321             //newlines = newlines + "\n";
322

323             file.delete();
324             //save the file:
325
RandomAccessFile JavaDoc writefile = new RandomAccessFile JavaDoc(file,"rw");
326             writefile.writeBytes(newlines);
327             writefile.close();
328         } else {
329             //the file does not exists so we can use the simple write routine
330
//there is nothing to merge
331
write(filename, "");
332         }
333     }
334
335     /**
336     * Read a file and returns everything in a String.
337     * @param file The File were to read from (has to exsists).
338     */

339     private String JavaDoc readOldProps(File JavaDoc file) throws IOException JavaDoc {
340         String JavaDoc line = "";
341
342         String JavaDoc lines = "";
343         RandomAccessFile JavaDoc readfile = new RandomAccessFile JavaDoc(file,"r");
344         do {
345             try {
346                 line = readfile.readLine();
347                 if (line != null) {
348                   lines= lines + line + "\n";
349                 }
350             } catch(Exception JavaDoc e) {
351                 log.error("EOF!");
352             }
353         } while (line != null);
354
355         if (!lines.equals("")) {
356             lines = lines.substring(0,lines.length()-1);
357         }
358         readfile.close();
359         return lines;
360     }
361
362     /**
363     * Set the Property.
364     * @param name the name of the Property (the part in front of the '=' in the Property file)
365     * @param value the (new) value of the Property (the part after the '=' in the Property file)
366     */

367     public Object JavaDoc setProperty(String JavaDoc name, String JavaDoc value) {
368         return(put(name, value));
369     }
370
371     /**
372     * Dump the contents of this Property to your screen (for debugging)
373     */

374     public void showContents() {
375         Enumeration JavaDoc names = propertyNames();
376         while (names.hasMoreElements()) {
377             String JavaDoc name = (String JavaDoc) names.nextElement();
378             log.debug(name + "=" + getProperty(name));
379         }
380     }
381
382     public synchronized String JavaDoc save() {
383         StringBuffer JavaDoc b=new StringBuffer JavaDoc();
384         b.append('#');
385         b.append(new Date JavaDoc());
386         b.append('\n');
387
388         for (Enumeration JavaDoc e = keys() ; e.hasMoreElements() ;) {
389             String JavaDoc key = (String JavaDoc)e.nextElement();
390             b.append(key);
391             b.append('=');
392
393             String JavaDoc val = (String JavaDoc)get(key);
394             int len = val.length();
395             if (len>0) b.append(val);
396             b.append('\n');
397         }
398         return(b.toString());
399     }
400 }
401
Popular Tags