/** * 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.increment; import com.liferay.portal.kernel.cache.key.CacheKeyGenerator; import com.liferay.portal.kernel.cache.key.CacheKeyGeneratorUtil; import com.liferay.portal.kernel.increment.BufferedIncrement; import com.liferay.portal.kernel.increment.Increment; import com.liferay.portal.kernel.increment.IncrementFactory; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.transaction.TransactionCommitCallbackUtil; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.spring.aop.AnnotationChainableMethodAdvice; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.aopalliance.intercept.MethodInvocation; /** * @author Zsolt Berentey * @author Shuyang Zhou */ public class BufferedIncrementAdvice extends AnnotationChainableMethodAdvice<BufferedIncrement> { @Override @SuppressWarnings("rawtypes") public Object before(MethodInvocation methodInvocation) throws Throwable { BufferedIncrement bufferedIncrement = findAnnotation(methodInvocation); if (bufferedIncrement == _nullBufferedIncrement) { return null; } String configuration = bufferedIncrement.configuration(); BufferedIncrementConfiguration bufferedIncrementConfiguration = _bufferedIncrementConfigurations.get(configuration); if (bufferedIncrementConfiguration == null) { bufferedIncrementConfiguration = new BufferedIncrementConfiguration( configuration); _bufferedIncrementConfigurations.put( configuration, bufferedIncrementConfiguration); } if (!bufferedIncrementConfiguration.isEnabled()) { return nullResult; } Method method = methodInvocation.getMethod(); BufferedIncrementProcessor bufferedIncrementProcessor = _bufferedIncrementProcessors.get(method); if (bufferedIncrementProcessor == null) { bufferedIncrementProcessor = new BufferedIncrementProcessor( bufferedIncrementConfiguration, method); BufferedIncrementProcessor previousBufferedIncrementProcessor = _bufferedIncrementProcessors.putIfAbsent( method, bufferedIncrementProcessor); if (previousBufferedIncrementProcessor != null) { bufferedIncrementProcessor = previousBufferedIncrementProcessor; } } Object[] arguments = methodInvocation.getArguments(); Object value = arguments[arguments.length - 1]; CacheKeyGenerator cacheKeyGenerator = CacheKeyGeneratorUtil.getCacheKeyGenerator( BufferedIncrementAdvice.class.getName()); for (int i = 0; i < arguments.length - 1; i++) { cacheKeyGenerator.append(StringUtil.toHexString(arguments[i])); } Serializable batchKey = cacheKeyGenerator.finish(); try { Increment<?> increment = IncrementFactory.createIncrement( bufferedIncrement.incrementClass(), value); final BufferedIncrementProcessor callbackBufferedIncrementProcessor = bufferedIncrementProcessor; final BufferedIncreasableEntry bufferedIncreasableEntry = new BufferedIncreasableEntry( methodInvocation, batchKey, increment); TransactionCommitCallbackUtil.registerCallback( new Callable<Void>() { @Override public Void call() throws Exception { callbackBufferedIncrementProcessor.process( bufferedIncreasableEntry); return null; } }); } catch (Exception e) { if (_log.isWarnEnabled()) { _log.warn("Unable to increment", e); } } return nullResult; } public void destroy() { for (BufferedIncrementProcessor bufferedIncrementProcessor : _bufferedIncrementProcessors.values()) { bufferedIncrementProcessor.destroy(); } } @Override public BufferedIncrement getNullAnnotation() { return _nullBufferedIncrement; } private static final Log _log = LogFactoryUtil.getLog( BufferedIncrementAdvice.class); private static final BufferedIncrement _nullBufferedIncrement = new BufferedIncrement() { @Override public Class<? extends Annotation> annotationType() { return BufferedIncrement.class; } @Override public String configuration() { return "default"; } @Override public Class<? extends Increment<?>> incrementClass() { return null; } }; private final Map<String, BufferedIncrementConfiguration> _bufferedIncrementConfigurations = new ConcurrentHashMap<>(); private final ConcurrentMap<Method, BufferedIncrementProcessor> _bufferedIncrementProcessors = new ConcurrentHashMap<>(); }