static void emitToNativeConversion( AsmBuilder builder, SkinnyMethodAdapter mv, ToNativeType toNativeType) { ToNativeConverter parameterConverter = toNativeType.getToNativeConverter(); if (parameterConverter != null) { Method toNativeMethod = getToNativeMethod(toNativeType, builder.getClassLoader()); if (toNativeType.getDeclaredType().isPrimitive()) { boxValue( builder, mv, getBoxedClass(toNativeType.getDeclaredType()), toNativeType.getDeclaredType()); } if (!toNativeMethod.getParameterTypes()[0].isAssignableFrom( getBoxedClass(toNativeType.getDeclaredType()))) { mv.checkcast(toNativeMethod.getParameterTypes()[0]); } mv.aload(0); AsmBuilder.ObjectField toNativeConverterField = builder.getToNativeConverterField(parameterConverter); mv.getfield( builder.getClassNamePath(), toNativeConverterField.name, ci(toNativeConverterField.klass)); if (!toNativeMethod.getDeclaringClass().equals(toNativeConverterField.klass)) { mv.checkcast(toNativeMethod.getDeclaringClass()); } // Re-order so the value to be converted is on the top of the stack mv.swap(); // load context parameter (if there is one) if (toNativeType.getToNativeContext() != null) { getfield(mv, builder, builder.getToNativeContextField(toNativeType.getToNativeContext())); } else { mv.aconst_null(); } if (toNativeMethod.getDeclaringClass().isInterface()) { mv.invokeinterface( toNativeMethod.getDeclaringClass(), toNativeMethod.getName(), toNativeMethod.getReturnType(), toNativeMethod.getParameterTypes()); } else { mv.invokevirtual( toNativeMethod.getDeclaringClass(), toNativeMethod.getName(), toNativeMethod.getReturnType(), toNativeMethod.getParameterTypes()); } if (!parameterConverter.nativeType().isAssignableFrom(toNativeMethod.getReturnType())) { mv.checkcast(p(parameterConverter.nativeType())); } } }
static Method getToNativeMethod(ToNativeType toNativeType, AsmClassLoader classLoader) { ToNativeConverter toNativeConverter = toNativeType.getToNativeConverter(); if (toNativeConverter == null) { return null; } try { Class<? extends ToNativeConverter> toNativeConverterClass = toNativeConverter.getClass(); if (Modifier.isPublic(toNativeConverterClass.getModifiers())) { for (Method method : toNativeConverterClass.getMethods()) { if (!method.getName().equals("toNative")) continue; Class[] methodParameterTypes = method.getParameterTypes(); if (toNativeConverter.nativeType().isAssignableFrom(method.getReturnType()) && methodParameterTypes.length == 2 && methodParameterTypes[0].isAssignableFrom(toNativeType.getDeclaredType()) && methodParameterTypes[1] == ToNativeContext.class && methodIsAccessible(method) && classIsVisible(classLoader, method.getDeclaringClass())) { return method; } } } Method method = toNativeConverterClass.getMethod("toNative", Object.class, ToNativeContext.class); return methodIsAccessible(method) && classIsVisible(classLoader, method.getDeclaringClass()) ? method : ToNativeConverter.class.getDeclaredMethod( "toNative", Object.class, ToNativeContext.class); } catch (NoSuchMethodException nsme) { try { return ToNativeConverter.class.getDeclaredMethod( "toNative", Object.class, ToNativeContext.class); } catch (NoSuchMethodException nsme2) { throw new RuntimeException( "internal error. " + ToNativeConverter.class + " has no toNative() method"); } } }