/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.cache.thread.local; import com.liferay.portal.kernel.cache.thread.local.Lifecycle; import com.liferay.portal.kernel.cache.thread.local.ThreadLocalCachable; import com.liferay.portal.kernel.cache.thread.local.ThreadLocalCache; import com.liferay.portal.kernel.cache.thread.local.ThreadLocalCacheManager; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.spring.aop.AnnotationChainableMethodAdvice; import java.lang.annotation.Annotation; import org.aopalliance.intercept.MethodInvocation; /** * @author Shuyang Zhou * @author Brian Wing Shun Chan */ public class ThreadLocalCacheAdvice extends AnnotationChainableMethodAdvice<ThreadLocalCachable> { @Override public ThreadLocalCachable getNullAnnotation() { return _nullThreadLocalCacheable; } @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { ThreadLocalCachable threadLocalCachable = findAnnotation( methodInvocation); if (threadLocalCachable == _nullThreadLocalCacheable) { return methodInvocation.proceed(); } ThreadLocalCache<Object> threadLocalCache = ThreadLocalCacheManager.getThreadLocalCache( threadLocalCachable.scope(), methodInvocation.getMethod()); String cacheKey = _getCacheKey(methodInvocation.getArguments()); Object value = threadLocalCache.get(cacheKey); if (value != null) { if (value == nullResult) { return null; } return value; } Object result = methodInvocation.proceed(); if (result == null) { threadLocalCache.put(cacheKey, nullResult); } else { threadLocalCache.put(cacheKey, result); } return result; } private String _getCacheKey(Object[] arguments) { if (arguments.length == 1) { return StringUtil.toHexString(arguments[0]); } StringBundler sb = new StringBundler(arguments.length * 2 - 1); for (int i = 0; i < arguments.length; i++) { sb.append(StringUtil.toHexString(arguments[i])); if ((i + 1) < arguments.length) { sb.append(StringPool.POUND); } } return sb.toString(); } private static final ThreadLocalCachable _nullThreadLocalCacheable = new ThreadLocalCachable() { @Override public Class<? extends Annotation> annotationType() { return ThreadLocalCachable.class; } @Override public Lifecycle scope() { return null; } }; }