001
014
015 package com.liferay.portal.increment;
016
017 import com.liferay.portal.kernel.cache.key.CacheKeyGenerator;
018 import com.liferay.portal.kernel.cache.key.CacheKeyGeneratorUtil;
019 import com.liferay.portal.kernel.increment.BufferedIncrement;
020 import com.liferay.portal.kernel.increment.BufferedIncrementThreadLocal;
021 import com.liferay.portal.kernel.increment.Increment;
022 import com.liferay.portal.kernel.increment.IncrementFactory;
023 import com.liferay.portal.kernel.transaction.TransactionCommitCallbackRegistryUtil;
024 import com.liferay.portal.kernel.util.StringUtil;
025 import com.liferay.portal.spring.aop.AnnotationChainableMethodAdvice;
026
027 import java.io.Serializable;
028
029 import java.lang.annotation.Annotation;
030 import java.lang.reflect.Method;
031
032 import java.util.Map;
033 import java.util.concurrent.Callable;
034 import java.util.concurrent.ConcurrentHashMap;
035 import java.util.concurrent.ConcurrentMap;
036
037 import org.aopalliance.intercept.MethodInvocation;
038
039
043 public class BufferedIncrementAdvice
044 extends AnnotationChainableMethodAdvice<BufferedIncrement> {
045
046 @Override
047 @SuppressWarnings("rawtypes")
048 public Object before(MethodInvocation methodInvocation) throws Throwable {
049 BufferedIncrement bufferedIncrement = findAnnotation(methodInvocation);
050
051 if (!BufferedIncrementThreadLocal.isEnabled() ||
052 (bufferedIncrement == _nullBufferedIncrement)) {
053
054 return null;
055 }
056
057 String configuration = bufferedIncrement.configuration();
058
059 BufferedIncrementConfiguration bufferedIncrementConfiguration =
060 _bufferedIncrementConfigurations.get(configuration);
061
062 if (bufferedIncrementConfiguration == null) {
063 bufferedIncrementConfiguration = new BufferedIncrementConfiguration(
064 configuration);
065
066 _bufferedIncrementConfigurations.put(
067 configuration, bufferedIncrementConfiguration);
068 }
069
070 if (!bufferedIncrementConfiguration.isEnabled()) {
071 return nullResult;
072 }
073
074 Method method = methodInvocation.getMethod();
075
076 BufferedIncrementProcessor bufferedIncrementProcessor =
077 _bufferedIncrementProcessors.get(method);
078
079 if (bufferedIncrementProcessor == null) {
080 bufferedIncrementProcessor = new BufferedIncrementProcessor(
081 bufferedIncrementConfiguration, method);
082
083 BufferedIncrementProcessor previousBufferedIncrementProcessor =
084 _bufferedIncrementProcessors.putIfAbsent(
085 method, bufferedIncrementProcessor);
086
087 if (previousBufferedIncrementProcessor != null) {
088 bufferedIncrementProcessor = previousBufferedIncrementProcessor;
089 }
090 }
091
092 Object[] arguments = methodInvocation.getArguments();
093
094 Object value = arguments[arguments.length - 1];
095
096 CacheKeyGenerator cacheKeyGenerator =
097 CacheKeyGeneratorUtil.getCacheKeyGenerator(
098 BufferedIncrementAdvice.class.getName());
099
100 for (int i = 0; i < arguments.length - 1; i++) {
101 cacheKeyGenerator.append(StringUtil.toHexString(arguments[i]));
102 }
103
104 Serializable batchKey = cacheKeyGenerator.finish();
105
106 Increment<?> increment = IncrementFactory.createIncrement(
107 bufferedIncrement.incrementClass(), value);
108
109 final BufferedIncrementProcessor callbackBufferedIncrementProcessor =
110 bufferedIncrementProcessor;
111
112 final BufferedIncreasableEntry bufferedIncreasableEntry =
113 new BufferedIncreasableEntry(methodInvocation, batchKey, increment);
114
115 TransactionCommitCallbackRegistryUtil.registerCallback(
116 new Callable<Void>() {
117
118 @Override
119 public Void call() throws Exception {
120 callbackBufferedIncrementProcessor.process(
121 bufferedIncreasableEntry);
122
123 return null;
124 }
125
126 });
127
128 return nullResult;
129 }
130
131 public void destroy() {
132 for (BufferedIncrementProcessor bufferedIncrementProcessor :
133 _bufferedIncrementProcessors.values()) {
134
135 bufferedIncrementProcessor.destroy();
136 }
137 }
138
139 @Override
140 public BufferedIncrement getNullAnnotation() {
141 return _nullBufferedIncrement;
142 }
143
144 private static BufferedIncrement _nullBufferedIncrement =
145 new BufferedIncrement() {
146
147 @Override
148 public Class<? extends Annotation> annotationType() {
149 return BufferedIncrement.class;
150 }
151
152 @Override
153 public String configuration() {
154 return "default";
155 }
156
157 @Override
158 public Class<? extends Increment<?>> incrementClass() {
159 return null;
160 }
161
162 };
163
164 private Map<String, BufferedIncrementConfiguration>
165 _bufferedIncrementConfigurations =
166 new ConcurrentHashMap<String, BufferedIncrementConfiguration>();
167 private ConcurrentMap<Method, BufferedIncrementProcessor>
168 _bufferedIncrementProcessors =
169 new ConcurrentHashMap<Method, BufferedIncrementProcessor>();
170
171 }