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.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                    Object thisObject = methodInvocation.getThis();
058    
059                    Class<?> targetClass = thisObject.getClass();
060    
061                    Method method = methodInvocation.getMethod();
062    
063                    List<Annotation> annotations = AnnotationLocator.locate(
064                            method, targetClass);
065    
066                    Iterator<Annotation> iterator = annotations.iterator();
067    
068                    while (iterator.hasNext()) {
069                            Annotation curAnnotation = iterator.next();
070    
071                            if (!serviceBeanAopCacheManager.isRegisteredAnnotationClass(
072                                            curAnnotation.annotationType())) {
073    
074                                    iterator.remove();
075                            }
076                    }
077    
078                    ServiceBeanAopCacheManager.putAnnotations(
079                            methodInvocation,
080                            annotations.toArray(new Annotation[annotations.size()]));
081    
082                    Set<Class<? extends Annotation>> annotationClasses =
083                            new HashSet<Class<? extends Annotation>>();
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<Class<? extends Annotation>,
104                                    AnnotationChainableMethodAdvice<?>[]> entry :
105                                            annotationChainableMethodAdvices.entrySet()) {
106    
107                            Class<? extends Annotation> annotationClass = entry.getKey();
108                            AnnotationChainableMethodAdvice<?>[]
109                                    annotationChainableMethodAdvicesArray = entry.getValue();
110    
111                            if (annotationClasses.contains(annotationClass) ||
112                                    (annotationChainableMethodAdvicesArray == null)) {
113    
114                                    continue;
115                            }
116    
117                            for (AnnotationChainableMethodAdvice<?>
118                                            annotationChainableMethodAdvice :
119                                                    annotationChainableMethodAdvicesArray) {
120    
121                                    serviceBeanAopCacheManager.removeMethodInterceptor(
122                                            methodInvocation, annotationChainableMethodAdvice);
123                            }
124                    }
125    
126                    return (T)annotation;
127            }
128    
129            @Override
130            protected void setServiceBeanAopCacheManager(
131                    ServiceBeanAopCacheManager serviceBeanAopCacheManager) {
132    
133                    if (this.serviceBeanAopCacheManager != null) {
134                            return;
135                    }
136    
137                    this.serviceBeanAopCacheManager = serviceBeanAopCacheManager;
138    
139                    serviceBeanAopCacheManager.registerAnnotationChainableMethodAdvice(
140                            _annotationClass, this);
141            }
142    
143            private Class<? extends Annotation> _annotationClass;
144            private T _nullAnnotation;
145    
146    }