View Javadoc

1   /*** 
2    * 
3    * Copyright 2004 Protique Ltd
4    * 
5    * Licensed under the Apache License, Version 2.0 (the "License"); 
6    * you may not use this file except in compliance with the License. 
7    * You may obtain a copy of the License at 
8    * 
9    * http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, 
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
14   * See the License for the specific language governing permissions and 
15   * limitations under the License. 
16   * 
17   **/
18  package org.codehaus.activespace.cache;
19  
20  import org.codehaus.activespace.cache.impl.CompositeCacheCommand;
21  import org.codehaus.activespace.cache.impl.NullTransactionRegistration;
22  import org.codehaus.activespace.cache.impl.ThreadCache;
23  import org.codehaus.activespace.cache.impl.TransactionRegistration;
24  
25  import javax.cache.Cache;
26  import javax.cache.CacheException;
27  import javax.cache.CacheManager;
28  import java.util.Collection;
29  import java.util.Collections;
30  import java.util.HashMap;
31  import java.util.Iterator;
32  import java.util.Map;
33  
34  /***
35   * A {@link CacheManager} which returns {@link TransactionalCache} instances
36   * using some backing {@link Cache} instances. This class also acts as the transaciton
37   *
38   * @version $Revision: 1.12 $
39   */
40  public class TransactionalCacheManager extends CacheManager {
41  
42      private Map caches = Collections.synchronizedMap(new HashMap());
43      private TransactionRegistration transactionRegistration = NullTransactionRegistration.getInstance();
44      private Map environment = new HashMap();
45  
46  
47      /***
48       * Shuts down this class, freeing any resources used up (such as open files or sockets).
49       * One this method has been called this class should not be used again.
50       */
51      public void stop() throws Exception {
52      }
53  
54      /***
55       * Creates a new transactional cache
56       */
57      public TransactionalCache createTransactionalCache(String name) throws CacheException {
58          Cache backingCache = createBackingCache(name);
59          return registerCache(caches, backingCache, name);
60      }
61  
62      /***
63       * Looks up a cache
64       */
65      public TransactionalCache getTransactionalCache(String name) {
66          TransactionalCache answer = (TransactionalCache) caches.get(name);
67          if (answer == null) {
68              Cache backingCache = getBackingCache(name);
69              if (backingCache != null) {
70                  answer = registerCache(caches, backingCache, name);
71              }
72          }
73          return answer;
74      }
75  
76      public Cache getCache(String cacheName) {
77          return getTransactionalCache(cacheName);
78      }
79  
80      /***
81       * Performs a thread local commit of all operations on all the caches
82       * used in this tranaction.
83       *
84       * @throws TransactionException if the transaction could not be committed
85       *                              due to an optimistic transaction failure or deadlock.
86       */
87      public void commit() throws TransactionException {
88          Collection caches = getTransactionalCaches();
89          CompositeCacheCommand command = createCommitCommand(caches);
90          if (!command.isEmpty()) {
91              command.run(this);
92              resetLocalChanges(caches);
93              handleCommitException(caches);
94          }
95      }
96  
97      /***
98       * Performs rollback of all pending transactions on all the caches
99       * accessed in the current thread.
100      */
101     public void rollback() {
102         Collection caches = getTransactionalCaches();
103         resetLocalChanges(caches);
104     }
105 
106     // Properties
107     //-------------------------------------------------------------------------
108     public TransactionRegistration getTransactionRegistration() {
109         return transactionRegistration;
110     }
111 
112     public void setTransactionRegistration(TransactionRegistration transactionRegistration) {
113         this.transactionRegistration = transactionRegistration;
114     }
115 
116     public Map getEnvironment() {
117         return environment;
118     }
119 
120     public void setEnvironment(Map environment) {
121         this.environment = environment;
122     }
123 
124     // Implementation methods
125     //-------------------------------------------------------------------------
126     protected TransactionalCache registerCache(Map caches, Cache backingCache, String name) {
127         TransactionalCache answer = createTransactionalCache(backingCache, name);
128         answer.setName(name);
129         answer.setTransactionRegistration(getTransactionRegistration());
130         caches.put(name, answer);
131         return answer;
132     }
133 
134     protected TransactionalCache createTransactionalCache(Cache backingCache, String name) {
135         return new TransactionalCache(backingCache);
136     }
137 
138     protected Collection getTransactionalCaches() {
139         return caches.values();
140     }
141 
142     protected Cache getBackingCache(String name) {
143         return super.getCache(name);
144     }
145 
146     protected synchronized Cache createBackingCache(String name) throws CacheException {
147         Cache cache = getCacheFactory().createCache(environment);
148         super.registerCache(name, cache);
149         return cache;
150     }
151 
152     protected void resetLocalChanges(Collection caches) {
153         for (Iterator iter = caches.iterator(); iter.hasNext();) {
154             TransactionalCache cache = (TransactionalCache) iter.next();
155             if (cache.isModifiedInTransaction()) {
156                 cache.resetLocalChanges();
157             }
158         }
159     }
160 
161     protected void handleCommitException(Collection caches) {
162         for (Iterator iter = caches.iterator(); iter.hasNext();) {
163             TransactionalCache cache = (TransactionalCache) iter.next();
164             if (cache.isModifiedInTransaction()) {
165                 cache.resetLocalChanges();
166             }
167         }
168 
169         for (Iterator iter = caches.iterator(); iter.hasNext();) {
170             TransactionalCache cache = (TransactionalCache) iter.next();
171             ThreadCache threadCache = cache.getThreadCache();
172             threadCache.handleCommitException();
173         }
174     }
175 
176     protected CompositeCacheCommand createCommitCommand(Collection caches) {
177         CompositeCacheCommand command = new CompositeCacheCommand();
178         for (Iterator iter = caches.iterator(); iter.hasNext();) {
179             TransactionalCache cache = (TransactionalCache) iter.next();
180             if (cache.isModifiedInTransaction()) {
181                 command.addCommand(cache.createTransactionCommand());
182             }
183         }
184         return command;
185     }
186 }