blob: b81e6d95cd1aac20dc44d50176708c43f54b43a8 [file] [log] [blame]
/*******************************************************************************
* 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();
}
}