private void processDelegatedMethods( final ClassWriter cw )
{
for( Method method : this.typeInterfaceClass.getMethods() )
{
final DelegateImplementation delegateImplementationAnnotation = method.getAnnotation( DelegateImplementation.class );
if( ! this.implementedMethods.contains( method ) && delegateImplementationAnnotation != null )
{
this.implementedMethods.add( method );
final Class<?>[] exceptionClasses = method.getExceptionTypes();
final String[] exceptionTypeNames = new String[ exceptionClasses.length ];
for( int i = 0, n = exceptionClasses.length; i < n; i++ )
{
exceptionTypeNames[ i ] = Type.getInternalName( exceptionClasses[ i ] );
}
final MethodVisitor mv = cw.visitMethod
(
ACC_PUBLIC,
method.getName(),
Type.getMethodDescriptor( method ),
null,
exceptionTypeNames
);
mv.visitCode();
mv.visitVarInsn( ALOAD, 0 );
mv.visitMethodInsn
(
INVOKEVIRTUAL,
this.typeImplClassInternalName,
"assertNotDisposed",
"()V"
);
final Type[] methodParameterTypes = Type.getArgumentTypes( method );
final Type[] delegateParameterTypes = new Type[ methodParameterTypes.length + 1 ];
mv.visitVarInsn( ALOAD, 0 );
delegateParameterTypes[ 0 ] = Type.getType( method.getDeclaringClass() );
for( int i = 0, j = 1, n = methodParameterTypes.length; i < n; i++, j++ )
{
final Type methodParameterType = methodParameterTypes[ i ];
mv.visitVarInsn( methodParameterType.getOpcode( ILOAD ), j );
delegateParameterTypes[ j ] = methodParameterType;
}
mv.visitMethodInsn
(
INVOKESTATIC,
Type.getInternalName( delegateImplementationAnnotation.value() ),
method.getName(),
Type.getMethodDescriptor( Type.getReturnType( method ), delegateParameterTypes )
);
mv.visitInsn( Type.getReturnType( method ).getOpcode( IRETURN ) );