001
014
015 package com.liferay.portal.cache;
016
017 import com.liferay.portal.kernel.cache.Lifecycle;
018 import com.liferay.portal.kernel.cache.ThreadLocalCachable;
019 import com.liferay.portal.kernel.cache.ThreadLocalCache;
020 import com.liferay.portal.kernel.cache.ThreadLocalCacheManager;
021 import com.liferay.portal.kernel.util.StringBundler;
022 import com.liferay.portal.kernel.util.StringPool;
023 import com.liferay.portal.kernel.util.StringUtil;
024 import com.liferay.portal.spring.aop.AnnotationChainableMethodAdvice;
025 import com.liferay.portal.spring.aop.ServiceBeanMethodInvocation;
026
027 import java.io.Serializable;
028
029 import java.lang.annotation.Annotation;
030
031 import org.aopalliance.intercept.MethodInvocation;
032
033
037 public class ThreadLocalCacheAdvice
038 extends AnnotationChainableMethodAdvice<ThreadLocalCachable> {
039
040 @Override
041 public void afterReturning(MethodInvocation methodInvocation, Object result)
042 throws Throwable {
043
044 ThreadLocalCachable threadLocalCachable = findAnnotation(
045 methodInvocation);
046
047 if (threadLocalCachable == _nullThreadLocalCacheable) {
048 return;
049 }
050
051 Serializable cacheName = _getCacheName(methodInvocation);
052
053 ThreadLocalCache<Object> threadLocalCache =
054 ThreadLocalCacheManager.getThreadLocalCache(
055 threadLocalCachable.scope(), cacheName);
056
057 String cacheKey = _getCacheKey(methodInvocation.getArguments());
058
059 if (result == null) {
060 threadLocalCache.put(cacheKey, nullResult);
061 }
062 else {
063 threadLocalCache.put(cacheKey, result);
064 }
065 }
066
067 @Override
068 public Object before(MethodInvocation methodInvocation) throws Throwable {
069 ThreadLocalCachable threadLocalCachable = findAnnotation(
070 methodInvocation);
071
072 if (threadLocalCachable == _nullThreadLocalCacheable) {
073 return null;
074 }
075
076 Serializable cacheName = _getCacheName(methodInvocation);
077
078 ThreadLocalCache<?> threadLocalCache =
079 ThreadLocalCacheManager.getThreadLocalCache(
080 threadLocalCachable.scope(), cacheName);
081
082 String cacheKey = _getCacheKey(methodInvocation.getArguments());
083
084 Object value = threadLocalCache.get(cacheKey);
085
086 if (value == nullResult) {
087 return null;
088 }
089
090 return value;
091 }
092
093 @Override
094 public ThreadLocalCachable getNullAnnotation() {
095 return _nullThreadLocalCacheable;
096 }
097
098 private String _getCacheKey(Object[] arguments) {
099 StringBundler sb = new StringBundler(arguments.length * 2 - 1);
100
101 for (int i = 0; i < arguments.length; i++) {
102 sb.append(StringUtil.toHexString(arguments[i]));
103
104 if ((i + 1) < arguments.length) {
105 sb.append(StringPool.POUND);
106 }
107 }
108
109 return sb.toString();
110 }
111
112 private Serializable _getCacheName(MethodInvocation methodInvocation) {
113 if (methodInvocation instanceof ServiceBeanMethodInvocation) {
114 ServiceBeanMethodInvocation serviceBeanMethodInvocation =
115 (ServiceBeanMethodInvocation)methodInvocation;
116
117 return serviceBeanMethodInvocation.toCacheKeyModel();
118 }
119 else {
120 return methodInvocation.toString();
121 }
122 }
123
124 private static ThreadLocalCachable _nullThreadLocalCacheable =
125 new ThreadLocalCachable() {
126
127 public Class<? extends Annotation> annotationType() {
128 return ThreadLocalCachable.class;
129 }
130
131 public Lifecycle scope() {
132 return null;
133 }
134
135 };
136
137 }