/** * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.juwimm.cms.common.beans; import java.io.Serializable; import java.util.Collection; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * @author <a href="mailto:irbouh@gmail.com">Omar Irbouh</a> * @author <a href="mailto:daniel.murygin@carano.de">Daniel Murygin</a> * @author <a href="mailto:j2ee@juwimm.com">Sascha-Matthias Kulawik</a> * @since 2004.10.07 */ public class MethodCacheInterceptor implements MethodInterceptor, InitializingBean { private static final Log log = LogFactory.getLog(MethodCacheInterceptor.class); private CacheManager cacheManager; private String defaultCacheName; public String getDefaultCacheName() { return defaultCacheName; } public void setDefaultCacheName(String defaultCacheName) { this.defaultCacheName = defaultCacheName; } public void setCacheManager(CacheManager cacheManager) { this.cacheManager = cacheManager; } public CacheManager getCacheManager() { return cacheManager; } /** * Checks if required attributes are provided. */ public void afterPropertiesSet() throws Exception { Assert.notNull(cacheManager, "A cache-manager is required. Use Manager(CacheManager) to provide one."); } /** * main method caches method result if method is configured for caching method results must be serializable */ public Object invoke(MethodInvocation invocation) throws Throwable { String targetName = invocation.getThis().getClass().getName(); String methodName = invocation.getMethod().getName(); Object[] arguments = invocation.getArguments(); String invocationClassName = invocation.getThis().getClass().getName(); Object result = null; Cache cache = getCache(invocation); Element element = null; String cacheKey = getCacheKey(targetName, methodName, arguments); if (cache != null) { element = cache.get(cacheKey); } else if (log.isInfoEnabled()) { log.info("Cache not found in cache manager for class: " + invocationClassName); } if (element == null) { // call target/sub-interceptor if (log.isTraceEnabled()) { log.trace("Calling intercepted method of class: " + invocationClassName); } result = invocation.proceed(); boolean isEmptyCollection = false; if (result != null && result instanceof Collection && ((Collection) result).isEmpty()) { isEmptyCollection = true; } if (cache != null && result != null && !isEmptyCollection) { // cache method result if (log.isTraceEnabled()) { log.trace("Caching result in cache: " + cache.getName() + ", using key: " + cacheKey); } element = new Element(cacheKey, (Serializable) result); cache.put(element); } } else { if (log.isTraceEnabled()) { log.trace("Result found in cache: " + cache.getName() + ", using key: " + cacheKey); } result = element.getObjectValue(); } return result; } /** * creates cache name: targetName.methodName(argument1-class-name,argument2-class-name...) * if argumentsClasses is null or empty name is: targetName.methodName() */ private Cache getCache(MethodInvocation invocation) { String methodName = invocation.getMethod().getName(); Class< ? >[] argumentsClasses = invocation.getMethod().getParameterTypes(); Class< ? > clazz = invocation.getThis().getClass(); String name = getCacheName(clazz, methodName, argumentsClasses); if (log.isTraceEnabled()) { log.trace("Looking for cache with name: " + name); } Cache cache = getCacheManager().getCache(name); // get default if(cache == null) { cache = getCacheManager().getCache(defaultCacheName); } if (log.isTraceEnabled() && cache != null) { log.trace("Cache found: " + cache.getName()); } return cache; } private String getCacheName(Class clazz, String methodName, Class< ? >[] argumentsClasses) { StringBuffer sb = new StringBuffer(); sb.append(clazz.getName()).append(".").append(methodName).append("("); if ((argumentsClasses != null) && (argumentsClasses.length != 0)) { for (int i = 0; i < argumentsClasses.length; i++) { sb.append(argumentsClasses[i].getName()); if ((i + 1) < argumentsClasses.length) { sb.append(","); } } } sb.append(")"); return sb.toString(); } /** * creates cache key: targetName.methodName.argument0.argument1... */ private String getCacheKey(String targetName, String methodName, Object[] arguments) { StringBuffer sb = new StringBuffer(); sb.append(targetName).append(".").append(methodName); if ((arguments != null) && (arguments.length != 0)) { for (int i = 0; i < arguments.length; i++) { sb.append(".").append(arguments[i]); } } return sb.toString(); } }