View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.joran.spi;
15  
16  
17  import java.lang.annotation.Annotation;
18  import java.util.HashSet;
19  import java.util.Set;
20  import ch.qos.logback.core.spi.LifeCycle;
21  
22  public class NoAutoStartUtil {
23  
24      /**
25       * Returns true if the class of the object 'o' passed as parameter is *not*
26       * marked with the NoAutoStart annotation. Return true otherwise.
27       *
28       * @param o
29       * @return true for classes not marked with the NoAutoStart annotation
30       */
31      public static boolean notMarkedWithNoAutoStart(Object o) {
32          if (o == null) {
33              return false;
34          }
35          Class<?> clazz = o.getClass();
36          NoAutoStart a = findAnnotation(clazz, NoAutoStart.class);
37          return a == null;
38      }
39  
40  	/**
41  	 * Find a single {@link Annotation} of {@code annotationType} on the
42  	 * supplied {@link Class}, traversing its interfaces, annotations, and
43  	 * superclasses if the annotation is not <em>directly present</em> on
44  	 * the given class itself.
45  	 * <p>This method explicitly handles class-level annotations which are not
46  	 * declared as {@link java.lang.annotation.Inherited inherited} <em>as well
47  	 * as meta-annotations and annotations on interfaces</em>.
48  	 * <p>The algorithm operates as follows:
49  	 * <ol>
50  	 * <li>Search for the annotation on the given class and return it if found.
51  	 * <li>Recursively search through all interfaces that the given class declares.
52  	 * <li>Recursively search through the superclass hierarchy of the given class.
53  	 * </ol>
54  	 * <p>Note: in this context, the term <em>recursively</em> means that the search
55  	 * process continues by returning to step #1 with the current interface,
56  	 * annotation, or superclass as the class to look for annotations on.
57  	 * @param clazz the class to look for annotations on
58  	 * @param annotationType the type of annotation to look for
59  	 * @return the first matching annotation, or {@code null} if not found
60  	 */
61  	private static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType) {
62  		return findAnnotation(clazz, annotationType, new HashSet<>());
63  	}
64  
65  	/**
66  	 * Perform the search algorithm for {@link #findAnnotation(Class, Class)},
67  	 * avoiding endless recursion by tracking which annotations have already
68  	 * been <em>visited</em>.
69  	 * @param clazz the class to look for annotations on
70  	 * @param annotationType the type of annotation to look for
71  	 * @param visited the set of annotations that have already been visited
72  	 * @return the first matching annotation, or {@code null} if not found
73  	 */
74  	@SuppressWarnings("unchecked")
75  	private static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType, Set<Annotation> visited) {
76  
77  		Annotation foundAnnotation = clazz.getAnnotation(annotationType);
78  		if(foundAnnotation != null) {
79  			return (A) foundAnnotation;
80  		}
81  
82  
83  		for (Class<?> ifc : clazz.getInterfaces()) {
84  			A annotation = findAnnotation(ifc, annotationType, visited);
85  			if (annotation != null) {
86  				return annotation;
87  			}
88  		}
89  
90  		Class<?> superclass = clazz.getSuperclass();
91  		if (superclass == null || Object.class == superclass) {
92  			return null;
93  		}
94  		return findAnnotation(superclass, annotationType, visited);
95  	}
96  
97    /**
98       * Is the object a {@link LifeCycle} and is it marked not marked with
99       * the NoAutoStart annotation.
100      * @param o
101      * @return
102      * @ since 1.5.2
103      */
104     static public boolean shouldBeStarted(Object o) {
105         if(o instanceof LifeCycle) {
106             return notMarkedWithNoAutoStart(o);
107         } else
108             return false;
109     }
110 }