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 void afterPropertiesSet() {
073                    ServiceBeanAopCacheManagerUtil.registerServiceBeanAopCacheManager(this);
074            }
075    
076            public void destroy() {
077                    ServiceBeanAopCacheManagerUtil.unregisterServiceBeanAopCacheManager(
078                            this);
079            }
080    
081            public MethodInterceptorsBag getMethodInterceptorsBag(
082                    MethodInvocation methodInvocation) {
083    
084                    return _methodInterceptorBags.get(methodInvocation);
085            }
086    
087            public Map<Class<? extends Annotation>, AnnotationChainableMethodAdvice<?>>
088                    getRegisteredAnnotationChainableMethodAdvices() {
089    
090                    return _annotationChainableMethodAdvices;
091            }
092    
093            public boolean isRegisteredAnnotationClass(
094                    Class<? extends Annotation> annotationClass) {
095    
096                    return _annotationChainableMethodAdvices.containsKey(annotationClass);
097            }
098    
099            public void putMethodInterceptorsBag(
100                    MethodInvocation methodInvocation,
101                    MethodInterceptorsBag methodInterceptorsBag) {
102    
103                    _methodInterceptorBags.put(methodInvocation, methodInterceptorsBag);
104            }
105    
106            public void registerAnnotationChainableMethodAdvice(
107                    Class<? extends Annotation> annotationClass,
108                    AnnotationChainableMethodAdvice<?> annotationChainableMethodAdvice) {
109    
110                    _annotationChainableMethodAdvices.put(
111                            annotationClass, annotationChainableMethodAdvice);
112            }
113    
114            public void removeMethodInterceptor(
115                    MethodInvocation methodInvocation,
116                    MethodInterceptor methodInterceptor) {
117    
118                    if (!(methodInvocation instanceof ServiceBeanMethodInvocation)) {
119                            return;
120                    }
121    
122                    ServiceBeanMethodInvocation serviceBeanMethodInvocation =
123                            (ServiceBeanMethodInvocation)methodInvocation;
124    
125                    MethodInterceptorsBag methodInterceptorsBag =
126                            _methodInterceptorBags.get(serviceBeanMethodInvocation);
127    
128                    if (methodInterceptorsBag == null) {
129                            return;
130                    }
131    
132                    ArrayList<MethodInterceptor> methodInterceptors =
133                            new ArrayList<MethodInterceptor>(
134                                    methodInterceptorsBag.getMergedMethodInterceptors());
135    
136                    methodInterceptors.remove(methodInterceptor);
137    
138                    MethodInterceptorsBag newMethodInterceptorsBag = null;
139    
140                    if (methodInterceptors.equals(
141                                    methodInterceptorsBag.getClassLevelMethodInterceptors())) {
142    
143                            newMethodInterceptorsBag = new MethodInterceptorsBag(
144                                    methodInterceptorsBag.getClassLevelMethodInterceptors(),
145                                    methodInterceptorsBag.getClassLevelMethodInterceptors());
146                    }
147                    else {
148                            methodInterceptors.trimToSize();
149    
150                            newMethodInterceptorsBag = new MethodInterceptorsBag(
151                                    methodInterceptorsBag.getClassLevelMethodInterceptors(),
152                                    methodInterceptors);
153                    }
154    
155                    _methodInterceptorBags.put(
156                            serviceBeanMethodInvocation.toCacheKeyModel(),
157                            newMethodInterceptorsBag);
158            }
159    
160            public void reset() {
161                    _annotations.clear();
162                    _methodInterceptorBags.clear();
163            }
164    
165            private static Map<MethodInvocation, Annotation[]> _annotations =
166                    new ConcurrentHashMap<MethodInvocation, Annotation[]>();
167            private static Annotation[] _nullAnnotations = new Annotation[0];
168    
169            private Map<Class<? extends Annotation>, AnnotationChainableMethodAdvice<?>>
170                    _annotationChainableMethodAdvices = new HashMap
171                            <Class<? extends Annotation>, AnnotationChainableMethodAdvice<?>>();
172            private Map<MethodInvocation, MethodInterceptorsBag>
173                    _methodInterceptorBags =
174                            new ConcurrentHashMap<MethodInvocation, MethodInterceptorsBag>();
175    
176    }