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.spring.aop;
016    
017    import com.liferay.portal.kernel.util.ArrayUtil;
018    
019    import java.lang.annotation.Annotation;
020    
021    import java.util.ArrayList;
022    import java.util.HashMap;
023    import java.util.Map;
024    import java.util.concurrent.ConcurrentHashMap;
025    
026    import org.aopalliance.intercept.MethodInterceptor;
027    import org.aopalliance.intercept.MethodInvocation;
028    
029    /**
030     * @author Shuyang Zhou
031     */
032    public class ServiceBeanAopCacheManager {
033    
034            public static <T> T getAnnotation(
035                    MethodInvocation methodInvocation,
036                    Class<? extends Annotation> annotationType, T defaultValue) {
037    
038                    Annotation[] annotations = _annotations.get(methodInvocation);
039    
040                    if (annotations == _nullAnnotations) {
041                            return defaultValue;
042                    }
043    
044                    if (annotations == null) {
045                            return null;
046                    }
047    
048                    for (Annotation annotation : annotations) {
049                            if (annotation.annotationType() == annotationType) {
050                                    return (T)annotation;
051                            }
052                    }
053    
054                    return defaultValue;
055            }
056    
057            public static void putAnnotations(
058                    MethodInvocation methodInvocation, Annotation[] annotations) {
059    
060                    if (ArrayUtil.isEmpty(annotations)) {
061                            annotations = _nullAnnotations;
062                    }
063    
064                    if (methodInvocation instanceof ServiceBeanMethodInvocation) {
065                            ServiceBeanMethodInvocation serviceBeanMethodInvocation =
066                                    (ServiceBeanMethodInvocation)methodInvocation;
067    
068                            methodInvocation = serviceBeanMethodInvocation.toCacheKeyModel();
069                    }
070    
071                    _annotations.put(methodInvocation, annotations);
072            }
073    
074            public MethodInterceptorsBag getMethodInterceptorsBag(
075                    MethodInvocation methodInvocation) {
076    
077                    return _methodInterceptorBags.get(methodInvocation);
078            }
079    
080            public Map
081                    <Class<? extends Annotation>, AnnotationChainableMethodAdvice<?>[]>
082                            getRegisteredAnnotationChainableMethodAdvices() {
083    
084                    return _annotationChainableMethodAdvices;
085            }
086    
087            public boolean isRegisteredAnnotationClass(
088                    Class<? extends Annotation> annotationClass) {
089    
090                    return _annotationChainableMethodAdvices.containsKey(annotationClass);
091            }
092    
093            public void putMethodInterceptorsBag(
094                    MethodInvocation methodInvocation,
095                    MethodInterceptorsBag methodInterceptorsBag) {
096    
097                    _methodInterceptorBags.put(methodInvocation, methodInterceptorsBag);
098            }
099    
100            public void registerAnnotationChainableMethodAdvice(
101                    Class<? extends Annotation> annotationClass,
102                    AnnotationChainableMethodAdvice<?> annotationChainableMethodAdvice) {
103    
104                    AnnotationChainableMethodAdvice<?>[] annotationChainableMethodAdvices =
105                            _annotationChainableMethodAdvices.get(annotationClass);
106    
107                    if (annotationChainableMethodAdvices == null) {
108                            annotationChainableMethodAdvices =
109                                    new AnnotationChainableMethodAdvice<?>[1];
110    
111                            annotationChainableMethodAdvices[0] =
112                                    annotationChainableMethodAdvice;
113                    }
114                    else {
115                            annotationChainableMethodAdvices = ArrayUtil.append(
116                                    annotationChainableMethodAdvices,
117                                    annotationChainableMethodAdvice);
118                    }
119    
120                    _annotationChainableMethodAdvices.put(
121                            annotationClass, annotationChainableMethodAdvices);
122            }
123    
124            public void removeMethodInterceptor(
125                    MethodInvocation methodInvocation,
126                    MethodInterceptor methodInterceptor) {
127    
128                    if (!(methodInvocation instanceof ServiceBeanMethodInvocation)) {
129                            return;
130                    }
131    
132                    ServiceBeanMethodInvocation serviceBeanMethodInvocation =
133                            (ServiceBeanMethodInvocation)methodInvocation;
134    
135                    MethodInterceptorsBag methodInterceptorsBag =
136                            _methodInterceptorBags.get(serviceBeanMethodInvocation);
137    
138                    if (methodInterceptorsBag == null) {
139                            return;
140                    }
141    
142                    ArrayList<MethodInterceptor> methodInterceptors =
143                            new ArrayList<MethodInterceptor>(
144                                    methodInterceptorsBag.getMergedMethodInterceptors());
145    
146                    methodInterceptors.remove(methodInterceptor);
147    
148                    MethodInterceptorsBag newMethodInterceptorsBag = null;
149    
150                    if (methodInterceptors.equals(
151                                    methodInterceptorsBag.getClassLevelMethodInterceptors())) {
152    
153                            newMethodInterceptorsBag = new MethodInterceptorsBag(
154                                    methodInterceptorsBag.getClassLevelMethodInterceptors(),
155                                    methodInterceptorsBag.getClassLevelMethodInterceptors());
156                    }
157                    else {
158                            methodInterceptors.trimToSize();
159    
160                            newMethodInterceptorsBag = new MethodInterceptorsBag(
161                                    methodInterceptorsBag.getClassLevelMethodInterceptors(),
162                                    methodInterceptors);
163                    }
164    
165                    _methodInterceptorBags.put(
166                            serviceBeanMethodInvocation.toCacheKeyModel(),
167                            newMethodInterceptorsBag);
168            }
169    
170            public void reset() {
171                    _annotations.clear();
172                    _methodInterceptorBags.clear();
173            }
174    
175            private static Map<MethodInvocation, Annotation[]> _annotations =
176                    new ConcurrentHashMap<MethodInvocation, Annotation[]>();
177            private static Annotation[] _nullAnnotations = new Annotation[0];
178    
179            private
180                    Map<Class<? extends Annotation>, AnnotationChainableMethodAdvice<?>[]>
181                            _annotationChainableMethodAdvices = new HashMap
182                                    <Class<? extends Annotation>,
183                                     AnnotationChainableMethodAdvice<?>[]>();
184            private Map<MethodInvocation, MethodInterceptorsBag>
185                    _methodInterceptorBags =
186                            new ConcurrentHashMap<MethodInvocation, MethodInterceptorsBag>();
187    
188    }