Merge branch '6.1.x'

# Conflicts:
#	spring-context/src/main/java/org/springframework/instrument/classloading/jboss/JBossLoadTimeWeaver.java
This commit is contained in:
Juergen Hoeller 2024-10-21 18:14:50 +02:00
commit 267d3a36ae
4 changed files with 32 additions and 19 deletions

View File

@ -17,6 +17,7 @@
package org.springframework.instrument.classloading.jboss; package org.springframework.instrument.classloading.jboss;
import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -26,12 +27,14 @@ import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
import org.springframework.util.function.ThrowingFunction;
/** /**
* {@link LoadTimeWeaver} implementation for JBoss's instrumentable ClassLoader. * {@link LoadTimeWeaver} implementation for JBoss's instrumentable ClassLoader.
* Thanks to Ales Justin and Marius Bogoevici for the initial prototype. * Thanks to Ales Justin and Marius Bogoevici for the initial prototype.
* *
* <p>This weaver supports WildFly 13+. * <p>This weaver supports WildFly 13-23 (DelegatingClassFileTransformer) as well as
* WildFly 24+ (DelegatingClassTransformer), as of Spring Framework 6.1.15.
* *
* @author Costin Leau * @author Costin Leau
* @author Juergen Hoeller * @author Juergen Hoeller
@ -39,9 +42,15 @@ import org.springframework.util.ReflectionUtils;
*/ */
public class JBossLoadTimeWeaver implements LoadTimeWeaver { public class JBossLoadTimeWeaver implements LoadTimeWeaver {
private static final String DELEGATING_TRANSFORMER_CLASS_NAME = private static final String LEGACY_DELEGATING_TRANSFORMER_CLASS_NAME =
"org.jboss.as.server.deployment.module.DelegatingClassFileTransformer"; "org.jboss.as.server.deployment.module.DelegatingClassFileTransformer";
private static final String DELEGATING_TRANSFORMER_CLASS_NAME =
"org.jboss.as.server.deployment.module.DelegatingClassTransformer";
private static final String CLASS_TRANSFORMER_CLASS_NAME =
"org.jboss.modules.ClassTransformer";
private static final String WRAPPER_TRANSFORMER_CLASS_NAME = private static final String WRAPPER_TRANSFORMER_CLASS_NAME =
"org.jboss.modules.JLIClassTransformer"; "org.jboss.modules.JLIClassTransformer";
@ -52,6 +61,8 @@ public class JBossLoadTimeWeaver implements LoadTimeWeaver {
private final Method addTransformer; private final Method addTransformer;
private final ThrowingFunction<Object, Object> adaptTransformer;
/** /**
* Create a new instance of the {@link JBossLoadTimeWeaver} class using * Create a new instance of the {@link JBossLoadTimeWeaver} class using
@ -90,18 +101,29 @@ public class JBossLoadTimeWeaver implements LoadTimeWeaver {
wrappedTransformer.setAccessible(true); wrappedTransformer.setAccessible(true);
suggestedTransformer = wrappedTransformer.get(suggestedTransformer); suggestedTransformer = wrappedTransformer.get(suggestedTransformer);
} }
if (!suggestedTransformer.getClass().getName().equals(DELEGATING_TRANSFORMER_CLASS_NAME)) {
Class<?> transformerType = ClassFileTransformer.class;
if (suggestedTransformer.getClass().getName().equals(LEGACY_DELEGATING_TRANSFORMER_CLASS_NAME)) {
this.adaptTransformer = (t -> t);
}
else if (suggestedTransformer.getClass().getName().equals(DELEGATING_TRANSFORMER_CLASS_NAME)) {
transformerType = classLoader.loadClass(CLASS_TRANSFORMER_CLASS_NAME);
Constructor<?> adaptedTransformer = classLoader.loadClass(WRAPPER_TRANSFORMER_CLASS_NAME)
.getConstructor(ClassFileTransformer.class);
this.adaptTransformer = adaptedTransformer::newInstance;
}
else {
throw new IllegalStateException( throw new IllegalStateException(
"Transformer not of the expected type DelegatingClassFileTransformer: " + "Transformer not of expected type DelegatingClass(File)Transformer: " +
suggestedTransformer.getClass().getName()); suggestedTransformer.getClass().getName());
} }
this.delegatingTransformer = suggestedTransformer; this.delegatingTransformer = suggestedTransformer;
Method addTransformer = ReflectionUtils.findMethod(this.delegatingTransformer.getClass(), Method addTransformer = ReflectionUtils.findMethod(this.delegatingTransformer.getClass(),
"addTransformer", ClassFileTransformer.class); "addTransformer", transformerType);
if (addTransformer == null) { if (addTransformer == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Could not find 'addTransformer' method on JBoss DelegatingClassFileTransformer: " + "Could not find 'addTransformer' method on JBoss DelegatingClass(File)Transformer: " +
this.delegatingTransformer.getClass().getName()); this.delegatingTransformer.getClass().getName());
} }
addTransformer.setAccessible(true); addTransformer.setAccessible(true);
@ -116,7 +138,7 @@ public class JBossLoadTimeWeaver implements LoadTimeWeaver {
@Override @Override
public void addTransformer(ClassFileTransformer transformer) { public void addTransformer(ClassFileTransformer transformer) {
try { try {
this.addTransformer.invoke(this.delegatingTransformer, transformer); this.addTransformer.invoke(this.delegatingTransformer, this.adaptTransformer.apply(transformer));
} }
catch (Throwable ex) { catch (Throwable ex) {
throw new IllegalStateException("Could not add transformer on JBoss ClassLoader: " + this.classLoader, ex); throw new IllegalStateException("Could not add transformer on JBoss ClassLoader: " + this.classLoader, ex);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -85,17 +85,14 @@ public interface ThrowingBiFunction<T, U, R> extends BiFunction<T, U, R> {
*/ */
default ThrowingBiFunction<T, U, R> throwing(BiFunction<String, Exception, RuntimeException> exceptionWrapper) { default ThrowingBiFunction<T, U, R> throwing(BiFunction<String, Exception, RuntimeException> exceptionWrapper) {
return new ThrowingBiFunction<>() { return new ThrowingBiFunction<>() {
@Override @Override
public R applyWithException(T t, U u) throws Exception { public R applyWithException(T t, U u) throws Exception {
return ThrowingBiFunction.this.applyWithException(t, u); return ThrowingBiFunction.this.applyWithException(t, u);
} }
@Override @Override
public R apply(T t, U u) { public R apply(T t, U u) {
return apply(t, u, exceptionWrapper); return apply(t, u, exceptionWrapper);
} }
}; };
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -77,17 +77,14 @@ public interface ThrowingConsumer<T> extends Consumer<T> {
*/ */
default ThrowingConsumer<T> throwing(BiFunction<String, Exception, RuntimeException> exceptionWrapper) { default ThrowingConsumer<T> throwing(BiFunction<String, Exception, RuntimeException> exceptionWrapper) {
return new ThrowingConsumer<>() { return new ThrowingConsumer<>() {
@Override @Override
public void acceptWithException(T t) throws Exception { public void acceptWithException(T t) throws Exception {
ThrowingConsumer.this.acceptWithException(t); ThrowingConsumer.this.acceptWithException(t);
} }
@Override @Override
public void accept(T t) { public void accept(T t) {
accept(t, exceptionWrapper); accept(t, exceptionWrapper);
} }
}; };
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -80,17 +80,14 @@ public interface ThrowingFunction<T, R> extends Function<T, R> {
*/ */
default ThrowingFunction<T, R> throwing(BiFunction<String, Exception, RuntimeException> exceptionWrapper) { default ThrowingFunction<T, R> throwing(BiFunction<String, Exception, RuntimeException> exceptionWrapper) {
return new ThrowingFunction<>() { return new ThrowingFunction<>() {
@Override @Override
public R applyWithException(T t) throws Exception { public R applyWithException(T t) throws Exception {
return ThrowingFunction.this.applyWithException(t); return ThrowingFunction.this.applyWithException(t);
} }
@Override @Override
public R apply(T t) { public R apply(T t) {
return apply(t, exceptionWrapper); return apply(t, exceptionWrapper);
} }
}; };
} }