001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.shiro.cache.ehcache;
020
021 import net.sf.ehcache.Element;
022 import org.apache.shiro.cache.Cache;
023 import org.apache.shiro.cache.CacheException;
024 import org.apache.shiro.util.CollectionUtils;
025 import org.slf4j.Logger;
026 import org.slf4j.LoggerFactory;
027
028 import java.util.*;
029
030 /**
031 * Shiro {@link org.apache.shiro.cache.Cache} implementation that wraps an {@link net.sf.ehcache.Ehcache} instance.
032 *
033 * @since 0.2
034 */
035 public class EhCache<K, V> implements Cache<K, V> {
036
037 /**
038 * Private internal log instance.
039 */
040 private static final Logger log = LoggerFactory.getLogger(EhCache.class);
041
042 /**
043 * The wrapped Ehcache instance.
044 */
045 private net.sf.ehcache.Ehcache cache;
046
047 /**
048 * Constructs a new EhCache instance with the given cache.
049 *
050 * @param cache - delegate EhCache instance this Shiro cache instance will wrap.
051 */
052 public EhCache(net.sf.ehcache.Ehcache cache) {
053 if (cache == null) {
054 throw new IllegalArgumentException("Cache argument cannot be null.");
055 }
056 this.cache = cache;
057 }
058
059 /**
060 * Gets a value of an element which matches the given key.
061 *
062 * @param key the key of the element to return.
063 * @return The value placed into the cache with an earlier put, or null if not found or expired
064 */
065 public V get(K key) throws CacheException {
066 try {
067 if (log.isTraceEnabled()) {
068 log.trace("Getting object from cache [" + cache.getName() + "] for key [" + key + "]");
069 }
070 if (key == null) {
071 return null;
072 } else {
073 Element element = cache.get(key);
074 if (element == null) {
075 if (log.isTraceEnabled()) {
076 log.trace("Element for [" + key + "] is null.");
077 }
078 return null;
079 } else {
080 //noinspection unchecked
081 return (V) element.getObjectValue();
082 }
083 }
084 } catch (Throwable t) {
085 throw new CacheException(t);
086 }
087 }
088
089 /**
090 * Puts an object into the cache.
091 *
092 * @param key the key.
093 * @param value the value.
094 */
095 public V put(K key, V value) throws CacheException {
096 if (log.isTraceEnabled()) {
097 log.trace("Putting object in cache [" + cache.getName() + "] for key [" + key + "]");
098 }
099 try {
100 V previous = get(key);
101 Element element = new Element(key, value);
102 cache.put(element);
103 return previous;
104 } catch (Throwable t) {
105 throw new CacheException(t);
106 }
107 }
108
109 /**
110 * Removes the element which matches the key.
111 *
112 * <p>If no element matches, nothing is removed and no Exception is thrown.</p>
113 *
114 * @param key the key of the element to remove
115 */
116 public V remove(K key) throws CacheException {
117 if (log.isTraceEnabled()) {
118 log.trace("Removing object from cache [" + cache.getName() + "] for key [" + key + "]");
119 }
120 try {
121 V previous = get(key);
122 cache.remove(key);
123 return previous;
124 } catch (Throwable t) {
125 throw new CacheException(t);
126 }
127 }
128
129 /**
130 * Removes all elements in the cache, but leaves the cache in a useable state.
131 */
132 public void clear() throws CacheException {
133 if (log.isTraceEnabled()) {
134 log.trace("Clearing all objects from cache [" + cache.getName() + "]");
135 }
136 try {
137 cache.removeAll();
138 } catch (Throwable t) {
139 throw new CacheException(t);
140 }
141 }
142
143 public int size() {
144 try {
145 return cache.getSize();
146 } catch (Throwable t) {
147 throw new CacheException(t);
148 }
149 }
150
151 public Set<K> keys() {
152 try {
153 @SuppressWarnings({"unchecked"})
154 List<K> keys = cache.getKeys();
155 if (!CollectionUtils.isEmpty(keys)) {
156 return Collections.unmodifiableSet(new LinkedHashSet<K>(keys));
157 } else {
158 return Collections.emptySet();
159 }
160 } catch (Throwable t) {
161 throw new CacheException(t);
162 }
163 }
164
165 public Collection<V> values() {
166 try {
167 @SuppressWarnings({"unchecked"})
168 List<K> keys = cache.getKeys();
169 if (!CollectionUtils.isEmpty(keys)) {
170 List<V> values = new ArrayList<V>(keys.size());
171 for (K key : keys) {
172 V value = get(key);
173 if (value != null) {
174 values.add(value);
175 }
176 }
177 return Collections.unmodifiableList(values);
178 } else {
179 return Collections.emptyList();
180 }
181 } catch (Throwable t) {
182 throw new CacheException(t);
183 }
184 }
185
186 /**
187 * Returns the size (in bytes) that this EhCache is using in memory (RAM), or <code>-1</code> if that
188 * number is unknown or cannot be calculated.
189 *
190 * @return the size (in bytes) that this EhCache is using in memory (RAM), or <code>-1</code> if that
191 * number is unknown or cannot be calculated.
192 */
193 public long getMemoryUsage() {
194 try {
195 return cache.calculateInMemorySize();
196 }
197 catch (Throwable t) {
198 return -1;
199 }
200 }
201
202 /**
203 * Returns the size (in bytes) that this EhCache's memory store is using (RAM), or <code>-1</code> if
204 * that number is unknown or cannot be calculated.
205 *
206 * @return the size (in bytes) that this EhCache's memory store is using (RAM), or <code>-1</code> if
207 * that number is unknown or cannot be calculated.
208 */
209 public long getMemoryStoreSize() {
210 try {
211 return cache.getMemoryStoreSize();
212 }
213 catch (Throwable t) {
214 throw new CacheException(t);
215 }
216 }
217
218 /**
219 * Returns the size (in bytes) that this EhCache's disk store is consuming or <code>-1</code> if
220 * that number is unknown or cannot be calculated.
221 *
222 * @return the size (in bytes) that this EhCache's disk store is consuming or <code>-1</code> if
223 * that number is unknown or cannot be calculated.
224 */
225 public long getDiskStoreSize() {
226 try {
227 return cache.getDiskStoreSize();
228 } catch (Throwable t) {
229 throw new CacheException(t);
230 }
231 }
232
233 /**
234 * Returns "EhCache [" + cache.getName() + "]"
235 *
236 * @return "EhCache [" + cache.getName() + "]"
237 */
238 public String toString() {
239 return "EhCache [" + cache.getName() + "]";
240 }
241 }