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