001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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.util.StringUtil;
023    import com.liferay.portal.spring.aop.AnnotationChainableMethodAdvice;
024    
025    import java.io.Serializable;
026    
027    import java.lang.annotation.Annotation;
028    import java.lang.reflect.Method;
029    
030    import java.util.Map;
031    import java.util.concurrent.ConcurrentHashMap;
032    import java.util.concurrent.ConcurrentMap;
033    
034    import org.aopalliance.intercept.MethodInvocation;
035    
036    /**
037     * @author Zsolt Berentey
038     * @author Shuyang Zhou
039     */
040    public class BufferedIncrementAdvice
041            extends AnnotationChainableMethodAdvice<BufferedIncrement> {
042    
043            @Override
044            @SuppressWarnings("rawtypes")
045            public Object before(MethodInvocation methodInvocation) throws Throwable {
046                    BufferedIncrement bufferedIncrement = findAnnotation(methodInvocation);
047    
048                    if (bufferedIncrement == _nullBufferedIncrement) {
049                            return null;
050                    }
051    
052                    String configuration = bufferedIncrement.configuration();
053    
054                    BufferedIncrementConfiguration bufferedIncrementConfiguration =
055                            _bufferedIncrementConfigurations.get(configuration);
056    
057                    if (bufferedIncrementConfiguration == null) {
058                            bufferedIncrementConfiguration = new BufferedIncrementConfiguration(
059                                    configuration);
060    
061                            _bufferedIncrementConfigurations.put(
062                                    configuration, bufferedIncrementConfiguration);
063                    }
064    
065                    if (!bufferedIncrementConfiguration.isEnabled()) {
066                            return nullResult;
067                    }
068    
069                    Method method = methodInvocation.getMethod();
070    
071                    BufferedIncrementProcessor bufferedIncrementProcessor =
072                            _bufferedIncrementProcessors.get(method);
073    
074                    if (bufferedIncrementProcessor == null) {
075                            bufferedIncrementProcessor = new BufferedIncrementProcessor(
076                                    bufferedIncrementConfiguration, method);
077    
078                            BufferedIncrementProcessor previousBufferedIncrementProcessor =
079                                    _bufferedIncrementProcessors.putIfAbsent(
080                                            method, bufferedIncrementProcessor);
081    
082                            if (previousBufferedIncrementProcessor != null) {
083                                    bufferedIncrementProcessor = previousBufferedIncrementProcessor;
084                            }
085                    }
086    
087                    Object[] arguments = methodInvocation.getArguments();
088    
089                    Object value = arguments[arguments.length - 1];
090    
091                    CacheKeyGenerator cacheKeyGenerator =
092                            CacheKeyGeneratorUtil.getCacheKeyGenerator(
093                                    BufferedIncrementAdvice.class.getName());
094    
095                    for (int i = 0; i < arguments.length - 1; i++) {
096                            cacheKeyGenerator.append(StringUtil.toHexString(arguments[i]));
097                    }
098    
099                    Serializable batchKey = cacheKeyGenerator.finish();
100    
101                    Increment<?> increment = IncrementFactory.createIncrement(
102                            bufferedIncrement.incrementClass(), value);
103    
104                    BufferedIncreasableEntry bufferedIncreasableEntry =
105                            new BufferedIncreasableEntry(methodInvocation, batchKey, increment);
106    
107                    bufferedIncrementProcessor.process(bufferedIncreasableEntry);
108    
109                    return nullResult;
110            }
111    
112            public void destroy() {
113                    for (BufferedIncrementProcessor bufferedIncrementProcessor :
114                                    _bufferedIncrementProcessors.values()) {
115    
116                            bufferedIncrementProcessor.destroy();
117                    }
118            }
119    
120            @Override
121            public BufferedIncrement getNullAnnotation() {
122                    return _nullBufferedIncrement;
123            }
124    
125            private static BufferedIncrement _nullBufferedIncrement =
126                    new BufferedIncrement() {
127    
128                            @Override
129                            public Class<? extends Annotation> annotationType() {
130                                    return BufferedIncrement.class;
131                            }
132    
133                            @Override
134                            public String configuration() {
135                                    return "default";
136                            }
137    
138                            @Override
139                            public Class<? extends Increment<?>> incrementClass() {
140                                    return null;
141                            }
142    
143                    };
144    
145            private Map<String, BufferedIncrementConfiguration>
146                    _bufferedIncrementConfigurations =
147                            new ConcurrentHashMap<String, BufferedIncrementConfiguration>();
148            private ConcurrentMap<Method, BufferedIncrementProcessor>
149                    _bufferedIncrementProcessors =
150                            new ConcurrentHashMap<Method, BufferedIncrementProcessor>();
151    
152    }