1 /***
2 * Copyright 2003-2010 Terracotta, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package net.sf.ehcache.hibernate;
17
18
19 import net.sf.ehcache.Element;
20 import net.sf.ehcache.concurrent.CacheLockProvider;
21 import net.sf.ehcache.concurrent.LockType;
22 import net.sf.ehcache.util.Timestamper;
23
24 import org.hibernate.cache.Cache;
25 import org.hibernate.cache.CacheException;
26
27 import java.util.HashMap;
28 import java.util.Map;
29
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /***
34 * EHCache plugin for Hibernate.
35 * <p/>
36 * EHCache uses a {@link net.sf.ehcache.store.MemoryStore} and a
37 * {@link net.sf.ehcache.store.disk.DiskStore}.
38 * <p/>
39 * The {@link net.sf.ehcache.store.disk.DiskStore} requires that both keys and values be {@link java.io.Serializable}.
40 * However the MemoryStore does not and in ehcache-1.2 nonSerializable Objects are permitted. They are discarded
41 * if an attempt it made to overflow them to Disk or to replicate them to remote cache peers.
42 * <p/>
43 *
44 * @author Greg Luck
45 * @author Emmanuel Bernard
46 * @version $Id: EhCache.html 13146 2011-08-01 17:12:39Z oletizi $
47 */
48 @Deprecated
49 public final class EhCache implements Cache {
50
51 private static final Logger LOG = LoggerFactory.getLogger(EhCache.class.getName());
52
53 private static final int SIXTY_THOUSAND_MS = 60000;
54
55 private final net.sf.ehcache.Ehcache cache;
56
57 private final CacheLockProvider lockProvider;
58
59 /***
60 * Creates a new Hibernate pluggable cache by name.
61 * <p/>
62 * ehcache will look in ehcache.xml to load the configuration for the cache.
63 * If the cache is not there, it will use the defaultCache settings. It is
64 * always a good idea to specifically configure each cache.
65 *
66 * @param cache The backing ehcache cache.
67 */
68 public EhCache(net.sf.ehcache.Ehcache cache) {
69 this.cache = cache;
70
71 Object context = cache.getInternalContext();
72 if (context instanceof CacheLockProvider) {
73 lockProvider = (CacheLockProvider) context;
74 } else {
75 lockProvider = null;
76 }
77 }
78
79 /***
80 * Gets a value of an element which matches the given key.
81 *
82 * @param key the key of the element to return.
83 * @return The value placed into the cache with an earlier put, or null if not found or expired
84 * @throws org.hibernate.cache.CacheException
85 *
86 */
87 public final Object get(Object key) throws CacheException {
88 try {
89 LOG.debug("key: {}", key);
90 if (key == null) {
91 return null;
92 } else {
93 Element element = cache.get(key);
94 if (element == null) {
95
96 LOG.debug("Element for key {} is null", key);
97 return null;
98 } else {
99 return element.getObjectValue();
100 }
101 }
102 } catch (net.sf.ehcache.CacheException e) {
103 throw new CacheException(e);
104 }
105 }
106
107 /***
108 * Gets an object from the cache.
109 *
110 * @param key an Object value
111 * @return the Object, or null if not found
112 * @throws CacheException
113 */
114 public final Object read(Object key) throws CacheException {
115 return get(key);
116 }
117
118
119 /***
120 * Updates an object in the cache, or if it does not exist, inserts it.
121 *
122 * @param key an Object key
123 * @param value an Object value
124 * @throws CacheException if the {@link net.sf.ehcache.CacheManager} is shutdown or another {@link Exception} occurs.
125 */
126 public final void update(Object key, Object value) throws CacheException {
127 put(key, value);
128 }
129
130 /***
131 * Puts an object into the cache.
132 *
133 * @param key an Object key
134 * @param value an Object value
135 * @throws CacheException if the {@link net.sf.ehcache.CacheManager} is shutdown or another {@link Exception} occurs.
136 */
137 public final void put(Object key, Object value) throws CacheException {
138 LOG.debug("key: {} value: {}", key, value);
139 try {
140 Element element = new Element(key, value);
141 cache.put(element);
142 } catch (IllegalArgumentException e) {
143 throw new CacheException(e);
144 } catch (IllegalStateException e) {
145 throw new CacheException(e);
146 }
147
148 }
149
150 /***
151 * Removes the element which matches the key.
152 * <p/>
153 * If no element matches, nothing is removed and no Exception is thrown.
154 *
155 * @param key the key of the element to remove
156 * @throws CacheException
157 */
158 public final void remove(Object key) throws CacheException {
159 try {
160 cache.remove(key);
161 } catch (ClassCastException e) {
162 throw new CacheException(e);
163 } catch (IllegalStateException e) {
164 throw new CacheException(e);
165 }
166 }
167
168 /***
169 * Remove all elements in the cache, but leave the cache in a useable state.
170 *
171 * @throws CacheException
172 */
173 public final void clear() throws CacheException {
174 try {
175 cache.removeAll();
176 } catch (IllegalStateException e) {
177 throw new CacheException(e);
178 }
179 }
180
181 /***
182 * Remove the cache and make it unuseable.
183 * <p/>
184 *
185 * @throws CacheException
186 */
187 public final void destroy() throws CacheException {
188 try {
189 cache.getCacheManager().removeCache(cache.getName());
190 } catch (IllegalStateException e) {
191
192
193
194 LOG.debug("This can happen if multiple frameworks both try to shutdown ehcache", e);
195 } catch (net.sf.ehcache.CacheException e) {
196 throw new CacheException(e);
197 }
198 }
199
200 /***
201 * {@inheritDoc}
202 */
203 public final void lock(Object key) throws CacheException {
204 if (lockProvider != null) {
205 lockProvider.getSyncForKey(key).lock(LockType.WRITE);
206 }
207 }
208
209 /***
210 * {@inheritDoc}
211 */
212 public final void unlock(Object key) throws CacheException {
213 if (lockProvider != null) {
214 lockProvider.getSyncForKey(key).unlock(LockType.WRITE);
215 }
216 }
217
218 /***
219 * Gets the next timestamp;
220 */
221 public final long nextTimestamp() {
222 return Timestamper.next();
223 }
224
225 /***
226 * Returns the lock timeout for this cache, which is 60s
227 */
228 public final int getTimeout() {
229
230 return Timestamper.ONE_MS * SIXTY_THOUSAND_MS;
231 }
232
233 /***
234 * @return the region name of the cache, which is the cache name in ehcache
235 */
236 public final String getRegionName() {
237 return cache.getName();
238 }
239
240 /***
241 * Warning: This method can be very expensive to run. Allow approximately 1 second
242 * per 1MB of entries. Running this method could create liveness problems
243 * because the object lock is held for a long period
244 * <p/>
245 *
246 * @return the approximate size of memory ehcache is using for the MemoryStore for this cache
247 */
248 public final long getSizeInMemory() {
249 try {
250 return cache.calculateInMemorySize();
251 } catch (Throwable t) {
252 return -1;
253 }
254 }
255
256 /***
257 * @return the number of elements in ehcache's MemoryStore
258 */
259 public final long getElementCountInMemory() {
260 try {
261 return cache.getMemoryStoreSize();
262 } catch (net.sf.ehcache.CacheException ce) {
263 throw new CacheException(ce);
264 }
265 }
266
267 /***
268 * @return the number of elements in ehcache's DiskStore. 0 is there is no DiskStore
269 */
270 public final long getElementCountOnDisk() {
271 return cache.getDiskStoreSize();
272 }
273
274
275 /***
276 * @return a copy of the cache Elements as a Map
277 */
278 public final Map toMap() {
279 try {
280 Map result = new HashMap();
281 for (Object key : cache.getKeys()) {
282 Element e = cache.get(key);
283 if (e != null) {
284 result.put(key, e.getObjectValue());
285 }
286 }
287 return result;
288 } catch (Exception e) {
289 throw new CacheException(e);
290 }
291 }
292
293 /***
294 * @return <code>true</code> if this cache supports entry locks.
295 */
296 public final boolean canLockEntries() {
297 return lockProvider != null;
298 }
299
300 /***
301 * @return the region name, which is the cache name in ehcache
302 */
303 public final String toString() {
304 return "EHCache(" + getRegionName() + ')';
305 }
306
307 /***
308 * Package protected method used for testing
309 */
310 final net.sf.ehcache.Ehcache getBackingCache() {
311 return cache;
312 }
313
314 }