| /******************************************************************************* |
| * Copyright (c) 2005 BEA Systems, Inc. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * tyeung@bea.com - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.jdt.apt.core.internal.env; |
| |
| import com.sun.mirror.type.MirroredTypeException; |
| import com.sun.mirror.type.MirroredTypesException; |
| import com.sun.mirror.type.TypeMirror; |
| import java.lang.reflect.InvocationHandler; |
| import java.lang.reflect.Method; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import org.eclipse.jdt.apt.core.internal.declaration.AnnotationMirrorImpl; |
| import org.eclipse.jdt.apt.core.internal.util.Factory; |
| import org.eclipse.jdt.core.dom.IMethodBinding; |
| import org.eclipse.jdt.core.dom.ITypeBinding; |
| |
| public class AnnotationInvocationHandler implements InvocationHandler |
| { |
| private final AnnotationMirrorImpl _instance; |
| |
| public AnnotationInvocationHandler(final AnnotationMirrorImpl annotation) |
| { |
| _instance = annotation; |
| } |
| |
| public Object invoke(Object proxy, Method method, Object[] args) throws Throwable |
| { |
| final String methodName = method.getName(); |
| if( args == null || args.length == 0 ) |
| { |
| if( methodName.equals("hashCode") ) |
| return new Integer( _instance.hashCode() ); |
| if( methodName.equals("toString") ) |
| return _instance.toString(); |
| } |
| else if( args.length == 1 && methodName.equals("equals") ) |
| { |
| return new Boolean( _instance.equals( args[0] ) ); |
| } |
| if( args != null && args.length != 0 ) |
| throw new NoSuchMethodException("method " + method.getName() + formatArgs(args) + " does not exists"); |
| final String c_methodName = method.getName(); |
| final IMethodBinding methodBinding = _instance.getMethodBinding(c_methodName); |
| if( methodBinding == null ) |
| throw new NoSuchMethodException("method " + method.getName() + "() does not exists"); |
| |
| final ITypeBinding retType = methodBinding.getReturnType(); |
| // type of annotation member is java.lang.Class |
| if( retType.isClass() && "java.lang.Class".equals(retType.getQualifiedName()) ){ |
| // need to figure out the class that's being accessed |
| final ITypeBinding[] classTypes = _instance.getMemberValueTypeBinding(c_methodName); |
| TypeMirror mirrorType = null; |
| if( classTypes != null && classTypes.length > 0 ){ |
| mirrorType = Factory.createTypeMirror(classTypes[0], _instance.getEnvironment() ); |
| } |
| if( mirrorType == null ) |
| mirrorType = Factory.createErrorClassType(classTypes[0]); |
| throw new MirroredTypeException(mirrorType); |
| } |
| else if( retType.isArray() ){ |
| final ITypeBinding leafType = retType.getElementType(); |
| // type of annotation member is java.lang.Class[] |
| if( leafType.isClass() && "java.lang.Class".equals(leafType.getQualifiedName()) ){ |
| final ITypeBinding[] classTypes = _instance.getMemberValueTypeBinding(c_methodName); |
| final Collection<TypeMirror> mirrorTypes; |
| if( classTypes == null || classTypes.length == 0 ) |
| mirrorTypes = Collections.emptyList(); |
| else{ |
| mirrorTypes = new ArrayList<TypeMirror>(classTypes.length); |
| for( ITypeBinding type : classTypes ){ |
| TypeMirror mirror = Factory.createTypeMirror(type, _instance.getEnvironment() ); |
| if( mirror == null ) |
| mirrorTypes.add( Factory.createTypeMirror(type, _instance.getEnvironment() ) ); |
| else |
| mirrorTypes.add(mirror); |
| } |
| } |
| |
| throw new MirroredTypesException(mirrorTypes); |
| } |
| } |
| return _instance.getReflectionValue(c_methodName, method); |
| } |
| |
| private String formatArgs(final Object[] args) |
| { |
| // estimate that each class name (plus the separators) is 10 characters long plus 2 for "()". |
| final StringBuilder builder = new StringBuilder(args.length * 8 + 2 ); |
| builder.append('('); |
| for( int i=0; i<args.length; i++ ) |
| { |
| if( i > 0 ) builder.append(", "); |
| builder.append(args[i].getClass().getName()); |
| } |
| |
| builder.append(')'); |
| |
| return builder.toString(); |
| } |
| } |