001    /**
002     * Copyright (c) 2000-present 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.annotation.AnnotationLocator;
018    
019    import java.lang.annotation.Annotation;
020    import java.lang.reflect.Method;
021    
022    import java.util.HashSet;
023    import java.util.Iterator;
024    import java.util.List;
025    import java.util.Map;
026    import java.util.Set;
027    
028    import org.aopalliance.intercept.MethodInvocation;
029    
030    /**
031     * @author Shuyang Zhou
032     * @author Brian Wing Shun Chan
033     */
034    public abstract class AnnotationChainableMethodAdvice<T extends Annotation>
035            extends ChainableMethodAdvice {
036    
037            public AnnotationChainableMethodAdvice() {
038                    _nullAnnotation = getNullAnnotation();
039    
040                    _annotationClass = _nullAnnotation.annotationType();
041            }
042    
043            public Class<? extends Annotation> getAnnotationClass() {
044                    return _annotationClass;
045            }
046    
047            public abstract T getNullAnnotation();
048    
049            protected T findAnnotation(MethodInvocation methodInvocation) {
050                    Annotation annotation = ServiceBeanAopCacheManager.getAnnotation(
051                            methodInvocation, _annotationClass, _nullAnnotation);
052    
053                    if (annotation != null) {
054                            return (T)annotation;
055                    }
056    
057                    Method method = methodInvocation.getMethod();
058    
059                    ServiceBeanMethodInvocation serviceBeanMethodInvocation =
060                            (ServiceBeanMethodInvocation)methodInvocation;
061    
062                    Class<?> targetClass = serviceBeanMethodInvocation.getTargetClass();
063    
064                    List<Annotation> annotations = AnnotationLocator.locate(
065                            method, targetClass);
066    
067                    Iterator<Annotation> iterator = annotations.iterator();
068    
069                    while (iterator.hasNext()) {
070                            Annotation curAnnotation = iterator.next();
071    
072                            if (!serviceBeanAopCacheManager.isRegisteredAnnotationClass(
073                                            curAnnotation.annotationType())) {
074    
075                                    iterator.remove();
076                            }
077                    }
078    
079                    ServiceBeanAopCacheManager.putAnnotations(
080                            methodInvocation,
081                            annotations.toArray(new Annotation[annotations.size()]));
082    
083                    Set<Class<? extends Annotation>> annotationClasses = new HashSet<>();
084    
085                    annotation = _nullAnnotation;
086    
087                    for (Annotation curAnnotation : annotations) {
088                            Class<? extends Annotation> annotationClass =
089                                    curAnnotation.annotationType();
090    
091                            if (annotationClass == _annotationClass) {
092                                    annotation = curAnnotation;
093                            }
094    
095                            annotationClasses.add(annotationClass);
096                    }
097    
098                    Map<Class<? extends Annotation>, AnnotationChainableMethodAdvice<?>[]>
099                            annotationChainableMethodAdvices =
100                                    serviceBeanAopCacheManager.
101                                            getRegisteredAnnotationChainableMethodAdvices();
102    
103                    for (Map.Entry
104                                    <Class<? extends Annotation>,
105                                            AnnotationChainableMethodAdvice<?>[]> entry :
106                                                    annotationChainableMethodAdvices.entrySet()) {
107    
108                            Class<? extends Annotation> annotationClass = entry.getKey();
109                            AnnotationChainableMethodAdvice<?>[]
110                                    annotationChainableMethodAdvicesArray = entry.getValue();
111    
112                            if (annotationClasses.contains(annotationClass) ||
113                                    (annotationChainableMethodAdvicesArray == null)) {
114    
115                                    continue;
116                            }
117    
118                            for (AnnotationChainableMethodAdvice<?>
119                                            annotationChainableMethodAdvice :
120                                                    annotationChainableMethodAdvicesArray) {
121    
122                                    serviceBeanAopCacheManager.removeMethodInterceptor(
123                                            methodInvocation, annotationChainableMethodAdvice);
124                            }
125                    }
126    
127                    return (T)annotation;
128            }
129    
130            @Override
131            protected void setServiceBeanAopCacheManager(
132                    ServiceBeanAopCacheManager serviceBeanAopCacheManager) {
133    
134                    if (this.serviceBeanAopCacheManager != null) {
135                            return;
136                    }
137    
138                    this.serviceBeanAopCacheManager = serviceBeanAopCacheManager;
139    
140                    serviceBeanAopCacheManager.registerAnnotationChainableMethodAdvice(
141                            _annotationClass, this);
142            }
143    
144            private final Class<? extends Annotation> _annotationClass;
145            private final T _nullAnnotation;
146    
147    }