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
);
70 public void loadProperties_sub(Properties pr
)
72 for (Enumeration e
= pr
.keys(); e
.hasMoreElements(); )
74 String key
= (String
) e
.nextElement();
76 /* fields with !! always have precedence */
77 if (key
.startsWith("!!"))
78 db
.put(key
.substring(2),(String
)pr
.get(key
));
80 /* fields with ++ are always added, not just overwritten */
81 else if (key
.startsWith("++"))
82 add(key
.substring(2),(String
)pr
.get(key
));
84 /* in this loading mode we do not overwrite existing fields */
85 else if (!db
.containsKey(key
))
86 set(key
,(String
)pr
.get(key
));
91 public void loadProperties_top(Properties pr
)
93 for (Enumeration e
= pr
.keys(); e
.hasMoreElements(); )
95 String key
= (String
) e
.nextElement();
96 if (key
.startsWith("!!"))
97 set(key
.substring(2),(String
)pr
.get(key
));
98 else if (key
.startsWith("++"))
99 add(key
.substring(2),(String
)pr
.get(key
));
101 set(key
,(String
)pr
.get(key
));
105 private Properties
_load_properties(String filename
)
107 if (enable_datasource_cache
)
109 if (db_recycling
==null)
110 db_recycling
= new Hashtable();
112 dbcache_ent ent
= (dbcache_ent
)db_recycling
.get(filename
);
115 // System.err.println("Found in cache: "+filename);
119 ent
= new dbcache_ent();
120 ent
.proplist
= new Properties();
121 if (!TextDB
.LoadIntoHashtable(filename
,ent
.proplist
))
123 // System.err.println("Could not load: "+filename);
127 // System.err.println("Loaded: "+filename);
129 db_recycling
.put(filename
,ent
);
134 Properties pr
= new Properties();
135 if (!TextDB
.LoadIntoHashtable(filename
,pr
))
142 public void remove ( String key
)
148 public void set ( String key
, String value
)
154 public void add ( String key
, String value
)
157 if ((key
==null)||(value
==null)) return;
159 if ((got
=db_get(key
))!=null)
160 db
.put(key
,got
+"\n"+value
);
165 // can be overwritten, ie for namespace handling, hierachies, etc
166 public String
get_raw(String name
)
169 if (name
.startsWith(":URLENCODE:"))
171 name
= name
.substring(11);
172 return URLEncoder
.encode(get_str(name
));
178 public String
get_str(String name
)
181 return get_str_rec(name
,100);
184 public String
[] get_list(String name
)
187 return StrSplit
.split(get_str(name
));
190 /* can be overwritten in order to handle special things like exec()
191 returns null if nothing happened */
192 public String
handle_special_str(String key
)
197 public boolean get_bool(String name
, boolean def
)
201 return get_bool(name
);
203 catch (EIllegalValue e
)
209 public boolean get_bool(String name
) throws EIllegalValue
211 String val
=get_str(name
);
214 return StrUtil
.toBool(val
);
216 catch (NumberFormatException e
)
218 throw new EIllegalValue(name
,val
);
222 private final String
get_str_rec(String key
, int depth
)
226 throw new EInfiniteRecursion(key
,get_raw(key
));
228 /* if we someday want to add special vars/commands, this
229 would probably be the right point */
232 boolean notnull
= false;
233 boolean notempty
= false;
235 /* handle subclass-defined specials */
236 if ((value
=handle_special_str(key
))!=null)
239 /* -- parse special modifiers -- */
240 for (boolean parsing
=true; parsing
;)
242 if (key
.startsWith("!notnull!"))
245 key
= key
.substring(9);
247 else if (key
.startsWith("!notempty!"))
250 key
= key
.substring(10);
256 if ((value
=get_raw(key
))==null)
259 throw new EVariableNull(key
,value
);
264 /* --- now replace variables --- */
267 while ((start
=value
.indexOf("$("))!=-1) /* scan for $( */
269 if ((end
=value
.indexOf(')', start
+2))!=-1)
271 String name
= value
.substring(start
+2,end
);
273 value
.substring(0,start
)+
274 get_str_rec(name
,depth
-1)+
275 value
.substring(end
+1);
280 throw new EVariableParseError(key
,value
);
283 if (value
.equals("") && notempty
)
284 throw new EVariableEmpty(key
,value
);
292 for (Enumeration e
= db
.keys(); e
.hasMoreElements(); )
294 String key
= (String
) e
.nextElement();
295 res
+= key
+"=\""+db_get(key
)+"\"\n";
300 public boolean load_content(String field
, File filename
, boolean strip_comments
)
302 String text
= datasource_cache
.loadContent(filename
,strip_comments
);
310 public boolean load_content(String field
, URL url
, boolean strip_comments
)
312 String text
= datasource_cache
.loadContent(url
,strip_comments
);
320 public Enumeration
propertyNames()
325 public IPropertylist
clone()
327 Propertylist pr
= new Propertylist();
328 pr
.db
= (Properties
)db
.clone();
331 for (Enumeration keys
= db
.keys(); keys
.hasMoreElements(); )
333 String k
= (String
)keys
.nextElement();
339 public String
toString()
341 String str
= "[PROPERTYLIST]\n";
342 for (Enumeration keys
= db
.keys(); keys
.hasMoreElements(); )
344 String k
= (String
)keys
.nextElement();
345 str
+= k
+"=\""+db_get(k
)+"\"\n";