001: /**
002: * Copyright 2003-2007 Luck Consulting Pty Ltd
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */package net.sf.ehcache.jcache;
016:
017: import net.sf.ehcache.Ehcache;
018: import net.sf.ehcache.Element;
019: import net.sf.ehcache.loader.CacheLoader;
020: import net.sf.jsr107cache.CacheEntry;
021: import net.sf.jsr107cache.CacheException;
022: import net.sf.jsr107cache.CacheListener;
023: import net.sf.jsr107cache.CacheStatistics;
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026:
027: import java.util.Collection;
028: import java.util.HashSet;
029: import java.util.Iterator;
030: import java.util.List;
031: import java.util.Map;
032: import java.util.Set;
033:
034: /**
035: * Warning: This class is related to the JSR107 specification, which is in draft. It is subject to change without notice.
036: * <p/>
037: * A cache implementation that matches the draft JCACHE specification.
038: * <p/>
039: * WARNING: The JCache specfication is in draft and this API will change up until the time that JCACHE is finalised.
040: * <p/>
041: * It is not possible for one class to implement both JCACHE and Ehcache
042: * in the same class due to conflicts with method signatures on get and remove.
043: * <p/>
044: * This implementation is an adaptor to Ehcache, and will exhibit the same underlying characteristics as Ehcache. Additiona features
045: * have been added to Ehcache to match the JCache features. All of these features can be configured in ehcache.xml.
046: * <p/>
047: * The current JCache CacheManager class, available in the draft, is considered unworkable. Instead, use the Ehcache <code>cacheManager.getJCache(String name)</code>
048: * to get a JCache. The JCache CacheManager is unlikely to make it into the final spec.
049: * <p/>
050: * The recommended creational pattern for JCache is one of:
051: * <ol>
052: * <li>Add a cache to ehcache.xml and use <code>cacheManager.getJCache(String name)</code> to access it.
053: * <li>Create a JCache from an Ehcache, using one of the constructors in this class. Two types of CacheLoader can be specified, in which
054: * case the underlying Ehcache loader is replaced by the one specified.
055: * <li>Create an Ehcache from a Cache using its constructor, then a JCache, and then add it to the ehcache CacheManager using <code>cacheManager.addCache(JCache jCache)</code>
056: * </ol>
057: * @author Greg Luck
058: * @version $Id: JCache.java 533 2007-08-11 04:15:34Z gregluck $
059: * @since 1.3
060: */
061: public class JCache implements net.sf.jsr107cache.Cache {
062:
063: private static final Log LOG = LogFactory.getLog(JCache.class
064: .getName());
065:
066: /**
067: * An Ehcache backing instance
068: */
069: private Ehcache cache;
070:
071: /**
072: * A constructor for JCache.
073: * <p/>
074: * JCache is an adaptor for an Ehcache, and therefore requires an Ehcache in its constructor.
075: * <p/>
076: * @param cache An ehcache
077: * @since 1.4
078: * @see "class description for recommended usage"
079: */
080: public JCache(Ehcache cache) {
081: this .cache = cache;
082: }
083:
084: /**
085: * A constructor for JCache.
086: * <p/>
087: * JCache is an adaptor for an Ehcache, and therefore requires an Ehcache in its constructor.
088: * <p/>
089: * @param cache An ehcache
090: * @param cacheLoader used to load entries when they are not in the cache. If this is null, it is
091: * set for the cache. If null, the JCache will inherit the CacheLoader set for the backing ehcache.
092: * If specified, the underlying ehcache will have it's loader replaced.
093: * @since 1.3
094: * @see "class description for recommended usage"
095: */
096: public JCache(Ehcache cache,
097: net.sf.jsr107cache.CacheLoader cacheLoader) {
098: this .cache = cache;
099: if (cacheLoader != null) {
100: cache.setCacheLoader((CacheLoader) cacheLoader);
101: }
102: }
103:
104: /**
105: * A constructor for JCache.
106: * <p/>
107: * JCache is an adaptor for an Ehcache, and therefore requires an Ehcache in its constructor.
108: * <p/>
109: * @param cache An ehcache
110: * @param cacheLoader used to load entries when they are not in the cache. If this is null, it is
111: * set for the cache. If null, the JCache will inherit the CacheLoader set for the backing ehcache.
112: * If specified, the underlying ehcache will have it's loader replaced.
113: * @since 1.3
114: * @see "class description for recommended usage"
115: */
116: public JCache(Ehcache cache, CacheLoader cacheLoader) {
117: this .cache = cache;
118: if (cacheLoader != null) {
119: cache.setCacheLoader(cacheLoader);
120: }
121: }
122:
123: /**
124: * Setter for the CacheLoader. Changing the CacheLoader takes immediate effect.
125: *
126: * @param cacheLoader the loader to dynamically load new cache entries. This replaces the CacheLoader in the underlying ehcache.
127: */
128: public void setCacheLoader(CacheLoader cacheLoader) {
129: cache.setCacheLoader(cacheLoader);
130: }
131:
132: /**
133: * Add a listener to the list of cache listeners. The behaviour of JCACHE and Ehcache listeners is a little
134: * different. See {@link JCacheListenerAdaptor} for details on how each event is adapted.
135: *
136: * @param cacheListener a JCACHE CacheListener
137: * @see JCacheListenerAdaptor
138: */
139: public void addListener(CacheListener cacheListener) {
140: JCacheListenerAdaptor cacheListenerAdaptor = new JCacheListenerAdaptor(
141: cacheListener);
142: cache.getCacheEventNotificationService().registerListener(
143: cacheListenerAdaptor);
144: }
145:
146: /**
147: * The evict method will remove objects from the cache that are no longer valid.
148: * Objects where the specified expiration time has been reached.
149: * <p/>
150: * This implementation synchronously checks each store for expired elements. Note that the DiskStore
151: * has an expiryThread that runs periodically to do the same thing, and that the MemoryStore lazily checks
152: * for expiry on overflow and peek, thus reducing the utility of calling this method.
153: */
154: public void evict() {
155: cache.evictExpiredElements();
156: }
157:
158: /**
159: * The getAll method will return, from the cache, a Map of the objects associated with the Collection of keys in argument "keys".
160: * If the objects are not in the cache, the associated cache loader will be called. If no loader is associated with an object,
161: * a null is returned. If a problem is encountered during the retrieving or loading of the objects, an exception will be thrown.
162: * If the "arg" argument is set, the arg object will be passed to the CacheLoader.loadAll method. The cache will not dereference
163: * the object. If no "arg" value is provided a null will be passed to the loadAll method. The storing of null values in the cache
164: * is permitted, however, the get method will not distinguish returning a null stored in the cache and not finding the object in
165: * the cache. In both cases a null is returned.
166: * <p/>
167: * The Ehcache native API provides similar functionality to loaders using the
168: * decorator {@link net.sf.ehcache.constructs.blocking.SelfPopulatingCache}
169: * <p/>
170: * Note. If the getAll exceeds the maximum cache
171: * size, the returned map will necessarily be less than the number specified.
172: *
173: * @param keys
174: * @return a Map populated from the Cache. If there are no elements, an empty Map is returned.
175: */
176: public Map getAll(Collection keys) throws CacheException {
177: return getAll(keys, null);
178: }
179:
180: /**
181: * The getAll method will return, from the cache, a Map of the objects associated with the Collection of keys in argument "keys".
182: * If the objects are not in the cache, the associated cache loader will be called. If no loader is associated with an object,
183: * a null is returned. If a problem is encountered during the retrieving or loading of the objects, an exception will be thrown.
184: * If the "arg" argument is set, the arg object will be passed to the CacheLoader.loadAll method. The cache will not dereference
185: * the object. If no "arg" value is provided a null will be passed to the loadAll method. The storing of null values in the cache
186: * is permitted, however, the get method will not distinguish returning a null stored in the cache and not finding the object in
187: * the cache. In both cases a null is returned.
188: * <p/>
189: * The Ehcache native API provides similar functionality to loaders using the
190: * decorator {@link net.sf.ehcache.constructs.blocking.SelfPopulatingCache}
191: * <p/>
192: * Note. If the getAll exceeds the maximum cache
193: * size, the returned map will necessarily be less than the number specified.
194: *
195: * @param keys
196: * @return a Map populated from the Cache. If there are no elements, an empty Map is returned.
197: */
198: public Map getAll(Collection keys, Object loaderArgument)
199: throws CacheException {
200: return cache.getAllWithLoader(keys, loaderArgument);
201: }
202:
203: /**
204: * Gets the CacheLoader registered in this cache
205: *
206: * @return the loader, or null if there is none
207: */
208: public CacheLoader getCacheLoader() {
209: return cache.getCacheLoader();
210: }
211:
212: /**
213: * returns the CacheEntry object associated with the key.
214: *
215: * @param key the key to look for in the cache
216: */
217: public CacheEntry getCacheEntry(Object key) {
218: Element element = cache.get(key);
219: if (element != null) {
220: return new net.sf.ehcache.jcache.JCacheEntry(element);
221: } else {
222: return null;
223: }
224: }
225:
226: /**
227: * Gets an immutable Statistics object representing the Cache statistics at the time. How the statistics are calculated
228: * depends on the statistics accuracy setting. The only aspect of statistics sensitive to the accuracy setting is
229: * object size. How that is calculated is discussed below.
230: * <h3>Best Effort Size</h3>
231: * This result is returned when the statistics accuracy setting is {@link CacheStatistics#STATISTICS_ACCURACY_BEST_EFFORT}.
232: * <p/>
233: * The size is the number of {@link Element}s in the {@link net.sf.ehcache.store.MemoryStore} plus
234: * the number of {@link Element}s in the {@link net.sf.ehcache.store.DiskStore}.
235: * <p/>
236: * This number is the actual number of elements, including expired elements that have
237: * not been removed. Any duplicates between stores are accounted for.
238: * <p/>
239: * Expired elements are removed from the the memory store when
240: * getting an expired element, or when attempting to spool an expired element to
241: * disk.
242: * <p/>
243: * Expired elements are removed from the disk store when getting an expired element,
244: * or when the expiry thread runs, which is once every five minutes.
245: * <p/>
246: * <h3>Guaranteed Accuracy Size</h3>
247: * This result is returned when the statistics accuracy setting is {@link CacheStatistics#STATISTICS_ACCURACY_GUARANTEED}.
248: * <p/>
249: * This method accounts for elements which might be expired or duplicated between stores. It take approximately
250: * 200ms per 1000 elements to execute.
251: * <h3>Fast but non-accurate Size</h3>
252: * This result is returned when the statistics accuracy setting is {@link CacheStatistics#STATISTICS_ACCURACY_NONE}.
253: * <p/>
254: * The number given may contain expired elements. In addition if the DiskStore is used it may contain some double
255: * counting of elements. It takes 6ms for 1000 elements to execute. Time to execute is O(log n). 50,000 elements take
256: * 36ms.
257: *
258: * @return the number of elements in the ehcache, with a varying degree of accuracy, depending on accuracy setting.
259: * @throws IllegalStateException if the cache is not {@link net.sf.ehcache.Status#STATUS_ALIVE}
260: */
261: public CacheStatistics getCacheStatistics()
262: throws IllegalStateException {
263: return new JCacheStatistics(cache.getStatistics());
264: }
265:
266: /**
267: * The load method provides a means to "pre load" the cache. This method will, asynchronously, load the specified
268: * object into the cache using the associated cacheloader. If the object already exists in the cache, no action is
269: * taken. If no loader is associated with the object, no object will be loaded into the cache. If a problem is
270: * encountered during the retrieving or loading of the object, an exception should be logged. If the "arg" argument
271: * is set, the arg object will be passed to the CacheLoader.load method. The cache will not dereference the object.
272: * If no "arg" value is provided a null will be passed to the load method. The storing of null values in the cache
273: * is permitted, however, the get method will not distinguish returning a null stored in the cache and not finding
274: * the object in the cache. In both cases a null is returned.
275: * <p/>
276: * The Ehcache native API provides similar functionality to loaders using the
277: * decorator {@link net.sf.ehcache.constructs.blocking.SelfPopulatingCache}
278: *
279: * @param key key whose associated value to be loaded using the associated cacheloader if this cache doesn't contain it.
280: */
281: public void load(final Object key) throws CacheException {
282: cache.load(key);
283: }
284:
285: /**
286: * The loadAll method provides a means to "pre load" objects into the cache. This method will, asynchronously, load
287: * the specified objects into the cache using the associated cache loader. If the an object already exists in the
288: * cache, no action is taken. If no loader is associated with the object, no object will be loaded into the cache.
289: * If a problem is encountered during the retrieving or loading of the objects, an exception (to be defined)
290: * should be logged. The getAll method will return, from the cache, a Map of the objects associated with the
291: * Collection of keys in argument "keys". If the objects are not in the cache, the associated cache loader will be
292: * called. If no loader is associated with an object, a null is returned. If a problem is encountered during the
293: * retrieving or loading of the objects, an exception (to be defined) will be thrown. If the "arg" argument is set,
294: * the arg object will be passed to the CacheLoader.loadAll method. The cache will not dereference the object.
295: * If no "arg" value is provided a null will be passed to the loadAll method.
296: * <p/>
297: * keys - collection of the keys whose associated values to be loaded into this cache by using the associated
298: * cacheloader if this cache doesn't contain them.
299: * <p/>
300: * The Ehcache native API provides similar functionality to loaders using the
301: * decorator {@link net.sf.ehcache.constructs.blocking.SelfPopulatingCache}
302: */
303: public void loadAll(final Collection keys) throws CacheException {
304: loadAll(keys, null);
305: }
306:
307: /**
308: * The loadAll method provides a means to "pre load" objects into the cache. This method will, asynchronously, load
309: * the specified objects into the cache using the associated cache loader. If the an object already exists in the
310: * cache, no action is taken. If no loader is associated with the object, no object will be loaded into the cache.
311: * If a problem is encountered during the retrieving or loading of the objects, an exception (to be defined)
312: * should be logged. The getAll method will return, from the cache, a Map of the objects associated with the
313: * Collection of keys in argument "keys". If the objects are not in the cache, the associated cache loader will be
314: * called. If no loader is associated with an object, a null is returned. If a problem is encountered during the
315: * retrieving or loading of the objects, an exception (to be defined) will be thrown. If the "arg" argument is set,
316: * the arg object will be passed to the CacheLoader.loadAll method. The cache will not dereference the object.
317: * If no "arg" value is provided a null will be passed to the loadAll method.
318: * <p/>
319: * keys - collection of the keys whose associated values to be loaded into this cache by using the associated
320: * cacheloader if this cache doesn't contain them.
321: * <p/>
322: * The Ehcache native API provides similar functionality to loaders using the
323: * decorator {@link net.sf.ehcache.constructs.blocking.SelfPopulatingCache}
324: */
325: public void loadAll(final Collection keys, final Object argument)
326: throws CacheException {
327: cache.loadAll(keys, argument);
328: }
329:
330: /**
331: * The peek method will return the object associated with "key" if it currently exists (and is valid) in the cache.
332: * If not, a null is returned. With "peek" the CacheLoader will not be invoked and other caches in the system will not be searched.
333: * <p/>
334: * In ehcache peek bahaves the same way as {@link #get}
335: *
336: * @param key
337: * @return the value stored in the cache by key, or null if it does not exist
338: */
339: public Object peek(Object key) {
340: Element element = cache.get(key);
341: if (element != null) {
342: return element.getObjectValue();
343: } else {
344: return null;
345: }
346: }
347:
348: /**
349: * Remove a listener from the list of cache listeners
350: *
351: * @param cacheListener a JCACHE CacheListener
352: * @see JCacheListenerAdaptor
353: */
354: public void removeListener(CacheListener cacheListener) {
355: JCacheListenerAdaptor cacheListenerAdaptor = new JCacheListenerAdaptor(
356: cacheListener);
357: cache.getCacheEventNotificationService().unregisterListener(
358: cacheListenerAdaptor);
359: }
360:
361: /**
362: * Returns the number of key-value mappings in this map. If the
363: * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
364: * <tt>Integer.MAX_VALUE</tt>.
365: *
366: * @return the number of key-value mappings in this map.
367: */
368: public int size() {
369: return cache.getSize();
370: }
371:
372: /**
373: * Returns <tt>true</tt> if this map contains no key-value mappings.
374: *
375: * @return <tt>true</tt> if this map contains no key-value mappings.
376: */
377: public boolean isEmpty() {
378: return (size() == 0);
379: }
380:
381: /**
382: * Returns <tt>true</tt> if this map contains a mapping for the specified
383: * key. More formally, returns <tt>true</tt> if and only if
384: * this map contains a mapping for a key <tt>k</tt> such that
385: * <tt>(key==null ? k==null : key.equals(k))</tt>. (There can be
386: * at most one such mapping.)
387: *
388: * @param key key whose presence in this map is to be tested.
389: * @return <tt>true</tt> if this map contains a mapping for the specified
390: * key.
391: */
392: public boolean containsKey(Object key) {
393: return cache.isKeyInCache(key);
394: }
395:
396: /**
397: * Returns <tt>true</tt> if this map maps one or more keys to the
398: * specified value. More formally, returns <tt>true</tt> if and only if
399: * this map contains at least one mapping to a value <tt>v</tt> such that
400: * <tt>(value==null ? v==null : value.equals(v))</tt>. This operation
401: * will probably require time linear in the map size for most
402: * implementations of the <tt>Map</tt> interface.
403: * <p/>
404: * Warning: This method is extremely slow. Ehcache is designed for efficient
405: * retrieval using keys, not values.
406: *
407: * @param value value whose presence in this map is to be tested.
408: * @return <tt>true</tt> if this map maps one or more keys to the
409: * specified value.
410: */
411: public boolean containsValue(Object value) {
412: long start = System.currentTimeMillis();
413:
414: boolean inCache = cache.isValueInCache(value);
415: long end = System.currentTimeMillis();
416:
417: if (LOG.isWarnEnabled()) {
418: LOG
419: .warn("Performance Warning: containsValue is not recommended. This call took "
420: + (end - start) + " ms");
421: }
422: return inCache;
423: }
424:
425: /**
426: * The get method will return, from the cache, the object associated with
427: * the argument "key".
428: * <p/>
429: * If the object is not in the cache, the associated
430: * cache loader will be called. If no loader is associated with the object,
431: * a null is returned.
432: * <p/>
433: * If a problem is encountered during the retrieving
434: * or loading of the object, an exception (to be defined) will be thrown. (Until it is
435: * defined, the ehcache implementation throws a RuntimeException.)
436: * <p/>
437: * If the "arg" argument is set, the arg object will be passed to the
438: * CacheLoader.load method. The cache will not dereference the object.
439: * If no "arg" value is provided a null will be passed to the load method.
440: * <p/>
441: * The storing of null values in the cache is permitted, however, the get
442: * method will not distinguish returning a null stored in the cache and
443: * not finding the object in the cache. In both cases a null is returned.
444: * <p/>
445: * Cache statistics are only updated for the initial attempt to get the cached entry.
446: *
447: * @param key key whose associated value is to be returned.
448: * @return the value to which this map maps the specified key, or
449: * <tt>null</tt> if the map contains no mapping for this key after an attempt has been
450: * made to load it.
451: * @throws RuntimeException JSR107 should really throw a CacheException here, but the
452: * spec does not allow it. Instead throw a RuntimeException if the underlying load method
453: * throws a CacheException.
454: * @see #containsKey(Object)
455: */
456: public Object get(Object key) throws RuntimeException {
457: return get(key, null);
458: }
459:
460: /**
461: * Same as {@link #get(Object)} except a CacheLoader argument is provided.
462: *
463: * @param key key whose associated value is to be returned.
464: * @param loaderArgument anything at all that a CacheLoader might find useful to load
465: * the entry. If the loaderArgument is null, this method is the same as {@link #get(Object)}
466: * @return the value to which this map maps the specified key, or
467: * <tt>null</tt> if the map contains no mapping for this key after an attempt has been
468: * made to load it.
469: * @throws RuntimeException JSR107 should really throw a CacheException here, but the
470: * spec does not allow it. Instead throw a RuntimeException if the underlying load method
471: * throws a CacheException.
472: */
473: public Object get(Object key, Object loaderArgument)
474: throws RuntimeException {
475: return get(key, null, loaderArgument);
476: }
477:
478: /**
479: * The get method will return, from the cache, the object associated with
480: * the argument "key".
481: * <p/>
482: * If the object is not in the cache, the associated
483: * cache loader will be called. If no loader is associated with the object,
484: * a null is returned.
485: * <p/>
486: * If a problem is encountered during the retrieving
487: * or loading of the object, an exception (to be defined) will be thrown. (Until it is
488: * defined, the ehcache implementation throws a RuntimeException.)
489: * <p/>
490: * If the "argument" argument is set, the arg object will be passed to the
491: * CacheLoader.load method. The cache will not dereference the object.
492: * If no "argument" value is provided a null will be passed to the load method.
493: * <p/>
494: * The storing of null values in the cache is permitted, however, the get
495: * method will not distinguish returning a null stored in the cache and
496: * not finding the object in the cache. In both cases a null is returned.
497: * <p/>
498: * Cache statistics are only updated for the initial attempt to get the cached entry.
499: *
500: * @param key key whose associated value is to be returned.
501: * @param loader A specific CacheLoader to use in place of the default one.
502: * @return the value to which this map maps the specified key, or
503: * <tt>null</tt> if the map contains no mapping for this key after an attempt has been
504: * made to load it.
505: * @throws RuntimeException JSR107 should really throw a CacheException here, but the
506: * spec does not allow it. Instead throw a RuntimeException if the underlying load method
507: * throws a CacheException.
508: * @see #containsKey(Object)
509: */
510: public Object get(Object key, CacheLoader loader)
511: throws RuntimeException {
512: return get(key, loader, null);
513: }
514:
515: /**
516: * The get method will return, from the cache, the object associated with
517: * the argument "key".
518: * <p/>
519: * If the object is not in the cache, the associated
520: * cache loader will be called. If no loader is associated with the object,
521: * a null is returned.
522: * <p/>
523: * If a problem is encountered during the retrieving
524: * or loading of the object, an exception (to be defined) will be thrown. (Until it is
525: * defined, the ehcache implementation throws a RuntimeException.)
526: * <p/>
527: * If the "loaderArgument" argument is set, it will be passed to the
528: * CacheLoader.load method. The cache will not dereference the object.
529: * If no "loaderArgument" value is provided a null will be passed to the load method.
530: * <p/>
531: * The storing of null values in the cache is permitted, however, the get
532: * method will not distinguish returning a null stored in the cache and
533: * not finding the object in the cache. In both cases a null is returned.
534: * <p/>
535: * Cache statistics are only updated for the initial attempt to get the cached entry.
536: *
537: * @param key key whose associated value is to be returned.
538: * @param loader A specific CacheLoader to use in place of the default one.
539: * @param loaderArgument an Object with acts as a loaderArgument. It can contain anything that makes sense to the loader.
540: * @return the value to which this map maps the specified key, or
541: * <tt>null</tt> if the map contains no mapping for this key after an attempt has been
542: * made to load it.
543: * @throws RuntimeException JSR107 should really throw a CacheException here, but the
544: * spec does not allow it. Instead throw a RuntimeException if the underlying load method
545: * throws a CacheException.
546: * @see #containsKey(Object)
547: */
548: public Object get(Object key, CacheLoader loader,
549: Object loaderArgument) throws RuntimeException {
550: Element element = cache.getWithLoader(key, loader,
551: loaderArgument);
552: if (element == null) {
553: return null;
554: } else {
555: return element.getObjectValue();
556: }
557: }
558:
559: /**
560: * Associates the specified value with the specified key in this map
561: * (optional operation). If the map previously contained a mapping for
562: * this key, the old value is replaced by the specified value. (A map
563: * <tt>m</tt> is said to contain a mapping for a key <tt>k</tt> if and only
564: * if {@link #containsKey(Object) m.containsKey(k)} would return
565: * <tt>true</tt>.))
566: *
567: * @param key key with which the specified value is to be associated.
568: * @param value value to be associated with the specified key.
569: * @return previous value associated with specified key, or <tt>null</tt>
570: * if there was no mapping for key. A <tt>null</tt> return can
571: * also indicate that the map previously associated <tt>null</tt>
572: * with the specified key, if the implementation supports
573: * <tt>null</tt> values.
574: */
575: public Object put(Object key, Object value) {
576: return put(key, value, 0);
577: }
578:
579: /**
580: * Associates the specified value with the specified key in this map
581: * (optional operation). If the map previously contained a mapping for
582: * this key, the old value is replaced by the specified value. (A map
583: * <tt>m</tt> is said to contain a mapping for a key <tt>k</tt> if and only
584: * if {@link #containsKey(Object) m.containsKey(k)} would return
585: * <tt>true</tt>.))
586: *
587: * @param key key with which the specified value is to be associated.
588: * @param value value to be associated with the specified key.
589: * @param timeToLiveSeconds the time this entry will live, overriding the default. If timeToLive
590: * is set to 0, the default will be applied.
591: * @return previous value associated with specified key, or <tt>null</tt>
592: * if there was no mapping for key. A <tt>null</tt> return can
593: * also indicate that the map previously associated <tt>null</tt>
594: * with the specified key, if the implementation supports
595: * <tt>null</tt> values.
596: */
597: public Object put(Object key, Object value, int timeToLiveSeconds) {
598: Element element = null;
599: if (cache.isKeyInCache(key)) {
600: element = cache.getQuiet(key);
601: }
602: Element newElement = new Element(key, value);
603: if (timeToLiveSeconds != 0) {
604: newElement.setTimeToLive(timeToLiveSeconds);
605: }
606: cache.put(newElement);
607:
608: if (element != null) {
609: return element.getObjectValue();
610: } else {
611: return null;
612: }
613: }
614:
615: /**
616: * Removes the mapping for this key from this map if it is present
617: * (optional operation). More formally, if this map contains a mapping
618: * from key <tt>k</tt> to value <tt>v</tt> such that
619: * <code>(key==null ? k==null : key.equals(k))</code>, that mapping
620: * is removed. (The map can contain at most one such mapping.)
621: * <p/>
622: * <p>Returns the value to which the map previously associated the key, or
623: * <tt>null</tt> if the map contained no mapping for this key. (A
624: * <tt>null</tt> return can also indicate that the map previously
625: * associated <tt>null</tt> with the specified key if the implementation
626: * supports <tt>null</tt> values.) The map will not contain a mapping for
627: * the specified key once the call returns.
628: *
629: * @param key key whose mapping is to be removed from the map.
630: * @return previous value associated with specified key, or <tt>null</tt>
631: * if there was no mapping for key.
632: */
633: public Object remove(Object key) {
634: Element element = cache.get(key);
635: cache.remove(key);
636: if (element != null) {
637: return element.getObjectValue();
638: } else {
639: return null;
640: }
641: }
642:
643: /**
644: * Copies all of the mappings from the specified map to this map
645: * (optional operation). The effect of this call is equivalent to that
646: * of calling {@link #put(Object,Object) put(k, v)} on this map once
647: * for each mapping from key <tt>k</tt> to value <tt>v</tt> in the
648: * N specified map. The behavior of this operation is unspecified if the
649: * specified map is modified while the operation is in progress.
650: *
651: * @param sourceMap Mappings to be stored in this map.
652: */
653:
654: public void putAll(Map sourceMap) {
655: if (sourceMap == null) {
656: return;
657: }
658: for (Iterator iterator = sourceMap.keySet().iterator(); iterator
659: .hasNext();) {
660: Object key = iterator.next();
661: cache.put(new Element(key, sourceMap.get(key)));
662: }
663: }
664:
665: /**
666: * Removes all mappings from this map (optional operation).
667: */
668: public void clear() {
669: cache.removeAll();
670: }
671:
672: /**
673: * Returns a set view of the keys contained in this map. The set is
674: * not live because ehcache is not backed by a simple map.
675: *
676: * @return a set view of the keys contained in this map.
677: */
678: public Set keySet() {
679: List list = cache.getKeys();
680: Set set = new HashSet();
681: set.addAll(list);
682: return set;
683: }
684:
685: /**
686: * Returns a collection view of the values contained in this map. The
687: * collection is backed by the map, so changes to the map are reflected in
688: * the collection, and vice-versa. If the map is modified while an
689: * iteration over the collection is in progress (except through the
690: * iterator's own <tt>remove</tt> operation), the results of the
691: * iteration are undefined. The collection supports element removal,
692: * which removes the corresponding mapping from the map, via the
693: * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
694: * <tt>removeAll</tt>, <tt>retainAll</tt> and <tt>clear</tt> operations.
695: * It does not support the add or <tt>addAll</tt> operations.
696: * <p/>
697: * Contradicting the above Map contract, whether cache changes after this method returns are not
698: * reflected in the Collection. This is because ehcache is not backed by a single map.
699: *
700: * @return a collection view of the values contained in this map.
701: */
702: public Collection values() {
703: List list = cache.getKeysNoDuplicateCheck();
704: Set set = new HashSet(list.size());
705: for (int i = 0; i < list.size(); i++) {
706: Object key = list.get(i);
707: Element element = cache.get(key);
708: if (element != null) {
709: set.add(element.getObjectValue());
710: }
711: }
712: return set;
713: }
714:
715: /**
716: * Returns a set view of the mappings contained in this map. Each element
717: * in the returned set is a {@link java.util.Map.Entry}. The set is backed by the
718: * map, so changes to the map are reflected in the set, and vice-versa.
719: * If the map is modified while an iteration over the set is in progress
720: * (except through the iterator's own <tt>remove</tt> operation, or through
721: * the <tt>setValue</tt> operation on a map entry returned by the iterator)
722: * the results of the iteration are undefined. The set supports element
723: * removal, which removes the corresponding mapping from the map, via the
724: * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>,
725: * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not support
726: * the <tt>add</tt> or <tt>addAll</tt> operations.
727: * <p/>
728: * Contradicting the above Map contract, whether or not changes to an entry affect the entry in the cache is undefined.
729: *
730: * @return a set view of the mappings contained in this map.
731: */
732: public Set entrySet() {
733: List list = cache.getKeysNoDuplicateCheck();
734: Set set = new HashSet(list.size());
735: for (int i = 0; i < list.size(); i++) {
736: Object key = list.get(i);
737: Element element = cache.get(key);
738: if (element != null) {
739: set.add(new net.sf.ehcache.jcache.JCacheEntry(element));
740: }
741: }
742: return set;
743: }
744:
745: /**
746: * Sets the statistics accuracy.
747: *
748: * @param statisticsAccuracy one of {@link CacheStatistics#STATISTICS_ACCURACY_BEST_EFFORT}, {@link CacheStatistics#STATISTICS_ACCURACY_GUARANTEED}, {@link CacheStatistics#STATISTICS_ACCURACY_NONE}
749: */
750: public void setStatisticsAccuracy(int statisticsAccuracy) {
751: cache.setStatisticsAccuracy(statisticsAccuracy);
752: }
753:
754: /**
755: * Gets the backing Ehcache
756: */
757: public Ehcache getBackingCache() {
758: return cache;
759: }
760:
761: /**
762: * Returns a {@link String} representation of the underlying {@link net.sf.ehcache.Cache}.
763: *
764: * @return a string representation of the object.
765: */
766: public String toString() {
767: return cache.toString();
768: }
769:
770: }
|