View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.cache.ehcache;
20  
21  import net.sf.ehcache.Element;
22  import org.apache.shiro.cache.Cache;
23  import org.apache.shiro.cache.CacheException;
24  import org.slf4j.Logger;
25  import org.slf4j.LoggerFactory;
26  
27  import java.util.*;
28  
29  /**
30   * Shiro {@link org.apache.shiro.cache.Cache} implementation that wraps an {@link net.sf.ehcache.Ehcache} instance.
31   *
32   * @since 0.2
33   */
34  public class EhCache<K, V> implements Cache<K, V> {
35  
36      /**
37       * Private internal log instance.
38       */
39      private static final Logger log = LoggerFactory.getLogger(EhCache.class);
40  
41      /**
42       * The wrapped Ehcache instance.
43       */
44      private net.sf.ehcache.Ehcache cache;
45  
46      /**
47       * Constructs a new EhCache instance with the given cache.
48       *
49       * @param cache - delegate EhCache instance this Shiro cache instance will wrap.
50       */
51      public EhCache(net.sf.ehcache.Ehcache cache) {
52          if (cache == null) {
53              throw new IllegalArgumentException("Cache argument cannot be null.");
54          }
55          this.cache = cache;
56      }
57  
58      /**
59       * Gets a value of an element which matches the given key.
60       *
61       * @param key the key of the element to return.
62       * @return The value placed into the cache with an earlier put, or null if not found or expired
63       */
64      public V get(K key) throws CacheException {
65          try {
66              if (log.isTraceEnabled()) {
67                  log.trace("Getting object from cache [" + cache.getName() + "] for key [" + key + "]");
68              }
69              if (key == null) {
70                  return null;
71              } else {
72                  Element element = cache.get(key);
73                  if (element == null) {
74                      if (log.isTraceEnabled()) {
75                          log.trace("Element for [" + key + "] is null.");
76                      }
77                      return null;
78                  } else {
79                      //noinspection unchecked
80                      return (V) element.getObjectValue();
81                  }
82              }
83          } catch (Throwable t) {
84              throw new CacheException(t);
85          }
86      }
87  
88      /**
89       * Puts an object into the cache.
90       *
91       * @param key   the key.
92       * @param value the value.
93       */
94      public V put(K key, V value) throws CacheException {
95          if (log.isTraceEnabled()) {
96              log.trace("Putting object in cache [" + cache.getName() + "] for key [" + key + "]");
97          }
98          try {
99              V previous = get(key);
100             Element element = new Element(key, value);
101             cache.put(element);
102             return previous;
103         } catch (Throwable t) {
104             throw new CacheException(t);
105         }
106     }
107 
108     /**
109      * Removes the element which matches the key.
110      *
111      * <p>If no element matches, nothing is removed and no Exception is thrown.</p>
112      *
113      * @param key the key of the element to remove
114      */
115     public V remove(K key) throws CacheException {
116         if (log.isTraceEnabled()) {
117             log.trace("Removing object from cache [" + cache.getName() + "] for key [" + key + "]");
118         }
119         try {
120             V previous = get(key);
121             cache.remove(key);
122             return previous;
123         } catch (Throwable t) {
124             throw new CacheException(t);
125         }
126     }
127 
128     /**
129      * Removes all elements in the cache, but leaves the cache in a useable state.
130      */
131     public void clear() throws CacheException {
132         if (log.isTraceEnabled()) {
133             log.trace("Clearing all objects from cache [" + cache.getName() + "]");
134         }
135         try {
136             cache.removeAll();
137         } catch (Throwable t) {
138             throw new CacheException(t);
139         }
140     }
141 
142     public int size() {
143         try {
144             return cache.getSize();
145         } catch (Throwable t) {
146             throw new CacheException(t);
147         }
148     }
149 
150     public Set<K> keys() {
151         try {
152             @SuppressWarnings({"unchecked"})
153             List<K> keys = cache.getKeys();
154             if (!isEmpty(keys)) {
155                 return Collections.unmodifiableSet(new LinkedHashSet<K>(keys));
156             } else {
157                 return Collections.emptySet();
158             }
159         } catch (Throwable t) {
160             throw new CacheException(t);
161         }
162     }
163 
164     public Collection<V> values() {
165         try {
166             @SuppressWarnings({"unchecked"})
167             List<K> keys = cache.getKeys();
168             if (!isEmpty(keys)) {
169                 List<V> values = new ArrayList<V>(keys.size());
170                 for (K key : keys) {
171                     V value = get(key);
172                     if (value != null) {
173                         values.add(value);
174                     }
175                 }
176                 return Collections.unmodifiableList(values);
177             } else {
178                 return Collections.emptyList();
179             }
180         } catch (Throwable t) {
181             throw new CacheException(t);
182         }
183     }
184 
185     /**
186      * Returns the size (in bytes) that this EhCache is using in memory (RAM), or <code>-1</code> if that
187      * number is unknown or cannot be calculated.
188      *
189      * @return the size (in bytes) that this EhCache is using in memory (RAM), or <code>-1</code> if that
190      *         number is unknown or cannot be calculated.
191      */
192     public long getMemoryUsage() {
193         try {
194             return cache.calculateInMemorySize();
195         }
196         catch (Throwable t) {
197             return -1;
198         }
199     }
200 
201     /**
202      * Returns the size (in bytes) that this EhCache's memory store is using (RAM), or <code>-1</code> if
203      * that number is unknown or cannot be calculated.
204      *
205      * @return the size (in bytes) that this EhCache's memory store is using (RAM), or <code>-1</code> if
206      *         that number is unknown or cannot be calculated.
207      */
208     public long getMemoryStoreSize() {
209         try {
210             return cache.getMemoryStoreSize();
211         }
212         catch (Throwable t) {
213             throw new CacheException(t);
214         }
215     }
216 
217     /**
218      * Returns the size (in bytes) that this EhCache's disk store is consuming or <code>-1</code> if
219      * that number is unknown or cannot be calculated.
220      *
221      * @return the size (in bytes) that this EhCache's disk store is consuming or <code>-1</code> if
222      *         that number is unknown or cannot be calculated.
223      */
224     public long getDiskStoreSize() {
225         try {
226             return cache.getDiskStoreSize();
227         } catch (Throwable t) {
228             throw new CacheException(t);
229         }
230     }
231 
232     /**
233      * Returns &quot;EhCache [&quot; + cache.getName() + &quot;]&quot;
234      *
235      * @return &quot;EhCache [&quot; + cache.getName() + &quot;]&quot;
236      */
237     public String toString() {
238         return "EhCache [" + cache.getName() + "]";
239     }
240 
241     //////////////////////////
242     // From CollectionUtils //
243     //////////////////////////
244     // CollectionUtils cannot be removed from shiro-core until 2.0 as it has a dependency on PrincipalCollection
245 
246     private static boolean isEmpty(Collection c) {
247         return c == null || c.isEmpty();
248     }
249 }