001/* 002 * Copyright 2002-2020 the original author or authors. 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 * https://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 */ 016 017package org.springframework.cache.ehcache; 018 019import java.util.concurrent.Callable; 020 021import net.sf.ehcache.Ehcache; 022import net.sf.ehcache.Element; 023import net.sf.ehcache.Status; 024 025import org.springframework.cache.Cache; 026import org.springframework.cache.support.SimpleValueWrapper; 027import org.springframework.util.Assert; 028 029/** 030 * {@link Cache} implementation on top of an {@link Ehcache} instance. 031 * 032 * @author Costin Leau 033 * @author Juergen Hoeller 034 * @author Stephane Nicoll 035 * @since 3.1 036 */ 037public class EhCacheCache implements Cache { 038 039 private final Ehcache cache; 040 041 042 /** 043 * Create an {@link EhCacheCache} instance. 044 * @param ehcache the backing Ehcache instance 045 */ 046 public EhCacheCache(Ehcache ehcache) { 047 Assert.notNull(ehcache, "Ehcache must not be null"); 048 Status status = ehcache.getStatus(); 049 if (!Status.STATUS_ALIVE.equals(status)) { 050 throw new IllegalArgumentException( 051 "An 'alive' Ehcache is required - current cache is " + status.toString()); 052 } 053 this.cache = ehcache; 054 } 055 056 057 @Override 058 public final String getName() { 059 return this.cache.getName(); 060 } 061 062 @Override 063 public final Ehcache getNativeCache() { 064 return this.cache; 065 } 066 067 @Override 068 public ValueWrapper get(Object key) { 069 Element element = lookup(key); 070 return toValueWrapper(element); 071 } 072 073 @SuppressWarnings("unchecked") 074 @Override 075 public <T> T get(Object key, Callable<T> valueLoader) { 076 Element element = lookup(key); 077 if (element != null) { 078 return (T) element.getObjectValue(); 079 } 080 else { 081 this.cache.acquireWriteLockOnKey(key); 082 try { 083 element = lookup(key); // one more attempt with the write lock 084 if (element != null) { 085 return (T) element.getObjectValue(); 086 } 087 else { 088 return loadValue(key, valueLoader); 089 } 090 } 091 finally { 092 this.cache.releaseWriteLockOnKey(key); 093 } 094 } 095 } 096 097 private <T> T loadValue(Object key, Callable<T> valueLoader) { 098 T value; 099 try { 100 value = valueLoader.call(); 101 } 102 catch (Throwable ex) { 103 throw new ValueRetrievalException(key, valueLoader, ex); 104 } 105 put(key, value); 106 return value; 107 } 108 109 @Override 110 @SuppressWarnings("unchecked") 111 public <T> T get(Object key, Class<T> type) { 112 Element element = this.cache.get(key); 113 Object value = (element != null ? element.getObjectValue() : null); 114 if (value != null && type != null && !type.isInstance(value)) { 115 throw new IllegalStateException( 116 "Cached value is not of required type [" + type.getName() + "]: " + value); 117 } 118 return (T) value; 119 } 120 121 @Override 122 public void put(Object key, Object value) { 123 this.cache.put(new Element(key, value)); 124 } 125 126 @Override 127 public ValueWrapper putIfAbsent(Object key, Object value) { 128 Element existingElement = this.cache.putIfAbsent(new Element(key, value)); 129 return toValueWrapper(existingElement); 130 } 131 132 @Override 133 public void evict(Object key) { 134 this.cache.remove(key); 135 } 136 137 @Override 138 public void clear() { 139 this.cache.removeAll(); 140 } 141 142 143 private Element lookup(Object key) { 144 return this.cache.get(key); 145 } 146 147 private ValueWrapper toValueWrapper(Element element) { 148 return (element != null ? new SimpleValueWrapper(element.getObjectValue()) : null); 149 } 150 151}