1 /* 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.reflect; 27 28 import java.lang.annotation.*; 29 import java.util.Map; 30 import sun.reflect.annotation.AnnotationParser; 31 import sun.reflect.generics.repository.ConstructorRepository; 32 import sun.reflect.generics.factory.CoreReflectionFactory; 33 import sun.reflect.generics.factory.GenericsFactory; 34 import sun.reflect.generics.scope.ConstructorScope; 35 36 /** 37 * A shared superclass for the common functionality of {@link Method} 38 * and {@link Constructor}. 39 * 40 * @since 1.8 41 */ 42 public abstract class Executable extends AccessibleObject 43 implements Member, GenericDeclaration { 44 /* 45 * Only grant package-visibility to the constructor. 46 */ 47 Executable() {} 48 49 /** 50 * Accessor method to allow code sharing 51 */ 52 abstract byte[] getAnnotationBytes(); 53 54 /** 55 * Does the Executable have generic information. 56 */ 57 abstract boolean hasGenericInformation(); 58 59 abstract ConstructorRepository getGenericInfo(); 60 61 boolean equalParamTypes(Class<?>[] params1, Class<?>[] params2) { 62 /* Avoid unnecessary cloning */ 63 if (params1.length == params2.length) { 64 for (int i = 0; i < params1.length; i++) { 65 if (params1[i] != params2[i]) 66 return false; 67 } 68 } 69 return true; 70 } 71 72 Annotation[][] parseParameterAnnotations(byte[] parameterAnnotations) { 73 return AnnotationParser.parseParameterAnnotations( 74 parameterAnnotations, 75 sun.misc.SharedSecrets.getJavaLangAccess(). 76 getConstantPool(getDeclaringClass()), 77 getDeclaringClass()); 78 } 79 80 void separateWithCommas(Class<?>[] types, StringBuilder sb) { 81 for (int j = 0; j < types.length; j++) { 82 sb.append(Field.getTypeName(types[j])); 83 if (j < (types.length - 1)) 84 sb.append(","); 85 } 86 87 } 88 89 void printModifiersIfNonzero(StringBuilder sb, int mask) { 90 int mod = getModifiers() & mask; 91 if (mod != 0) { 92 sb.append(Modifier.toString(mod)).append(' '); 93 } 94 } 95 96 String sharedToString(int modifierMask, 97 Class<?>[] parameterTypes, 98 Class<?>[] exceptionTypes) { 99 try { 100 StringBuilder sb = new StringBuilder(); 101 102 printModifiersIfNonzero(sb, modifierMask); 103 specificToStringHeader(sb); 104 105 sb.append('('); 106 separateWithCommas(parameterTypes, sb); 107 sb.append(')'); 108 if (exceptionTypes.length > 0) { 109 sb.append(" throws "); 110 separateWithCommas(exceptionTypes, sb); 111 } 112 return sb.toString(); 113 } catch (Exception e) { 114 return "<" + e + ">"; 115 } 116 } 117 118 /** 119 * Generate toString header information specific to a method or 120 * constructor. 121 */ 122 abstract void specificToStringHeader(StringBuilder sb); 123 124 String sharedToGenericString(int modifierMask) { 125 try { 126 StringBuilder sb = new StringBuilder(); 127 128 printModifiersIfNonzero(sb, modifierMask); 129 130 TypeVariable<?>[] typeparms = getTypeParameters(); 131 if (typeparms.length > 0) { 132 boolean first = true; 133 sb.append('<'); 134 for(TypeVariable<?> typeparm: typeparms) { 135 if (!first) 136 sb.append(','); 137 // Class objects can't occur here; no need to test 138 // and call Class.getName(). 139 sb.append(typeparm.toString()); 140 first = false; 141 } 142 sb.append("> "); 143 } 144 145 specificToGenericStringHeader(sb); 146 147 sb.append('('); 148 Type[] params = getGenericParameterTypes(); 149 for (int j = 0; j < params.length; j++) { 150 String param = (params[j] instanceof Class)? 151 Field.getTypeName((Class)params[j]): 152 (params[j].toString()); 153 if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... 154 param = param.replaceFirst("\\[\\]$", "..."); 155 sb.append(param); 156 if (j < (params.length - 1)) 157 sb.append(','); 158 } 159 sb.append(')'); 160 Type[] exceptions = getGenericExceptionTypes(); 161 if (exceptions.length > 0) { 162 sb.append(" throws "); 163 for (int k = 0; k < exceptions.length; k++) { 164 sb.append((exceptions[k] instanceof Class)? 165 ((Class)exceptions[k]).getName(): 166 exceptions[k].toString()); 167 if (k < (exceptions.length - 1)) 168 sb.append(','); 169 } 170 } 171 return sb.toString(); 172 } catch (Exception e) { 173 return "<" + e + ">"; 174 } 175 } 176 177 /** 178 * Generate toGenericString header information specific to a 179 * method or constructor. 180 */ 181 abstract void specificToGenericStringHeader(StringBuilder sb); 182 183 /** 184 * Returns the {@code Class} object representing the class or interface 185 * that declares the method represented by this executable object. 186 */ 187 public abstract Class<?> getDeclaringClass(); 188 189 /** 190 * Returns the name of the executable represented by this object. 191 */ 192 public abstract String getName(); 193 194 /** 195 * Returns the Java language {@linkplain Modifier modifiers} for 196 * the executable represented by this object. 197 */ 198 public abstract int getModifiers(); 199 200 /** 201 * Returns an array of {@code TypeVariable} objects that represent the 202 * type variables declared by the generic declaration represented by this 203 * {@code GenericDeclaration} object, in declaration order. Returns an 204 * array of length 0 if the underlying generic declaration declares no type 205 * variables. 206 * 207 * @return an array of {@code TypeVariable} objects that represent 208 * the type variables declared by this generic declaration 209 * @throws GenericSignatureFormatError if the generic 210 * signature of this generic declaration does not conform to 211 * the format specified in 212 * <cite>The Java™ Virtual Machine Specification</cite> 213 */ 214 public abstract TypeVariable<?>[] getTypeParameters(); 215 216 /** 217 * Returns an array of {@code Class} objects that represent the formal 218 * parameter types, in declaration order, of the executable 219 * represented by this object. Returns an array of length 220 * 0 if the underlying method takes no parameters. 221 * 222 * @return the parameter types for the method this object 223 * represents 224 */ 225 public abstract Class<?>[] getParameterTypes(); 226 227 /** 228 * Returns an array of {@code Type} objects that represent the formal 229 * parameter types, in declaration order, of the method represented by 230 * this executable object. Returns an array of length 0 if the 231 * underlying method takes no parameters. 232 * 233 * <p>If a formal parameter type is a parameterized type, 234 * the {@code Type} object returned for it must accurately reflect 235 * the actual type parameters used in the source code. 236 * 237 * <p>If a formal parameter type is a type variable or a parameterized 238 * type, it is created. Otherwise, it is resolved. 239 * 240 * @return an array of {@code Type}s that represent the formal 241 * parameter types of the underlying method, in declaration order 242 * @throws GenericSignatureFormatError 243 * if the generic method signature does not conform to the format 244 * specified in 245 * <cite>The Java™ Virtual Machine Specification</cite> 246 * @throws TypeNotPresentException if any of the parameter 247 * types of the underlying method refers to a non-existent type 248 * declaration 249 * @throws MalformedParameterizedTypeException if any of 250 * the underlying method's parameter types refer to a parameterized 251 * type that cannot be instantiated for any reason 252 */ 253 public Type[] getGenericParameterTypes() { 254 if (hasGenericInformation()) 255 return getGenericInfo().getParameterTypes(); 256 else 257 return getParameterTypes(); 258 } 259 260 /** 261 * Returns an array of {@code Class} objects that represent the 262 * types of exceptions declared to be thrown by the underlying 263 * executable represented by this object. Returns an array of 264 * length 0 if the executable declares no exceptions in its {@code 265 * throws} clause. 266 * 267 * @return the exception types declared as being thrown by the 268 * executable this object represents 269 */ 270 public abstract Class<?>[] getExceptionTypes(); 271 272 /** 273 * Returns an array of {@code Type} objects that represent the 274 * exceptions declared to be thrown by this executable object. 275 * Returns an array of length 0 if the underlying executable declares 276 * no exceptions in its {@code throws} clause. 277 * 278 * <p>If an exception type is a type variable or a parameterized 279 * type, it is created. Otherwise, it is resolved. 280 * 281 * @return an array of Types that represent the exception types 282 * thrown by the underlying method 283 * @throws GenericSignatureFormatError 284 * if the generic method signature does not conform to the format 285 * specified in 286 * <cite>The Java™ Virtual Machine Specification</cite> 287 * @throws TypeNotPresentException if the underlying method's 288 * {@code throws} clause refers to a non-existent type declaration 289 * @throws MalformedParameterizedTypeException if 290 * the underlying method's {@code throws} clause refers to a 291 * parameterized type that cannot be instantiated for any reason 292 */ 293 public Type[] getGenericExceptionTypes() { 294 Type[] result; 295 if (hasGenericInformation() && 296 ((result = getGenericInfo().getExceptionTypes()).length > 0)) 297 return result; 298 else 299 return getExceptionTypes(); 300 } 301 302 /** 303 * Returns a string describing this {@code Executable}, including 304 * any type parameters. 305 */ 306 public abstract String toGenericString(); 307 308 /** 309 * Returns {@code true} if this executable was declared to take a 310 * variable number of arguments; returns {@code false} otherwise. 311 * 312 * @return {@code true} if an only if this executable was declared 313 * to take a variable number of arguments. 314 */ 315 public boolean isVarArgs() { 316 return (getModifiers() & Modifier.VARARGS) != 0; 317 } 318 319 /** 320 * Returns {@code true} if this executable is a synthetic 321 * construct; returns {@code false} otherwise. 322 * 323 * @return true if and only if this executable is a synthetic 324 * construct as defined by 325 * <cite>The Java™ Language Specification</cite>. 326 */ 327 public boolean isSynthetic() { 328 return Modifier.isSynthetic(getModifiers()); 329 } 330 331 /** 332 * Returns an array of arrays that represent the annotations on 333 * the formal parameters, in declaration order, of the executable 334 * represented by this object. (Returns an array of length zero if 335 * the underlying method is parameterless. If the executable has 336 * one or more parameters, a nested array of length zero is 337 * returned for each parameter with no annotations.) The 338 * annotation objects contained in the returned arrays are 339 * serializable. The caller of this method is free to modify the 340 * returned arrays; it will have no effect on the arrays returned 341 * to other callers. 342 * 343 * @return an array of arrays that represent the annotations on the formal 344 * parameters, in declaration order, of the exectuable represented by this 345 * object 346 */ 347 public abstract Annotation[][] getParameterAnnotations(); 348 349 Annotation[][] sharedGetParameterAnnotations(Class<?>[] parameterTypes, 350 byte[] parameterAnnotations) { 351 int numParameters = parameterTypes.length; 352 if (parameterAnnotations == null) 353 return new Annotation[numParameters][0]; 354 355 Annotation[][] result = parseParameterAnnotations(parameterAnnotations); 356 357 if (result.length != numParameters) 358 handleParameterNumberMismatch(result.length, numParameters); 359 return result; 360 } 361 362 abstract void handleParameterNumberMismatch(int resultLength, int numParameters); 363 364 /** 365 * {@inheritDoc} 366 * @throws NullPointerException {@inheritDoc} 367 */ 368 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { 369 if (annotationClass == null) 370 throw new NullPointerException(); 371 372 return (T) declaredAnnotations().get(annotationClass); 373 } 374 375 /** 376 * {@inheritDoc} 377 */ 378 public Annotation[] getDeclaredAnnotations() { 379 return AnnotationParser.toArray(declaredAnnotations()); 380 } 381 382 private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; 383 384 private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() { 385 if (declaredAnnotations == null) { 386 declaredAnnotations = AnnotationParser.parseAnnotations( 387 getAnnotationBytes(), 388 sun.misc.SharedSecrets.getJavaLangAccess(). 389 getConstantPool(getDeclaringClass()), 390 getDeclaringClass()); 391 } 392 return declaredAnnotations; 393 } 394 }