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