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
));
114 public void loadHash_top(Hashtable h
)
116 for (Enumeration e
= h
.keys(); e
.hasMoreElements(); )
118 String key
= (String
) e
.nextElement();
119 if (key
.startsWith("!!"))
120 set(key
.substring(2),(String
)h
.get(key
));
121 else if (key
.startsWith("++"))
122 add(key
.substring(2),(String
)h
.get(key
));
124 set(key
,(String
)h
.get(key
));
128 public void loadProperties_top(Properties pr
)
130 for (Enumeration e
= pr
.keys(); e
.hasMoreElements(); )
132 String key
= (String
) e
.nextElement();
133 if (key
.startsWith("!!"))
134 set(key
.substring(2),(String
)pr
.get(key
));
135 else if (key
.startsWith("++"))
136 add(key
.substring(2),(String
)pr
.get(key
));
138 set(key
,(String
)pr
.get(key
));
142 private Properties
_load_properties(String filename
)
144 if (enable_datasource_cache
)
146 if (db_recycling
==null)
147 db_recycling
= new Hashtable();
149 dbcache_ent ent
= (dbcache_ent
)db_recycling
.get(filename
);
152 // System.err.println("Found in cache: "+filename);
156 ent
= new dbcache_ent();
157 ent
.proplist
= new Properties();
158 if (!TextDB
.LoadIntoHashtable(filename
,ent
.proplist
))
160 // System.err.println("Could not load: "+filename);
164 // System.err.println("Loaded: "+filename);
166 db_recycling
.put(filename
,ent
);
171 Properties pr
= new Properties();
172 if (!TextDB
.LoadIntoHashtable(filename
,pr
))
179 public boolean loadTextDB_sub(String filename
)
181 Properties pr
= _load_properties(filename
);
184 // System.err.println("Couldnt load properties from: "+filename);
191 public boolean loadTextDB_top(File filename
)
193 return loadTextDB_top(filename
.toString());
196 public boolean loadTextDB_top(String filename
)
198 Properties pr
= _load_properties(filename
);
207 public void remove ( String key
)
213 public void set ( String key
, String value
)
219 public void add ( String key
, String value
)
222 if ((key
==null)||(value
==null)) return;
224 if ((got
=db_get(key
))!=null)
225 db
.put(key
,got
+"\n"+value
);
230 // can be overwritten, ie for namespace handling, hierachies, etc
231 public String
get_raw(String name
)
234 if (name
.startsWith(":URLENCODE:"))
236 name
= name
.substring(11);
237 return URLEncoder
.encode(get_str(name
));
243 public String
get_str(String name
)
246 return get_str_rec(name
,100);
249 public String
[] get_list(String name
)
252 return StrSplit
.split(get_str(name
));
255 /* can be overwritten in order to handle special things like exec()
256 returns null if nothing happened */
257 public String
handle_special_str(String key
)
262 public boolean get_bool(String name
, boolean def
)
266 return get_bool(name
);
268 catch (EIllegalValue e
)
274 public boolean get_bool(String name
) throws EIllegalValue
276 String val
=get_str(name
);
279 return StrUtil
.toBool(val
);
281 catch (NumberFormatException e
)
283 throw new EIllegalValue(name
,val
);
287 private final String
get_str_rec(String key
, int depth
)
291 throw new EInfiniteRecursion(key
,get_raw(key
));
293 /* if we someday want to add special vars/commands, this
294 would probably be the right point */
297 boolean notnull
= false;
298 boolean notempty
= false;
300 /* handle subclass-defined specials */
301 if ((value
=handle_special_str(key
))!=null)
304 /* -- parse special modifiers -- */
305 for (boolean parsing
=true; parsing
;)
307 if (key
.startsWith("!notnull!"))
310 key
= key
.substring(9);
312 else if (key
.startsWith("!notempty!"))
315 key
= key
.substring(10);
321 if ((value
=get_raw(key
))==null)
324 throw new EVariableNull(key
,value
);
329 /* --- now replace variables --- */
332 while ((start
=value
.indexOf("$("))!=-1) /* scan for $( */
334 if ((end
=value
.indexOf(')', start
+2))!=-1)
336 String name
= value
.substring(start
+2,end
);
338 value
.substring(0,start
)+
339 get_str_rec(name
,depth
-1)+
340 value
.substring(end
+1);
345 throw new EVariableParseError(key
,value
);
348 if (value
.equals("") && notempty
)
349 throw new EVariableEmpty(key
,value
);
357 for (Enumeration e
= db
.keys(); e
.hasMoreElements(); )
359 String key
= (String
) e
.nextElement();
360 res
+= key
+"=\""+db_get(key
)+"\"\n";
365 public boolean load_content(String field
, File filename
, boolean strip_comments
)
367 String text
= datasource_cache
.loadContent(filename
,strip_comments
);
375 public boolean load_content(String field
, URL url
, boolean strip_comments
)
377 String text
= datasource_cache
.loadContent(url
,strip_comments
);
385 public Enumeration
propertyNames()
390 public IPropertylist
clone()
392 Propertylist pr
= new Propertylist();
393 pr
.db
= (Properties
)db
.clone();
396 for (Enumeration keys
= db
.keys(); keys
.hasMoreElements(); )
398 String k
= (String
)keys
.nextElement();
404 public String
toString()
406 String str
= "[PROPERTYLIST]\n";
407 for (Enumeration keys
= db
.keys(); keys
.hasMoreElements(); )
409 String k
= (String
)keys
.nextElement();
410 str
+= k
+"=\""+db_get(k
)+"\"\n";