1 11 package org.eclipse.jdt.internal.compiler.apt.model; 12 13 import java.lang.reflect.Array ; 14 import java.lang.reflect.Field ; 15 import java.lang.reflect.InvocationHandler ; 16 import java.lang.reflect.Method ; 17 import java.lang.reflect.Proxy ; 18 import java.util.ArrayList ; 19 import java.util.Collections ; 20 import java.util.HashMap ; 21 import java.util.List ; 22 import java.util.Map ; 23 24 import javax.lang.model.element.AnnotationMirror; 25 import javax.lang.model.element.AnnotationValue; 26 import javax.lang.model.element.ExecutableElement; 27 import javax.lang.model.type.DeclaredType; 28 import javax.lang.model.type.MirroredTypeException; 29 import javax.lang.model.type.MirroredTypesException; 30 import javax.lang.model.type.TypeMirror; 31 32 import org.eclipse.jdt.internal.compiler.apt.dispatch.BaseProcessingEnvImpl; 33 import org.eclipse.jdt.internal.compiler.impl.Constant; 34 import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding; 35 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; 36 import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair; 37 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; 38 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; 39 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; 40 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; 41 import org.eclipse.jdt.internal.compiler.lookup.TypeIds; 42 43 public class AnnotationMirrorImpl implements AnnotationMirror, InvocationHandler { 44 45 public final BaseProcessingEnvImpl _env; 46 public final AnnotationBinding _binding; 47 48 AnnotationMirrorImpl(BaseProcessingEnvImpl env, AnnotationBinding binding) { 49 _env = env; 50 _binding = binding; 51 } 52 53 @Override 54 public boolean equals(Object obj) { 55 if (obj instanceof AnnotationMirrorImpl) { 56 if (this._binding == null) { 57 return ((AnnotationMirrorImpl) obj)._binding == null; 58 } 59 return equals(this._binding, ((AnnotationMirrorImpl) obj)._binding); 60 } 61 return false; 62 } 63 64 private static boolean equals(AnnotationBinding annotationBinding, AnnotationBinding annotationBinding2) { 65 if (annotationBinding.getAnnotationType() != annotationBinding2.getAnnotationType()) return false; 66 final ElementValuePair[] elementValuePairs = annotationBinding.getElementValuePairs(); 67 final ElementValuePair[] elementValuePairs2 = annotationBinding2.getElementValuePairs(); 68 final int length = elementValuePairs.length; 69 if (length != elementValuePairs2.length) return false; 70 loop: for (int i = 0; i < length; i++) { 71 ElementValuePair pair = elementValuePairs[i]; 72 for (int j = 0; j < length; j++) { 74 ElementValuePair pair2 = elementValuePairs2[j]; 75 if (pair.binding == pair2.binding) { 76 if (pair.value == null) { 77 if (pair2.value == null) { 78 continue loop; 79 } 80 return false; 81 } else { 82 if (pair2.value == null 83 || !pair2.value.equals(pair.value)) { 84 return false; 85 } 86 } 87 continue loop; 88 } 89 } 90 return false; 91 } 92 return true; 93 } 94 95 public DeclaredType getAnnotationType() { 96 if (this._binding == null) { 97 return _env.getFactory().getErrorType(); 98 } 99 ReferenceBinding annoType = _binding.getAnnotationType(); 100 return _env.getFactory().newDeclaredType(annoType); 101 } 102 103 107 public Map <? extends ExecutableElement, ? extends AnnotationValue> getElementValues() { 108 if (this._binding == null) { 109 return Collections.emptyMap(); 110 } 111 ElementValuePair[] pairs = _binding.getElementValuePairs(); 112 Map <ExecutableElement, AnnotationValue> valueMap = 113 new HashMap <ExecutableElement, AnnotationValue>(pairs.length); 114 for (ElementValuePair pair : pairs) { 115 MethodBinding method = pair.getMethodBinding(); 116 if (method == null) { 117 continue; 119 } 120 ExecutableElement e = new ExecutableElementImpl(_env, method); 121 AnnotationValue v = new AnnotationValueImpl(_env, pair.getValue(), method.returnType); 122 valueMap.put(e, v); 123 } 124 return Collections.unmodifiableMap(valueMap); 125 } 126 127 132 public Map <? extends ExecutableElement, ? extends AnnotationValue> getElementValuesWithDefaults() { 133 if (this._binding == null) { 134 return Collections.emptyMap(); 135 } 136 ElementValuePair[] pairs = _binding.getElementValuePairs(); 137 ReferenceBinding annoType = _binding.getAnnotationType(); 138 Map <ExecutableElement, AnnotationValue> valueMap = 139 new HashMap <ExecutableElement, AnnotationValue>(); 140 for (MethodBinding method : annoType.methods()) { 141 boolean foundExplicitValue = false; 143 for (int i = 0; i < pairs.length; ++i) { 144 MethodBinding explicitBinding = pairs[i].getMethodBinding(); 145 if (method == explicitBinding) { 146 ExecutableElement e = new ExecutableElementImpl(_env, explicitBinding); 147 AnnotationValue v = new AnnotationValueImpl(_env, pairs[i].getValue(), explicitBinding.returnType); 148 valueMap.put(e, v); 149 foundExplicitValue = true; 150 break; 151 } 152 } 153 if (!foundExplicitValue) { 155 Object defaultVal = method.getDefaultValue(); 156 if (null != defaultVal) { 157 ExecutableElement e = new ExecutableElementImpl(_env, method); 158 AnnotationValue v = new AnnotationValueImpl(_env, defaultVal, method.returnType); 159 valueMap.put(e, v); 160 } 161 } 162 } 163 return Collections.unmodifiableMap(valueMap); 164 } 165 166 public int hashCode() { 167 if (this._binding == null) return this._env.hashCode(); 168 return this._binding.hashCode(); 169 } 170 171 183 @Override 184 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable 185 { 186 if (this._binding == null) return null; 187 final String methodName = method.getName(); 188 if ( args == null || args.length == 0 ) { 189 if( methodName.equals("hashCode") ) { return new Integer ( hashCode() ); 191 } 192 else if( methodName.equals("toString") ) { return toString(); 194 } 195 else if( methodName.equals("annotationType")) { return proxy.getClass().getInterfaces()[0]; 197 } 198 } 199 else if ( args.length == 1 && methodName.equals("equals") ) { return new Boolean ( equals( args[0] ) ); 201 } 202 203 if ( args != null && args.length != 0 ) { 205 throw new NoSuchMethodException ("method " + method.getName() + formatArgs(args) + " does not exist on annotation " + toString()); } 207 final MethodBinding methodBinding = getMethodBinding(methodName); 208 if ( methodBinding == null ) { 209 throw new NoSuchMethodException ("method " + method.getName() + "() does not exist on annotation" + toString()); } 211 212 Object actualValue = null; 213 boolean foundMethod = false; 214 ElementValuePair[] pairs = _binding.getElementValuePairs(); 215 for (ElementValuePair pair : pairs) { 216 if (methodName.equals(new String (pair.getName()))) { 217 actualValue = pair.getValue(); 218 foundMethod = true; 219 break; 220 } 221 } 222 if (!foundMethod) { 223 actualValue = methodBinding.getDefaultValue(); 225 } 226 Class <?> expectedType = method.getReturnType(); 227 TypeBinding actualType = methodBinding.returnType; 228 return getReflectionValue(actualValue, actualType, expectedType); 229 } 230 231 236 @Override 237 public String toString() { 238 if (this._binding == null) { 239 return "@any()"; } 241 return "@" + _binding.getAnnotationType().debugName(); } 243 244 248 private String formatArgs(final Object [] args) 249 { 250 final StringBuilder builder = new StringBuilder (args.length * 8 + 2 ); 252 builder.append('('); 253 for( int i=0; i<args.length; i++ ) 254 { 255 if( i > 0 ) 256 builder.append(", "); builder.append(args[i].getClass().getName()); 258 } 259 builder.append(')'); 260 return builder.toString(); 261 } 262 263 267 private MethodBinding getMethodBinding(String name) { 268 ReferenceBinding annoType = _binding.getAnnotationType(); 269 MethodBinding[] methods = annoType.getMethods(name.toCharArray()); 270 for (MethodBinding method : methods) { 271 if (method.parameters.length == 0) { 273 return method; 274 } 275 } 276 return null; 277 } 278 279 293 private Object getReflectionValue(Object actualValue, TypeBinding actualType, Class <?> expectedType) 294 { 295 if (null == expectedType) { 296 return null; 298 } 299 if (null == actualValue) { 300 return Factory.getMatchingDummyValue(expectedType); 302 } 303 if (expectedType.isArray()) { 304 if (Class .class.equals(expectedType.getComponentType())) { 305 if (actualType.isArrayType() && actualValue instanceof Object [] && 307 ((ArrayBinding)actualType).leafComponentType.erasure().id == TypeIds.T_JavaLangClass) { 308 Object [] bindings = (Object [])actualValue; 309 List <TypeMirror> mirrors = new ArrayList <TypeMirror>(bindings.length); 310 for (int i = 0; i < bindings.length; ++i) { 311 if (bindings[i] instanceof TypeBinding) { 312 mirrors.add(_env.getFactory().newTypeMirror((TypeBinding)bindings[i])); 313 } 314 } 315 throw new MirroredTypesException(mirrors); 316 } 317 return null; 319 } 320 return convertJDTArrayToReflectionArray(actualValue, actualType, expectedType); 322 } 323 else if (Class .class.equals(expectedType)) { 324 if (actualValue instanceof TypeBinding) { 326 TypeMirror mirror = _env.getFactory().newTypeMirror((TypeBinding)actualValue); 327 throw new MirroredTypeException(mirror); 328 } 329 else { 330 return null; 332 } 333 } 334 else { 335 return convertJDTValueToReflectionType(actualValue, actualType, expectedType); 337 } 338 } 339 340 352 private Object convertJDTArrayToReflectionArray(Object jdtValue, TypeBinding jdtType, Class <?> expectedType) 353 { 354 assert null != expectedType && expectedType.isArray(); 355 if (!jdtType.isArrayType() || !(jdtValue instanceof Object [])) { 356 return null; 358 } 359 TypeBinding jdtLeafType = jdtType.leafComponentType(); 360 Object [] jdtArray = (Object [])jdtValue; 361 Class <?> expectedLeafType = expectedType.getComponentType(); 362 final int length = jdtArray.length; 363 final Object returnArray = Array.newInstance(expectedLeafType, length); 364 for (int i = 0; i < length; ++i) { 365 Object jdtElementValue = jdtArray[i]; 366 if (expectedLeafType.isPrimitive() || String .class.equals(expectedLeafType)) { 367 if (jdtElementValue instanceof Constant) { 368 if (boolean.class.equals(expectedLeafType)) { 369 Array.setBoolean(returnArray, i, ((Constant)jdtElementValue).booleanValue()); 370 } 371 else if (byte.class.equals(expectedLeafType)) { 372 Array.setByte(returnArray, i, ((Constant)jdtElementValue).byteValue()); 373 } 374 else if (char.class.equals(expectedLeafType)) { 375 Array.setChar(returnArray, i, ((Constant)jdtElementValue).charValue()); 376 } 377 else if (double.class.equals(expectedLeafType)) { 378 Array.setDouble(returnArray, i, ((Constant)jdtElementValue).doubleValue()); 379 } 380 else if (float.class.equals(expectedLeafType)) { 381 Array.setFloat(returnArray, i, ((Constant)jdtElementValue).floatValue()); 382 } 383 else if (int.class.equals(expectedLeafType)) { 384 Array.setInt(returnArray, i, ((Constant)jdtElementValue).intValue()); 385 } 386 else if (long.class.equals(expectedLeafType)) { 387 Array.setLong(returnArray, i, ((Constant)jdtElementValue).longValue()); 388 } 389 else if (short.class.equals(expectedLeafType)) { 390 Array.setShort(returnArray, i, ((Constant)jdtElementValue).shortValue()); 391 } 392 else if (String .class.equals(expectedLeafType)) { 393 Array.set(returnArray, i, ((Constant)jdtElementValue).stringValue()); 394 } 395 } 396 else { 397 Factory.setArrayMatchingDummyValue(returnArray, i, expectedLeafType); 400 } 401 } 402 else if (expectedLeafType.isEnum()) { 403 Object returnVal = null; 404 if (jdtLeafType != null && jdtLeafType.isEnum() && jdtElementValue instanceof FieldBinding) { 405 FieldBinding binding = (FieldBinding)jdtElementValue; 406 try { 407 Field returnedField = null; 408 returnedField = expectedLeafType.getField( new String (binding.name) ); 409 if (null != returnedField) { 410 returnVal = returnedField.get(null); 411 } 412 } 413 catch (NoSuchFieldException nsfe) { 414 } 416 catch (IllegalAccessException iae) { 417 } 419 } 420 Array.set(returnArray, i, returnVal); 421 } 422 else if (expectedLeafType.isAnnotation()) { 423 Object returnVal = null; 425 if (jdtLeafType.isAnnotationType() && jdtElementValue instanceof AnnotationBinding) { 426 AnnotationMirrorImpl annoMirror = 427 (AnnotationMirrorImpl)_env.getFactory().newAnnotationMirror((AnnotationBinding)jdtElementValue); 428 returnVal = Proxy.newProxyInstance(expectedLeafType.getClassLoader(), 429 new Class []{ expectedLeafType }, annoMirror ); 430 } 431 Array.set(returnArray, i, returnVal); 432 } 433 else { 434 Array.set(returnArray, i, null); 435 } 436 } 437 return returnArray; 438 } 439 440 447 private Object convertJDTValueToReflectionType(Object jdtValue, TypeBinding actualType, Class <?> expectedType) { 448 if (expectedType.isPrimitive() || String .class.equals(expectedType)) { 449 if (jdtValue instanceof Constant) { 450 if (boolean.class.equals(expectedType)) { 451 return ((Constant)jdtValue).booleanValue(); 452 } 453 else if (byte.class.equals(expectedType)) { 454 return ((Constant)jdtValue).byteValue(); 455 } 456 else if (char.class.equals(expectedType)) { 457 return ((Constant)jdtValue).charValue(); 458 } 459 else if (double.class.equals(expectedType)) { 460 return ((Constant)jdtValue).doubleValue(); 461 } 462 else if (float.class.equals(expectedType)) { 463 return ((Constant)jdtValue).floatValue(); 464 } 465 else if (int.class.equals(expectedType)) { 466 return ((Constant)jdtValue).intValue(); 467 } 468 else if (long.class.equals(expectedType)) { 469 return ((Constant)jdtValue).longValue(); 470 } 471 else if (short.class.equals(expectedType)) { 472 return ((Constant)jdtValue).shortValue(); 473 } 474 else if (String .class.equals(expectedType)) { 475 return ((Constant)jdtValue).stringValue(); 476 } 477 } 478 return Factory.getMatchingDummyValue(expectedType); 481 } 482 else if (expectedType.isEnum()) { 483 Object returnVal = null; 484 if (actualType != null && actualType.isEnum() && jdtValue instanceof FieldBinding) { 485 486 FieldBinding binding = (FieldBinding)jdtValue; 487 try { 488 Field returnedField = null; 489 returnedField = expectedType.getField( new String (binding.name) ); 490 if (null != returnedField) { 491 returnVal = returnedField.get(null); 492 } 493 } 494 catch (NoSuchFieldException nsfe) { 495 } 497 catch (IllegalAccessException iae) { 498 } 500 } 501 return null == returnVal ? Factory.getMatchingDummyValue(expectedType) : returnVal; 502 } 503 else if (expectedType.isAnnotation()) { 504 if (actualType.isAnnotationType() && jdtValue instanceof AnnotationBinding) { 506 AnnotationMirrorImpl annoMirror = 507 (AnnotationMirrorImpl)_env.getFactory().newAnnotationMirror((AnnotationBinding)jdtValue); 508 return Proxy.newProxyInstance(expectedType.getClassLoader(), 509 new Class []{ expectedType }, annoMirror ); 510 } 511 else { 512 return null; 514 } 515 } 516 else { 517 return Factory.getMatchingDummyValue(expectedType); 518 } 519 } 520 521 } 522 | Popular Tags |