ConstPool cp = classfile.getConstPool();
int target_type_index = cp.addClassInfo( this.targetBean.getName() );
String desc = GET_SETTER_DESC;
MethodInfo mi = new MethodInfo( cp, GENERATED_SETTER_NAME, desc );
Bytecode code = new Bytecode( cp, 4, 6 );
/* | this | bean | args | i | raw bean | exception | */
if ( setters.length > 0 ) {
int start, end; // required to exception table
// iconst_0 // i
code.addIconst( 0 );
// istore_3 // store i
code.addIstore( 3 );
// aload_1 // load the bean
code.addAload( 1 );
// checkcast // cast the bean into a raw bean
code.addCheckcast( this.targetBean.getName() );
// astore 4 // store the raw bean
code.addAstore( 4 );
/* current stack len = 0 */
// start region to handling exception (BulkAccessorException)
start = code.currentPc();
int lastIndex = 0;
for ( int i = 0; i < setters.length; ++i ) {
if ( setters[i] != null ) {
int diff = i - lastIndex;
if ( diff > 0 ) {
// iinc 3, 1
code.addOpcode( Opcode.IINC );
code.add( 3 );
code.add( diff );
lastIndex = i;
}
}
/* current stack len = 0 */
// aload 4 // load the raw bean
code.addAload( 4 );
// aload_2 // load the args
code.addAload( 2 );
// iconst_i
code.addIconst( i );
// aaload
code.addOpcode( Opcode.AALOAD );
// checkcast
Class[] setterParamTypes = setters[i].getParameterTypes();
Class setterParamType = setterParamTypes[0];
if ( setterParamType.isPrimitive() ) {
// checkcast (case of primitive type)
// invokevirtual (case of primitive type)
this.addUnwrapper( classfile, code, setterParamType );
}
else {
// checkcast (case of reference type)
code.addCheckcast( setterParamType.getName() );
}
/* current stack len = 2 */
String rawSetterMethod_desc = RuntimeSupport.makeDescriptor( setters[i] );
if ( !this.targetBean.isInterface() ) {
// invokevirtual
code.addInvokevirtual( target_type_index, setters[i].getName(), rawSetterMethod_desc );
}
else {
// invokeinterface
Class[] params = setters[i].getParameterTypes();
int size;
if ( params[0].equals( Double.TYPE ) || params[0].equals( Long.TYPE ) ) {
size = 3;
}
else {
size = 2;
}
code.addInvokeinterface( target_type_index, setters[i].getName(), rawSetterMethod_desc, size );
}
}
// end region to handling exception (BulkAccessorException)
end = code.currentPc();
// return
code.addOpcode( Opcode.RETURN );
/* current stack len = 0 */
// register in exception table
int throwableType_index = cp.addClassInfo( THROWABLE_CLASS_NAME );
code.addExceptionHandler( start, end, code.currentPc(), throwableType_index );
// astore 5 // store exception
code.addAstore( 5 );
// new // BulkAccessorException
code.addNew( BULKEXCEPTION_CLASS_NAME );
// dup
code.addOpcode( Opcode.DUP );
// aload 5 // load exception
code.addAload( 5 );
// iload_3 // i
code.addIload( 3 );
// invokespecial // BulkAccessorException.<init>
String cons_desc = "(Ljava/lang/Throwable;I)V";
code.addInvokespecial( BULKEXCEPTION_CLASS_NAME, MethodInfo.nameInit, cons_desc );
// athrow
code.addOpcode( Opcode.ATHROW );
}
else {
// return
code.addOpcode( Opcode.RETURN );
}
mi.setCodeAttribute( code.toCodeAttribute() );
mi.setAccessFlags( AccessFlag.PUBLIC );
classfile.addMethod( mi );
}