View Javadoc

1   package com.atlassian.user.impl.cache.properties;
2   
3   /**
4    * Copied over from the bucket.
5    *
6    * A PropertySet which decorates another PropertySet and caches the results.
7    * <p/>
8    * <p/>
9    * This class performs similar objective as the
10   * com.opensymphony.module.propertyset.cached.CachingPropertySet class but does more
11   * caching.
12   * <p/>
13   * (originally from JiraCachingPropertySet in JIRA)
14   * <p>At some stage it would be very nice to stop using this and start using
15   * the almost identical class in atlassian core.
16   */
17  import com.opensymphony.module.propertyset.PropertySet;
18  import com.opensymphony.module.propertyset.PropertySetManager;
19  import com.opensymphony.module.propertyset.PropertyException;
20  import com.opensymphony.module.propertyset.PropertySetSchema;
21  import com.opensymphony.module.propertyset.memory.SerializablePropertySet;
22  import com.opensymphony.util.DataUtil;
23  import java.io.Serializable;
24  import java.util.*;
25  
26  import org.w3c.dom.Document;
27  
28  /**
29   * CachedPropertySet provides a fast cache of properties read to and written from a decorated PropertySet.
30   * The CachedPropertySet is Serializable but relies on the decorated PropertySet also being Serializable.
31   */
32  public class CachedPropertySet implements PropertySet, Serializable
33  {
34      /**
35       * The PropertySet whose contents are cached by this property set.  Note that if decoratedPS is not Serializable,
36       * which it needn't be, things could go horribly wrong.
37       */
38      private PropertySet decoratedPS;
39      private SerializablePropertySet cachePS;
40      private Map<String, Object> existantKeyCache;
41  
42      /**
43       * Initialise this object's fields.
44       *
45       * Args required are:
46       * <ul>
47       * <li>PropertySet - the PropertySet being decorated, must be Serializable if the initialized property set
48       * could ever be Serialised.
49       * <li>serializableName - the name of the serializable PropertySet to use for the 'property cache' (optional - defaults to 'serializable')
50       * <li>bulkload - a Boolean determining whether or not to bulk load all of the properties into the cache upon startup
51       * </ul>
52       */
53      public void init(Map config, Map args)
54      {
55          decoratedPS = (PropertySet) args.get("PropertySet");
56  
57          String serializableName = (String) config.get("serializableName");
58  
59          if (serializableName == null)
60          {
61              serializableName = "serializable";
62          }
63  
64          cachePS = (SerializablePropertySet) PropertySetManager.getInstance(serializableName, null);
65          existantKeyCache = new HashMap<String, Object>();
66  
67          Boolean bulkload = (Boolean) args.get("bulkload");
68  
69          if ((bulkload != null) && bulkload)
70          {
71              PropertySetManager.clone(decoratedPS, cachePS);
72          }
73      }
74  
75      public void setAsActualType(String key, Object value) throws PropertyException
76      {
77          if (value instanceof Boolean)
78          {
79              setBoolean(key, DataUtil.getBoolean((Boolean) value));
80          }
81          else if (value instanceof Integer)
82          {
83              setInt(key, DataUtil.getInt((Integer) value));
84          }
85          else if (value instanceof Long)
86          {
87              setLong(key, DataUtil.getLong((Long) value));
88          }
89          else if (value instanceof Double)
90          {
91              setDouble(key, DataUtil.getDouble((Double) value));
92          }
93          else if (value instanceof String)
94          {
95              setString(key, (String) value);
96          }
97          else if (value instanceof Date)
98          {
99              setDate(key, (Date) value);
100         }
101         else if (value instanceof Document)
102         {
103             setXML(key, (Document) value);
104         }
105         else if (value instanceof byte[])
106         {
107             setData(key, (byte[]) value);
108         }
109         else if (value instanceof Properties)
110         {
111             setProperties(key, (Properties) value);
112         }
113         else
114         {
115             setObject(key, value);
116         }
117     }
118 
119     public Object getAsActualType(String key) throws PropertyException
120     {
121         int type = getType(key);
122         Object value = null;
123 
124         switch (type)
125         {
126             case BOOLEAN:
127                 value = getBoolean(key);
128                 break;
129 
130             case INT:
131                 value = getInt(key);
132                 break;
133 
134             case LONG:
135                 value = getLong(key);
136                 break;
137 
138             case DOUBLE:
139                 value = getDouble(key);
140                 break;
141 
142             case STRING:
143                 value = getString(key);
144                 break;
145 
146             case DATE:
147                 value = getDate(key);
148                 break;
149 
150             case XML:
151                 value = getXML(key);
152                 break;
153 
154             case DATA:
155                 value = getData(key);
156                 break;
157 
158             case PROPERTIES:
159                 value = getProperties(key);
160                 break;
161 
162             case OBJECT:
163                 value = getObject(key);
164                 break;
165         }
166 
167         return value;
168     }
169 
170     public void setBoolean(String key, boolean value) throws PropertyException
171     {
172         decoratedPS.setBoolean(key, value);
173         cachePS.setBoolean(key, value);
174 
175         // Clear cache
176         existantKeyCache.remove(key);
177     }
178 
179     public boolean getBoolean(String key) throws PropertyException
180     {
181         if (!cachePS.exists(key))
182         {
183             cachePS.setBoolean(key, decoratedPS.getBoolean(key));
184         }
185 
186         return cachePS.getBoolean(key);
187     }
188 
189     public void setData(String key, byte[] value) throws PropertyException
190     {
191         decoratedPS.setData(key, value);
192         cachePS.setData(key, value);
193 
194         // Clear cache
195         existantKeyCache.remove(key);
196     }
197 
198     public byte[] getData(String key) throws PropertyException
199     {
200         if (!cachePS.exists(key))
201         {
202             cachePS.setData(key, decoratedPS.getData(key));
203         }
204 
205         return cachePS.getData(key);
206     }
207 
208     public void setDate(String key, Date value) throws PropertyException
209     {
210         decoratedPS.setDate(key, value);
211         cachePS.setDate(key, value);
212 
213         // Clear cache
214         existantKeyCache.remove(key);
215     }
216 
217     public Date getDate(String key) throws PropertyException
218     {
219         if (!cachePS.exists(key))
220         {
221             cachePS.setDate(key, decoratedPS.getDate(key));
222         }
223 
224         return cachePS.getDate(key);
225     }
226 
227     public void setDouble(String key, double value) throws PropertyException
228     {
229         decoratedPS.setDouble(key, value);
230         cachePS.setDouble(key, value);
231 
232         // Clear cache
233         existantKeyCache.remove(key);
234     }
235 
236     public double getDouble(String key) throws PropertyException
237     {
238         if (!cachePS.exists(key))
239         {
240             cachePS.setDouble(key, decoratedPS.getDouble(key));
241         }
242 
243         return cachePS.getDouble(key);
244     }
245 
246     public void setInt(String key, int value) throws PropertyException
247     {
248         decoratedPS.setInt(key, value);
249         cachePS.setInt(key, value);
250 
251         // Clear cache
252         existantKeyCache.remove(key);
253     }
254 
255     public int getInt(String key) throws PropertyException
256     {
257         if (!cachePS.exists(key))
258         {
259             cachePS.setInt(key, decoratedPS.getInt(key));
260         }
261 
262         return cachePS.getInt(key);
263     }
264 
265     public Collection getKeys() throws PropertyException
266     {
267         return decoratedPS.getKeys();
268     }
269 
270     public Collection getKeys(int type) throws PropertyException
271     {
272         return decoratedPS.getKeys(type);
273     }
274 
275     public Collection getKeys(String prefix) throws PropertyException
276     {
277         return decoratedPS.getKeys(prefix);
278     }
279 
280     public Collection getKeys(String prefix, int type) throws PropertyException
281     {
282         return decoratedPS.getKeys(prefix, type);
283     }
284 
285     public void setLong(String key, long value) throws PropertyException
286     {
287         decoratedPS.setLong(key, value);
288         cachePS.setLong(key, value);
289 
290         // Clear cache
291         existantKeyCache.remove(key);
292     }
293 
294     public long getLong(String key) throws PropertyException
295     {
296         if (!cachePS.exists(key))
297         {
298             cachePS.setLong(key, decoratedPS.getLong(key));
299         }
300 
301         return cachePS.getLong(key);
302     }
303 
304     public void setObject(String key, Object value) throws PropertyException
305     {
306         decoratedPS.setObject(key, value);
307         cachePS.setObject(key, value);
308 
309         // Clear cache
310         existantKeyCache.remove(key);
311     }
312 
313     public Object getObject(String key) throws PropertyException
314     {
315         if (!cachePS.exists(key))
316         {
317             cachePS.setObject(key, decoratedPS.getObject(key));
318         }
319 
320         return cachePS.getObject(key);
321     }
322 
323     public void setProperties(String key, Properties value) throws PropertyException
324     {
325         decoratedPS.setProperties(key, value);
326         cachePS.setProperties(key, value);
327 
328         // Clear cache
329         existantKeyCache.remove(key);
330     }
331 
332     public Properties getProperties(String key) throws PropertyException
333     {
334         if (!cachePS.exists(key))
335         {
336             cachePS.setProperties(key, decoratedPS.getProperties(key));
337         }
338 
339         return cachePS.getProperties(key);
340     }
341 
342     public void setSchema(PropertySetSchema schema) throws PropertyException
343     {
344         decoratedPS.setSchema(schema);
345     }
346 
347     public PropertySetSchema getSchema() throws PropertyException
348     {
349         return decoratedPS.getSchema();
350     }
351 
352     public boolean isSettable(String property)
353     {
354         return decoratedPS.isSettable(property);
355     }
356 
357     public void setString(String key, String value) throws PropertyException
358     {
359         decoratedPS.setString(key, value);
360         cachePS.setString(key, value);
361 
362         // Clear cache
363         existantKeyCache.remove(key);
364     }
365 
366     public String getString(String key) throws PropertyException
367     {
368         if (!cachePS.exists(key))
369         {
370             cachePS.setString(key, decoratedPS.getString(key));
371         }
372 
373         return cachePS.getString(key);
374     }
375 
376     public void setText(String key, String value) throws PropertyException
377     {
378         decoratedPS.setText(key, value);
379         cachePS.setText(key, value);
380 
381         // Clear cache
382         existantKeyCache.remove(key);
383     }
384 
385     public String getText(String key) throws PropertyException
386     {
387         if (!cachePS.exists(key))
388         {
389             cachePS.setText(key, decoratedPS.getText(key));
390         }
391 
392         return cachePS.getText(key);
393     }
394 
395     public int getType(String key) throws PropertyException
396     {
397         return decoratedPS.getType(key);
398     }
399 
400     public void setXML(String key, Document value) throws PropertyException
401     {
402         decoratedPS.setXML(key, value);
403         cachePS.setXML(key, value);
404 
405         // Clear cache
406         existantKeyCache.remove(key);
407     }
408 
409     public Document getXML(String key) throws PropertyException
410     {
411         if (!cachePS.exists(key))
412         {
413             cachePS.setXML(key, decoratedPS.getXML(key));
414         }
415 
416         return cachePS.getXML(key);
417     }
418 
419     public boolean exists(String key) throws PropertyException
420     {
421         // Check if we have the result for the exists() call cached. If not check the
422         // decoratedPS
423         if (existantKeyCache.containsKey(key))
424         {
425             return Boolean.TRUE.equals(existantKeyCache.get(key));
426         }
427 
428         boolean keyExists = decoratedPS.exists(key);
429 
430         // Cache the result
431         existantKeyCache.put(key, keyExists);
432         return keyExists;
433     }
434 
435     public void remove(String key) throws PropertyException
436     {
437         existantKeyCache.remove(key);
438         cachePS.remove(key);
439         decoratedPS.remove(key);
440     }
441 
442     public boolean supportsType(int type)
443     {
444         return decoratedPS.supportsType(type);
445     }
446 
447     public boolean supportsTypes()
448     {
449         return decoratedPS.supportsTypes();
450     }
451 }