1 11 12 package org.eclipse.jdt.apt.core.internal.env; 13 14 import com.sun.mirror.type.MirroredTypeException; 15 import com.sun.mirror.type.MirroredTypesException; 16 import com.sun.mirror.type.TypeMirror; 17 18 import java.lang.reflect.Array ; 19 import java.lang.reflect.Field ; 20 import java.lang.reflect.InvocationHandler ; 21 import java.lang.reflect.Method ; 22 import java.lang.reflect.Proxy ; 23 import java.util.ArrayList ; 24 import java.util.Collection ; 25 import java.util.Collections ; 26 import org.eclipse.jdt.apt.core.internal.declaration.AnnotationMirrorImpl; 27 import org.eclipse.jdt.apt.core.internal.util.Factory; 28 import org.eclipse.jdt.core.dom.IMethodBinding; 29 import org.eclipse.jdt.core.dom.IAnnotationBinding; 30 import org.eclipse.jdt.core.dom.ITypeBinding; 31 import org.eclipse.jdt.core.dom.IVariableBinding; 32 33 public class AnnotationInvocationHandler implements InvocationHandler 34 { 35 private static final String JAVA_LANG_CLASS = "java.lang.Class"; private final AnnotationMirrorImpl _instance; 37 private final Class <?> _clazz; 38 39 public AnnotationInvocationHandler(final AnnotationMirrorImpl annotation, 40 final Class <?> clazz) 41 { 42 _instance = annotation; 43 _clazz = clazz; 44 } 45 46 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable 47 { 48 final String methodName = method.getName(); 49 if( args == null || args.length == 0 ) 50 { 51 if( methodName.equals("hashCode") ) return new Integer ( _instance.hashCode() ); 53 if( methodName.equals("toString") ) return _instance.toString(); 55 if( methodName.equals("annotationType")) return _clazz; 57 } 58 else if( args.length == 1 && methodName.equals("equals") ) { 60 return new Boolean ( _instance.equals( args[0] ) ); 61 } 62 if( args != null && args.length != 0 ) 63 throw new NoSuchMethodException ("method " + method.getName() + formatArgs(args) + " does not exists"); final String c_methodName = method.getName(); 65 final IMethodBinding methodBinding = _instance.getMethodBinding(c_methodName); 66 if( methodBinding == null ) 67 throw new NoSuchMethodException ("method " + method.getName() + "() does not exists"); 69 final ITypeBinding retType = methodBinding.getReturnType(); 70 if( retType == null ) return null; 71 72 final String qName = retType.getTypeDeclaration().getQualifiedName(); 73 if( retType.isClass() && JAVA_LANG_CLASS.equals(qName) ){ 75 final ITypeBinding[] classTypes = _instance.getMemberValueTypeBinding(c_methodName); 77 TypeMirror mirrorType = null; 78 if( classTypes != null && classTypes.length > 0 ){ 79 mirrorType = Factory.createTypeMirror(classTypes[0], _instance.getEnvironment() ); 80 } 81 if( mirrorType == null ) 82 mirrorType = Factory.createErrorClassType(classTypes[0]); 83 throw new MirroredTypeException(mirrorType); 84 } 85 else if( retType.isArray() ){ 86 final ITypeBinding leafType = retType.getElementType(); 87 final String leafQName = leafType.getTypeDeclaration().getQualifiedName(); 88 if( leafType.isClass() && JAVA_LANG_CLASS.equals(leafQName) ){ 90 final ITypeBinding[] classTypes = _instance.getMemberValueTypeBinding(c_methodName); 91 final Collection <TypeMirror> mirrorTypes; 92 if( classTypes == null || classTypes.length == 0 ) 93 mirrorTypes = Collections.emptyList(); 94 else{ 95 mirrorTypes = new ArrayList <TypeMirror>(classTypes.length); 96 for( ITypeBinding type : classTypes ){ 97 TypeMirror mirror = Factory.createTypeMirror(type, _instance.getEnvironment() ); 98 if( mirror == null ) 99 mirrorTypes.add(Factory.createErrorClassType(type)); 100 else 101 mirrorTypes.add(mirror); 102 } 103 } 104 105 throw new MirroredTypesException(mirrorTypes); 106 } 107 } 108 final Object sourceValue = _instance.getValue(c_methodName); 109 return getReflectionValueWithTypeConversion(sourceValue, method.getReturnType()); 110 } 111 112 private Object getReflectionValueWithTypeConversion( 113 final Object domValue, 114 final Class <?> expectedType ) 115 { 116 117 final Object actualValue = _getReflectionValue(domValue, expectedType); 118 return performNecessaryTypeConversion(expectedType, actualValue); 119 } 120 121 private Object _getReflectionValue(final Object domValue, final Class <?> expectedType) 122 { 123 if( expectedType == null || domValue == null ) 124 return null; 125 126 if( domValue instanceof IVariableBinding ) 127 { 128 final IVariableBinding varBinding = (IVariableBinding)domValue; 129 final ITypeBinding declaringClass = varBinding.getDeclaringClass(); 130 if( declaringClass != null ){ 131 try { 132 final Field returnedField = expectedType.getField( varBinding.getName() ); 133 return returnedField == null ? null : returnedField.get(null); 134 } 135 catch (NoSuchFieldException nsfe) { 136 return null; 137 } 138 catch (IllegalAccessException iae) { 139 return null; 140 } 141 } 142 return null; 143 } 144 else if (domValue instanceof Object []) 145 { 146 final Object [] elements = (Object [])domValue; 147 if(!expectedType.isArray()) 148 return null; final Class <?> componentType = expectedType.getComponentType(); 150 final int length = elements.length; 151 final Object array = Array.newInstance(componentType, length); 152 153 for( int i=0; i<length; i++ ){ 154 final Object returnObj = 155 getReflectionValueWithTypeConversion( elements[i], componentType ); 156 if( componentType.isPrimitive() ){ 159 if( componentType == boolean.class ){ 160 final Boolean bool = (Boolean )returnObj; 161 Array.setBoolean( array, i, bool.booleanValue()); 162 } 163 else if( componentType == byte.class ){ 164 final Byte b = (Byte )returnObj; 165 Array.setByte( array, i, b.byteValue() ); 166 } 167 else if( componentType == char.class ){ 168 final Character c = (Character )returnObj; 169 Array.setChar( array, i, c.charValue() ); 170 } 171 else if( componentType == double.class ){ 172 final Double d = (Double )returnObj; 173 Array.setDouble( array, i, d.doubleValue() ); 174 } 175 else if( componentType == float.class ){ 176 final Float f = (Float )returnObj; 177 Array.setFloat( array, i, f.floatValue() ); 178 } 179 else if( componentType == int.class ){ 180 final Integer integer = (Integer )returnObj; 181 Array.setInt( array, i, integer.intValue() ); 182 } 183 else if( componentType == long.class ){ 184 final Long l = (Long )returnObj; 185 Array.setLong( array, i, l.longValue() ); 186 } 187 else if( componentType == short.class ){ 188 final Short s = (Short )returnObj; 189 Array.setShort( array, i, s.shortValue() ); 190 } 191 else { 192 throw new IllegalStateException ("unrecognized primitive type: " + componentType ); } 194 } 195 else{ 196 Array.set( array, i, returnObj ); 197 } 198 } 199 return array; 200 } 201 else if( domValue instanceof ITypeBinding ) 203 throw new IllegalStateException ("sourceValue is a type binding."); 205 else if( domValue instanceof IAnnotationBinding ) 206 { 207 if (!expectedType.isAnnotation()) { 209 return null; 210 } 211 212 final AnnotationMirrorImpl annoMirror = 213 (AnnotationMirrorImpl)Factory.createAnnotationMirror( 214 (IAnnotationBinding)domValue, 215 _instance.getAnnotatedDeclaration(), 216 _instance.getEnvironment()); 217 final AnnotationInvocationHandler handler = new AnnotationInvocationHandler(annoMirror, expectedType); 218 return Proxy.newProxyInstance(expectedType.getClassLoader(), 219 new Class []{ expectedType }, handler ); 220 } 221 else 223 return domValue; 224 } 225 226 private Object performNecessaryTypeConversion(Class <?> expectedType, Object actualValue){ 227 if( actualValue == null ) 228 return Factory.getMatchingDummyValue(expectedType); 229 else if( expectedType.isPrimitive() ) 230 return Factory.performNecessaryPrimitiveTypeConversion( expectedType, actualValue, true); 231 else if( expectedType.isAssignableFrom(actualValue.getClass())) 232 return actualValue; 233 else if( expectedType.isArray() ){ 234 actualValue = performNecessaryTypeConversion(expectedType.getComponentType(), actualValue); 238 return arrayify(expectedType, actualValue); 239 } 240 else return null; 243 } 244 245 private Object arrayify(final Class <?> expectedType, Object actualValue){ 246 assert expectedType.isArray() : "expected type must be an array"; assert ( !(actualValue instanceof Object []) ) : 248 "actual value cannot be of type Object[]"; final Class <?> componentType = expectedType.getComponentType(); 250 final Object array = Array.newInstance(componentType, 1); 251 252 if( componentType.isPrimitive() ){ 253 if( componentType == boolean.class ){ 254 final Boolean bool = (Boolean )actualValue; 255 Array.setBoolean( array, 0, bool.booleanValue()); 256 } 257 else if( componentType == byte.class ){ 258 final Byte b = (Byte )actualValue; 259 Array.setByte( array, 0, b.byteValue() ); 260 } 261 else if( componentType == char.class ){ 262 final Character c = (Character )actualValue; 263 Array.setChar( array, 0, c.charValue() ); 264 } 265 else if( componentType == double.class ){ 266 final Double d = (Double )actualValue; 267 Array.setDouble( array, 0, d.doubleValue() ); 268 } 269 else if( componentType == float.class ){ 270 final Float f = (Float )actualValue; 271 Array.setFloat( array, 0, f.floatValue() ); 272 } 273 else if( componentType == int.class ){ 274 final Integer integer = (Integer )actualValue; 275 Array.setInt( array, 0, integer.intValue() ); 276 } 277 else if( componentType == long.class ){ 278 final Long l = (Long )actualValue; 279 Array.setLong( array, 0, l.longValue() ); 280 } 281 else if( componentType == short.class ){ 282 final Short s = (Short )actualValue; 283 Array.setShort( array, 0, s.shortValue() ); 284 } 285 else { 286 throw new IllegalStateException ("unrecognized primitive type: " + componentType ); } 288 } 289 else{ 290 Array.set( array, 0, actualValue ); 291 } 292 return array; 293 } 294 295 private String formatArgs(final Object [] args) 296 { 297 final StringBuilder builder = new StringBuilder (args.length * 8 + 2 ); 299 builder.append('('); 300 for( int i=0; i<args.length; i++ ) 301 { 302 if( i > 0 ) builder.append(", "); builder.append(args[i].getClass().getName()); 304 } 305 306 builder.append(')'); 307 308 return builder.toString(); 309 } 310 } 311 | Popular Tags |