Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add expression language 6.0 Optional and Record resolvers #5481

Merged
merged 1 commit into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,16 @@
import jakarta.el.BeanELResolver;
import jakarta.el.ListELResolver;
import jakarta.el.MapELResolver;
import jakarta.el.OptionalELResolver;
import jakarta.el.RecordELResolver;
import jakarta.el.ResourceBundleELResolver;
import jakarta.el.StaticFieldELResolver;

public class ResolversRegistry {
public final BeanELResolver BEAN_RESOLVER = new BeanELResolver();
public final OptionalELResolver OPTIONAL_RESOLVER = new OptionalELResolver();
public final RecordELResolver RECORD_RESOLVER = new RecordELResolver();
public final StaticFieldELResolver STATIC_FIELD_RESOLVER = new StaticFieldELResolver();
public final ArrayELResolver ARRAY_RESOLVER = new ArrayELResolver();
public final FacesResourceBundleELResolver FACES_BUNDLE_RESOLVER = new FacesResourceBundleELResolver();
public final FlashELResolver FLASH_RESOLVER = new FlashELResolver();
Expand Down
79 changes: 35 additions & 44 deletions impl/src/main/java/com/sun/faces/el/ELUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@
*/
package com.sun.faces.el;

import static com.sun.faces.RIConstants.EMPTY_CLASS_ARGS;
import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.InterpretEmptyStringSubmittedValuesAsNull;
import static com.sun.faces.util.MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID;
import static com.sun.faces.util.MessageUtils.getExceptionMessageString;
import static com.sun.faces.util.ReflectionUtils.lookupMethod;
import static com.sun.faces.util.ReflectionUtils.newInstance;
import static com.sun.faces.util.Util.getCdiBeanManager;
import static com.sun.faces.util.Util.isEmpty;
import static java.lang.Boolean.FALSE;

import com.sun.faces.application.ApplicationAssociate;
Expand All @@ -37,7 +35,6 @@
import jakarta.el.ValueExpression;
import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext;
import java.lang.reflect.Method;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand All @@ -56,6 +53,7 @@ public class ELUtils {
* Helps to determine if a EL expression represents a composite component EL expression.
*/
private static final Pattern COMPOSITE_COMPONENT_EXPRESSION = Pattern.compile(".(?:[ ]+|[\\[{,(])cc[.].+[}]");

// do not use this Matcher, it's only for the Cache Factory
private static final Matcher COMPOSITE_COMPONENT_EXPRESSION_MATCHER = COMPOSITE_COMPONENT_EXPRESSION.matcher("");

Expand Down Expand Up @@ -136,6 +134,7 @@ public static boolean isCompositeComponentLookupWithArgs(String expression) {
public static void buildFacesResolver(FacesCompositeELResolver composite, ApplicationAssociate associate) {
checkNotNull(composite, associate);
addCDIELResolver(composite);

ResolversRegistry elRegistry = associate.getGlobalResolversRegistry();
composite.add(elRegistry.FLASH_RESOLVER);
composite.addPropertyELResolver(elRegistry.COMPOSITE_COMPONENT_ATTRIBUTES_EL_RESOLVER);
Expand All @@ -148,48 +147,25 @@ public static void buildFacesResolver(FacesCompositeELResolver composite, Applic

composite.addPropertyELResolver(elRegistry.RESOURCE_RESOLVER);
composite.addPropertyELResolver(elRegistry.BUNDLE_RESOLVER);
composite.addRootELResolver(elRegistry.FACES_BUNDLE_RESOLVER);
addEL3_0_Resolvers(composite, associate);
composite.addPropertyELResolver(elRegistry.MAP_RESOLVER);
composite.addPropertyELResolver(elRegistry.LIST_RESOLVER);
composite.addPropertyELResolver(elRegistry.ARRAY_RESOLVER);
composite.addPropertyELResolver(elRegistry.BEAN_RESOLVER);
composite.addRootELResolver(elRegistry.SCOPED_RESOLVER);
}

private static void checkNotNull(FacesCompositeELResolver composite, ApplicationAssociate associate) {
if (associate == null) {
throw new NullPointerException(getExceptionMessageString(NULL_PARAMETERS_ERROR_MESSAGE_ID, "associate"));
}
composite.addRootELResolver(elRegistry.FACES_BUNDLE_RESOLVER);

if (composite == null) {
throw new NullPointerException(getExceptionMessageString(NULL_PARAMETERS_ERROR_MESSAGE_ID, "composite"));
// Not sure when/why this would ever be null, but Thomas Hoffman believes it can be null.
ELResolver streamELResolver = associate.getExpressionFactory().getStreamELResolver();
if (streamELResolver != null) {
composite.addRootELResolver(streamELResolver);
}
}

private static void addCDIELResolver(FacesCompositeELResolver composite) {
composite.add(getCdiBeanManager(FacesContext.getCurrentInstance()).getELResolver());
}

private static void addEL3_0_Resolvers(FacesCompositeELResolver composite, ApplicationAssociate associate) {
ExpressionFactory expressionFactory = associate.getExpressionFactory();

Method getStreamELResolverMethod = lookupMethod(ExpressionFactory.class, "getStreamELResolver", EMPTY_CLASS_ARGS);
composite.addRootELResolver(elRegistry.STATIC_FIELD_RESOLVER);

if (getStreamELResolverMethod != null) {
try {
ELResolver streamELResolver = (ELResolver) getStreamELResolverMethod.invoke(expressionFactory, (Object[]) null);
if (streamELResolver != null) {
composite.addRootELResolver(streamELResolver);
composite.addPropertyELResolver(elRegistry.MAP_RESOLVER);
composite.addPropertyELResolver(elRegistry.LIST_RESOLVER);
composite.addPropertyELResolver(elRegistry.ARRAY_RESOLVER);
composite.addPropertyELResolver(elRegistry.OPTIONAL_RESOLVER);
composite.addPropertyELResolver(elRegistry.RECORD_RESOLVER);
composite.addPropertyELResolver(elRegistry.BEAN_RESOLVER);

// Assume that if we have getStreamELResolver, then we must have
// jakarta.el.staticFieldELResolver
composite.addRootELResolver((ELResolver) newInstance("jakarta.el.StaticFieldELResolver"));
}
} catch (IllegalArgumentException | ReflectiveOperationException | SecurityException t) {
// This is normal on containers that do not have these ELResolvers
}
}
composite.addRootELResolver(elRegistry.SCOPED_RESOLVER);
}

public static Object evaluateValueExpression(ValueExpression expression, ELContext elContext) {
Expand Down Expand Up @@ -231,13 +207,28 @@ public static Object coerce(Object value, Class<?> toType) {
* @param resolvers a <code>List</code> of <code>ELResolver</code>s
*/
private static void addELResolvers(CompositeELResolver target, List<ELResolver> resolvers) {
if (resolvers != null && !resolvers.isEmpty()) {
if (!isEmpty(resolvers)) {
for (ELResolver resolver : resolvers) {
target.add(resolver);
}
}
}

private static void addCDIELResolver(FacesCompositeELResolver composite) {
composite.add(getCdiBeanManager(FacesContext.getCurrentInstance()).getELResolver());
}

private static void checkNotNull(FacesCompositeELResolver composite, ApplicationAssociate associate) {
if (associate == null) {
throw new NullPointerException(getExceptionMessageString(NULL_PARAMETERS_ERROR_MESSAGE_ID, "associate"));
}

if (composite == null) {
throw new NullPointerException(getExceptionMessageString(NULL_PARAMETERS_ERROR_MESSAGE_ID, "composite"));
}
}


/*
* First look in the ApplicationAssociate. If that fails, return null;
*
Expand All @@ -247,12 +238,12 @@ public static ExpressionFactory getDefaultExpressionFactory(FacesContext facesCo
return null;
}

ExternalContext extContext = facesContext.getExternalContext();
if (extContext == null) {
ExternalContext externalContext = facesContext.getExternalContext();
if (externalContext == null) {
return null;
}

return getDefaultExpressionFactory(ApplicationAssociate.getInstance(extContext), facesContext);
return getDefaultExpressionFactory(ApplicationAssociate.getInstance(externalContext), facesContext);
}

public static ExpressionFactory getDefaultExpressionFactory(ApplicationAssociate associate, FacesContext facesContext) {
Expand Down
Loading