static void emitFromNativeConversion( AsmBuilder builder, SkinnyMethodAdapter mv, FromNativeType fromNativeType, Class nativeClass) { // If there is a result converter, retrieve it and put on the stack FromNativeConverter fromNativeConverter = fromNativeType.getFromNativeConverter(); if (fromNativeConverter != null) { convertPrimitive( mv, nativeClass, unboxedType(fromNativeConverter.nativeType()), fromNativeType.getNativeType()); boxValue(builder, mv, fromNativeConverter.nativeType(), nativeClass); Method fromNativeMethod = getFromNativeMethod(fromNativeType, builder.getClassLoader()); getfield(mv, builder, builder.getFromNativeConverterField(fromNativeConverter)); mv.swap(); if (fromNativeType.getFromNativeContext() != null) { getfield( mv, builder, builder.getFromNativeContextField(fromNativeType.getFromNativeContext())); } else { mv.aconst_null(); } if (fromNativeMethod.getDeclaringClass().isInterface()) { mv.invokeinterface( fromNativeMethod.getDeclaringClass(), fromNativeMethod.getName(), fromNativeMethod.getReturnType(), fromNativeMethod.getParameterTypes()); } else { mv.invokevirtual( fromNativeMethod.getDeclaringClass(), fromNativeMethod.getName(), fromNativeMethod.getReturnType(), fromNativeMethod.getParameterTypes()); } if (fromNativeType.getDeclaredType().isPrimitive()) { // The actual return type is a primitive, but there was a converter for it - extract the // primitive value Class boxedType = getBoxedClass(fromNativeType.getDeclaredType()); if (!boxedType.isAssignableFrom(fromNativeMethod.getReturnType())) mv.checkcast(p(boxedType)); unboxNumber( mv, boxedType, fromNativeType.getDeclaredType(), fromNativeType.getNativeType()); } else if (!fromNativeType .getDeclaredType() .isAssignableFrom(fromNativeMethod.getReturnType())) { mv.checkcast(p(fromNativeType.getDeclaredType())); } } else if (!fromNativeType.getDeclaredType().isPrimitive()) { Class unboxedType = unboxedType(fromNativeType.getDeclaredType()); convertPrimitive(mv, nativeClass, unboxedType, fromNativeType.getNativeType()); boxValue(builder, mv, fromNativeType.getDeclaredType(), unboxedType); } }
static Method getFromNativeMethod(FromNativeType fromNativeType, AsmClassLoader classLoader) { FromNativeConverter fromNativeConverter = fromNativeType.getFromNativeConverter(); if (fromNativeConverter == null) { return null; } try { Class<? extends FromNativeConverter> fromNativeConverterClass = fromNativeConverter.getClass(); if (Modifier.isPublic(fromNativeConverterClass.getModifiers())) { for (Method method : fromNativeConverterClass.getMethods()) { if (!method.getName().equals("fromNative")) continue; Class[] methodParameterTypes = method.getParameterTypes(); Class javaType = fromNativeType.getDeclaredType().isPrimitive() ? boxedType(fromNativeType.getDeclaredType()) : fromNativeType.getDeclaredType(); if (javaType.isAssignableFrom(method.getReturnType()) && methodParameterTypes.length == 2 && methodParameterTypes[0].isAssignableFrom(fromNativeConverter.nativeType()) && methodParameterTypes[1] == FromNativeContext.class && methodIsAccessible(method) && classIsVisible(classLoader, method.getDeclaringClass())) { return method; } } } Method method = fromNativeConverterClass.getMethod("fromNative", Object.class, FromNativeContext.class); return methodIsAccessible(method) && classIsVisible(classLoader, method.getDeclaringClass()) ? method : FromNativeConverter.class.getDeclaredMethod( "fromNative", Object.class, FromNativeContext.class); } catch (NoSuchMethodException nsme) { try { return FromNativeConverter.class.getDeclaredMethod( "fromNative", Object.class, FromNativeContext.class); } catch (NoSuchMethodException nsme2) { throw new RuntimeException( "internal error. " + FromNativeConverter.class + " has no fromNative() method"); } } }