This is an automated email from the ASF dual-hosted git repository. jlmonteiro pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomee.git
commit de6398935587f57e88300fd434a9335a7a195f46 Author: Jean-Louis Monteiro <[email protected]> AuthorDate: Thu Apr 22 13:58:09 2021 +0200 Fix some enum conversion with the EL Processor --- .../tomee/security/TomEEELInvocationHandler.java | 58 +++++++++++++++++++++- .../security/TomEEELInvocationHandlerTest.java | 6 ++- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/tomee/tomee-security/src/main/java/org/apache/tomee/security/TomEEELInvocationHandler.java b/tomee/tomee-security/src/main/java/org/apache/tomee/security/TomEEELInvocationHandler.java index 1faddd3..3393788 100644 --- a/tomee/tomee-security/src/main/java/org/apache/tomee/security/TomEEELInvocationHandler.java +++ b/tomee/tomee-security/src/main/java/org/apache/tomee/security/TomEEELInvocationHandler.java @@ -19,6 +19,7 @@ package org.apache.tomee.security; import javax.el.ELProcessor; import javax.enterprise.inject.spi.BeanManager; import java.lang.annotation.Annotation; +import java.lang.reflect.Array; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -70,7 +71,62 @@ public class TomEEELInvocationHandler implements InvocationHandler { // expression maybe #{expression} instead of ${expression} // the ELProcessor anyways wraps it with ${} final String sanitizedExpression = expression.replaceAll("^[#$]\\{(.+)}$", "$1"); - return processor.getValue(sanitizedExpression, expectedType); + + // ELProcessor does not do a good job with enums, so try to be a bit better (not sure) + // otherwise, let the EL processor do its best to convert into the expected value + if (!isEnumOrArrayOfEnums(expectedType)) { + return processor.getValue(sanitizedExpression, expectedType); + } + + final Object value = processor.getValue(sanitizedExpression, Object.class); + + // Convert single enum name to single enum + if (expectedType.isEnum() && value instanceof String) { + // yeah could use Enum.valueOf .... + return of(expectedType, value); + } + + // Convert single enum name to enum array (multiple enum values not supported) + if (expectedType.isArray() && value instanceof String) { + final Class<?> enumType = expectedType.getComponentType(); + + if (enumType.isEnum()) { // just in case + final Enum<?> enumConstant = (Enum<?>) of(enumType, value); + final Enum<?>[] outcomeArray = (Enum<?>[]) Array.newInstance(enumType, 1); + outcomeArray[0] = enumConstant; + + return outcomeArray; + } + + // else not sure what else we can do but let the Object go + + } + + return value; + } + + private boolean isEnumOrArrayOfEnums(final Class type) { + if (type.isEnum()) { + return true; + } + + if (type.isArray()) { + final Class componentType = type.getComponentType(); + return componentType.isEnum(); + } + + return false; + } + + private <T /*extends Enum<T>*/> T of(final Class<T> type, final Object name) { + try { + return (T) type.getDeclaredMethod("valueOf", String.class).invoke(null, name); + + } catch (final Exception e) { + // this will most likely result in a conversion error, but at least we know + // it won't be swallowed + return (T) name; + } } public static <T extends Annotation> T of(final Class<T> annotationClass, final T annotation, final BeanManager beanManager) { diff --git a/tomee/tomee-security/src/test/java/org/apache/tomee/security/TomEEELInvocationHandlerTest.java b/tomee/tomee-security/src/test/java/org/apache/tomee/security/TomEEELInvocationHandlerTest.java index 3516527..80db047 100644 --- a/tomee/tomee-security/src/test/java/org/apache/tomee/security/TomEEELInvocationHandlerTest.java +++ b/tomee/tomee-security/src/test/java/org/apache/tomee/security/TomEEELInvocationHandlerTest.java @@ -25,6 +25,7 @@ import javax.enterprise.inject.Vetoed; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.CDI; import javax.security.enterprise.identitystore.DatabaseIdentityStoreDefinition; +import javax.security.enterprise.identitystore.IdentityStore; import javax.security.enterprise.identitystore.PasswordHash; import java.lang.reflect.InvocationHandler; import java.util.Map; @@ -46,6 +47,7 @@ public class TomEEELInvocationHandlerTest extends AbstractTomEESecurityTest { Assert.assertEquals(90, proxiedAnnotation.priority()); Assert.assertEquals("90", proxiedAnnotation.priorityExpression()); + Assert.assertArrayEquals(new IdentityStore.ValidationType[] {IdentityStore.ValidationType.VALIDATE}, proxiedAnnotation.useFor()); } @@ -58,7 +60,9 @@ public class TomEEELInvocationHandlerTest extends AbstractTomEESecurityTest { callerQuery = "select password from caller where name = ?", groupsQuery = "select group_name from caller_groups where caller_name = ?", hashAlgorithm = CleartextPasswordHash.class, - priority = 30, priorityExpression = "90") + priority = 30, + priorityExpression = "90", + useForExpression = "#{'VALIDATE'}") public static class Color { }
