From 91a2f52e5f795bc845b8f2bda70d5ff2f3bddcc5 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Tue, 2 Apr 2024 10:43:16 +0300 Subject: [PATCH] Ensure ParameterConverter is loaded from the TCCL This is needed because otherwise dev-mode could break in some cases Fixes: #39777 Follows up on: #39691 --- .../scanning/ClassInjectorTransformer.java | 24 +++++++++--------- .../converters/ParameterConverterSupport.java | 25 +++++++++++++++++++ 2 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/parameters/converters/ParameterConverterSupport.java diff --git a/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/scanning/ClassInjectorTransformer.java b/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/scanning/ClassInjectorTransformer.java index f1235df88f3ff..261445e972f44 100644 --- a/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/scanning/ClassInjectorTransformer.java +++ b/independent-projects/resteasy-reactive/server/processor/src/main/java/org/jboss/resteasy/reactive/server/processor/scanning/ClassInjectorTransformer.java @@ -36,6 +36,7 @@ import org.jboss.resteasy.reactive.server.core.parameters.converters.DelegatingParameterConverterSupplier; import org.jboss.resteasy.reactive.server.core.parameters.converters.ParameterConverter; import org.jboss.resteasy.reactive.server.core.parameters.converters.ParameterConverterSupplier; +import org.jboss.resteasy.reactive.server.core.parameters.converters.ParameterConverterSupport; import org.jboss.resteasy.reactive.server.core.parameters.converters.RuntimeResolvedConverter; import org.jboss.resteasy.reactive.server.injection.ResteasyReactiveInjectionContext; import org.jboss.resteasy.reactive.server.injection.ResteasyReactiveInjectionTarget; @@ -77,6 +78,9 @@ public class ClassInjectorTransformer implements BiFunction", - "()V", false); - // stack: [converter] - // If we don't cast this to ParameterConverter, ASM in computeFrames will call getCommonSuperType - // and try to load our generated class before we can load it, so we insert this cast to avoid that - initConverterMethod.visitTypeInsn(Opcodes.CHECKCAST, PARAMETER_CONVERTER_BINARY_NAME); + + // className param + initConverterMethod.visitLdcInsn(delegateBinaryName.replace('/', '.')); + initConverterMethod.visitMethodInsn(Opcodes.INVOKESTATIC, PARAMETER_CONVERTER_SUPPORT_BINARY_NAME, + "create", + "(" + STRING_DESCRIPTOR + ")" + PARAMETER_CONVERTER_DESCRIPTOR, + false); + // end default delegate initConverterMethod.visitLabel(notNull); } diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/parameters/converters/ParameterConverterSupport.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/parameters/converters/ParameterConverterSupport.java new file mode 100644 index 0000000000000..dcadcec91e4ea --- /dev/null +++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/parameters/converters/ParameterConverterSupport.java @@ -0,0 +1,25 @@ +package org.jboss.resteasy.reactive.server.core.parameters.converters; + +/** + * This class isn't used directly, it is however used by generated code meant to deal with {@link ParameterConverter}. + */ +@SuppressWarnings("unused") +public final class ParameterConverterSupport { + + private ParameterConverterSupport() { + } + + /** + * Normally the reflective instantiation would not be needed, and we could just instantiate normally, + * however that could break dev-mode when the converters are in a different module and non-standard Maven + * configuration is used (see this) + */ + public static ParameterConverter create(String className) { + try { + Class clazz = Class.forName(className, true, Thread.currentThread().getContextClassLoader()); + return (ParameterConverter) clazz.getConstructor().newInstance(); + } catch (Exception e) { + throw new RuntimeException("Unable to create instance of " + className, e); + } + } +}