1 // Copyright 2009 Google Inc. All Rights Reserved.
3 package com
.google
.appengine
.api
.memcache
.stdimpl
;
5 import com
.google
.appengine
.api
.memcache
.MemcacheService
;
6 import com
.google
.appengine
.api
.memcache
.MemcacheServiceFactory
;
7 import com
.google
.appengine
.api
.memcache
.Expiration
;
8 import com
.google
.appengine
.api
.memcache
.Stats
;
10 import java
.util
.Collection
;
11 import java
.util
.Date
;
12 import java
.util
.LinkedList
;
13 import java
.util
.List
;
17 import javax
.cache
.Cache
;
18 import javax
.cache
.CacheEntry
;
19 import javax
.cache
.CacheListener
;
20 import javax
.cache
.CacheStatistics
;
23 * JCache Cache implementation using Memcache.
26 public class GCache
implements Cache
{
28 private final MemcacheService service
;
29 private final List
<CacheListener
> listeners
;
30 private final Expiration expiration
;
31 private final MemcacheService
.SetPolicy setPolicy
;
34 * Creates a JCache implementation over the provided service with the given
36 * @param properties Properties for this cache.
38 public GCache(Map properties
) {
39 listeners
= new LinkedList
<CacheListener
>();
40 if (properties
!= null) {
41 Object expirationProperty
= properties
.get(
42 GCacheFactory
.EXPIRATION_DELTA
);
44 if (expirationProperty
instanceof Integer
) {
45 millis
= (Integer
) expirationProperty
* 1000;
47 expirationProperty
= properties
.get(
48 GCacheFactory
.EXPIRATION_DELTA_MILLIS
);
49 if (expirationProperty
instanceof Integer
) {
50 millis
= (Integer
) expirationProperty
;
53 expiration
= Expiration
.byDeltaMillis(millis
);
55 expirationProperty
= properties
.get(GCacheFactory
.EXPIRATION
);
56 if (expirationProperty
instanceof Date
) {
57 expiration
= Expiration
.onDate((Date
) expirationProperty
);
62 Object setProperty
= properties
.get(GCacheFactory
.SET_POLICY
);
63 if (setProperty
instanceof MemcacheService
.SetPolicy
) {
64 setPolicy
= (MemcacheService
.SetPolicy
) setProperty
;
66 setPolicy
= MemcacheService
.SetPolicy
.SET_ALWAYS
;
68 Object memcacheService
= properties
.get(GCacheFactory
.MEMCACHE_SERVICE
);
69 if (memcacheService
instanceof MemcacheService
) {
70 this.service
= (MemcacheService
) memcacheService
;
72 Object namespace
= properties
.get(GCacheFactory
.NAMESPACE
);
73 if (!(namespace
instanceof String
)) {
76 this.service
= MemcacheServiceFactory
.getMemcacheService(
81 setPolicy
= MemcacheService
.SetPolicy
.SET_ALWAYS
;
82 this.service
= MemcacheServiceFactory
.getMemcacheService();
86 public void addListener(CacheListener cacheListener
) {
87 listeners
.add(cacheListener
);
93 @SuppressWarnings("unchecked")
94 public Map
getAll(Collection collection
) {
95 return service
.getAll(collection
);
98 public CacheEntry
getCacheEntry(Object o
) {
99 Object value
= service
.get(o
);
100 if (value
== null && !service
.contains(o
)) {
103 return new GCacheEntry(this, o
, value
);
106 public CacheStatistics
getCacheStatistics() {
107 return new GCacheStats(service
.getStatistics());
113 public void load(Object o
) {
114 throw new UnsupportedOperationException();
120 public void loadAll(Collection collection
) {
121 throw new UnsupportedOperationException();
124 public Object
peek(Object o
) {
128 public void removeListener(CacheListener cacheListener
) {
129 listeners
.remove(cacheListener
);
133 return getCacheStatistics().getObjectCount();
136 public boolean isEmpty() {
140 public boolean containsKey(Object key
) {
141 return service
.contains(key
);
147 public boolean containsValue(Object value
) {
148 throw new UnsupportedOperationException();
151 public Object
get(Object key
) {
152 return service
.get(key
);
155 public Object
put(Object key
, Object value
) {
156 for (CacheListener listener
: listeners
) {
157 listener
.onPut(value
);
159 if (!service
.put(key
, value
, expiration
, setPolicy
)) {
160 throw new GCacheException("Policy prevented put operation");
165 public Object
remove(Object key
) {
166 for (CacheListener listener
: listeners
) {
167 listener
.onRmove(key
);
169 Object value
= service
.get(key
);
174 @SuppressWarnings("unchecked")
175 public void putAll(Map m
) {
176 Set added
= service
.putAll(m
, expiration
, setPolicy
);
177 added
.removeAll(m
.keySet());
178 if (!added
.isEmpty()) {
179 throw new GCacheException("Policy prevented some put operations");
183 public void clear() {
184 for (CacheListener listener
: listeners
) {
193 public Set
keySet() {
194 throw new UnsupportedOperationException();
200 public Collection
values() {
201 throw new UnsupportedOperationException();
207 public Set
entrySet() {
208 throw new UnsupportedOperationException();
212 * Implementation of the JCache {@link CacheStatistics} using memcache
213 * provided statistics.
215 private static class GCacheStats
implements CacheStatistics
{
220 * Creates a statistics snapshot using the provided stats.
221 * @param stats Statistics to use.
223 private GCacheStats(Stats stats
) {
227 public void clearStatistics() {
228 throw new UnsupportedOperationException();
231 public int getCacheHits() {
232 return (int) stats
.getHitCount();
235 public int getCacheMisses() {
236 return (int) stats
.getMissCount();
239 public int getObjectCount() {
240 return (int) stats
.getItemCount();
243 public int getStatisticsAccuracy() {
244 throw new UnsupportedOperationException();
247 public String
toString() {
248 return stats
.toString();