View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.surefire.common.junit4;
20  
21  import java.lang.annotation.Annotation;
22  import java.lang.reflect.Method;
23  
24  import org.junit.Ignore;
25  import org.junit.runner.Description;
26  
27  import static org.apache.maven.surefire.api.util.ReflectionUtils.getMethod;
28  import static org.apache.maven.surefire.api.util.ReflectionUtils.invokeMethodWithArray;
29  import static org.apache.maven.surefire.api.util.ReflectionUtils.tryGetMethod;
30  
31  /**
32   * JUnit4 reflection helper
33   *
34   */
35  public final class JUnit4Reflector {
36      private static final Class<?>[] PARAMS = {Class.class};
37  
38      private static final Object[] IGNORE_PARAMS = {Ignore.class};
39  
40      private static final Class<?>[] PARAMS_WITH_ANNOTATIONS = {String.class, Annotation[].class};
41  
42      private JUnit4Reflector() {
43          throw new IllegalStateException("not instantiable constructor");
44      }
45  
46      public static Ignore getAnnotatedIgnore(Description d) {
47          Method getAnnotation = tryGetMethod(d.getClass(), "getAnnotation", PARAMS);
48          return getAnnotation == null ? null : (Ignore) invokeMethodWithArray(d, getAnnotation, IGNORE_PARAMS);
49      }
50  
51      static String getAnnotatedIgnoreValue(Description description) {
52          final Ignore ignore = getAnnotatedIgnore(description);
53          return ignore != null ? ignore.value() : null;
54      }
55  
56      public static Description createDescription(String description) {
57          try {
58              return Description.createSuiteDescription(description);
59          } catch (NoSuchMethodError e) {
60              Method method = getMethod(Description.class, "createSuiteDescription", PARAMS_WITH_ANNOTATIONS);
61              // may throw exception probably with broken JUnit 4.x
62              return invokeMethodWithArray(null, method, description, new Annotation[0]);
63          }
64      }
65  
66      public static Description createDescription(String description, Annotation... annotations) {
67          Method method = tryGetMethod(Description.class, "createSuiteDescription", PARAMS_WITH_ANNOTATIONS);
68          return method == null
69                  ? Description.createSuiteDescription(description)
70                  : (Description) invokeMethodWithArray(null, method, description, annotations);
71      }
72  
73      public static Ignore createIgnored(String value) {
74          return new IgnoredWithUserError(value);
75      }
76  
77      @SuppressWarnings("ClassExplicitlyAnnotation")
78      private static class IgnoredWithUserError implements Annotation, Ignore {
79          private final String value;
80  
81          IgnoredWithUserError(String value) {
82              this.value = value;
83          }
84  
85          @Override
86          public String value() {
87              return value;
88          }
89  
90          @Override
91          public Class<? extends Annotation> annotationType() {
92              return Ignore.class;
93          }
94  
95          @Override
96          public int hashCode() {
97              return value == null ? 0 : value.hashCode();
98          }
99  
100         @Override
101         public boolean equals(Object obj) {
102             return obj instanceof Ignore && equalValue((Ignore) obj);
103         }
104 
105         @Override
106         public String toString() {
107             return String.format("%s(%s)", Ignore.class, value);
108         }
109 
110         private boolean equalValue(Ignore ignore) {
111             return ignore != null && ignore.value().equals(value);
112         }
113     }
114 }