001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020package org.apache.isis.core.metamodel.facets; 021 022import java.lang.annotation.Annotation; 023import java.lang.reflect.Method; 024 025public final class Annotations { 026 027 private Annotations() {} 028 029 /** 030 * For convenience of the several annotations that apply only to 031 * {@link String}s. 032 */ 033 public static boolean isString(final Class<?> cls) { 034 return cls.equals(String.class); 035 } 036 037 @SuppressWarnings("unchecked") 038 public static <T extends Annotation> T getDeclaredAnnotation(Class<?> cls, Class<T> annotationClass) { 039 final Annotation[] declaredAnnotations = cls.getDeclaredAnnotations(); 040 if(declaredAnnotations == null) { 041 return null; 042 } 043 for (Annotation annotation : declaredAnnotations) { 044 if(annotationClass.isAssignableFrom(annotation.getClass())) { 045 return (T) annotation; 046 } 047 } 048 return null; 049 } 050 051 /** 052 * Searches for annotation on provided class, and if not found for the 053 * superclass. 054 * 055 * <p> 056 * Added to allow bytecode-mangling libraries such as CGLIB to be supported. 057 */ 058 public static <T extends Annotation> T getAnnotation(final Class<?> cls, final Class<T> annotationClass) { 059 if (cls == null) { 060 return null; 061 } 062 final T annotation = cls.getAnnotation(annotationClass); 063 if (annotation != null) { 064 return annotation; 065 } 066 067 // search superclasses 068 final Class<?> superclass = cls.getSuperclass(); 069 if (superclass != null) { 070 try { 071 final T annotationFromSuperclass = getAnnotation(superclass, annotationClass); 072 if (annotationFromSuperclass != null) { 073 return annotationFromSuperclass; 074 } 075 } catch (final SecurityException e) { 076 // fall through 077 } 078 } 079 080 // search implemented interfaces 081 final Class<?>[] interfaces = cls.getInterfaces(); 082 for (final Class<?> iface : interfaces) { 083 final T annotationFromInterface = getAnnotation(iface, annotationClass); 084 if (annotationFromInterface != null) { 085 return annotationFromInterface; 086 } 087 } 088 return null; 089 } 090 091 /** 092 * Searches for annotation on provided method, and if not found for any 093 * inherited methods up from the superclass. 094 * 095 * <p> 096 * Added to allow bytecode-mangling libraries such as CGLIB to be supported. 097 */ 098 public static <T extends Annotation> T getAnnotation(final Method method, final Class<T> annotationClass) { 099 if (method == null) { 100 return null; 101 } 102 final T annotation = method.getAnnotation(annotationClass); 103 if (annotation != null) { 104 return annotation; 105 } 106 107 final Class<?> methodDeclaringClass = method.getDeclaringClass(); 108 109 // search superclasses 110 final Class<?> superclass = methodDeclaringClass.getSuperclass(); 111 if (superclass != null) { 112 try { 113 final Method parentClassMethod = superclass.getMethod(method.getName(), method.getParameterTypes()); 114 return getAnnotation(parentClassMethod, annotationClass); 115 } catch (final SecurityException e) { 116 // fall through 117 } catch (final NoSuchMethodException e) { 118 // fall through 119 } 120 } 121 122 // search implemented interfaces 123 final Class<?>[] interfaces = methodDeclaringClass.getInterfaces(); 124 for (final Class<?> iface : interfaces) { 125 try { 126 final Method ifaceMethod = iface.getMethod(method.getName(), method.getParameterTypes()); 127 return getAnnotation(ifaceMethod, annotationClass); 128 } catch (final SecurityException e) { 129 // fall through 130 } catch (final NoSuchMethodException e) { 131 // fall through 132 } 133 } 134 return null; 135 } 136 137 /** 138 * Searches for annotation on provided method, and if not found for any 139 * inherited methods up from the superclass. 140 * 141 * <p> 142 * Added to allow bytecode-mangling libraries such as CGLIB to be supported. 143 */ 144 public static boolean isAnnotationPresent(final Method method, final Class<? extends Annotation> annotationClass) { 145 if (method == null) { 146 return false; 147 } 148 final boolean present = method.isAnnotationPresent(annotationClass); 149 if (present) { 150 return true; 151 } 152 153 final Class<?> methodDeclaringClass = method.getDeclaringClass(); 154 155 // search superclasses 156 final Class<?> superclass = methodDeclaringClass.getSuperclass(); 157 if (superclass != null) { 158 try { 159 final Method parentClassMethod = superclass.getMethod(method.getName(), method.getParameterTypes()); 160 return isAnnotationPresent(parentClassMethod, annotationClass); 161 } catch (final SecurityException e) { 162 // fall through 163 } catch (final NoSuchMethodException e) { 164 // fall through 165 } 166 } 167 168 // search implemented interfaces 169 final Class<?>[] interfaces = methodDeclaringClass.getInterfaces(); 170 for (final Class<?> iface : interfaces) { 171 try { 172 final Method ifaceMethod = iface.getMethod(method.getName(), method.getParameterTypes()); 173 return isAnnotationPresent(ifaceMethod, annotationClass); 174 } catch (final SecurityException e) { 175 // fall through 176 } catch (final NoSuchMethodException e) { 177 // fall through 178 } 179 } 180 return false; 181 } 182 183 /** 184 * Searches for parameter annotations on provided method, and if not found 185 * for any inherited methods up from the superclass. 186 * 187 * <p> 188 * Added to allow bytecode-mangling libraries such as CGLIB to be supported. 189 */ 190 public static Annotation[][] getParameterAnnotations(final Method method) { 191 if (method == null) { 192 return new Annotation[0][0]; 193 } 194 final Annotation[][] allParamAnnotations = method.getParameterAnnotations(); 195 196 boolean foundAnnotationsForAnyParameter = false; 197 for (final Annotation[] singleParamAnnotations : allParamAnnotations) { 198 if (singleParamAnnotations.length > 0) { 199 foundAnnotationsForAnyParameter = true; 200 break; 201 } 202 } 203 if (foundAnnotationsForAnyParameter) { 204 return allParamAnnotations; 205 } 206 207 final Class<?> methodDeclaringClass = method.getDeclaringClass(); 208 209 // search superclasses 210 final Class<?> superclass = methodDeclaringClass.getSuperclass(); 211 if (superclass != null) { 212 try { 213 final Method parentClassMethod = superclass.getMethod(method.getName(), method.getParameterTypes()); 214 return getParameterAnnotations(parentClassMethod); 215 } catch (final SecurityException e) { 216 // fall through 217 } catch (final NoSuchMethodException e) { 218 // fall through 219 } 220 } 221 222 // search implemented interfaces 223 final Class<?>[] interfaces = methodDeclaringClass.getInterfaces(); 224 for (final Class<?> iface : interfaces) { 225 try { 226 final Method ifaceMethod = iface.getMethod(method.getName(), method.getParameterTypes()); 227 return getParameterAnnotations(ifaceMethod); 228 } catch (final SecurityException e) { 229 // fall through 230 } catch (final NoSuchMethodException e) { 231 // fall through 232 } 233 } 234 235 return noParamAnnotationsFor(method); 236 } 237 238 private static Annotation[][] noParamAnnotationsFor(final Method method) { 239 return new Annotation[method.getParameterTypes().length][0]; 240 } 241 242}