/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.kernel.annotation; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Queue; /** * @author Shuyang Zhou */ public class AnnotationLocator { public static List<Annotation> locate(Class<?> targetClass) { Queue<Class<?>> queue = new LinkedList<>(); queue.offer(targetClass); ArrayList<Annotation> annotationsList = new ArrayList<>(); Class<?> clazz = null; while ((clazz = queue.poll()) != null) { Annotation[] annotations = clazz.getAnnotations(); _mergeAnnotations(annotations, annotationsList); _queueSuperTypes(queue, clazz); } annotationsList.trimToSize(); return annotationsList; } public static <T extends Annotation> T locate( Class<?> targetClass, Class<T> annotationClass) { Queue<Class<?>> queue = new LinkedList<>(); queue.offer(targetClass); Class<?> clazz = null; while ((clazz = queue.poll()) != null) { T annotation = clazz.getAnnotation(annotationClass); if (annotation == null) { _queueSuperTypes(queue, clazz); } else { return annotation; } } return null; } public static List<Annotation> locate(Method method, Class<?> targetClass) { Queue<Class<?>> queue = new LinkedList<>(); if (targetClass == null) { queue.offer(method.getDeclaringClass()); } else { queue.offer(targetClass); } ArrayList<Annotation> annotationsList = new ArrayList<>(); Class<?> clazz = null; while ((clazz = queue.poll()) != null) { try { Method specificMethod = clazz.getDeclaredMethod( method.getName(), method.getParameterTypes()); Annotation[] annotations = specificMethod.getAnnotations(); _mergeAnnotations(annotations, annotationsList); } catch (Exception e) { } try { // Ensure the class has a publicly inherited method clazz.getMethod(method.getName(), method.getParameterTypes()); Annotation[] annotations = clazz.getAnnotations(); _mergeAnnotations(annotations, annotationsList); } catch (Exception e) { } _queueSuperTypes(queue, clazz); } annotationsList.trimToSize(); return annotationsList; } public static <T extends Annotation> T locate( Method method, Class<?> targetClass, Class<T> annotationClass) { Queue<Class<?>> queue = new LinkedList<>(); if (targetClass == null) { queue.offer(method.getDeclaringClass()); } else { queue.offer(targetClass); } Class<?> clazz = null; while ((clazz = queue.poll()) != null) { T annotation = null; try { Method specificMethod = clazz.getDeclaredMethod( method.getName(), method.getParameterTypes()); annotation = specificMethod.getAnnotation(annotationClass); if (annotation != null) { return annotation; } } catch (Exception e) { } try { // Ensure the class has a publicly inherited method clazz.getMethod(method.getName(), method.getParameterTypes()); annotation = clazz.getAnnotation(annotationClass); } catch (Exception e) { } if (annotation == null) { _queueSuperTypes(queue, clazz); } else { return annotation; } } return null; } private static void _mergeAnnotations( Annotation[] sourceAnnotations, List<Annotation> targetAnnotationList) { merge: for (Annotation sourceAnnotation : sourceAnnotations) { for (Annotation targetAnnotation : targetAnnotationList) { if (sourceAnnotation.annotationType() == targetAnnotation.annotationType()) { continue merge; } } targetAnnotationList.add(sourceAnnotation); } } private static void _queueSuperTypes( Queue<Class<?>> queue, Class<?> clazz) { Class<?> supperClass = clazz.getSuperclass(); if ((supperClass != null) && (supperClass != Object.class)) { queue.offer(supperClass); } Class<?>[] interfaceClasses = clazz.getInterfaces(); for (Class<?> interfaceClass : interfaceClasses) { if (!queue.contains(interfaceClass)) { queue.offer(interfaceClass); } } } }