KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > cache > loader > ChainingCacheLoader


1 /*
2  * JBoss, Home of Professional Open Source
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7 package org.jboss.cache.loader;
8
9 import org.jboss.cache.Fqn;
10 import org.jboss.cache.Modification;
11 import org.jboss.cache.RegionManager;
12 import org.jboss.cache.config.CacheLoaderConfig;
13 import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
14
15 import java.io.ObjectInputStream JavaDoc;
16 import java.io.ObjectOutputStream JavaDoc;
17 import java.util.ArrayList JavaDoc;
18 import java.util.Collections JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.Set JavaDoc;
23
24 /**
25  * This decorator is used whenever more than one cache loader is configured. READ operations are directed to
26  * each of the cache loaders (in the order which they were configured) until a non-null (or non-empty in the case
27  * of retrieving collection objects) result is achieved.
28  * <p/>
29  * WRITE operations are propagated to ALL registered cacheloaders that specified set ignoreModifications to false.
30  *
31  * @author <a HREF="mailto:manik@jboss.org">Manik Surtani (manik@jboss.org)</a>
32  */

33 public class ChainingCacheLoader extends AbstractCacheLoader
34 {
35    private final List JavaDoc<CacheLoader> cacheLoaders = new ArrayList JavaDoc<CacheLoader>(2);
36    private final List JavaDoc<CacheLoader> writeCacheLoaders = new ArrayList JavaDoc<CacheLoader>(2);
37    private final List JavaDoc<CacheLoaderConfig.IndividualCacheLoaderConfig> cacheLoaderConfigs = new ArrayList JavaDoc<CacheLoaderConfig.IndividualCacheLoaderConfig>(2);
38
39    /**
40     * Sets the configuration. Will be called before {@link #create()} and {@link #start()}
41     *
42     * @param config ignored
43     */

44    public void setConfig(IndividualCacheLoaderConfig config)
45    {
46       // don't do much here?
47
}
48
49    public IndividualCacheLoaderConfig getConfig()
50    {
51       return null;
52    }
53
54    /**
55     * Returns a list of children names, all names are <em>relative</em>. Returns null if the parent node is not found.
56     * The returned set must not be modified, e.g. use Collections.unmodifiableSet(s) to return the result
57     *
58     * @param fqn The FQN of the parent
59     * @return Set<String>. A list of children. Returns null if no children nodes are present, or the parent is
60     * not present
61     */

62    public Set JavaDoc<String JavaDoc> getChildrenNames(Fqn fqn) throws Exception JavaDoc
63    {
64       Set JavaDoc<String JavaDoc> answer = null;
65       Iterator JavaDoc<CacheLoader> i = cacheLoaders.iterator();
66       while (i.hasNext())
67       {
68          CacheLoader l = i.next();
69          answer = l.getChildrenNames(fqn);
70          if (answer != null && answer.size() > 0) break;
71       }
72       return answer;
73    }
74
75    /**
76     * Returns all keys and values from the persistent store, given a fully qualified name
77     *
78     * @param name
79     * @return Map<Object,Object> of keys and values for the given node. Returns null if the node was not found, or
80     * if the node has no attributes
81     * @throws Exception
82     */

83    public Map JavaDoc get(Fqn name) throws Exception JavaDoc
84    {
85       Map JavaDoc answer = null;
86       Iterator JavaDoc<CacheLoader> i = cacheLoaders.iterator();
87       while (i.hasNext())
88       {
89          CacheLoader l = i.next();
90          answer = l.get(name);
91          if (answer != null) break;
92       }
93       return answer;
94    }
95
96    /**
97     * Checks whether the CacheLoader has a node with Fqn
98     *
99     * @param name
100     * @return True if node exists, false otherwise
101     */

102    public boolean exists(Fqn name) throws Exception JavaDoc
103    {
104       boolean answer = false;
105       Iterator JavaDoc<CacheLoader> i = cacheLoaders.iterator();
106       while (i.hasNext())
107       {
108          CacheLoader l = i.next();
109          answer = l.exists(name);
110          if (answer) break;
111       }
112       return answer;
113    }
114
115    /**
116     * Inserts key and value into the attributes hashmap of the given node. If the node does not exist, all
117     * parent nodes from the root down are created automatically. Returns the old value
118     */

119    public Object JavaDoc put(Fqn name, Object JavaDoc key, Object JavaDoc value) throws Exception JavaDoc
120    {
121       Object JavaDoc answer = null;
122       Iterator JavaDoc<CacheLoader> i = writeCacheLoaders.iterator();
123       boolean isFirst = true;
124       while (i.hasNext())
125       {
126          CacheLoader l = i.next();
127          Object JavaDoc tAnswer = l.put(name, key, value);
128          if (isFirst)
129          {
130             answer = tAnswer;
131             isFirst = false;
132          }
133
134       }
135       return answer;
136    }
137
138    /**
139     * Inserts all elements of attributes into the attributes hashmap of the given node, overwriting existing
140     * attributes, but not clearing the existing hashmap before insertion (making it a union of existing and
141     * new attributes)
142     * If the node does not exist, all parent nodes from the root down are created automatically
143     *
144     * @param name The fully qualified name of the node
145     * @param attributes A Map of attributes. Can be null
146     */

147    public void put(Fqn name, Map JavaDoc attributes) throws Exception JavaDoc
148    {
149       Iterator JavaDoc<CacheLoader> i = writeCacheLoaders.iterator();
150       while (i.hasNext())
151       {
152          CacheLoader l = i.next();
153          l.put(name, attributes);
154       }
155    }
156
157    /**
158     * Inserts all modifications to the backend store. Overwrite whatever is already in
159     * the datastore.
160     *
161     * @param modifications A List<Modification> of modifications
162     * @throws Exception
163     */

164    public void put(List JavaDoc<Modification> modifications) throws Exception JavaDoc
165    {
166       Iterator JavaDoc<CacheLoader> i = writeCacheLoaders.iterator();
167       while (i.hasNext())
168       {
169          CacheLoader l = i.next();
170          l.put(modifications);
171       }
172    }
173
174    /**
175     * Removes the given key and value from the attributes of the given node. No-op if node doesn't exist.
176     * Returns the first response from the loader chain.
177     */

178    public Object JavaDoc remove(Fqn name, Object JavaDoc key) throws Exception JavaDoc
179    {
180       Object JavaDoc answer = null;
181       Iterator JavaDoc<CacheLoader> i = writeCacheLoaders.iterator();
182       boolean isFirst = true;
183       while (i.hasNext())
184       {
185          CacheLoader l = i.next();
186          Object JavaDoc tAnswer = l.remove(name, key);
187          if (isFirst)
188          {
189             answer = tAnswer;
190             isFirst = false;
191          }
192       }
193       return answer;
194    }
195
196    /**
197     * Removes the given node. If the node is the root of a subtree, this will recursively remove all subnodes,
198     * depth-first
199     */

200    public void remove(Fqn name) throws Exception JavaDoc
201    {
202       Iterator JavaDoc<CacheLoader> i = writeCacheLoaders.iterator();
203       while (i.hasNext())
204       {
205          CacheLoader l = i.next();
206          l.remove(name);
207       }
208    }
209
210    /**
211     * Removes all attributes from a given node, but doesn't delete the node itself
212     *
213     * @param name
214     * @throws Exception
215     */

216    public void removeData(Fqn name) throws Exception JavaDoc
217    {
218       Iterator JavaDoc<CacheLoader> i = writeCacheLoaders.iterator();
219       while (i.hasNext())
220       {
221          CacheLoader l = i.next();
222          l.removeData(name);
223       }
224    }
225
226    /**
227     * Prepare the modifications. For example, for a DB-based CacheLoader:
228     * <ol>
229     * <li>Create a local (JDBC) transaction
230     * <li>Associate the local transaction with <code>tx</code> (tx is the key)
231     * <li>Execute the coresponding SQL statements against the DB (statements derived from modifications)
232     * </ol>
233     * For non-transactional CacheLoader (e.g. file-based), this could be a null operation
234     *
235     * @param tx The transaction, just used as a hashmap key
236     * @param modifications List<Modification>, a list of all modifications within the given transaction
237     * @param one_phase Persist immediately and (for example) commit the local JDBC transaction as well. When true,
238     * we won't get a {@link #commit(Object)} or {@link #rollback(Object)} method call later
239     * @throws Exception
240     */

241    public void prepare(Object JavaDoc tx, List JavaDoc modifications, boolean one_phase) throws Exception JavaDoc
242    {
243       Iterator JavaDoc<CacheLoader> i = writeCacheLoaders.iterator();
244       while (i.hasNext())
245       {
246          CacheLoader l = i.next();
247          l.prepare(tx, modifications, one_phase);
248       }
249    }
250
251    /**
252     * Commit the transaction. A DB-based CacheLoader would look up the local JDBC transaction asociated
253     * with <code>tx</code> and commit that transaction<br/>
254     * Non-transactional CacheLoaders could simply write the data that was previously saved transiently under the
255     * given <code>tx</code> key, to (for example) a file system (note this only holds if the previous prepare() did
256     * not define one_phase=true
257     *
258     * @param tx
259     */

260    public void commit(Object JavaDoc tx) throws Exception JavaDoc
261    {
262       Iterator JavaDoc<CacheLoader> i = writeCacheLoaders.iterator();
263       while (i.hasNext())
264       {
265          CacheLoader l = i.next();
266          l.commit(tx);
267       }
268    }
269
270    /**
271     * Roll the transaction back. A DB-based CacheLoader would look up the local JDBC transaction asociated
272     * with <code>tx</code> and roll back that transaction
273     *
274     * @param tx
275     */

276    public void rollback(Object JavaDoc tx)
277    {
278       Iterator JavaDoc<CacheLoader> i = writeCacheLoaders.iterator();
279       while (i.hasNext())
280       {
281          CacheLoader l = i.next();
282          l.rollback(tx);
283       }
284    }
285
286
287    /**
288     * Creates individual cache loaders.
289     *
290     * @throws Exception
291     */

292    public void create() throws Exception JavaDoc
293    {
294       Iterator JavaDoc<CacheLoader> it = cacheLoaders.iterator();
295       Iterator JavaDoc<CacheLoaderConfig.IndividualCacheLoaderConfig> cfgIt = cacheLoaderConfigs.iterator();
296       while (it.hasNext() && cfgIt.hasNext())
297       {
298          CacheLoader cl = it.next();
299          CacheLoaderConfig.IndividualCacheLoaderConfig cfg = cfgIt.next();
300          cl.create();
301       }
302    }
303
304    public void start() throws Exception JavaDoc
305    {
306       Iterator JavaDoc<CacheLoader> it = cacheLoaders.iterator();
307       while (it.hasNext())
308       {
309          (it.next()).start();
310       }
311    }
312
313    public void stop()
314    {
315       Iterator JavaDoc<CacheLoader> it = cacheLoaders.iterator();
316       while (it.hasNext())
317       {
318          (it.next()).stop();
319       }
320    }
321
322    public void destroy()
323    {
324       Iterator JavaDoc<CacheLoader> it = cacheLoaders.iterator();
325       while (it.hasNext())
326       {
327          (it.next()).destroy();
328       }
329    }
330
331    /**
332     * No-op, as this class doesn't directly use the ERegionManager.
333     */

334    public void setRegionManager(RegionManager manager)
335    {
336       // no-op -- we don't do anything with the region manager
337
}
338
339    public void loadEntireState(ObjectOutputStream JavaDoc os) throws Exception JavaDoc
340    {
341       Iterator JavaDoc<CacheLoader> i = cacheLoaders.iterator();
342       Iterator JavaDoc<CacheLoaderConfig.IndividualCacheLoaderConfig> cfgs = cacheLoaderConfigs.iterator();
343       while (i.hasNext() && cfgs.hasNext())
344       {
345          CacheLoader l = i.next();
346          CacheLoaderConfig.IndividualCacheLoaderConfig cfg = cfgs.next();
347          if (cfg.isFetchPersistentState())
348          {
349             l.loadEntireState(os);
350             break;
351          }
352       }
353    }
354
355    public void loadState(Fqn subtree, ObjectOutputStream JavaDoc os) throws Exception JavaDoc
356    {
357       Iterator JavaDoc<CacheLoader> i = cacheLoaders.iterator();
358       Iterator JavaDoc<CacheLoaderConfig.IndividualCacheLoaderConfig> cfgs = cacheLoaderConfigs.iterator();
359       while (i.hasNext() && cfgs.hasNext())
360       {
361          CacheLoader l = i.next();
362          CacheLoaderConfig.IndividualCacheLoaderConfig cfg = cfgs.next();
363          if (cfg.isFetchPersistentState())
364          {
365             l.loadState(subtree, os);
366             break;
367          }
368       }
369    }
370
371    public void storeEntireState(ObjectInputStream JavaDoc is) throws Exception JavaDoc
372    {
373       Iterator JavaDoc<CacheLoader> i = writeCacheLoaders.iterator();
374       Iterator JavaDoc<CacheLoaderConfig.IndividualCacheLoaderConfig> cfgs = cacheLoaderConfigs.iterator();
375       while (i.hasNext())
376       {
377          CacheLoader l = i.next();
378          CacheLoaderConfig.IndividualCacheLoaderConfig cfg = cfgs.next();
379          if (cfg.isFetchPersistentState())
380          {
381             l.storeEntireState(is);
382             break;
383          }
384       }
385
386    }
387
388    public void storeState(Fqn subtree, ObjectInputStream JavaDoc is) throws Exception JavaDoc
389    {
390       Iterator JavaDoc<CacheLoader> i = writeCacheLoaders.iterator();
391       Iterator JavaDoc<CacheLoaderConfig.IndividualCacheLoaderConfig> cfgs = cacheLoaderConfigs.iterator();
392       while (i.hasNext())
393       {
394          CacheLoader l = i.next();
395          CacheLoaderConfig.IndividualCacheLoaderConfig cfg = cfgs.next();
396          if (cfg.isFetchPersistentState())
397          {
398             l.storeState(subtree, is);
399             break;
400          }
401       }
402    }
403
404    /**
405     * Returns the number of cache loaders in the chain.
406     */

407    public int getSize()
408    {
409       return cacheLoaders.size();
410    }
411
412    /**
413     * Returns a List<CacheLoader> of individual cache loaders configured.
414     */

415    public List JavaDoc<CacheLoader> getCacheLoaders()
416    {
417       return Collections.unmodifiableList(cacheLoaders);
418    }
419
420    /**
421     * Adds a cache loader to the chain (always added at the end of the chain)
422     *
423     * @param l the cache loader to add
424     * @param cfg and its configuration
425     */

426    public void addCacheLoader(CacheLoader l, CacheLoaderConfig.IndividualCacheLoaderConfig cfg)
427    {
428       synchronized (this)
429       {
430          cacheLoaderConfigs.add(cfg);
431          cacheLoaders.add(l);
432
433          if (!cfg.isIgnoreModifications())
434          {
435             writeCacheLoaders.add(l);
436          }
437       }
438    }
439
440    public String JavaDoc toString()
441    {
442       StringBuffer JavaDoc buf = new StringBuffer JavaDoc("ChainingCacheLoader{");
443       Iterator JavaDoc<CacheLoader> i = cacheLoaders.iterator();
444       Iterator JavaDoc<CacheLoaderConfig.IndividualCacheLoaderConfig> c = cacheLoaderConfigs.iterator();
445       int count = 0;
446       while (i.hasNext() && c.hasNext())
447       {
448          CacheLoader loader = i.next();
449          CacheLoaderConfig.IndividualCacheLoaderConfig cfg = c.next();
450
451          buf.append(++count);
452          buf.append(": IgnoreMods? ");
453          buf.append(cfg.isIgnoreModifications());
454          buf.append(" CLoader: ");
455          buf.append(loader);
456          buf.append("; ");
457       }
458       buf.append("}");
459       return buf.toString();
460    }
461
462    public void purgeIfNecessary() throws Exception JavaDoc
463    {
464       Iterator JavaDoc<CacheLoader> loaders = cacheLoaders.iterator();
465       Iterator JavaDoc<CacheLoaderConfig.IndividualCacheLoaderConfig> configs = cacheLoaderConfigs.iterator();
466
467       while (loaders.hasNext() && configs.hasNext())
468       {
469          CacheLoader myLoader = loaders.next();
470          CacheLoaderConfig.IndividualCacheLoaderConfig myConfig = configs.next();
471
472          if (!myConfig.isIgnoreModifications() && myConfig.isPurgeOnStartup()) myLoader.remove(Fqn.ROOT);
473       }
474
475
476    }
477 }
478
Popular Tags