diff --git a/engine/pom.xml b/engine/pom.xml index ccd16e6d46..4a6b79ff55 100644 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -52,11 +52,6 @@ - - org.glassfish - jakarta.el - provided - org.jboss.logging jboss-logging-processor @@ -79,6 +74,11 @@ + + jakarta.el + jakarta.el-api + true + jakarta.persistence jakarta.persistence-api @@ -115,6 +115,11 @@ + + org.glassfish + jakarta.el + test + org.testng testng diff --git a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java index b7164aa1a8..9bf4cbba49 100644 --- a/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java +++ b/engine/src/main/java/org/hibernate/validator/messageinterpolation/ResourceBundleMessageInterpolator.java @@ -7,6 +7,9 @@ package org.hibernate.validator.messageinterpolation; import java.lang.invoke.MethodHandles; +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Collections; @@ -24,8 +27,6 @@ import org.hibernate.validator.spi.messageinterpolation.LocaleResolver; import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator; -import com.sun.el.ExpressionFactoryImpl; - import jakarta.el.ELManager; import jakarta.el.ExpressionFactory; @@ -200,7 +201,10 @@ private static ExpressionFactory buildExpressionFactory() { // Finally we try the CL of the EL implementation itself. This is necessary for OSGi now that the // implementation is separated from the API. - run( SetContextClassLoader.action( ExpressionFactoryImpl.class.getClassLoader() ) ); + // Instead of running this: + // run( SetContextClassLoader.action( ExpressionFactoryImpl.class.getClassLoader() ) ); + // we do some reflection "magic" to not have a dependency on an implementation of the expression language: + run( SetContextClassLoader.action( classLoaderForExpressionFactory( originalContextClassLoader ) ) ); if ( canLoadExpressionFactory() ) { ExpressionFactory expressionFactory = ELManager.getExpressionFactory(); LOG.debug( "Loaded expression factory via com.sun.el classloader" ); @@ -218,6 +222,33 @@ private static ExpressionFactory buildExpressionFactory() { throw LOG.getUnableToInitializeELExpressionFactoryException( null ); } + private static ClassLoader classLoaderForExpressionFactory(ClassLoader cl) throws Exception { + try { + Class fu = cl.loadClass( "org.osgi.framework.FrameworkUtil" ); + Method getBundle = fu.getMethod( "getBundle", Class.class ); + Object currentBundle = getBundle.invoke( null, ResourceBundleMessageInterpolator.class ); + if ( currentBundle != null ) { + Object context = cl.loadClass( "org.osgi.framework.Bundle" ).getMethod( "getBundleContext" ).invoke( currentBundle ); + Object bundles = cl.loadClass( "org.osgi.framework.BundleContext" ).getMethod( "getBundles" ).invoke( context ); + Method loadClass = cl.loadClass( "org.osgi.framework.Bundle" ).getMethod( "loadClass", String.class ); + int n = Array.getLength( bundles ); + for ( int i = 0; i < n; i++ ) { + try { + Object bundle = Array.get( bundles, i ); + return ( (Class) loadClass.invoke( bundle, "com.sun.el.ExpressionFactoryImpl" ) ).getClassLoader(); + } + catch (Exception e) { + // + } + } + } + } + catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + throw e; + } + return null; + } + /** * Instead of testing the different class loaders via {@link ELManager}, we directly access the * {@link ExpressionFactory}. This avoids issues with loading the {@code ELUtil} class (used by {@code ELManager}) diff --git a/pom.xml b/pom.xml index 01bebc13a4..03df29830e 100644 --- a/pom.xml +++ b/pom.xml @@ -390,6 +390,11 @@ jakarta.el ${version.org.glassfish.jakarta.el} + + jakarta.el + jakarta.el-api + ${version.jakarta.el-api} + com.fasterxml classmate