3 // FIXME: replace Hashtable by Properties
6 package org
.de
.metux
.propertylist
;
9 import java
.util
.Enumeration
;
10 import java
.util
.Hashtable
;
11 import java
.util
.Properties
;
13 import java
.lang
.NumberFormatException
;
15 import org
.de
.metux
.util
.StrSplit
;
16 import org
.de
.metux
.util
.TextDB
;
17 import org
.de
.metux
.util
.UniqueNameList
;
18 import org
.de
.metux
.util
.LoadFile
;
19 import org
.de
.metux
.util
.StrUtil
;
20 import org
.de
.metux
.util
.CachedDatasource
;
22 import java
.net
.URLEncoder
;
26 public class Propertylist
implements IPropertylist
28 Properties db
= new Properties();
29 Properties cache
= new Properties();
30 IPostprocessor postprocessor
;
32 public boolean enable_datasource_cache
= false;
33 public static Hashtable db_recycling
= null;
34 public static CachedDatasource datasource_cache
= new CachedDatasource();
36 private class dbcache_ent
38 public Properties proplist
;
42 /* this method loads data from a hashtable into the propertysheet
43 with low priority, means that existing fields are not touched.
45 the opposite would be high priority meaning existing fields
49 public void setPostprocessor(IPostprocessor p
)
54 public void runPostprocessor()
57 if (postprocessor
==null)
60 /* run as long as it returns true */
61 while(postprocessor
.propertylist_postprocess((IPropertylist
)this));
64 /* get a really raw string, directly from database */
65 public String
db_get(String field
)
67 return (String
)db
.get(field
);
71 public void loadHash_sub(Hashtable h
)
73 for (Enumeration e
= h
.keys(); e
.hasMoreElements(); )
75 String key
= (String
) e
.nextElement();
77 /* fields with !! always have precedence */
78 if (key
.startsWith("!!"))
79 db
.put(key
.substring(2),(String
)h
.get(key
));
81 /* fields with ++ are always added, not just overwritten */
82 else if (key
.startsWith("++"))
83 add(key
.substring(2),(String
)h
.get(key
));
85 /* in this loading mode we do not overwrite existing fields */
86 else if (!db
.containsKey(key
))
87 set(key
,(String
)h
.get(key
));
92 public void loadProperties_sub(Properties pr
)
94 for (Enumeration e
= pr
.keys(); e
.hasMoreElements(); )
96 String key
= (String
) e
.nextElement();
98 /* fields with !! always have precedence */
99 if (key
.startsWith("!!"))
100 db
.put(key
.substring(2),(String
)pr
.get(key
));
102 /* fields with ++ are always added, not just overwritten */
103 else if (key
.startsWith("++"))
104 add(key
.substring(2),(String
)pr
.get(key
));
106 /* in this loading mode we do not overwrite existing fields */
107 else if (!db
.containsKey(key
))
108 set(key
,(String
)pr
.get(key
));
113 public void loadHash_low(Hashtable h
)
121 public void loadHash_top(Hashtable h
)
123 for (Enumeration e
= h
.keys(); e
.hasMoreElements(); )
125 String key
= (String
) e
.nextElement();
126 if (key
.startsWith("!!"))
127 set(key
.substring(2),(String
)h
.get(key
));
128 else if (key
.startsWith("++"))
129 add(key
.substring(2),(String
)h
.get(key
));
131 set(key
,(String
)h
.get(key
));
135 public void loadProperties_top(Properties pr
)
137 for (Enumeration e
= pr
.keys(); e
.hasMoreElements(); )
139 String key
= (String
) e
.nextElement();
140 if (key
.startsWith("!!"))
141 set(key
.substring(2),(String
)pr
.get(key
));
142 else if (key
.startsWith("++"))
143 add(key
.substring(2),(String
)pr
.get(key
));
145 set(key
,(String
)pr
.get(key
));
149 private Properties
_load_properties(String filename
)
151 if (enable_datasource_cache
)
153 if (db_recycling
==null)
154 db_recycling
= new Hashtable();
156 dbcache_ent ent
= (dbcache_ent
)db_recycling
.get(filename
);
159 // System.err.println("Found in cache: "+filename);
163 ent
= new dbcache_ent();
164 ent
.proplist
= new Properties();
165 if (!TextDB
.LoadIntoHashtable(filename
,ent
.proplist
))
167 // System.err.println("Could not load: "+filename);
171 // System.err.println("Loaded: "+filename);
173 db_recycling
.put(filename
,ent
);
178 Properties pr
= new Properties();
179 if (!TextDB
.LoadIntoHashtable(filename
,pr
))
186 public boolean loadTextDB_low(String filename
)
189 Properties pr
= _load_properties(filename
);
196 public boolean loadTextDB_sub(String filename
)
198 Properties pr
= _load_properties(filename
);
201 // System.err.println("Couldnt load properties from: "+filename);
208 public boolean loadTextDB_top(File filename
)
210 return loadTextDB_top(filename
.toString());
213 public boolean loadTextDB_top(String filename
)
215 Properties pr
= _load_properties(filename
);
224 public void remove ( String key
)
230 public void set ( String key
, String value
)
236 public void add ( String key
, String value
)
239 if ((key
==null)||(value
==null)) return;
241 if ((got
=db_get(key
))!=null)
242 db
.put(key
,got
+"\n"+value
);
247 // can be overwritten, ie for namespace handling, hierachies, etc
248 public String
get_raw(String name
)
251 if (name
.startsWith(":URLENCODE:"))
253 name
= name
.substring(11);
254 return URLEncoder
.encode(get_str(name
));
260 public String
get_str(String name
)
263 return get_str_rec(name
,100);
266 public String
[] get_list(String name
)
269 return StrSplit
.split(get_str(name
));
272 /* can be overwritten in order to handle special things like exec()
273 returns null if nothing happened */
274 public String
handle_special_str(String key
)
279 public boolean get_bool(String name
, boolean def
)
283 return get_bool(name
);
285 catch (EIllegalValue e
)
291 public boolean get_bool(String name
) throws EIllegalValue
293 String val
=get_str(name
);
296 return StrUtil
.toBool(val
);
298 catch (NumberFormatException e
)
300 throw new EIllegalValue(name
,val
);
304 private final String
get_str_rec(String key
, int depth
)
308 throw new EInfiniteRecursion(key
,get_raw(key
));
310 /* if we someday want to add special vars/commands, this
311 would probably be the right point */
314 boolean notnull
= false;
315 boolean notempty
= false;
317 /* handle subclass-defined specials */
318 if ((value
=handle_special_str(key
))!=null)
321 /* -- parse special modifiers -- */
322 for (boolean parsing
=true; parsing
;)
324 if (key
.startsWith("!notnull!"))
327 key
= key
.substring(9);
329 else if (key
.startsWith("!notempty!"))
332 key
= key
.substring(10);
338 if ((value
=get_raw(key
))==null)
341 throw new EVariableNull(key
,value
);
346 /* --- now replace variables --- */
349 while ((start
=value
.indexOf("$("))!=-1) /* scan for $( */
351 if ((end
=value
.indexOf(')', start
+2))!=-1)
353 String name
= value
.substring(start
+2,end
);
355 value
.substring(0,start
)+
356 get_str_rec(name
,depth
-1)+
357 value
.substring(end
+1);
362 throw new EVariableParseError(key
,value
);
365 if (value
.equals("") && notempty
)
366 throw new EVariableEmpty(key
,value
);
374 for (Enumeration e
= db
.keys(); e
.hasMoreElements(); )
376 String key
= (String
) e
.nextElement();
377 res
+= key
+"=\""+db_get(key
)+"\"\n";
382 public boolean load_content(String field
, File filename
, boolean strip_comments
)
384 String text
= datasource_cache
.loadContent(filename
,strip_comments
);
392 public boolean load_content(String field
, URL url
, boolean strip_comments
)
394 String text
= datasource_cache
.loadContent(url
,strip_comments
);
402 public Enumeration
propertyNames()
407 public IPropertylist
clone()
409 Propertylist pr
= new Propertylist();
410 pr
.db
= (Properties
)db
.clone();
413 for (Enumeration keys
= db
.keys(); keys
.hasMoreElements(); )
415 String k
= (String
)keys
.nextElement();
421 public String
toString()
423 String str
= "[PROPERTYLIST]\n";
424 for (Enumeration keys
= db
.keys(); keys
.hasMoreElements(); )
426 String k
= (String
)keys
.nextElement();
427 str
+= k
+"=\""+db_get(k
)+"\"\n";