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
));
92 public void loadHash_top(Hashtable h
)
94 for (Enumeration e
= h
.keys(); e
.hasMoreElements(); )
96 String key
= (String
) e
.nextElement();
97 if (key
.startsWith("!!"))
98 set(key
.substring(2),(String
)h
.get(key
));
99 else if (key
.startsWith("++"))
100 add(key
.substring(2),(String
)h
.get(key
));
102 set(key
,(String
)h
.get(key
));
106 public void loadProperties_top(Properties pr
)
108 for (Enumeration e
= pr
.keys(); e
.hasMoreElements(); )
110 String key
= (String
) e
.nextElement();
111 if (key
.startsWith("!!"))
112 set(key
.substring(2),(String
)pr
.get(key
));
113 else if (key
.startsWith("++"))
114 add(key
.substring(2),(String
)pr
.get(key
));
116 set(key
,(String
)pr
.get(key
));
120 private Properties
_load_properties(String filename
)
122 if (enable_datasource_cache
)
124 if (db_recycling
==null)
125 db_recycling
= new Hashtable();
127 dbcache_ent ent
= (dbcache_ent
)db_recycling
.get(filename
);
130 // System.err.println("Found in cache: "+filename);
134 ent
= new dbcache_ent();
135 ent
.proplist
= new Properties();
136 if (!TextDB
.LoadIntoHashtable(filename
,ent
.proplist
))
138 // System.err.println("Could not load: "+filename);
142 // System.err.println("Loaded: "+filename);
144 db_recycling
.put(filename
,ent
);
149 Properties pr
= new Properties();
150 if (!TextDB
.LoadIntoHashtable(filename
,pr
))
157 public void remove ( String key
)
163 public void set ( String key
, String value
)
169 public void add ( String key
, String value
)
172 if ((key
==null)||(value
==null)) return;
174 if ((got
=db_get(key
))!=null)
175 db
.put(key
,got
+"\n"+value
);
180 // can be overwritten, ie for namespace handling, hierachies, etc
181 public String
get_raw(String name
)
184 if (name
.startsWith(":URLENCODE:"))
186 name
= name
.substring(11);
187 return URLEncoder
.encode(get_str(name
));
193 public String
get_str(String name
)
196 return get_str_rec(name
,100);
199 public String
[] get_list(String name
)
202 return StrSplit
.split(get_str(name
));
205 /* can be overwritten in order to handle special things like exec()
206 returns null if nothing happened */
207 public String
handle_special_str(String key
)
212 public boolean get_bool(String name
, boolean def
)
216 return get_bool(name
);
218 catch (EIllegalValue e
)
224 public boolean get_bool(String name
) throws EIllegalValue
226 String val
=get_str(name
);
229 return StrUtil
.toBool(val
);
231 catch (NumberFormatException e
)
233 throw new EIllegalValue(name
,val
);
237 private final String
get_str_rec(String key
, int depth
)
241 throw new EInfiniteRecursion(key
,get_raw(key
));
243 /* if we someday want to add special vars/commands, this
244 would probably be the right point */
247 boolean notnull
= false;
248 boolean notempty
= false;
250 /* handle subclass-defined specials */
251 if ((value
=handle_special_str(key
))!=null)
254 /* -- parse special modifiers -- */
255 for (boolean parsing
=true; parsing
;)
257 if (key
.startsWith("!notnull!"))
260 key
= key
.substring(9);
262 else if (key
.startsWith("!notempty!"))
265 key
= key
.substring(10);
271 if ((value
=get_raw(key
))==null)
274 throw new EVariableNull(key
,value
);
279 /* --- now replace variables --- */
282 while ((start
=value
.indexOf("$("))!=-1) /* scan for $( */
284 if ((end
=value
.indexOf(')', start
+2))!=-1)
286 String name
= value
.substring(start
+2,end
);
288 value
.substring(0,start
)+
289 get_str_rec(name
,depth
-1)+
290 value
.substring(end
+1);
295 throw new EVariableParseError(key
,value
);
298 if (value
.equals("") && notempty
)
299 throw new EVariableEmpty(key
,value
);
307 for (Enumeration e
= db
.keys(); e
.hasMoreElements(); )
309 String key
= (String
) e
.nextElement();
310 res
+= key
+"=\""+db_get(key
)+"\"\n";
315 public boolean load_content(String field
, File filename
, boolean strip_comments
)
317 String text
= datasource_cache
.loadContent(filename
,strip_comments
);
325 public boolean load_content(String field
, URL url
, boolean strip_comments
)
327 String text
= datasource_cache
.loadContent(url
,strip_comments
);
335 public Enumeration
propertyNames()
340 public IPropertylist
clone()
342 Propertylist pr
= new Propertylist();
343 pr
.db
= (Properties
)db
.clone();
346 for (Enumeration keys
= db
.keys(); keys
.hasMoreElements(); )
348 String k
= (String
)keys
.nextElement();
354 public String
toString()
356 String str
= "[PROPERTYLIST]\n";
357 for (Enumeration keys
= db
.keys(); keys
.hasMoreElements(); )
359 String k
= (String
)keys
.nextElement();
360 str
+= k
+"=\""+db_get(k
)+"\"\n";