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.kernel.annotation;
016    
017    import java.lang.annotation.Annotation;
018    import java.lang.reflect.Method;
019    
020    import java.util.LinkedList;
021    import java.util.Queue;
022    
023    /**
024     * @author Shuyang Zhou
025     */
026    public class AnnotationLocator {
027    
028            public static <T extends Annotation> T locate(
029                    Class<?> targetClass, Class<T> annotationClass) {
030    
031                    Queue<Class<?>> queue = new LinkedList<Class<?>>();
032    
033                    queue.offer(targetClass);
034    
035                    return _deepSearchTypes(queue, annotationClass);
036            }
037    
038            public static <T extends Annotation> T locate(
039                    Method method, Class<?> targetClass, Class<T> annotationClass) {
040    
041                    Queue<Class<?>> queue = new LinkedList<Class<?>>();
042    
043                    if (targetClass == null) {
044                            queue.offer(method.getDeclaringClass());
045                    }
046                    else {
047                            queue.offer(targetClass);
048                    }
049    
050                    return _deepSearchMethods(queue, method, annotationClass);
051            }
052    
053            private static <T extends Annotation> T _deepSearchMethods(
054                    Queue<Class<?>> queue, Method method, Class<T> annotationClass) {
055    
056                    if (queue.isEmpty()) {
057                            return null;
058                    }
059    
060                    T annotation = null;
061    
062                    Class<?> clazz = queue.poll();
063    
064                    try {
065                            Method specificMethod = clazz.getDeclaredMethod(
066                                    method.getName(), method.getParameterTypes());
067    
068                            annotation = specificMethod.getAnnotation(annotationClass);
069    
070                            if (annotation != null) {
071                                    return annotation;
072                            }
073                    }
074                    catch (Exception e) {
075                    }
076    
077                    annotation = clazz.getAnnotation(annotationClass);
078    
079                    if (annotation == null) {
080                            _queueSuperTypes(queue, clazz);
081    
082                            return _deepSearchMethods(queue, method, annotationClass);
083                    }
084                    else {
085                            return annotation;
086                    }
087            }
088    
089            private static <T extends Annotation> T _deepSearchTypes(
090                    Queue<Class<?>> queue, Class<T> annotationClass) {
091    
092                    if (queue.isEmpty()) {
093                            return null;
094                    }
095    
096                    Class<?> clazz = queue.poll();
097    
098                    T annotation = clazz.getAnnotation(annotationClass);
099    
100                    if (annotation == null) {
101                            _queueSuperTypes(queue, clazz);
102    
103                            return _deepSearchTypes(queue, annotationClass);
104                    }
105                    else {
106                            return annotation;
107                    }
108            }
109    
110            private static void _queueSuperTypes(
111                    Queue<Class<?>> queue, Class<?> clazz) {
112    
113                    Class<?> supperClass = clazz.getSuperclass();
114    
115                    if ((supperClass != null) && (supperClass != Object.class)) {
116                            queue.offer(supperClass);
117                    }
118    
119                    Class<?>[] interfaceClasses = clazz.getInterfaces();
120    
121                    for (Class<?> interfaceClass : interfaceClasses) {
122                            queue.offer(interfaceClass);
123                    }
124            }
125    
126    }