From 1a24255fd4edcaaae3d5ec712b73611f83caf9f2 Mon Sep 17 00:00:00 2001 From: Bauke Scholtz Date: Sat, 28 Oct 2023 08:18:07 -0400 Subject: [PATCH 1/4] Ensure that all default values of context params are already in spec https://github.com/jakartaee/faces/issues/1416 --- .../faces/application/ResourceHandler.java | 24 ++++++++++++++++--- .../faces/application/ViewHandler.java | 12 +++++++++- .../jakarta/faces/lifecycle/ClientWindow.java | 21 +++++++++++++++- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/impl/src/main/java/jakarta/faces/application/ResourceHandler.java b/impl/src/main/java/jakarta/faces/application/ResourceHandler.java index f7e28c21ad..42092da871 100644 --- a/impl/src/main/java/jakarta/faces/application/ResourceHandler.java +++ b/impl/src/main/java/jakarta/faces/application/ResourceHandler.java @@ -191,26 +191,44 @@ public abstract class ResourceHandler { * {@link #WEBAPP_RESOURCES_DIRECTORY_PARAM_NAME} exists, the runtime must interpret its value as a path, relative to * the web app root, where resources are to be located. This param value must not start with a "/", though it may * contain "/" characters. If no such <context-param> exists, or its value is invalid, the value - * "resources", without the quotes, must be used by the runtime as the value. + * {@value #WEBAPP_RESOURCES_DIRECTORY_DEFAULT_VALUE}, without the quotes, must be used by the runtime as the value. *

* * @since 2.2 */ public static final String WEBAPP_RESOURCES_DIRECTORY_PARAM_NAME = "jakarta.faces.WEBAPP_RESOURCES_DIRECTORY"; + /** + *

+ * The default value of the {@link #WEBAPP_RESOURCES_DIRECTORY_PARAM_NAME} context-param. + *

+ * + * @since 5.0 + */ + public static final String WEBAPP_RESOURCES_DIRECTORY_DEFAULT_VALUE = "resources"; + /** *

* If a <context-param> with the param name equal to the value of * {@link #WEBAPP_CONTRACTS_DIRECTORY_PARAM_NAME} exists, the runtime must interpret its value as a path, relative to * the web app root, where resource library contracts are to be located. This param value must not start with a "/", * though it may contain "/" characters. If no such <context-param> exists, or its value is invalid, - * the value "contracts", without the quotes, must be used by the runtime as the value. + * the value {@value #WEBAPP_CONTRACTS_DIRECTORY_DEFAULT_VALUE}, without the quotes, must be used by the runtime as the value. *

* * @since 2.2 */ public static final String WEBAPP_CONTRACTS_DIRECTORY_PARAM_NAME = "jakarta.faces.WEBAPP_CONTRACTS_DIRECTORY"; + /** + *

+ * The default value of the {@link #WEBAPP_CONTRACTS_DIRECTORY_PARAM_NAME} context-param. + *

+ * + * @since 5.0 + */ + public static final String WEBAPP_CONTRACTS_DIRECTORY_DEFAULT_VALUE = "contracts"; + /** *

* The name of a key within the application message bundle named by the return from {@link Application#getMessageBundle} @@ -235,7 +253,7 @@ public abstract class ResourceHandler { * The default value for the {@link #RESOURCE_EXCLUDES_PARAM_NAME} init param. *

*/ - public static final String RESOURCE_EXCLUDES_DEFAULT_VALUE = ".class .jsp .jspx .properties .xhtml .groovy"; + public static final String RESOURCE_EXCLUDES_DEFAULT_VALUE = ".class .jsp .jspx .properties .xhtml .groovy"; // NOTE: when changing, ensure {@link FacesConfig#resourceExcludes()} is also adjusted. // ---------------------------------------------------------- Public Methods diff --git a/impl/src/main/java/jakarta/faces/application/ViewHandler.java b/impl/src/main/java/jakarta/faces/application/ViewHandler.java index d4c868349a..a14b08c495 100644 --- a/impl/src/main/java/jakarta/faces/application/ViewHandler.java +++ b/impl/src/main/java/jakarta/faces/application/ViewHandler.java @@ -127,7 +127,8 @@ public abstract class ViewHandler { /** *

- * The buffer size to set on the response when the ResponseWriter is generated. By default the value is 1024. A value of + * The buffer size to set on the response when the ResponseWriter is generated. By default the value is + * {@value #FACELETS_BUFFER_SIZE_DEFAULT_VALUE}. A value of * -1 will not assign a buffer size on the response. This should be increased if you are using development mode in order * to guarantee that the response isn't partially rendered when an error is generated. *

@@ -136,6 +137,15 @@ public abstract class ViewHandler { */ public static final String FACELETS_BUFFER_SIZE_PARAM_NAME = "jakarta.faces.FACELETS_BUFFER_SIZE"; + /** + *

+ * The default value of the {@link #FACELETS_BUFFER_SIZE_PARAM_NAME} context-param. + *

+ * + * @since 5.0 + */ + public static final int FACELETS_BUFFER_SIZE_DEFAULT_VALUE = 1024; + /** *

* When a page is requested, what interval in seconds should the compiler diff --git a/impl/src/main/java/jakarta/faces/lifecycle/ClientWindow.java b/impl/src/main/java/jakarta/faces/lifecycle/ClientWindow.java index be9ee237b5..d1ef3bd4c0 100644 --- a/impl/src/main/java/jakarta/faces/lifecycle/ClientWindow.java +++ b/impl/src/main/java/jakarta/faces/lifecycle/ClientWindow.java @@ -94,16 +94,26 @@ public abstract class ClientWindow { *

* The context-param that controls the operation of the ClientWindow feature. The runtime must support the * values "none" and "url", without the quotes, but other values are possible. If not specified, or the value is not - * understood by the implementation, "none" is assumed. + * understood by the implementation, {@value #CLIENT_WINDOW_MODE_DEFAULT_VALUE} is assumed. *

* * @since 2.2 */ public static final String CLIENT_WINDOW_MODE_PARAM_NAME = "jakarta.faces.CLIENT_WINDOW_MODE"; + /** + *

+ * The default value of the {@link #CLIENT_WINDOW_MODE_PARAM_NAME} context-param. + *

+ * + * @since 5.0 + */ + public static final String CLIENT_WINDOW_MODE_DEFAULT_VALUE = "none"; + /** *

* Indicate the max number of ClientWindows, which is used by {@link ClientWindowScoped}. + * By default the value is {@link #NUMBER_OF_CLIENT_WINDOWS_DEFAULT_VALUE}. * It is only active when jakarta.faces.CLIENT_WINDOW_MODE is enabled. *

* @@ -111,6 +121,15 @@ public abstract class ClientWindow { */ public static final String NUMBER_OF_CLIENT_WINDOWS_PARAM_NAME = "jakarta.faces.NUMBER_OF_CLIENT_WINDOWS"; + /** + *

+ * The default value of the {@link #NUMBER_OF_CLIENT_WINDOWS_PARAM_NAME} context-param. + *

+ * + * @since 5.0 + */ + public static final int NUMBER_OF_CLIENT_WINDOWS_DEFAULT_VALUE = 10; + /** *

* This method will be called whenever a URL is generated by the runtime where client window related parameters need to From 0d99a4c53a4e72ddcaf145e2b9d85e9a91b248fb Mon Sep 17 00:00:00 2001 From: Bauke Scholtz Date: Sat, 28 Oct 2023 08:36:50 -0400 Subject: [PATCH 2/4] Add new FacesConfig.ContextParam enum https://github.com/jakartaee/faces/issues/1416 --- .../main/java/com/sun/faces/RIConstants.java | 1 + .../main/java/com/sun/faces/cdi/CdiUtils.java | 42 ++ .../jakarta/faces/annotation/FacesConfig.java | 711 +++++++++++++++++- 3 files changed, 753 insertions(+), 1 deletion(-) diff --git a/impl/src/main/java/com/sun/faces/RIConstants.java b/impl/src/main/java/com/sun/faces/RIConstants.java index 62b400c6b4..5177bc8738 100644 --- a/impl/src/main/java/com/sun/faces/RIConstants.java +++ b/impl/src/main/java/com/sun/faces/RIConstants.java @@ -44,6 +44,7 @@ public class RIConstants { public static final String TLV_RESOURCE_LOCATION = FACES_PREFIX + "resources.Resources"; public static final String NO_VALUE = ""; + public static final String[] EMPTY_STRING_ARRAY = {}; public static final Class[] EMPTY_CLASS_ARGS = new Class[0]; public static final Object[] EMPTY_METH_ARGS = new Object[0]; diff --git a/impl/src/main/java/com/sun/faces/cdi/CdiUtils.java b/impl/src/main/java/com/sun/faces/cdi/CdiUtils.java index 3fe829b478..f24ef137b2 100644 --- a/impl/src/main/java/com/sun/faces/cdi/CdiUtils.java +++ b/impl/src/main/java/com/sun/faces/cdi/CdiUtils.java @@ -22,6 +22,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Comparator; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -35,6 +36,7 @@ import com.sun.faces.util.FacesLogger; import com.sun.faces.util.Util; +import jakarta.annotation.Priority; import jakarta.enterprise.context.ContextNotActiveException; import jakarta.enterprise.context.spi.Context; import jakarta.enterprise.context.spi.CreationalContext; @@ -60,6 +62,33 @@ */ public final class CdiUtils { + /** + * This does unfortunately not exist in cdi spec: https://stackoverflow.com/a/63653513 + * + * This basically sorts descending by priority with fallback to FQN. + * Highest priority first. + * Priotityless bean last. + * Same priorities ordered by FQN (for now?) + */ + public static final Comparator BEAN_PRIORITY_COMPARATOR = (left, right) -> { + Class leftClass = left.getClass(); + Class rightClass = right.getClass(); + Priority leftPriority = leftClass.getAnnotation(Priority.class); + Priority rightPriority = rightClass.getAnnotation(Priority.class); + + int compare = leftPriority != null && rightPriority != null ? Integer.compare(leftPriority.value(), rightPriority.value()) + : leftPriority != null ? -1 + : rightPriority != null ? 1 + : 0; + + if (compare == 0) { + return leftClass.getName().compareTo(rightClass.getName()); + } + + return compare; + }; + + /** * Stores the logger. */ @@ -252,6 +281,19 @@ private static Object getBeanReferenceByType(BeanManager beanManager, Type type, return beanReference; } + public static Set getBeanReferencesByQualifier(FacesContext context, Annotation... qualifiers) { + if (qualifiers.length == 0) { + throw new IllegalArgumentException(); + } + + BeanManager beanManager = Util.getCdiBeanManager(context); + return beanManager.getBeans(Object.class, qualifiers).stream().map(bean -> getBeanReference(beanManager, bean)).collect(toSet()); + } + + private static Object getBeanReference(BeanManager beanManager, Bean bean) { + return beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean)); + } + private static String getBeanName(Bean bean) { String name = bean.getName(); diff --git a/impl/src/main/java/jakarta/faces/annotation/FacesConfig.java b/impl/src/main/java/jakarta/faces/annotation/FacesConfig.java index 4d89a8a234..094fb7c0ba 100644 --- a/impl/src/main/java/jakarta/faces/annotation/FacesConfig.java +++ b/impl/src/main/java/jakarta/faces/annotation/FacesConfig.java @@ -17,21 +17,53 @@ package jakarta.faces.annotation; +import static com.sun.faces.RIConstants.EMPTY_STRING_ARRAY; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import java.util.EnumMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; +import java.util.logging.Logger; +import java.util.regex.Pattern; + +import com.sun.faces.cdi.CdiUtils; +import com.sun.faces.util.FacesLogger; import jakarta.enterprise.util.AnnotationLiteral; import jakarta.enterprise.util.Nonbinding; +import jakarta.faces.application.Application; +import jakarta.faces.application.ProjectStage; +import jakarta.faces.application.ResourceHandler; +import jakarta.faces.application.StateManager; +import jakarta.faces.application.StateManager.StateSavingMethod; +import jakarta.faces.application.ViewHandler; +import jakarta.faces.component.NamingContainer; +import jakarta.faces.component.UIInput; +import jakarta.faces.component.UIInput.ValidateEmptyFields; +import jakarta.faces.component.UINamingContainer; +import jakarta.faces.component.UIViewRoot; +import jakarta.faces.context.ExternalContext; +import jakarta.faces.context.FacesContext; +import jakarta.faces.convert.Converter; +import jakarta.faces.lifecycle.ClientWindow; +import jakarta.faces.push.PushContext; +import jakarta.faces.validator.BeanValidator; +import jakarta.faces.webapp.FacesServlet; import jakarta.inject.Qualifier; /** *

* The presence of this annotation on a class deployed within an application * guarantees activation of Jakarta Faces and its CDI specific features, even when - * /WEB-INF/faces-config.xml is absent and FacesServlet is not explicitly registered. + * {@code /WEB-INF/faces-config.xml} is absent and {@code FacesServlet} is not explicitly registered. + * The attributes can be used to preconfigure the context parameters of your Jakarta Faces application. + * The {@link ContextParam} can be used to obtain the context parameters of your Jakarta Faces application. *

*/ @Qualifier @@ -39,7 +71,204 @@ @Retention(RUNTIME) public @interface FacesConfig { + /** + *

+ * Returns {@value UIInput#ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE} as {@link Boolean} with default of {@code false}. + *

+ */ + @Nonbinding boolean alwaysPerformValidationWhenRequiredIsTrue() default false; + + /** + *

+ * Returns {@value FacesServlet#AUTOMATIC_EXTENSIONLESS_MAPPING_PARAM_NAME} as {@link Boolean} with default of {@code false}. + *

+ */ + @Nonbinding boolean automaticExtensionlessMapping() default false; + + /** + *

+ * Returns {@value ClientWindow#CLIENT_WINDOW_MODE_PARAM_NAME} as {@link String} with default of {@value ClientWindow#CLIENT_WINDOW_MODE_DEFAULT_VALUE}. + *

+ */ + @Nonbinding String clientWindowMode() default ClientWindow.CLIENT_WINDOW_MODE_DEFAULT_VALUE; + + /** + *

+ * Returns {@value FacesServlet#CONFIG_FILES_ATTR} as {@link String} array with default of empty string array. + *

+ */ + @Nonbinding String[] configFiles() default {}; + + /** + *

+ * Returns {@value Converter#DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE_PARAM_NAME} as {@link Boolean} with default of {@code false}. + *

+ */ + @Nonbinding boolean datetimeConverterDefaultTimezoneIsSystemTimezone() default false; + + /** + *

+ * Returns {@value BeanValidator#DISABLE_DEFAULT_BEAN_VALIDATOR_PARAM_NAME} as {@link Boolean} with default of {@code false}. + *

+ */ + @Nonbinding boolean disableDefaultBeanValidator() default false; + + /** + *

+ * Returns {@value FacesServlet#DISABLE_FACESSERVLET_TO_XHTML_PARAM_NAME} as {@link Boolean} with default of {@code false}. + *

+ */ + @Nonbinding boolean disableFacesservletToXhtml() default false; + + /** + *

+ * Returns {@value BeanValidator#ENABLE_VALIDATE_WHOLE_BEAN_PARAM_NAME} as {@link Boolean} with default of {@code false}. + *

+ */ + @Nonbinding boolean enableValidateWholeBean() default false; + + /** + *

+ * Returns {@value PushContext#ENABLE_WEBSOCKET_ENDPOINT_PARAM_NAME} as {@link Boolean} with default of {@code false}. + *

+ */ + @Nonbinding boolean enableWebsocketEndpoint() default false; + + /** + *

+ * Returns {@value ViewHandler#FACELETS_BUFFER_SIZE_PARAM_NAME} as {@link Integer} with default of {@value ViewHandler#FACELETS_BUFFER_SIZE_DEFAULT_VALUE}. + *

+ */ + @Nonbinding int faceletsBufferSize() default ViewHandler.FACELETS_BUFFER_SIZE_DEFAULT_VALUE; + + /** + *

+ * Returns {@value ViewHandler#FACELETS_DECORATORS_PARAM_NAME} as {@link String} array with default of empty string array. + *

+ */ + @Nonbinding String[] faceletsDecorators() default {}; + + /** + *

+ * Returns {@value ViewHandler#FACELETS_LIBRARIES_PARAM_NAME} as {@link String} array with default of empty string array. + *

+ */ + @Nonbinding String[] faceletsLibraries() default {}; + + /** + *

+ * Returns {@value ViewHandler#FACELETS_REFRESH_PERIOD_PARAM_NAME} as {@link Integer} with default of {@link Integer#MIN_VALUE}, + * meaning that the runtime then needs to determine the final default value via {@code ContextParam.FACELETS_REFRESH_PERIOD.getDefaultValue(FacesContext)} + * because that depends on the currently configured {@link Application#getProjectStage()}. + *

+ */ + @Nonbinding int faceletsRefreshPeriod() default Integer.MIN_VALUE; + + /** + *

+ * Returns {@value ViewHandler#FACELETS_SKIP_COMMENTS_PARAM_NAME} as {@link Boolean} with default of {@code false}. + *

+ */ + @Nonbinding boolean faceletsSkipComments() default false; + + /** + *

+ * Returns {@value ViewHandler#FACELETS_SUFFIX_PARAM_NAME} as {@link String} with default of {@value ViewHandler#DEFAULT_FACELETS_SUFFIX}. + *

+ */ + @Nonbinding String faceletsSuffix() default ViewHandler.DEFAULT_FACELETS_SUFFIX; + + /** + *

+ * Returns {@value ViewHandler#FACELETS_VIEW_MAPPINGS_PARAM_NAME} as {@link String} array with default of empty string array. + *

+ */ + @Nonbinding String[] faceletsViewMappings() default {}; + + /** + *

+ * Returns {@value UIInput#EMPTY_STRING_AS_NULL_PARAM_NAME} as {@link Boolean} with default of {@code false}. + *

+ */ + @Nonbinding boolean interpretEmptyStringSubmittedValuesAsNull() default false; + + /** + *

+ * Returns {@value ClientWindow#NUMBER_OF_CLIENT_WINDOWS_PARAM_NAME} as {@link Integer} with default of {@value ClientWindow#NUMBER_OF_CLIENT_WINDOWS_DEFAULT_VALUE}. + *

+ */ + @Nonbinding int numberOfClientWindows() default ClientWindow.NUMBER_OF_CLIENT_WINDOWS_DEFAULT_VALUE; + + /** + *

+ * Returns {@value ProjectStage#PROJECT_STAGE_PARAM_NAME} as {@link ProjectStage} with default of {@link ProjectStage#Production}. + * Note that this value can be overridden via JNDI entry {@value ProjectStage#PROJECT_STAGE_JNDI_NAME}. + *

+ */ + @Nonbinding ProjectStage projectStage() default ProjectStage.Production; + + /** + *

+ * Returns {@value ResourceHandler#RESOURCE_EXCLUDES_PARAM_NAME} as {@link String} array with default of {@value ResourceHandler#RESOURCE_EXCLUDES_DEFAULT_VALUE}. + *

+ */ + @Nonbinding String[] resourceExcludes() default { ".class", ".jsp", ".jspx", ".properties", ".xhtml", ".groovy" }; // We cannot reference ResourceHandler#RESOURCE_EXCLUDES_DEFAULT_VALUE, it had to be hardcoded. + + /** + *

+ * Returns {@value StateManager#SERIALIZE_SERVER_STATE_PARAM_NAME} as {@link Boolean} with default of {@code false}. + *

+ */ + @Nonbinding boolean serializeServerState() default false; + + /** + *

+ * Returns {@value UINamingContainer#SEPARATOR_CHAR_PARAM_NAME} as {@link Character} with default of {@value NamingContainer#SEPARATOR_CHAR}. + *

+ */ + @Nonbinding char separatorChar() default NamingContainer.SEPARATOR_CHAR; + + /** + *

+ * Returns {@value StateManager#STATE_SAVING_METHOD_PARAM_NAME} as {@link String} with default of {@link StateSavingMethod#CLIENT}. + *

+ */ + @Nonbinding StateSavingMethod stateSavingMethod() default StateSavingMethod.CLIENT; + + /** + *

+ * Returns {@value UIInput#VALIDATE_EMPTY_FIELDS_PARAM_NAME} as {@link String} with default of {@link ValidateEmptyFields#AUTO}. + *

+ */ + @Nonbinding ValidateEmptyFields validateEmptyFields() default ValidateEmptyFields.AUTO; + + /** + *

+ * Returns {@value UIViewRoot#VIEWROOT_PHASE_LISTENER_QUEUES_EXCEPTIONS_PARAM_NAME} as {@link Boolean} with default of {@code false}. + *

+ */ + @Nonbinding boolean viewrootPhaseListenerQueuesExceptions() default false; + + /** + *

+ * Returns {@value ResourceHandler#WEBAPP_CONTRACTS_DIRECTORY_PARAM_NAME} as {@link String} with default of {@value ResourceHandler#WEBAPP_CONTRACTS_DIRECTORY_DEFAULT_VALUE}. + *

+ */ + @Nonbinding String webappContractsDirectory() default ResourceHandler.WEBAPP_CONTRACTS_DIRECTORY_DEFAULT_VALUE; + + /** + *

+ * Returns {@value ResourceHandler#WEBAPP_RESOURCES_DIRECTORY_PARAM_NAME} as {@link String} with default of {@value ResourceHandler#WEBAPP_RESOURCES_DIRECTORY_DEFAULT_VALUE}. + *

+ */ + @Nonbinding String webappResourcesDirectory() default ResourceHandler.WEBAPP_RESOURCES_DIRECTORY_DEFAULT_VALUE; + /** + *

+ * Returns {@value PushContext#WEBSOCKET_ENDPOINT_PORT_PARAM_NAME} as {@link Integer} with default of {@code 0} (default 0 means the code will take the port from the request). + *

+ */ + @Nonbinding int websocketEndpointPort() default 0; /** *

* Supports inline instantiation of the {@link FacesConfig} qualifier. @@ -54,6 +283,486 @@ public static final class Literal extends AnnotationLiteral impleme * Instance of the {@link FacesConfig} qualifier. */ public static final Literal INSTANCE = new Literal(); + + @Override + public boolean alwaysPerformValidationWhenRequiredIsTrue() { + return false; + } + + @Override + public boolean automaticExtensionlessMapping() { + return false; + } + + @Override + public String clientWindowMode() { + return ClientWindow.CLIENT_WINDOW_MODE_DEFAULT_VALUE; + } + + @Override + public String[] configFiles() { + return EMPTY_STRING_ARRAY; + } + + @Override + public boolean datetimeConverterDefaultTimezoneIsSystemTimezone() { + return false; + } + + @Override + public boolean disableDefaultBeanValidator() { + return false; + } + + @Override + public boolean disableFacesservletToXhtml() { + return false; + } + + @Override + public boolean enableValidateWholeBean() { + return false; + } + + @Override + public boolean enableWebsocketEndpoint() { + return false; + } + + @Override + public int faceletsBufferSize() { + return ViewHandler.FACELETS_BUFFER_SIZE_DEFAULT_VALUE; + } + + @Override + public String[] faceletsDecorators() { + return EMPTY_STRING_ARRAY; + } + + @Override + public String[] faceletsLibraries() { + return EMPTY_STRING_ARRAY; + } + + @Override + public int faceletsRefreshPeriod() { + return Integer.MIN_VALUE; + } + + @Override + public boolean faceletsSkipComments() { + return false; + } + + @Override + public String faceletsSuffix() { + return ViewHandler.DEFAULT_FACELETS_SUFFIX; + } + + @Override + public String[] faceletsViewMappings() { + return EMPTY_STRING_ARRAY; + } + + @Override + public boolean interpretEmptyStringSubmittedValuesAsNull() { + return false; + } + + @Override + public int numberOfClientWindows() { + return ClientWindow.NUMBER_OF_CLIENT_WINDOWS_DEFAULT_VALUE; + } + + @Override + public ProjectStage projectStage() { + return ProjectStage.Production; + } + + @Override + public String[] resourceExcludes() { + return ContextParam.StringArray.SPACE_SEPARATED.split(ResourceHandler.RESOURCE_EXCLUDES_DEFAULT_VALUE); + } + + @Override + public boolean serializeServerState() { + return false; + } + + @Override + public char separatorChar() { + return NamingContainer.SEPARATOR_CHAR; + } + + @Override + public StateSavingMethod stateSavingMethod() { + return StateSavingMethod.CLIENT; + } + + @Override + public ValidateEmptyFields validateEmptyFields() { + return ValidateEmptyFields.AUTO; + } + + @Override + public boolean viewrootPhaseListenerQueuesExceptions() { + return false; + } + + @Override + public String webappContractsDirectory() { + return ResourceHandler.WEBAPP_CONTRACTS_DIRECTORY_DEFAULT_VALUE; + } + + @Override + public String webappResourcesDirectory() { + return ResourceHandler.WEBAPP_RESOURCES_DIRECTORY_DEFAULT_VALUE; + } + + @Override + public int websocketEndpointPort() { + return 0; + } } + /** + *

+ * Enumeration of all available {@code jakarta.faces.*} context parameters. + *

+ * + * @since 5.0 + */ + public static enum ContextParam { + + /** + * Returns {@value UIInput#ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE} as {@link Boolean} with default of {@code false}. + */ + ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE(UIInput.ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE, FacesConfig::alwaysPerformValidationWhenRequiredIsTrue), + + /** + * Returns {@value FacesServlet#AUTOMATIC_EXTENSIONLESS_MAPPING_PARAM_NAME} as {@link Boolean} with default of {@code false}. + */ + AUTOMATIC_EXTENSIONLESS_MAPPING(FacesServlet.AUTOMATIC_EXTENSIONLESS_MAPPING_PARAM_NAME, FacesConfig::automaticExtensionlessMapping), + + /** + * Returns {@value ClientWindow#CLIENT_WINDOW_MODE_PARAM_NAME} as {@link String} with default of {@code none}. + */ + CLIENT_WINDOW_MODE(ClientWindow.CLIENT_WINDOW_MODE_PARAM_NAME, FacesConfig::clientWindowMode), + + /** + * Returns {@value FacesServlet#CONFIG_FILES_ATTR} as {@link String} array with default of empty string array. + */ + CONFIG_FILES(FacesServlet.CONFIG_FILES_ATTR, FacesConfig::configFiles, StringArray.COMMA_SEPARATED), + + /** + * Returns {@value Converter#DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE_PARAM_NAME} as {@link Boolean} with default of {@code false}. + */ + DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE(Converter.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE_PARAM_NAME, FacesConfig::datetimeConverterDefaultTimezoneIsSystemTimezone), + + /** + * Returns {@value BeanValidator#DISABLE_DEFAULT_BEAN_VALIDATOR_PARAM_NAME} as {@link Boolean} with default of {@code false}. + */ + DISABLE_DEFAULT_BEAN_VALIDATOR(BeanValidator.DISABLE_DEFAULT_BEAN_VALIDATOR_PARAM_NAME, FacesConfig::disableDefaultBeanValidator), + + /** + * Returns {@value FacesServlet#DISABLE_FACESSERVLET_TO_XHTML_PARAM_NAME} as {@link Boolean} with default of {@code false}. + */ + DISABLE_FACESSERVLET_TO_XHTML(FacesServlet.DISABLE_FACESSERVLET_TO_XHTML_PARAM_NAME, FacesConfig::disableFacesservletToXhtml), + + /** + * Returns {@value BeanValidator#ENABLE_VALIDATE_WHOLE_BEAN_PARAM_NAME} as {@link Boolean} with default of {@code false}. + */ + ENABLE_VALIDATE_WHOLE_BEAN(BeanValidator.ENABLE_VALIDATE_WHOLE_BEAN_PARAM_NAME, FacesConfig::enableValidateWholeBean), + + /** + * Returns {@value PushContext#ENABLE_WEBSOCKET_ENDPOINT_PARAM_NAME} as {@link Boolean} with default of {@code false}. + */ + ENABLE_WEBSOCKET_ENDPOINT(PushContext.ENABLE_WEBSOCKET_ENDPOINT_PARAM_NAME, FacesConfig::enableWebsocketEndpoint), + + /** + * Returns {@value ViewHandler#FACELETS_BUFFER_SIZE_PARAM_NAME} as {@link Integer} with default of {@value ViewHandler#FACELETS_BUFFER_SIZE_DEFAULT_VALUE}. + */ + FACELETS_BUFFER_SIZE(ViewHandler.FACELETS_BUFFER_SIZE_PARAM_NAME, FacesConfig::faceletsBufferSize), + + /** + * Returns {@value ViewHandler#FACELETS_DECORATORS_PARAM_NAME} as {@link String} array with default of empty string array. + */ + FACELETS_DECORATORS(ViewHandler.FACELETS_DECORATORS_PARAM_NAME, FacesConfig::faceletsDecorators, StringArray.SEMICOLON_SEPARATED), + + /** + * Returns {@value ViewHandler#FACELETS_LIBRARIES_PARAM_NAME} as {@link String} array with default of empty string array. + */ + FACELETS_LIBRARIES(ViewHandler.FACELETS_LIBRARIES_PARAM_NAME, FacesConfig::faceletsLibraries, StringArray.SEMICOLON_SEPARATED), + + /** + * Returns {@value ViewHandler#FACELETS_REFRESH_PERIOD_PARAM_NAME} as {@link Integer} with default of {@code -1} when + * {@link Application#getProjectStage()} is {@link ProjectStage#Production} else default of {@code 0}. + */ + FACELETS_REFRESH_PERIOD(ViewHandler.FACELETS_REFRESH_PERIOD_PARAM_NAME, FacesConfig::faceletsRefreshPeriod, (Function) context -> context.getApplication().getProjectStage() == ProjectStage.Production ? -1 : 0), + + /** + * Returns {@value ViewHandler#FACELETS_SKIP_COMMENTS_PARAM_NAME} as {@link Boolean} with default of {@code false}. + */ + FACELETS_SKIP_COMMENTS(ViewHandler.FACELETS_SKIP_COMMENTS_PARAM_NAME, FacesConfig::faceletsSkipComments), + + /** + * Returns {@value ViewHandler#FACELETS_SUFFIX_PARAM_NAME} as {@link String} with default of {@value ViewHandler#DEFAULT_FACELETS_SUFFIX}. + */ + FACELETS_SUFFIX(ViewHandler.FACELETS_SUFFIX_PARAM_NAME, FacesConfig::faceletsSuffix), + + /** + * Returns {@value ViewHandler#FACELETS_VIEW_MAPPINGS_PARAM_NAME} as {@link String} array with default of empty string array. + */ + FACELETS_VIEW_MAPPINGS(ViewHandler.FACELETS_VIEW_MAPPINGS_PARAM_NAME, FacesConfig::faceletsViewMappings, StringArray.SEMICOLON_SEPARATED), + + /** + * Returns {@value UIInput#EMPTY_STRING_AS_NULL_PARAM_NAME} as {@link Boolean} with default of {@code false}. + */ + INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL(UIInput.EMPTY_STRING_AS_NULL_PARAM_NAME, FacesConfig::interpretEmptyStringSubmittedValuesAsNull), + + /** + * Returns {@value ClientWindow#NUMBER_OF_CLIENT_WINDOWS_PARAM_NAME} as {@link Integer} with default of {@value ClientWindow#NUMBER_OF_CLIENT_WINDOWS_DEFAULT_VALUE}. + */ + NUMBER_OF_CLIENT_WINDOWS(ClientWindow.NUMBER_OF_CLIENT_WINDOWS_PARAM_NAME, FacesConfig::numberOfClientWindows), + + /** + * Returns {@value ProjectStage#PROJECT_STAGE_PARAM_NAME} as {@link ProjectStage} with default of {@link ProjectStage#Production}. + * Note that this value can be overridden via JNDI entry {@value ProjectStage#PROJECT_STAGE_JNDI_NAME}. + */ + PROJECT_STAGE(ProjectStage.PROJECT_STAGE_PARAM_NAME, FacesConfig::projectStage), + + /** + * Returns {@value ResourceHandler#RESOURCE_EXCLUDES_PARAM_NAME} as {@link String} array with default of {@value ResourceHandler#RESOURCE_EXCLUDES_DEFAULT_VALUE}. + */ + RESOURCE_EXCLUDES(ResourceHandler.RESOURCE_EXCLUDES_PARAM_NAME, FacesConfig::resourceExcludes, StringArray.SPACE_SEPARATED), + + /** + * Returns {@value StateManager#SERIALIZE_SERVER_STATE_PARAM_NAME} as {@link Boolean} with default of {@code false}. + */ + SERIALIZE_SERVER_STATE(StateManager.SERIALIZE_SERVER_STATE_PARAM_NAME, FacesConfig::serializeServerState), + + /** + * Returns {@value UINamingContainer#SEPARATOR_CHAR_PARAM_NAME} as {@link Character} with default of {@value NamingContainer#SEPARATOR_CHAR}. + */ + SEPARATOR_CHAR(UINamingContainer.SEPARATOR_CHAR_PARAM_NAME, FacesConfig::separatorChar), + + /** + * Returns {@value StateManager#STATE_SAVING_METHOD_PARAM_NAME} as {@link String} with default of {@link StateSavingMethod#CLIENT}.. + * @see StateManager#STATE_SAVING_METHOD_PARAM_NAME + */ + STATE_SAVING_METHOD(StateManager.STATE_SAVING_METHOD_PARAM_NAME, FacesConfig::stateSavingMethod), + + /** + * Returns {@value UIInput#VALIDATE_EMPTY_FIELDS_PARAM_NAME} as {@link String} with default of {@link ValidateEmptyFields#AUTO}. + */ + VALIDATE_EMPTY_FIELDS(UIInput.VALIDATE_EMPTY_FIELDS_PARAM_NAME, FacesConfig::validateEmptyFields), + + /** + * Returns {@value UIViewRoot#VIEWROOT_PHASE_LISTENER_QUEUES_EXCEPTIONS_PARAM_NAME} as {@link Boolean} with default of {@code false}. + */ + VIEWROOT_PHASE_LISTENER_QUEUES_EXCEPTIONS(UIViewRoot.VIEWROOT_PHASE_LISTENER_QUEUES_EXCEPTIONS_PARAM_NAME, FacesConfig::viewrootPhaseListenerQueuesExceptions), + + /** + * Returns {@value ResourceHandler#WEBAPP_CONTRACTS_DIRECTORY_PARAM_NAME} as {@link String} with default of {@value ResourceHandler#WEBAPP_CONTRACTS_DIRECTORY_DEFAULT_VALUE}. + */ + WEBAPP_CONTRACTS_DIRECTORY(ResourceHandler.WEBAPP_CONTRACTS_DIRECTORY_PARAM_NAME, FacesConfig::webappContractsDirectory), + + /** + * Returns {@value ResourceHandler#WEBAPP_RESOURCES_DIRECTORY_PARAM_NAME} as {@link String} with default of {@value ResourceHandler#WEBAPP_RESOURCES_DIRECTORY_DEFAULT_VALUE}. + */ + WEBAPP_RESOURCES_DIRECTORY(ResourceHandler.WEBAPP_RESOURCES_DIRECTORY_PARAM_NAME, FacesConfig::webappResourcesDirectory), + + /** + * Returns {@value PushContext#WEBSOCKET_ENDPOINT_PORT_PARAM_NAME} as {@link Integer} with default of {@code 0} (default 0 means the code will take the port from the request). + */ + WEBSOCKET_ENDPOINT_PORT(PushContext.WEBSOCKET_ENDPOINT_PORT_PARAM_NAME, FacesConfig::websocketEndpointPort), + + ; + + private static final Logger LOGGER = FacesLogger.CONFIG.getLogger(); + private static final Map VALUES = new EnumMap<>(ContextParam.class); + private static final AtomicReference> ANNOTATED_CONFIG = new AtomicReference<>(); + + private enum StringArray { + SPACE_SEPARATED("\\s+"), + SEMICOLON_SEPARATED("\\s*;\\s*"), + COMMA_SEPARATED("\\s*,\\s*"); + + private Pattern pattern; + + private StringArray(String pattern) { + this.pattern = Pattern.compile(pattern); + } + + public String[] split(String value) { + return pattern.split(value); + } + } + + private final String name; + private final Function annotatedValue; + private final Optional> defaultValueSupplier; + private final StringArray separated; + private final Object defaultAnnotatedValue; + private final Class type; + + private ContextParam(String name, Function annotatedValue) { + this(name, annotatedValue, null, null); + } + + private ContextParam(String name, Function annotatedValue, StringArray separated) { + this(name, annotatedValue, null, separated); + } + + private ContextParam(String name, Function annotatedValue, Function defaultValueSupplier) { + this(name, annotatedValue, defaultValueSupplier, null); + } + + private ContextParam(String name, Function annotatedValue, Function defaultValueSupplier, StringArray separated) { + this.name = name; + this.annotatedValue = annotatedValue; + this.defaultValueSupplier = Optional.ofNullable(defaultValueSupplier); + this.separated = separated; + this.defaultAnnotatedValue = annotatedValue.apply(FacesConfig.Literal.INSTANCE); + this.type = defaultAnnotatedValue.getClass(); + } + + /** + *

+ * Returns the name of the context parameter. + * @return The name of the context parameter. + */ + public String getName() { + return name; + } + + /** + *

+ * Returns the expected type of the context parameter value. + * Supported values are: + *

    + *
  • {@link String} + *
  • {@link String}{@code []} + *
  • {@link Character} + *
  • {@link Boolean} + *
  • {@link Integer} + *
  • {@link Enum} + *
+ * @return The expected type of the context parameter value. + */ + public Class getType() { + return type; + } + + /** + *

+ * Returns the value of the context parameter, converted to the expected type as indicated by {@link #getType()}. + * This method never returns {@code null}. When the context parameter is not set, a default value is returned. + *

+ * The implementation must first look for {@link ExternalContext#getInitParameter(String)} . If it is non-{@code null}, then return it. + * Else look for any {@link FacesConfig} annotation. If present, then return it. Else return the default value. + * @param The expected return type. + * @param context The involved faces context. + * @return The value of the context parameter, converted to the expected type as indicated by {@link #getType()}. + * @throws ClassCastException When inferred T is of wrong type. See {@link #getType()} for the correct type. + * @throws IllegalArgumentException When the value of the context parameter cannot be converted to the expected type as indicated by {@link #getType()}. + */ + @SuppressWarnings("unchecked") + public T getValue(FacesContext context) { + return (T) VALUES.computeIfAbsent(this, param -> getContextParamValue(context).orElseGet(() -> getAnnotatedValue(context).orElseGet(() -> getDefaultValue(context)))); + } + + /** + *

+ * Returns {@code true} in case a boolean context parameter is {@code true}, or a non-boolean context parameter is explicitly set with a non-{@code null} value. + * @param context The involved faces context. + * @return {@code true} in case a boolean context parameter is {@code true}, or a non-boolean context parameter is explicitly set with a non-{@code null} value. + * @throws IllegalArgumentException When the value of the context parameter cannot be converted to the expected type as indicated by {@link #getType()}. + */ + public boolean isSet(FacesContext context) { + return (getType() == Boolean.class) ? (boolean) getValue(context) : context.getExternalContext().getInitParameter(name) != null; + } + + /** + *

+ * Returns the default value of the context parameter, converted to the expected type as indicated by {@link #getType()}. + * @param The expected return type. + * @param context The involved faces context. + * @return The default value of the context parameter, converted to the expected type as indicated by {@link #getType()}. + * @throws ClassCastException When inferred T is of wrong type. See {@link #getType()} for the correct type. + */ + @SuppressWarnings("unchecked") + public T getDefaultValue(FacesContext context) { + Object supplied = defaultValueSupplier.map(supplier -> supplier.apply(context)).orElse(null); + return (T) (supplied != null ? supplied : defaultAnnotatedValue); + } + + /** + *

+ * Returns {@code true} when the value of the context parameter equals to the default value, irrespective of whether it is explicitly set. + * @param context The involved faces context. + * @return {@code true} when the value of the context parameter equals to the default value, irrespective of whether it is explicitly set. + * @throws IllegalArgumentException When the value of the context parameter cannot be converted to the expected type as indicated by {@link #getType()}. + */ + public boolean isDefault(FacesContext context) { + return Objects.equals(getValue(context), getDefaultValue(context)); + } + + @SuppressWarnings("unchecked") + private Optional getContextParamValue(FacesContext context) { + String value = context.getExternalContext().getInitParameter(name); + + if (value == null) { + return Optional.empty(); + } + else if (type == String.class) { + return Optional.of((T) value); + } + else if (type == String[].class) { + return Optional.of((T) separated.split(value)); + } + else if (type == Character.class) { + if (value.length() == 1) { + return Optional.of((T) Character.valueOf(value.charAt(0))); + } + } + else if (type == Boolean.class) { + return Optional.of((T) Boolean.valueOf(value)); + } + else if (type == Integer.class) { + try { + return Optional.of((T) Integer.valueOf(value)); + } + catch (NumberFormatException e) { + throw new IllegalArgumentException(getName() + ": invalid value: " + value, e); + } + } + else if (type.isEnum()) { + for (Object constant : type.getEnumConstants()) { + if (constant.toString().equalsIgnoreCase(value)) { + return Optional.of((T) constant); + } + } + } + + throw new IllegalArgumentException(getName() + ": invalid value: " + value); + } + + @SuppressWarnings("unchecked") + private Optional getAnnotatedValue(FacesContext context) { + Optional annotatedConfig = ANNOTATED_CONFIG.updateAndGet(config -> config != null ? config : CdiUtils + .getBeanReferencesByQualifier(context, FacesConfig.Literal.INSTANCE).stream() + .sorted(CdiUtils.BEAN_PRIORITY_COMPARATOR) + .peek(bean -> LOGGER.info("@FacesConfig found on " + bean.getClass() + " -- if any, others are ignored")) + .map(bean -> bean.getClass().getAnnotation(FacesConfig.class)) + .findFirst()); + return annotatedConfig.map(config -> (T) annotatedValue.apply(config)).filter(value -> !shouldDelegateToDefaultValueSupplier(value)); + } + + private boolean shouldDelegateToDefaultValueSupplier(T value) { + return defaultValueSupplier.isPresent() && Objects.equals(value, defaultAnnotatedValue); + } + + } + } From 3144516f2e9ba71ebc187f8884ad75d516b40c69 Mon Sep 17 00:00:00 2001 From: Bauke Scholtz Date: Sat, 28 Oct 2023 08:37:33 -0400 Subject: [PATCH 3/4] Utilize new FacesConfig.ContextParam enum https://github.com/jakartaee/faces/issues/1416 --- .../application/ApplicationAssociate.java | 65 ++++++------------- .../application/JavaFlowLoaderHelper.java | 18 ++--- .../applicationimpl/InstanceFactory.java | 7 +- .../application/applicationimpl/Stage.java | 36 +++------- .../resource/FaceletWebappResourceHelper.java | 8 +-- .../resource/ResourceHandlerImpl.java | 13 ++-- .../resource/WebappResourceHelper.java | 6 +- .../view/FaceletViewHandlingStrategy.java | 45 +++++-------- .../application/view/MultiViewHandler.java | 10 +-- .../ClientWindowScopeContextManager.java | 17 +---- .../sun/faces/config/ConfigureListener.java | 8 +-- .../sun/faces/config/FacesInitializer.java | 16 ++--- .../sun/faces/config/WebConfiguration.java | 62 +----------------- .../BaseWebConfigResourceProvider.java | 31 ++++----- .../WebFaceletTaglibResourceProvider.java | 8 +-- .../WebFacesConfigResourceProvider.java | 9 +-- .../processor/AbstractConfigProcessor.java | 19 +++--- .../processor/ApplicationConfigProcessor.java | 5 +- .../FacesFlowDefinitionConfigProcessor.java | 15 +---- .../com/sun/faces/context/ContextParam.java | 8 +-- .../faces/context/ExternalContextImpl.java | 3 +- .../context/FacesContextFactoryImpl.java | 15 ++--- .../main/java/com/sun/faces/el/ELUtils.java | 5 +- .../impl/FaceletCacheFactoryImpl.java | 8 +-- .../facelets/tag/ui/CompositionHandler.java | 1 + .../facelets/tag/ui/DecorateHandler.java | 1 + .../faces/facelets/tag/ui/IncludeHandler.java | 1 + .../lifecycle/ClientWindowFactoryImpl.java | 12 ++-- .../sun/faces/renderkit/RenderKitUtils.java | 6 +- .../renderkit/ResponseStateManagerImpl.java | 9 +-- .../renderkit/ServerSideStateHelper.java | 6 +- .../jakarta/faces/annotation/FacesConfig.java | 12 ++-- .../faces/application/StateManager.java | 12 +--- .../java/jakarta/faces/component/UIInput.java | 28 ++++---- .../faces/component/UINamingContainer.java | 11 +--- .../jakarta/faces/component/UIWebsocket.java | 6 +- .../validator/MethodExpressionValidator.java | 27 +++++--- 37 files changed, 201 insertions(+), 368 deletions(-) diff --git a/impl/src/main/java/com/sun/faces/application/ApplicationAssociate.java b/impl/src/main/java/com/sun/faces/application/ApplicationAssociate.java index 4bdabc4f1b..c288a4920c 100644 --- a/impl/src/main/java/com/sun/faces/application/ApplicationAssociate.java +++ b/impl/src/main/java/com/sun/faces/application/ApplicationAssociate.java @@ -18,10 +18,6 @@ import static com.sun.faces.RIConstants.FACES_CONFIG_VERSION; import static com.sun.faces.RIConstants.FACES_PREFIX; -import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.AutomaticExtensionlessMapping; -import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.FaceletsSkipComments; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.FaceletsDecorators; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.FaceletsDefaultRefreshPeriod; import static com.sun.faces.el.ELUtils.buildFacesResolver; import static com.sun.faces.el.FacesCompositeELResolver.ELResolverChainType.Faces; import static com.sun.faces.facelets.util.ReflectionUtil.forName; @@ -29,13 +25,10 @@ import static com.sun.faces.util.MessageUtils.getExceptionMessageString; import static com.sun.faces.util.Util.getFacesConfigXmlVersion; import static com.sun.faces.util.Util.getFacesServletRegistration; -import static com.sun.faces.util.Util.split; import static jakarta.faces.FactoryFinder.FACELET_CACHE_FACTORY; import static jakarta.faces.FactoryFinder.FLOW_HANDLER_FACTORY; import static jakarta.faces.application.ProjectStage.Development; -import static jakarta.faces.application.ProjectStage.Production; import static jakarta.faces.application.ViewVisitOption.RETURN_AS_MINIMAL_IMPLICIT_OUTCOME; -import static java.lang.Long.parseLong; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static java.util.logging.Level.FINE; @@ -61,7 +54,6 @@ import com.sun.faces.application.resource.ResourceManager; import com.sun.faces.component.search.SearchExpressionHandlerImpl; import com.sun.faces.config.ConfigManager; -import com.sun.faces.config.WebConfiguration; import com.sun.faces.el.DemuxCompositeELResolver; import com.sun.faces.facelets.compiler.Compiler; import com.sun.faces.facelets.compiler.SAXCompiler; @@ -85,6 +77,7 @@ import jakarta.el.ExpressionFactory; import jakarta.faces.FacesException; import jakarta.faces.FactoryFinder; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.Application; import jakarta.faces.application.NavigationCase; import jakarta.faces.application.ViewHandler; @@ -162,8 +155,6 @@ public class ApplicationAssociate { private final NamedEventManager namedEventManager; - private final WebConfiguration webConfig; - private FlowHandler flowHandler; private SearchExpressionHandler searchExpressionHandler; @@ -245,7 +236,6 @@ public ApplicationAssociate(ApplicationImpl appImpl) { navigationMap = new ConcurrentHashMap<>(); injectionProvider = (InjectionProvider) facesContext.getAttributes().get(ConfigManager.INJECTION_PROVIDER_KEY); - webConfig = WebConfiguration.getInstance(externalContext); annotationManager = new AnnotationManager(); @@ -313,7 +303,7 @@ public void processEvent(SystemEvent event) { String facesConfigVersion = getFacesConfigXmlVersion(context); context.getExternalContext().getApplicationMap().put(FACES_CONFIG_VERSION, facesConfigVersion); - if (webConfig.isOptionEnabled(AutomaticExtensionlessMapping)) { + if (ContextParam.AUTOMATIC_EXTENSIONLESS_MAPPING.isSet(context)) { getFacesServletRegistration(context) .ifPresent(registration -> viewHandler.getViews(context, "/", RETURN_AS_MINIMAL_IMPLICIT_OUTCOME) @@ -331,9 +321,8 @@ public void initializeFacelets() { FacesContext ctx = FacesContext.getCurrentInstance(); - Map appMap = ctx.getExternalContext().getApplicationMap(); - compiler = createCompiler(appMap, webConfig); - faceletFactory = createFaceletFactory(ctx, compiler, webConfig); + compiler = createCompiler(ctx); + faceletFactory = createFaceletFactory(ctx, compiler); } public long getTimeOfInstantiation() { @@ -620,20 +609,10 @@ public void relateUrlToDefiningDocumentInJar(URL url, String definingDocumentId) definingDocumentIdsToTruncatedJarUrls.put(definingDocumentId, candidate); } - protected DefaultFaceletFactory createFaceletFactory(FacesContext context, Compiler compiler, WebConfiguration webConfig) { + protected DefaultFaceletFactory createFaceletFactory(FacesContext context, Compiler compiler) { // refresh period - boolean isProduction = applicationImpl.getProjectStage() == Production; - String refreshPeriod; - if (webConfig.isSet(FaceletsDefaultRefreshPeriod)) { - refreshPeriod = webConfig.getOptionValue(FaceletsDefaultRefreshPeriod); - } else if (isProduction) { - refreshPeriod = "-1"; - } else { - refreshPeriod = FaceletsDefaultRefreshPeriod.getDefaultValue(); - } - - long period = parseLong(refreshPeriod); + int period = ContextParam.FACELETS_REFRESH_PERIOD.getValue(context); // resource resolver DefaultResourceResolver resolver = new DefaultResourceResolver(applicationImpl.getResourceHandler()); @@ -647,35 +626,33 @@ protected DefaultFaceletFactory createFaceletFactory(FacesContext context, Compi return toReturn; } - protected Compiler createCompiler(Map appMap, WebConfiguration webConfig) { + protected Compiler createCompiler(FacesContext context) { Compiler newCompiler = new SAXCompiler(); - loadDecorators(appMap, newCompiler); + loadDecorators(context, newCompiler); // Skip params? - newCompiler.setTrimmingComments(webConfig.isOptionEnabled(FaceletsSkipComments)); + newCompiler.setTrimmingComments(ContextParam.FACELETS_SKIP_COMMENTS.isSet(context)); addTagLibraries(newCompiler); return newCompiler; } - protected void loadDecorators(Map appMap, Compiler newCompiler) { - String decoratorsParamValue = webConfig.getOptionValue(FaceletsDecorators); + protected void loadDecorators(FacesContext context, Compiler newCompiler) { + String[] decorators = ContextParam.FACELETS_DECORATORS.getValue(context); - if (decoratorsParamValue != null) { - for (String decorator : split(appMap, decoratorsParamValue.trim(), ";")) { - try { - newCompiler - .addTagDecorator((TagDecorator) forName(decorator).getDeclaredConstructor().newInstance()); + for (String decorator : decorators) { + try { + newCompiler + .addTagDecorator((TagDecorator) forName(decorator).getDeclaredConstructor().newInstance()); - if (LOGGER.isLoggable(FINE)) { - LOGGER.log(FINE, "Successfully Loaded Decorator: {0}", decorator); - } - } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { - if (LOGGER.isLoggable(SEVERE)) { - LOGGER.log(SEVERE, "Error Loading Decorator: " + decorator, e); - } + if (LOGGER.isLoggable(FINE)) { + LOGGER.log(FINE, "Successfully Loaded Decorator: {0}", decorator); + } + } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { + if (LOGGER.isLoggable(SEVERE)) { + LOGGER.log(SEVERE, "Error Loading Decorator: " + decorator, e); } } } diff --git a/impl/src/main/java/com/sun/faces/application/JavaFlowLoaderHelper.java b/impl/src/main/java/com/sun/faces/application/JavaFlowLoaderHelper.java index 99d95114de..051c06dc88 100644 --- a/impl/src/main/java/com/sun/faces/application/JavaFlowLoaderHelper.java +++ b/impl/src/main/java/com/sun/faces/application/JavaFlowLoaderHelper.java @@ -16,7 +16,6 @@ package com.sun.faces.application; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.ClientWindowMode; import static com.sun.faces.util.Util.getCdiBeanManager; import static java.util.logging.Level.SEVERE; import static java.util.logging.Level.WARNING; @@ -32,12 +31,13 @@ import jakarta.enterprise.inject.spi.BeanManager; import jakarta.enterprise.inject.spi.Producer; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.context.FacesContext; import jakarta.faces.flow.Flow; import jakarta.faces.flow.FlowHandler; import jakarta.faces.flow.builder.FlowDefinition; -class JavaFlowLoaderHelper { +public class JavaFlowLoaderHelper { private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger(); @@ -70,24 +70,26 @@ synchronized void loadFlows(FacesContext context, FlowHandler flowHandler) throw } } - private void enableClientWindowModeIfNecessary(FacesContext context) { - WebConfiguration config = WebConfiguration.getInstance(context.getExternalContext()); - - String optionValue = config.getOptionValue(ClientWindowMode); + public static void enableClientWindowModeIfNecessary(FacesContext context) { + String optionValue = ContextParam.CLIENT_WINDOW_MODE.getValue(context); boolean clientWindowNeedsEnabling = false; if ("none".equals(optionValue)) { clientWindowNeedsEnabling = true; LOGGER.log(WARNING, "{0} was set to none, but Faces Flows requires {0} is enabled. Setting to ''url''.", - new Object[] { ClientWindowMode.getQualifiedName() }); + new Object[] { ContextParam.CLIENT_WINDOW_MODE.getName() }); } else if (optionValue == null) { clientWindowNeedsEnabling = true; } if (clientWindowNeedsEnabling) { - config.setOptionValue(ClientWindowMode, "url"); + context.getExternalContext().getApplicationMap().put(JavaFlowLoaderHelper.class.getName(), Boolean.TRUE); } } + + public static boolean isClientWindowModeForciblyEnabled(FacesContext context) { + return context.getExternalContext().getApplicationMap().get(JavaFlowLoaderHelper.class.getName()) == Boolean.TRUE; + } } diff --git a/impl/src/main/java/com/sun/faces/application/applicationimpl/InstanceFactory.java b/impl/src/main/java/com/sun/faces/application/applicationimpl/InstanceFactory.java index 2c6e702683..50458c1038 100644 --- a/impl/src/main/java/com/sun/faces/application/applicationimpl/InstanceFactory.java +++ b/impl/src/main/java/com/sun/faces/application/applicationimpl/InstanceFactory.java @@ -17,7 +17,6 @@ package com.sun.faces.application.applicationimpl; import static com.sun.faces.application.ApplicationImpl.THIS_LIBRARY; -import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.DateTimeConverterUsesSystemTimezone; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.RegisterConverterPropertyEditors; import static com.sun.faces.util.Util.isEmpty; import static com.sun.faces.util.Util.loadClass; @@ -71,6 +70,7 @@ import jakarta.el.ValueExpression; import jakarta.enterprise.inject.spi.BeanManager; import jakarta.faces.FacesException; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.Application; import jakarta.faces.application.Resource; import jakarta.faces.component.UIComponent; @@ -155,10 +155,11 @@ public InstanceFactory(ApplicationAssociate applicationAssociate) { defaultValidatorIds = new LinkedHashSet<>(); behaviorMap = new ViewMemberInstanceFactoryMetadataMap<>(new ConcurrentHashMap<>()); - WebConfiguration webConfig = WebConfiguration.getInstance(FacesContext.getCurrentInstance().getExternalContext()); + FacesContext context = FacesContext.getCurrentInstance(); + WebConfiguration webConfig = WebConfiguration.getInstance(context.getExternalContext()); registerPropertyEditors = webConfig.isOptionEnabled(RegisterConverterPropertyEditors); - passDefaultTimeZone = webConfig.isOptionEnabled(DateTimeConverterUsesSystemTimezone); + passDefaultTimeZone = ContextParam.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE.getValue(context); if (passDefaultTimeZone) { systemTimeZone = TimeZone.getDefault(); } diff --git a/impl/src/main/java/com/sun/faces/application/applicationimpl/Stage.java b/impl/src/main/java/com/sun/faces/application/applicationimpl/Stage.java index 8859d0a9ab..2a51e45cb8 100644 --- a/impl/src/main/java/com/sun/faces/application/applicationimpl/Stage.java +++ b/impl/src/main/java/com/sun/faces/application/applicationimpl/Stage.java @@ -16,11 +16,8 @@ package com.sun.faces.application.applicationimpl; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.JakartaFacesProjectStage; import static jakarta.faces.application.ProjectStage.Development; -import static jakarta.faces.application.ProjectStage.Production; import static java.util.logging.Level.FINE; -import static java.util.logging.Level.INFO; import java.util.logging.Logger; @@ -28,6 +25,7 @@ import com.sun.faces.config.WebConfiguration; import com.sun.faces.util.FacesLogger; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.Application; import jakarta.faces.application.ProjectStage; import jakarta.faces.context.FacesContext; @@ -45,9 +43,7 @@ public class Stage { public ProjectStage getProjectStage(Application application) { if (projectStage == null) { - String value = fetchProjectStageFromConfig(); - - setProjectStageFromValue(value, Production); + projectStage = fetchProjectStageFromConfig(); if (projectStage == Development) { application.subscribeToEvent(PostAddToViewEvent.class, new ValidateComponentNesting()); @@ -59,38 +55,24 @@ public ProjectStage getProjectStage(Application application) { // ----------------------------------------------------------- Private methods - private String fetchProjectStageFromConfig() { - WebConfiguration webConfig = WebConfiguration.getInstance(FacesContext.getCurrentInstance().getExternalContext()); + private ProjectStage fetchProjectStageFromConfig() { + FacesContext context = FacesContext.getCurrentInstance(); + WebConfiguration webConfig = WebConfiguration.getInstance(context.getExternalContext()); String value = webConfig.getEnvironmentEntry(WebConfiguration.WebEnvironmentEntry.ProjectStage); if (value != null) { + projectStage = ProjectStage.valueOf(value); if (LOGGER.isLoggable(FINE)) { LOGGER.log(FINE, "ProjectStage configured via JNDI: {0}", value); } } else { - value = webConfig.getOptionValue(JakartaFacesProjectStage); - if (value != null && LOGGER.isLoggable(FINE)) { + projectStage = ContextParam.PROJECT_STAGE.getValue(context); + if (LOGGER.isLoggable(FINE)) { LOGGER.log(FINE, "ProjectStage configured via servlet context init parameter: {0}", value); } } - return value; - } - - private void setProjectStageFromValue(String value, ProjectStage defaultStage) { - if (value != null) { - try { - projectStage = ProjectStage.valueOf(value); - } catch (IllegalArgumentException iae) { - if (LOGGER.isLoggable(INFO)) { - LOGGER.log(INFO, "Unable to discern ProjectStage for value {0}.", value); - } - } - } - - if (projectStage == null) { - projectStage = defaultStage; - } + return projectStage; } } diff --git a/impl/src/main/java/com/sun/faces/application/resource/FaceletWebappResourceHelper.java b/impl/src/main/java/com/sun/faces/application/resource/FaceletWebappResourceHelper.java index 2d5508650e..b849c27513 100644 --- a/impl/src/main/java/com/sun/faces/application/resource/FaceletWebappResourceHelper.java +++ b/impl/src/main/java/com/sun/faces/application/resource/FaceletWebappResourceHelper.java @@ -18,7 +18,7 @@ import static com.sun.faces.RIConstants.FLOW_IN_JAR_PREFIX; import static com.sun.faces.config.WebConfiguration.META_INF_CONTRACTS_DIR; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.FaceletsSuffix; +import static com.sun.faces.util.Util.ensureLeadingSlash; import static jakarta.faces.application.ResourceVisitOption.TOP_LEVEL_VIEWS_ONLY; import static java.util.Spliterator.DISTINCT; import static java.util.Spliterators.spliteratorUnknownSize; @@ -34,10 +34,10 @@ import java.util.stream.Stream; import com.sun.faces.application.ApplicationAssociate; -import com.sun.faces.config.WebConfiguration; import com.sun.faces.util.Util; import jakarta.faces.FacesException; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.ResourceVisitOption; import jakarta.faces.context.ExternalContext; import jakarta.faces.context.FacesContext; @@ -52,8 +52,8 @@ public class FaceletWebappResourceHelper extends ResourceHelper { public FaceletWebappResourceHelper(WebappResourceHelper webappResourceHelper) { this.webappResourceHelper = webappResourceHelper; - WebConfiguration webConfig = WebConfiguration.getInstance(); - configuredExtensions = webConfig.getOptionValue(FaceletsSuffix, " "); + FacesContext context = FacesContext.getCurrentInstance(); + configuredExtensions = new String[] { ContextParam.FACELETS_SUFFIX.getValue(context) }; } @Override diff --git a/impl/src/main/java/com/sun/faces/application/resource/ResourceHandlerImpl.java b/impl/src/main/java/com/sun/faces/application/resource/ResourceHandlerImpl.java index be648e5744..fac6fc149f 100644 --- a/impl/src/main/java/com/sun/faces/application/resource/ResourceHandlerImpl.java +++ b/impl/src/main/java/com/sun/faces/application/resource/ResourceHandlerImpl.java @@ -18,7 +18,6 @@ import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.DefaultResourceMaxAge; import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.ResourceBufferSize; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.ResourceExcludes; import static com.sun.faces.util.RequestStateManager.RESOURCE_REQUEST; import static com.sun.faces.util.Util.getFacesMapping; import static com.sun.faces.util.Util.notNegative; @@ -50,8 +49,8 @@ import com.sun.faces.config.WebConfiguration; import com.sun.faces.util.FacesLogger; import com.sun.faces.util.RequestStateManager; -import com.sun.faces.util.Util; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.Resource; import jakarta.faces.application.ResourceHandler; import jakarta.faces.application.ResourceVisitOption; @@ -80,9 +79,10 @@ public class ResourceHandlerImpl extends ResourceHandler { public ResourceHandlerImpl() { creationTime = System.currentTimeMillis(); webconfig = WebConfiguration.getInstance(); - ExternalContext extContext = FacesContext.getCurrentInstance().getExternalContext(); + FacesContext context = FacesContext.getCurrentInstance(); + ExternalContext extContext = context.getExternalContext(); manager = ApplicationAssociate.getInstance(extContext).getResourceManager(); - initExclusions(extContext.getApplicationMap()); + initExclusions(context); initMaxAge(); } @@ -554,9 +554,8 @@ private boolean isExcluded(String resourceId) { *

    * will be used. */ - private void initExclusions(Map appMap) { - String excludesParam = webconfig.getOptionValue(ResourceExcludes); - String[] patterns = Util.split(appMap, excludesParam, " "); + private void initExclusions(FacesContext context) { + String[] patterns = ContextParam.RESOURCE_EXCLUDES.getValue(context); excludePatterns = new ArrayList<>(patterns.length); for (String pattern : patterns) { diff --git a/impl/src/main/java/com/sun/faces/application/resource/WebappResourceHelper.java b/impl/src/main/java/com/sun/faces/application/resource/WebappResourceHelper.java index 702b42ddbb..965cb61c0e 100644 --- a/impl/src/main/java/com/sun/faces/application/resource/WebappResourceHelper.java +++ b/impl/src/main/java/com/sun/faces/application/resource/WebappResourceHelper.java @@ -34,6 +34,7 @@ import com.sun.faces.util.FacesLogger; import jakarta.faces.FacesException; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.ProjectStage; import jakarta.faces.component.UIViewRoot; import jakarta.faces.context.FacesContext; @@ -61,9 +62,10 @@ public class WebappResourceHelper extends ResourceHelper { public WebappResourceHelper() { WebConfiguration webconfig = WebConfiguration.getInstance(); + FacesContext context = FacesContext.getCurrentInstance(); cacheTimestamp = webconfig.isOptionEnabled(CacheResourceModificationTimestamp); - BASE_RESOURCE_PATH = ensureLeadingSlash(webconfig.getOptionValue(WebConfiguration.WebContextInitParameter.WebAppResourcesDirectory)); - BASE_CONTRACTS_PATH = ensureLeadingSlash(webconfig.getOptionValue(WebConfiguration.WebContextInitParameter.WebAppContractsDirectory)); + BASE_RESOURCE_PATH = ensureLeadingSlash(ContextParam.WEBAPP_RESOURCES_DIRECTORY.getValue(context)); + BASE_CONTRACTS_PATH = ensureLeadingSlash(ContextParam.WEBAPP_CONTRACTS_DIRECTORY.getValue(context)); } diff --git a/impl/src/main/java/com/sun/faces/application/view/FaceletViewHandlingStrategy.java b/impl/src/main/java/com/sun/faces/application/view/FaceletViewHandlingStrategy.java index c4154ed06a..5fbe1beb5c 100644 --- a/impl/src/main/java/com/sun/faces/application/view/FaceletViewHandlingStrategy.java +++ b/impl/src/main/java/com/sun/faces/application/view/FaceletViewHandlingStrategy.java @@ -19,8 +19,6 @@ import static com.sun.faces.RIConstants.DYNAMIC_COMPONENT; import static com.sun.faces.RIConstants.FACELETS_ENCODING_KEY; import static com.sun.faces.RIConstants.FLOW_DEFINITION_ID_SUFFIX; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.FaceletsBufferSize; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.FaceletsViewMappings; import static com.sun.faces.context.StateContext.getStateContext; import static com.sun.faces.facelets.tag.ui.UIDebug.debugRequest; import static com.sun.faces.renderkit.RenderKitUtils.getResponseStateManager; @@ -36,7 +34,6 @@ import static com.sun.faces.util.Util.saveDOCTYPEToFacesContextAttributes; import static com.sun.faces.util.Util.saveXMLDECLToFacesContextAttributes; import static com.sun.faces.util.Util.setViewPopulated; -import static com.sun.faces.util.Util.split; import static jakarta.faces.FactoryFinder.VIEW_DECLARATION_LANGUAGE_FACTORY; import static jakarta.faces.application.ProjectStage.Development; import static jakarta.faces.application.Resource.COMPONENT_RESOURCE_KEY; @@ -77,8 +74,6 @@ import java.util.stream.Stream; import com.sun.faces.application.ApplicationAssociate; -import com.sun.faces.config.WebConfiguration; -import com.sun.faces.config.WebConfiguration.WebContextInitParameter; import com.sun.faces.context.StateContext; import com.sun.faces.facelets.compiler.FaceletDoctype; import com.sun.faces.facelets.el.ContextualCompositeMethodExpression; @@ -104,6 +99,7 @@ import jakarta.el.VariableMapper; import jakarta.faces.FacesException; import jakarta.faces.FactoryFinder; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.Resource; import jakarta.faces.application.StateManager.StateSavingMethod; import jakarta.faces.application.ViewHandler; @@ -411,7 +407,7 @@ public void renderView(FacesContext ctx, UIViewRoot viewToRender) throws IOExcep } // If the buffer size is -1, use the default buffer size - final int bufferSize = responseBufferSize != -1 ? responseBufferSize : Integer.parseInt(FaceletsBufferSize.getDefaultValue()); + final int bufferSize = responseBufferSize != -1 ? responseBufferSize : ViewHandler.FACELETS_BUFFER_SIZE_DEFAULT_VALUE; stateWriter = new WriteBehindStateWriter(extContext.getResponseOutputWriter(), ctx, bufferSize); ResponseWriter writer = origWriter.cloneWithWriter(stateWriter); @@ -777,8 +773,8 @@ public Stream getViews(FacesContext context, String path, int maxDepth, * @return true if assuming a default configuration and the view ID's extension in {@link ViewHandler#FACELETS_SUFFIX_PARAM_NAME} * Otherwise try to match the view ID based on the configured extensions and prefixes in {@link ViewHandler#FACELETS_VIEW_MAPPINGS_PARAM_NAME} * - * @see com.sun.faces.config.WebConfiguration.WebContextInitParameter#FaceletsSuffix - * @see com.sun.faces.config.WebConfiguration.WebContextInitParameter#FaceletsViewMappings + * @see ContextParam#FACELETS_SUFFIX + * @see ContextParam#FACELETS_VIEW_MAPPINGS */ @Override public boolean handlesViewId(String viewId) { @@ -818,11 +814,7 @@ protected void initialize() { return FaceletViewHandlingStrategy.this.createComponentMetadata(context, ccResource); }); - try { - responseBufferSize = Integer.parseInt(webConfig.getOptionValue(FaceletsBufferSize)); - } catch (NumberFormatException nfe) { - responseBufferSize = Integer.parseInt(FaceletsBufferSize.getDefaultValue()); - } + responseBufferSize = ContextParam.FACELETS_BUFFER_SIZE.getValue(FacesContext.getCurrentInstance()); LOGGER.fine("Initialization Successful"); @@ -849,12 +841,9 @@ protected void initialize() { * Initialize mappings, during the first request. */ protected void initializeMappings() { - String viewMappings = webConfig.getOptionValue(FaceletsViewMappings); - if (viewMappings != null && viewMappings.length() > 0) { - Map appMap = FacesContext.getCurrentInstance().getExternalContext().getApplicationMap(); - - String[] mappingsArray = split(appMap, viewMappings, ";"); - + FacesContext context = FacesContext.getCurrentInstance(); + String[] mappingsArray = ContextParam.FACELETS_VIEW_MAPPINGS.getValue(context); + if (mappingsArray.length > 0) { List extensionsList = new ArrayList<>(mappingsArray.length); List prefixesList = new ArrayList<>(mappingsArray.length); @@ -1854,7 +1843,7 @@ private void reapplyDynamicRemove(FacesContext context, ComponentStruct struct) * @return true if we are, false otherwise. */ private boolean isServerStateSaving() { - if (StateSavingMethod.SERVER.name().equalsIgnoreCase(webConfig.getOptionValue(WebContextInitParameter.StateSavingMethod))) { + if (StateSavingMethod.SERVER == ContextParam.STATE_SAVING_METHOD.getValue(FacesContext.getCurrentInstance())) { return true; } @@ -1891,22 +1880,18 @@ private DefaultFaceletFactory getFaceletFactory() { } private boolean isMatchedWithFaceletsSuffix(String viewId) { - String[] defaultsuffixes = webConfig.getOptionValue(WebConfiguration.WebContextInitParameter.FaceletsSuffix, " "); - for (String suffix : defaultsuffixes) { - if (viewId.endsWith(suffix)) { - return true; - } + String suffix = ContextParam.FACELETS_SUFFIX.getValue(FacesContext.getCurrentInstance()); + if (viewId.endsWith(suffix)) { + return true; } return false; } private String getMatchedWithFaceletsSuffix(String viewId) { - String[] defaultsuffixes = webConfig.getOptionValue(WebConfiguration.WebContextInitParameter.FaceletsSuffix, " "); - for (String suffix : defaultsuffixes) { - if (viewId.endsWith(suffix)) { - return suffix; - } + String suffix = ContextParam.FACELETS_SUFFIX.getValue(FacesContext.getCurrentInstance()); + if (viewId.endsWith(suffix)) { + return suffix; } return null; diff --git a/impl/src/main/java/com/sun/faces/application/view/MultiViewHandler.java b/impl/src/main/java/com/sun/faces/application/view/MultiViewHandler.java index 9fa2bcca7f..50e28a16f7 100644 --- a/impl/src/main/java/com/sun/faces/application/view/MultiViewHandler.java +++ b/impl/src/main/java/com/sun/faces/application/view/MultiViewHandler.java @@ -19,8 +19,8 @@ import static com.sun.faces.RIConstants.FACELETS_ENCODING_KEY; import static com.sun.faces.RIConstants.SAVESTATE_FIELD_MARKER; -import static com.sun.faces.renderkit.RenderKitUtils.PredefinedPostbackParameter.RENDER_KIT_ID_PARAM; import static com.sun.faces.renderkit.RenderKitUtils.getResponseStateManager; +import static com.sun.faces.renderkit.RenderKitUtils.PredefinedPostbackParameter.RENDER_KIT_ID_PARAM; import static com.sun.faces.util.MessageUtils.ILLEGAL_VIEW_ID_ID; import static com.sun.faces.util.MessageUtils.getExceptionMessageString; import static com.sun.faces.util.Util.getFacesMapping; @@ -36,6 +36,7 @@ import static jakarta.servlet.http.MappingMatch.EXTENSION; import static jakarta.servlet.http.MappingMatch.PATH; import static java.text.MessageFormat.format; +import static java.util.Arrays.asList; import static java.util.Collections.unmodifiableSet; import static java.util.Objects.requireNonNull; import static java.util.logging.Level.FINE; @@ -59,12 +60,12 @@ import java.util.logging.Logger; import java.util.stream.Stream; -import com.sun.faces.config.WebConfiguration; import com.sun.faces.util.FacesLogger; import com.sun.faces.util.Util; import jakarta.faces.FacesException; import jakarta.faces.FactoryFinder; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.ViewHandler; import jakarta.faces.application.ViewVisitOption; import jakarta.faces.component.UIViewParameter; @@ -93,9 +94,8 @@ public class MultiViewHandler extends ViewHandler { // ------------------------------------------------------------ Constructors public MultiViewHandler() { - WebConfiguration config = WebConfiguration.getInstance(); - - configuredExtensions = config.getConfiguredExtensions(); + String faceletsSuffix = ContextParam.FACELETS_SUFFIX.getValue(FacesContext.getCurrentInstance()); + configuredExtensions = asList(faceletsSuffix); vdlFactory = (ViewDeclarationLanguageFactory) FactoryFinder.getFactory(VIEW_DECLARATION_LANGUAGE_FACTORY); protectedViews = new CopyOnWriteArraySet<>(); } diff --git a/impl/src/main/java/com/sun/faces/cdi/clientwindow/ClientWindowScopeContextManager.java b/impl/src/main/java/com/sun/faces/cdi/clientwindow/ClientWindowScopeContextManager.java index 5a2a9d4c90..b92ad221c3 100644 --- a/impl/src/main/java/com/sun/faces/cdi/clientwindow/ClientWindowScopeContextManager.java +++ b/impl/src/main/java/com/sun/faces/cdi/clientwindow/ClientWindowScopeContextManager.java @@ -18,13 +18,11 @@ package com.sun.faces.cdi.clientwindow; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableDistributable; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.NumberOfClientWindows; import static java.util.logging.Level.FINEST; import java.util.Collections; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Level; import java.util.logging.Logger; import com.sun.faces.config.WebConfiguration; @@ -34,6 +32,7 @@ import jakarta.enterprise.context.spi.Contextual; import jakarta.enterprise.context.spi.CreationalContext; import jakarta.enterprise.inject.spi.PassivationCapable; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.context.ExternalContext; import jakarta.faces.context.FacesContext; import jakarta.servlet.http.HttpSession; @@ -143,19 +142,7 @@ private Map getContextMap(FacesContext f String clientWindowId = getCurrentClientWindowId(facesContext); if (clientWindowScopeContexts == null && create) { - Integer numberOfClientWindows = null; - - try { - numberOfClientWindows = Integer.parseInt(WebConfiguration.getInstance(externalContext).getOptionValue(NumberOfClientWindows)); - } catch (NumberFormatException nfe) { - if (LOGGER.isLoggable(Level.WARNING)) { - LOGGER.log(Level.WARNING, "Unable to set number of client windows. Defaulting to {0}", NumberOfClientWindows.getDefaultValue()); - } - } - - if (numberOfClientWindows == null) { - numberOfClientWindows = Integer.valueOf(NumberOfClientWindows.getDefaultValue()); - } + int numberOfClientWindows = ContextParam.NUMBER_OF_CLIENT_WINDOWS.getValue(facesContext); synchronized (session) { sessionMap.put(CLIENT_WINDOW_CONTEXTS, Collections.synchronizedMap(new LRUMap(numberOfClientWindows))); diff --git a/impl/src/main/java/com/sun/faces/config/ConfigureListener.java b/impl/src/main/java/com/sun/faces/config/ConfigureListener.java index 1fcd3e56ef..81cf4019ad 100644 --- a/impl/src/main/java/com/sun/faces/config/ConfigureListener.java +++ b/impl/src/main/java/com/sun/faces/config/ConfigureListener.java @@ -23,10 +23,8 @@ import static com.sun.faces.config.InitFacesContext.getInitContextServletContextMap; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableLazyBeanValidation; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableThreading; -import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableWebsocketEndpoint; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.ForceLoadFacesConfigFiles; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.VerifyFacesConfigObjects; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.JakartaFacesProjectStage; import static com.sun.faces.push.WebsocketEndpoint.URI_TEMPLATE; import static java.lang.Boolean.TRUE; import static java.text.MessageFormat.format; @@ -73,7 +71,9 @@ import jakarta.el.ELManager; import jakarta.faces.FactoryFinder; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.Application; +import jakarta.faces.application.ProjectStage; import jakarta.faces.context.FacesContext; import jakarta.faces.event.PreDestroyApplicationEvent; import jakarta.servlet.ServletContext; @@ -212,7 +212,7 @@ public void contextInitialized(ServletContextEvent servletContextEvent) { // Register websocket endpoint if explicitly enabled. // Note: websocket channel filter is registered in FacesInitializer. - if (webConfig.isOptionEnabled(EnableWebsocketEndpoint)) { + if (ContextParam.ENABLE_WEBSOCKET_ENDPOINT.isSet(initFacesContext)) { ServerContainer serverContainer = (ServerContainer) servletContext.getAttribute(ServerContainer.class.getName()); if (serverContainer == null) { @@ -390,7 +390,7 @@ private void initConfigMonitoring(ServletContext context) { private boolean isDevModeEnabled() { // interrogate the init parameter directly vs looking up the application - return "Development".equals(webConfig.getOptionValue(JakartaFacesProjectStage)); + return ContextParam.PROJECT_STAGE.getValue(FacesContext.getCurrentInstance()) == ProjectStage.Development; } /** diff --git a/impl/src/main/java/com/sun/faces/config/FacesInitializer.java b/impl/src/main/java/com/sun/faces/config/FacesInitializer.java index c01c0aa277..5d874a0623 100644 --- a/impl/src/main/java/com/sun/faces/config/FacesInitializer.java +++ b/impl/src/main/java/com/sun/faces/config/FacesInitializer.java @@ -21,7 +21,6 @@ import static com.sun.faces.RIConstants.FACES_SERVLET_MAPPINGS; import static com.sun.faces.RIConstants.FACES_SERVLET_REGISTRATION; import static com.sun.faces.util.Util.isEmpty; -import static java.lang.Boolean.parseBoolean; import static java.util.logging.Level.WARNING; import java.util.HashSet; @@ -33,11 +32,13 @@ import jakarta.enterprise.inject.spi.BeanManager; import jakarta.faces.annotation.FacesConfig; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.ResourceDependencies; import jakarta.faces.application.ResourceDependency; import jakarta.faces.component.FacesComponent; import jakarta.faces.component.UIComponent; import jakarta.faces.component.behavior.FacesBehavior; +import jakarta.faces.context.FacesContext; import jakarta.faces.convert.Converter; import jakarta.faces.convert.FacesConverter; import jakarta.faces.event.ListenerFor; @@ -51,7 +52,6 @@ import jakarta.faces.model.DataModel; import jakarta.faces.model.FacesDataModel; import jakarta.faces.push.Push; -import jakarta.faces.push.PushContext; import jakarta.faces.render.FacesBehaviorRenderer; import jakarta.faces.render.FacesRenderer; import jakarta.faces.render.Renderer; @@ -115,12 +115,12 @@ public void onStartup(Set> classes, ServletContext servletContext) thro try { if (appHasFacesContent) { // Only look at mapping concerns if there is Faces content - handleMappingConcerns(servletContext); + handleMappingConcerns(servletContext, initFacesContext); } // Other concerns also handled if there is an existing Faces Servlet mapping handleCdiConcerns(servletContext); - handleWebSocketConcerns(servletContext); + handleWebSocketConcerns(servletContext, initFacesContext); // The Configure listener will do the bulk of initializing (configuring) Faces in a later phase. servletContext.addListener(ConfigureListener.class); @@ -190,7 +190,7 @@ private static ServletRegistration getExistingFacesServletRegistration(ServletCo return null; } - private static void handleMappingConcerns(ServletContext servletContext) throws ServletException { + private static void handleMappingConcerns(ServletContext servletContext, FacesContext facesContext) throws ServletException { ServletRegistration existingFacesServletRegistration = getExistingFacesServletRegistration(servletContext); if (existingFacesServletRegistration != null) { @@ -201,7 +201,7 @@ private static void handleMappingConcerns(ServletContext servletContext) throws ServletRegistration newFacesServletRegistration = servletContext.addServlet(FacesServlet.class.getSimpleName(), FACES_SERVLET_CLASS_NAME); - if (parseBoolean(servletContext.getInitParameter(FacesServlet.DISABLE_FACESSERVLET_TO_XHTML_PARAM_NAME))) { + if (ContextParam.DISABLE_FACESSERVLET_TO_XHTML.isSet(facesContext)) { newFacesServletRegistration.addMapping(FACES_SERVLET_MAPPINGS_WITHOUT_XHTML); } else { @@ -247,13 +247,13 @@ private static void handleCdiConcerns(ServletContext context) throws ServletExce } } - private static void handleWebSocketConcerns(ServletContext context) throws ServletException { + private static void handleWebSocketConcerns(ServletContext context, FacesContext facesContext) throws ServletException { if (context.getAttribute(ServerContainer.class.getName()) != null) { // Already initialized return; } - if (!parseBoolean(context.getInitParameter(PushContext.ENABLE_WEBSOCKET_ENDPOINT_PARAM_NAME))) { + if (!ContextParam.ENABLE_WEBSOCKET_ENDPOINT.isSet(facesContext)) { // Register websocket endpoint is not enabled return; } diff --git a/impl/src/main/java/com/sun/faces/config/WebConfiguration.java b/impl/src/main/java/com/sun/faces/config/WebConfiguration.java index 28c3aa4c65..46b2fd3903 100644 --- a/impl/src/main/java/com/sun/faces/config/WebConfiguration.java +++ b/impl/src/main/java/com/sun/faces/config/WebConfiguration.java @@ -17,9 +17,7 @@ package com.sun.faces.config; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.FaceletsSuffix; import static com.sun.faces.util.Util.split; -import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; import static java.util.logging.Level.FINE; import static java.util.regex.Pattern.CASE_INSENSITIVE; @@ -33,7 +31,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -54,22 +51,13 @@ import com.sun.faces.util.Util; import jakarta.faces.FactoryFinder; -import jakarta.faces.application.ProjectStage; import jakarta.faces.application.ResourceHandler; import jakarta.faces.application.StateManager; -import jakarta.faces.application.ViewHandler; -import jakarta.faces.component.UIInput; -import jakarta.faces.component.UIViewRoot; import jakarta.faces.context.ExternalContext; import jakarta.faces.context.FacesContext; -import jakarta.faces.convert.Converter; import jakarta.faces.event.PhaseListener; -import jakarta.faces.lifecycle.ClientWindow; import jakarta.faces.lifecycle.Lifecycle; import jakarta.faces.lifecycle.LifecycleFactory; -import jakarta.faces.push.PushContext; -import jakarta.faces.validator.BeanValidator; -import jakarta.faces.webapp.FacesServlet; import jakarta.servlet.ServletContext; /** @@ -86,7 +74,7 @@ public class WebConfiguration { // Key under which we store our WebConfiguration instance. private static final String WEB_CONFIG_KEY = "com.sun.faces.config.WebConfiguration"; - public static final String META_INF_CONTRACTS_DIR = "META-INF" + WebContextInitParameter.WebAppContractsDirectory.getDefaultValue(); + public static final String META_INF_CONTRACTS_DIR = "META-INF" + ResourceHandler.WEBAPP_CONTRACTS_DIRECTORY_DEFAULT_VALUE; private static final int META_INF_CONTRACTS_DIR_LEN = META_INF_CONTRACTS_DIR.length(); @@ -103,7 +91,7 @@ public class WebConfiguration { private final Map envEntries = new EnumMap<>(WebEnvironmentEntry.class); - private final Map cachedListParams; + private final Map cachedListParams = new HashMap<>(); private final Set setParams = new HashSet<>(); @@ -130,12 +118,6 @@ private WebConfiguration(ServletContext servletContext) { if (canProcessJndiEntries()) { processJndiEntries(contextName); } - - // build the cache of list type params - cachedListParams = new HashMap<>(3); - getOptionValue(WebContextInitParameter.ResourceExcludes, " "); - getOptionValue(WebContextInitParameter.FaceletsViewMappings, ";"); - getOptionValue(WebContextInitParameter.FaceletsSuffix, " "); specificationVersion = getClass().getPackage().getSpecificationVersion(); } @@ -330,17 +312,6 @@ public void overrideContextInitParameter(BooleanWebContextInitParameter param, b } - /** - * @return the facelet suffixes. - */ - public List getConfiguredExtensions() { - String[] faceletsSuffix = getOptionValue(FaceletsSuffix, " "); - - Set deduplicatedFaceletsSuffixes = new LinkedHashSet<>(asList(faceletsSuffix)); - - return new ArrayList<>(deduplicatedFaceletsSuffixes); - } - public void overrideContextInitParameter(WebContextInitParameter param, String value) { if (param == null || value == null || value.length() == 0) { return; @@ -748,13 +719,6 @@ public enum WebContextInitParameter { // if a parameter is to be deprecated, then the Deprecated enum element *must* appear after the one that is taking // its place. The reporting logic depends on this. - StateSavingMethod(StateManager.STATE_SAVING_METHOD_PARAM_NAME, "server"), - FaceletsSuffix(ViewHandler.FACELETS_SUFFIX_PARAM_NAME, ViewHandler.DEFAULT_FACELETS_SUFFIX), - JakartaFacesConfigFiles(FacesServlet.CONFIG_FILES_ATTR, ""), - JakartaFacesProjectStage(ProjectStage.PROJECT_STAGE_PARAM_NAME, "Production"), - AlternateLifecycleId(FacesServlet.LIFECYCLE_ID_ATTR, ""), - ResourceExcludes(ResourceHandler.RESOURCE_EXCLUDES_PARAM_NAME, ResourceHandler.RESOURCE_EXCLUDES_DEFAULT_VALUE), - NumberOfClientWindows(ClientWindow.NUMBER_OF_CLIENT_WINDOWS_PARAM_NAME, "10"), NumberOfViews("com.sun.faces.numberOfViewsInSession", "15"), NumberOfLogicalViews("com.sun.faces.numberOfLogicalViews", "15"), NumberOfActiveViewMaps("com.sun.faces.numberOfActiveViewMaps", "25"), @@ -762,7 +726,6 @@ public enum WebContextInitParameter { NumberOfFlashesBetweenFlashReapings("com.sun.faces.numberOfFlashesBetweenFlashReapings", "5000"), InjectionProviderClass("com.sun.faces.injectionProvider", ""), SerializationProviderClass("com.sun.faces.serializationProvider", ""), - FaceletsBufferSize(ViewHandler.FACELETS_BUFFER_SIZE_PARAM_NAME, "1024"), ClientStateWriteBufferSize("com.sun.faces.clientStateWriteBufferSize", "8192"), ResourceBufferSize("com.sun.faces.resourceBufferSize", "2048"), ClientStateTimeout("com.sun.faces.clientStateTimeout", ""), @@ -770,18 +733,10 @@ public enum WebContextInitParameter { ResourceUpdateCheckPeriod("com.sun.faces.resourceUpdateCheckPeriod", "5"), // in minutes CompressableMimeTypes("com.sun.faces.compressableMimeTypes", ""), DisableUnicodeEscaping("com.sun.faces.disableUnicodeEscaping", "auto"), - FaceletsDefaultRefreshPeriod(ViewHandler.FACELETS_REFRESH_PERIOD_PARAM_NAME, "0"), // this is default for non-prod; default for prod is set in WebConfiguration - FaceletsViewMappings(ViewHandler.FACELETS_VIEW_MAPPINGS_PARAM_NAME, ""), - FaceletsLibraries(ViewHandler.FACELETS_LIBRARIES_PARAM_NAME, ""), - FaceletsDecorators(ViewHandler.FACELETS_DECORATORS_PARAM_NAME, ""), DuplicateJARPattern("com.sun.faces.duplicateJARPattern", ""), - ValidateEmptyFields(UIInput.VALIDATE_EMPTY_FIELDS_PARAM_NAME, "auto"), FullStateSavingViewIds(StateManager.FULL_STATE_SAVING_VIEW_IDS_PARAM_NAME, ""), AnnotationScanPackages("com.sun.faces.annotationScanPackages", ""), FaceletsProcessingFileExtensionProcessAs("", ""), - ClientWindowMode(ClientWindow.CLIENT_WINDOW_MODE_PARAM_NAME, "none"), - WebAppResourcesDirectory(ResourceHandler.WEBAPP_RESOURCES_DIRECTORY_PARAM_NAME, "/resources"), - WebAppContractsDirectory(ResourceHandler.WEBAPP_CONTRACTS_DIRECTORY_PARAM_NAME, "/contracts"), ; private final String defaultValue; @@ -847,14 +802,11 @@ public enum BooleanWebContextInitParameter { // *must* appear after the one that is taking // its place. The reporting logic depends on this - AlwaysPerformValidationWhenRequiredTrue(UIInput.ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE, false), DisplayConfiguration("com.sun.faces.displayConfiguration", false), ValidateFacesConfigFiles("com.sun.faces.validateXml", false), VerifyFacesConfigObjects("com.sun.faces.verifyObjects", false), ForceLoadFacesConfigFiles("com.sun.faces.forceLoadConfiguration", false), DisableClientStateEncryption("com.sun.faces.disableClientStateEncryption", false), - DisableFacesServletAutomaticMapping(FacesServlet.DISABLE_FACESSERVLET_TO_XHTML_PARAM_NAME, false), - AutomaticExtensionlessMapping(FacesServlet.AUTOMATIC_EXTENSIONLESS_MAPPING_PARAM_NAME, false), EnableClientStateDebugging("com.sun.faces.enableClientStateDebugging", false), PreferXHTMLContentType("com.sun.faces.preferXHTML", false), CompressViewState("com.sun.faces.compressViewState", true), @@ -862,28 +814,20 @@ public enum BooleanWebContextInitParameter { EnableScriptInAttributeValue("com.sun.faces.enableScriptsInAttributeValues", true), WriteStateAtFormEnd("com.sun.faces.writeStateAtFormEnd", true), EnableLazyBeanValidation("com.sun.faces.enableLazyBeanValidation", true), - SerializeServerState(StateManager.SERIALIZE_SERVER_STATE_PARAM_NAME, false), EnableViewStateIdRendering("com.sun.faces.enableViewStateIdRendering", true), RegisterConverterPropertyEditors("com.sun.faces.registerConverterPropertyEditors", false), - DisableDefaultBeanValidator(BeanValidator.DISABLE_DEFAULT_BEAN_VALIDATOR_PARAM_NAME, false), - DateTimeConverterUsesSystemTimezone(Converter.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE_PARAM_NAME, false), EnableHttpMethodRestrictionPhaseListener("com.sun.faces.ENABLE_HTTP_METHOD_RESTRICTION_PHASE_LISTENER", false), - FaceletsSkipComments(ViewHandler.FACELETS_SKIP_COMMENTS_PARAM_NAME, false), PartialStateSaving(StateManager.PARTIAL_STATE_SAVING_PARAM_NAME, true), GenerateUniqueServerStateIds("com.sun.faces.generateUniqueServerStateIds", true), - InterpretEmptyStringSubmittedValuesAsNull(UIInput.EMPTY_STRING_AS_NULL_PARAM_NAME, false), AutoCompleteOffOnViewState("com.sun.faces.autoCompleteOffOnViewState", true), EnableThreading("com.sun.faces.enableThreading", false), AllowTextChildren("com.sun.faces.allowTextChildren", false), CacheResourceModificationTimestamp("com.sun.faces.cacheResourceModificationTimestamp", false), - EnableDistributable("com.sun.faces.enableDistributable", false), + EnableDistributable("com.sun.faces.enableDistributable", false), // NOTE: this is indeed implicitly set to true when web.xml distributable is also set, see ConfigureListener. EnableMissingResourceLibraryDetection("com.sun.faces.enableMissingResourceLibraryDetection", false), DisableIdUniquenessCheck("com.sun.faces.disableIdUniquenessCheck", false), EnableTransitionTimeNoOpFlash("com.sun.faces.enableTransitionTimeNoOpFlash", false), ForceAlwaysWriteFlashCookie("com.sun.faces.forceAlwaysWriteFlashCookie", false), - ViewRootPhaseListenerQueuesException(UIViewRoot.VIEWROOT_PHASE_LISTENER_QUEUES_EXCEPTIONS_PARAM_NAME, false), - EnableValidateWholeBean(BeanValidator.ENABLE_VALIDATE_WHOLE_BEAN_PARAM_NAME, false), - EnableWebsocketEndpoint(PushContext.ENABLE_WEBSOCKET_ENDPOINT_PARAM_NAME, false), DisallowDoctypeDecl("com.sun.faces.disallowDoctypeDecl", false), UseFaceletsID("com.sun.faces.useFaceletsID",false), ; diff --git a/impl/src/main/java/com/sun/faces/config/configprovider/BaseWebConfigResourceProvider.java b/impl/src/main/java/com/sun/faces/config/configprovider/BaseWebConfigResourceProvider.java index 70615c9edc..c434c6b232 100644 --- a/impl/src/main/java/com/sun/faces/config/configprovider/BaseWebConfigResourceProvider.java +++ b/impl/src/main/java/com/sun/faces/config/configprovider/BaseWebConfigResourceProvider.java @@ -16,8 +16,6 @@ package com.sun.faces.config.configprovider; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.JakartaFacesConfigFiles; -import static com.sun.faces.util.Util.split; import static java.util.Arrays.binarySearch; import static java.util.logging.Level.WARNING; @@ -30,12 +28,12 @@ import java.util.Set; import java.util.logging.Logger; -import com.sun.faces.config.WebConfiguration; -import com.sun.faces.config.WebConfiguration.WebContextInitParameter; import com.sun.faces.spi.ConfigurationResourceProvider; import com.sun.faces.util.FacesLogger; import jakarta.faces.FacesException; +import jakarta.faces.annotation.FacesConfig.ContextParam; +import jakarta.faces.context.FacesContext; import jakarta.servlet.ServletContext; /** @@ -50,24 +48,19 @@ public abstract class BaseWebConfigResourceProvider implements ConfigurationReso @Override public Collection getResources(ServletContext context) { - WebConfiguration webConfig = WebConfiguration.getInstance(context); - String paths = webConfig.getOptionValue(getParameter()); + String[] paths = getParameter().getValue(FacesContext.getCurrentInstance()); Set urls = new LinkedHashSet<>(6); - if (paths != null) { - for (String token : split(context, paths.trim(), getSeparatorRegex())) { - String path = token.trim(); - if (!isExcluded(path) && path.length() != 0) { - URI u = getContextURLForPath(context, path); - if (u != null) { - urls.add(u); - } else { - if (LOGGER.isLoggable(WARNING)) { - LOGGER.log(WARNING, "faces.config.web_resource_not_found", new Object[] { path, JakartaFacesConfigFiles.getQualifiedName() }); - } + for (String path : paths) { + if (!isExcluded(path) && path.length() != 0) { + URI u = getContextURLForPath(context, path); + if (u != null) { + urls.add(u); + } else { + if (LOGGER.isLoggable(WARNING)) { + LOGGER.log(WARNING, "faces.config.web_resource_not_found", new Object[] { path, getParameter().getName() }); } } - } } @@ -76,7 +69,7 @@ public Collection getResources(ServletContext context) { // ------------------------------------------------------- Protected Methods - protected abstract WebContextInitParameter getParameter(); + protected abstract ContextParam getParameter(); protected abstract String[] getExcludedResources(); diff --git a/impl/src/main/java/com/sun/faces/config/configprovider/WebFaceletTaglibResourceProvider.java b/impl/src/main/java/com/sun/faces/config/configprovider/WebFaceletTaglibResourceProvider.java index 9e5356ee23..0604cb02af 100644 --- a/impl/src/main/java/com/sun/faces/config/configprovider/WebFaceletTaglibResourceProvider.java +++ b/impl/src/main/java/com/sun/faces/config/configprovider/WebFaceletTaglibResourceProvider.java @@ -16,9 +16,7 @@ package com.sun.faces.config.configprovider; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.FaceletsLibraries; - -import com.sun.faces.config.WebConfiguration.WebContextInitParameter; +import jakarta.faces.annotation.FacesConfig.ContextParam; /** * @@ -31,8 +29,8 @@ public class WebFaceletTaglibResourceProvider extends BaseWebConfigResourceProvi // ------------------------------ Methods from BaseWebConfigResourceProvider @Override - protected WebContextInitParameter getParameter() { - return FaceletsLibraries; + protected ContextParam getParameter() { + return ContextParam.FACELETS_LIBRARIES; } @Override diff --git a/impl/src/main/java/com/sun/faces/config/configprovider/WebFacesConfigResourceProvider.java b/impl/src/main/java/com/sun/faces/config/configprovider/WebFacesConfigResourceProvider.java index d14cdef62c..f699a22380 100644 --- a/impl/src/main/java/com/sun/faces/config/configprovider/WebFacesConfigResourceProvider.java +++ b/impl/src/main/java/com/sun/faces/config/configprovider/WebFacesConfigResourceProvider.java @@ -16,13 +16,10 @@ package com.sun.faces.config.configprovider; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.JakartaFacesConfigFiles; - import java.net.URI; import java.util.Collection; -import com.sun.faces.config.WebConfiguration.WebContextInitParameter; - +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.servlet.ServletContext; /** @@ -66,8 +63,8 @@ public Collection getResources(ServletContext context) { // ------------------------------ Methods from BaseWebConfigResourceProvider @Override - protected WebContextInitParameter getParameter() { - return JakartaFacesConfigFiles; + protected ContextParam getParameter() { + return ContextParam.CONFIG_FILES; } @Override diff --git a/impl/src/main/java/com/sun/faces/config/processor/AbstractConfigProcessor.java b/impl/src/main/java/com/sun/faces/config/processor/AbstractConfigProcessor.java index b75123fab8..135a915305 100644 --- a/impl/src/main/java/com/sun/faces/config/processor/AbstractConfigProcessor.java +++ b/impl/src/main/java/com/sun/faces/config/processor/AbstractConfigProcessor.java @@ -18,7 +18,6 @@ import static com.sun.faces.application.ApplicationResourceBundle.DEFAULT_KEY; import static com.sun.faces.config.ConfigManager.INJECTION_PROVIDER_KEY; -import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.JakartaFacesProjectStage; import static com.sun.faces.util.ReflectionUtils.lookupConstructor; import static jakarta.faces.FactoryFinder.APPLICATION_FACTORY; import static jakarta.faces.application.ProjectStage.Development; @@ -53,6 +52,7 @@ import jakarta.faces.FacesException; import jakarta.faces.FactoryFinder; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.Application; import jakarta.faces.application.ApplicationFactory; import jakarta.faces.application.ProjectStage; @@ -324,16 +324,6 @@ private ProjectStage getProjectStage(ServletContext sc, FacesContext facesContex if (LOGGER.isLoggable(FINE)) { LOGGER.log(FINE, "ProjectStage configured via JNDI: {0}", value); } - } else { - value = webConfig.getOptionValue(JakartaFacesProjectStage); - if (value != null) { - if (LOGGER.isLoggable(FINE)) { - LOGGER.log(FINE, "ProjectStage configured via servlet context init parameter: {0}", value); - } - } - } - - if (value != null) { try { projectStage = ProjectStage.valueOf(value); } catch (IllegalArgumentException iae) { @@ -341,6 +331,13 @@ private ProjectStage getProjectStage(ServletContext sc, FacesContext facesContex LOGGER.log(INFO, "Unable to discern ProjectStage for value {0}.", value); } } + } else { + projectStage = ContextParam.PROJECT_STAGE.getValue(facesContext); + if (projectStage != null) { + if (LOGGER.isLoggable(FINE)) { + LOGGER.log(FINE, "ProjectStage configured via servlet context init parameter: {0}", value); + } + } } if (projectStage == null) { diff --git a/impl/src/main/java/com/sun/faces/config/processor/ApplicationConfigProcessor.java b/impl/src/main/java/com/sun/faces/config/processor/ApplicationConfigProcessor.java index 9b8824268c..99eec5b887 100644 --- a/impl/src/main/java/com/sun/faces/config/processor/ApplicationConfigProcessor.java +++ b/impl/src/main/java/com/sun/faces/config/processor/ApplicationConfigProcessor.java @@ -47,13 +47,13 @@ import com.sun.faces.application.ApplicationAssociate; import com.sun.faces.application.ApplicationResourceBundle; import com.sun.faces.config.ConfigurationException; -import com.sun.faces.config.WebConfiguration; import com.sun.faces.config.manager.documents.DocumentInfo; import com.sun.faces.util.FacesLogger; import com.sun.faces.util.Util; import jakarta.el.ELResolver; import jakarta.faces.FacesException; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.Application; import jakarta.faces.application.ConfigurableNavigationHandler; import jakarta.faces.application.NavigationHandler; @@ -340,8 +340,7 @@ private void registerDefaultValidatorIds(FacesContext facesContext, Application if (defaultValidatorIds == null) { defaultValidatorIds = new LinkedHashSet<>(); if (isBeanValidatorAvailable(facesContext)) { - WebConfiguration webConfig = WebConfiguration.getInstance(); - if (!webConfig.isOptionEnabled(WebConfiguration.BooleanWebContextInitParameter.DisableDefaultBeanValidator)) { + if (!ContextParam.DISABLE_DEFAULT_BEAN_VALIDATOR.isSet(facesContext)) { defaultValidatorIds.add(BeanValidator.VALIDATOR_ID); } } diff --git a/impl/src/main/java/com/sun/faces/config/processor/FacesFlowDefinitionConfigProcessor.java b/impl/src/main/java/com/sun/faces/config/processor/FacesFlowDefinitionConfigProcessor.java index 294e737125..2aca9b68bc 100644 --- a/impl/src/main/java/com/sun/faces/config/processor/FacesFlowDefinitionConfigProcessor.java +++ b/impl/src/main/java/com/sun/faces/config/processor/FacesFlowDefinitionConfigProcessor.java @@ -47,6 +47,7 @@ import com.sun.faces.RIConstants; import com.sun.faces.application.ApplicationAssociate; +import com.sun.faces.application.JavaFlowLoaderHelper; import com.sun.faces.config.WebConfiguration; import com.sun.faces.config.manager.documents.DocumentInfo; import com.sun.faces.facelets.util.ReflectionUtil; @@ -177,19 +178,7 @@ public void process(ServletContext sc, FacesContext facesContext, DocumentInfo[] } if (config.isHasFlows()) { - String optionValue = config.getOptionValue(WebConfiguration.WebContextInitParameter.ClientWindowMode); - boolean clientWindowNeedsEnabling = false; - if ("none".equals(optionValue)) { - clientWindowNeedsEnabling = true; - String featureName = WebConfiguration.WebContextInitParameter.ClientWindowMode.getQualifiedName(); - LOGGER.log(Level.WARNING, "{0} was set to none, but Faces Flows requires {0} is enabled. Setting to ''url''.", new Object[] { featureName }); - } else if (null == optionValue) { - clientWindowNeedsEnabling = true; - } - if (clientWindowNeedsEnabling) { - config.setOptionValue(WebConfiguration.WebContextInitParameter.ClientWindowMode, "url"); - } - + JavaFlowLoaderHelper.enableClientWindowModeIfNecessary(facesContext); facesContext.getApplication().subscribeToEvent(PostConstructApplicationEvent.class, Application.class, new PerformDeferredFlowProcessing()); } diff --git a/impl/src/main/java/com/sun/faces/context/ContextParam.java b/impl/src/main/java/com/sun/faces/context/ContextParam.java index e4cd1830f8..d921da4206 100644 --- a/impl/src/main/java/com/sun/faces/context/ContextParam.java +++ b/impl/src/main/java/com/sun/faces/context/ContextParam.java @@ -16,8 +16,6 @@ package com.sun.faces.context; -import jakarta.faces.push.PushContext; - /** * The enumeration of all our context-param entries. */ @@ -30,11 +28,7 @@ public enum ContextParam { /** * Send the "X-Powered-By" header. */ - SendPoweredByHeader("com.sun.faces.sendPoweredByHeader", Boolean.class, false), - /** - * The websocket endpoint port (default 0 means the code will take the port from the request) - */ - WebsocketEndpointPort(PushContext.WEBSOCKET_ENDPOINT_PORT_PARAM_NAME, Integer.class, 0); + SendPoweredByHeader("com.sun.faces.sendPoweredByHeader", Boolean.class, false); /** * Stores the default value. diff --git a/impl/src/main/java/com/sun/faces/context/ExternalContextImpl.java b/impl/src/main/java/com/sun/faces/context/ExternalContextImpl.java index 55dbf6c5d8..36bf87b8ae 100644 --- a/impl/src/main/java/com/sun/faces/context/ExternalContextImpl.java +++ b/impl/src/main/java/com/sun/faces/context/ExternalContextImpl.java @@ -53,6 +53,7 @@ import jakarta.faces.FacesException; import jakarta.faces.FactoryFinder; +import jakarta.faces.annotation.FacesConfig; import jakarta.faces.application.ProjectStage; import jakarta.faces.context.ExternalContext; import jakarta.faces.context.FacesContext; @@ -568,7 +569,7 @@ public String encodeWebsocketURL(String url) { Util.notNull("url", url); HttpServletRequest request = (HttpServletRequest) getRequest(); - int port = ContextParamUtils.getValue(servletContext, ContextParam.WebsocketEndpointPort, Integer.class); + int port = FacesConfig.ContextParam.WEBSOCKET_ENDPOINT_PORT.getValue(FacesContext.getCurrentInstance()); try { final URL requestURL = new URL(request.getRequestURL().toString()); diff --git a/impl/src/main/java/com/sun/faces/context/FacesContextFactoryImpl.java b/impl/src/main/java/com/sun/faces/context/FacesContextFactoryImpl.java index 2d65ad7b42..7bb42ed560 100644 --- a/impl/src/main/java/com/sun/faces/context/FacesContextFactoryImpl.java +++ b/impl/src/main/java/com/sun/faces/context/FacesContextFactoryImpl.java @@ -16,11 +16,8 @@ package com.sun.faces.context; -import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.AlwaysPerformValidationWhenRequiredTrue; -import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableValidateWholeBean; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.ForceAlwaysWriteFlashCookie; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.PartialStateSaving; -import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.ViewRootPhaseListenerQueuesException; import java.util.Map; @@ -30,7 +27,7 @@ import jakarta.faces.FacesException; import jakarta.faces.FactoryFinder; -import jakarta.faces.component.UIInput; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.context.ExceptionHandlerFactory; import jakarta.faces.context.ExternalContext; import jakarta.faces.context.ExternalContextFactory; @@ -81,15 +78,11 @@ private void savePerRequestInitParams(FacesContext context, WebConfiguration web ExternalContext extContext = context.getExternalContext(); Map appMap = extContext.getApplicationMap(); Map attrs = context.getAttributes(); - attrs.put(UIInput.ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE, - webConfig.isOptionEnabled(AlwaysPerformValidationWhenRequiredTrue) ? Boolean.TRUE : Boolean.FALSE); + attrs.put(ContextParam.ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE.getName(), ContextParam.ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE.getValue(context)); attrs.put(PartialStateSaving, webConfig.isOptionEnabled(PartialStateSaving) ? Boolean.TRUE : Boolean.FALSE); attrs.put(ForceAlwaysWriteFlashCookie, webConfig.isOptionEnabled(ForceAlwaysWriteFlashCookie) ? Boolean.TRUE : Boolean.FALSE); - // We must use getQualifiedName here because the consumer is in faces-api - // and thus cannot import the enum. - attrs.put(ViewRootPhaseListenerQueuesException.getQualifiedName(), - webConfig.isOptionEnabled(ViewRootPhaseListenerQueuesException) ? Boolean.TRUE : Boolean.FALSE); - attrs.put(EnableValidateWholeBean.getQualifiedName(), webConfig.isOptionEnabled(EnableValidateWholeBean) ? Boolean.TRUE : Boolean.FALSE); + attrs.put(ContextParam.VIEWROOT_PHASE_LISTENER_QUEUES_EXCEPTIONS.getName(), ContextParam.VIEWROOT_PHASE_LISTENER_QUEUES_EXCEPTIONS.getValue(context)); + attrs.put(ContextParam.ENABLE_VALIDATE_WHOLE_BEAN.getName(), ContextParam.ENABLE_VALIDATE_WHOLE_BEAN.getValue(context)); String facesConfigVersion = String.valueOf(appMap.get(RIConstants.FACES_CONFIG_VERSION)); attrs.put(RIConstants.FACES_CONFIG_VERSION, facesConfigVersion); diff --git a/impl/src/main/java/com/sun/faces/el/ELUtils.java b/impl/src/main/java/com/sun/faces/el/ELUtils.java index 5468789f64..9bc3852859 100644 --- a/impl/src/main/java/com/sun/faces/el/ELUtils.java +++ b/impl/src/main/java/com/sun/faces/el/ELUtils.java @@ -16,7 +16,6 @@ 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; @@ -30,7 +29,6 @@ import java.util.regex.Pattern; import com.sun.faces.application.ApplicationAssociate; -import com.sun.faces.config.WebConfiguration; import com.sun.faces.context.flash.FlashELResolver; import com.sun.faces.util.Cache; import com.sun.faces.util.LRUCache; @@ -46,6 +44,7 @@ import jakarta.el.ResourceBundleELResolver; import jakarta.el.ValueExpression; import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.context.ExternalContext; import jakarta.faces.context.FacesContext; @@ -160,7 +159,7 @@ public static void buildFacesResolver(FacesCompositeELResolver composite, Applic addELResolvers(composite, associate.getELResolversFromFacesConfig()); composite.add(associate.getApplicationELResolvers()); - if (WebConfiguration.getInstance().isOptionEnabled(InterpretEmptyStringSubmittedValuesAsNull)) { + if (ContextParam.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL.isSet(FacesContext.getCurrentInstance())) { composite.addPropertyELResolver(EMPTY_STRING_TO_NULL_RESOLVER); } diff --git a/impl/src/main/java/com/sun/faces/facelets/impl/FaceletCacheFactoryImpl.java b/impl/src/main/java/com/sun/faces/facelets/impl/FaceletCacheFactoryImpl.java index ceac74dacc..5475257c4a 100644 --- a/impl/src/main/java/com/sun/faces/facelets/impl/FaceletCacheFactoryImpl.java +++ b/impl/src/main/java/com/sun/faces/facelets/impl/FaceletCacheFactoryImpl.java @@ -16,8 +16,8 @@ package com.sun.faces.facelets.impl; -import com.sun.faces.config.WebConfiguration; - +import jakarta.faces.annotation.FacesConfig.ContextParam; +import jakarta.faces.context.FacesContext; import jakarta.faces.view.facelets.FaceletCache; import jakarta.faces.view.facelets.FaceletCacheFactory; @@ -32,9 +32,7 @@ public FaceletCacheFactoryImpl() { @Override public FaceletCache getFaceletCache() { - WebConfiguration webConfig = WebConfiguration.getInstance(); - String refreshPeriod = webConfig.getOptionValue(WebConfiguration.WebContextInitParameter.FaceletsDefaultRefreshPeriod); - long period = Long.parseLong(refreshPeriod) * 1000; + int period = ContextParam.FACELETS_REFRESH_PERIOD.getValue(FacesContext.getCurrentInstance()); FaceletCache result = new DefaultFaceletCache(period); return result; diff --git a/impl/src/main/java/com/sun/faces/facelets/tag/ui/CompositionHandler.java b/impl/src/main/java/com/sun/faces/facelets/tag/ui/CompositionHandler.java index cf004f77a4..09a6f73323 100644 --- a/impl/src/main/java/com/sun/faces/facelets/tag/ui/CompositionHandler.java +++ b/impl/src/main/java/com/sun/faces/facelets/tag/ui/CompositionHandler.java @@ -32,6 +32,7 @@ import com.sun.faces.util.FacesLogger; import jakarta.el.VariableMapper; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.component.UIComponent; import jakarta.faces.context.FacesContext; import jakarta.faces.view.facelets.FaceletContext; diff --git a/impl/src/main/java/com/sun/faces/facelets/tag/ui/DecorateHandler.java b/impl/src/main/java/com/sun/faces/facelets/tag/ui/DecorateHandler.java index 7af0fbf184..41996a3ea0 100644 --- a/impl/src/main/java/com/sun/faces/facelets/tag/ui/DecorateHandler.java +++ b/impl/src/main/java/com/sun/faces/facelets/tag/ui/DecorateHandler.java @@ -32,6 +32,7 @@ import com.sun.faces.util.FacesLogger; import jakarta.el.VariableMapper; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.component.UIComponent; import jakarta.faces.view.facelets.FaceletContext; import jakarta.faces.view.facelets.TagAttribute; diff --git a/impl/src/main/java/com/sun/faces/facelets/tag/ui/IncludeHandler.java b/impl/src/main/java/com/sun/faces/facelets/tag/ui/IncludeHandler.java index 0704901d5d..b7e1ea912a 100644 --- a/impl/src/main/java/com/sun/faces/facelets/tag/ui/IncludeHandler.java +++ b/impl/src/main/java/com/sun/faces/facelets/tag/ui/IncludeHandler.java @@ -25,6 +25,7 @@ import com.sun.faces.util.FacesLogger; import jakarta.el.VariableMapper; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.component.UIComponent; import jakarta.faces.view.facelets.FaceletContext; import jakarta.faces.view.facelets.TagAttribute; diff --git a/impl/src/main/java/com/sun/faces/lifecycle/ClientWindowFactoryImpl.java b/impl/src/main/java/com/sun/faces/lifecycle/ClientWindowFactoryImpl.java index 20d099e0f6..96954b56e3 100644 --- a/impl/src/main/java/com/sun/faces/lifecycle/ClientWindowFactoryImpl.java +++ b/impl/src/main/java/com/sun/faces/lifecycle/ClientWindowFactoryImpl.java @@ -16,10 +16,10 @@ package com.sun.faces.lifecycle; -import com.sun.faces.config.WebConfiguration; +import com.sun.faces.application.JavaFlowLoaderHelper; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.Application; -import jakarta.faces.context.ExternalContext; import jakarta.faces.context.FacesContext; import jakarta.faces.event.AbortProcessingException; import jakarta.faces.event.PostConstructApplicationEvent; @@ -31,7 +31,6 @@ public class ClientWindowFactoryImpl extends ClientWindowFactory { private boolean isClientWindowEnabled = false; - private WebConfiguration config = null; public ClientWindowFactoryImpl() { super(null); @@ -60,11 +59,8 @@ public void processEvent(SystemEvent event) throws AbortProcessingException { private void postConstructApplicationInitialization() { FacesContext context = FacesContext.getCurrentInstance(); - ExternalContext extContext = context.getExternalContext(); - config = WebConfiguration.getInstance(extContext); - String optionValue = config.getOptionValue(WebConfiguration.WebContextInitParameter.ClientWindowMode); - - isClientWindowEnabled = null != optionValue && "url".equals(optionValue); + String optionValue = ContextParam.CLIENT_WINDOW_MODE.getValue(context); + isClientWindowEnabled = "url".equals(optionValue) || JavaFlowLoaderHelper.isClientWindowModeForciblyEnabled(context); } @Override diff --git a/impl/src/main/java/com/sun/faces/renderkit/RenderKitUtils.java b/impl/src/main/java/com/sun/faces/renderkit/RenderKitUtils.java index a6ba9a48eb..f8b971899c 100644 --- a/impl/src/main/java/com/sun/faces/renderkit/RenderKitUtils.java +++ b/impl/src/main/java/com/sun/faces/renderkit/RenderKitUtils.java @@ -38,7 +38,6 @@ import com.sun.faces.RIConstants; import com.sun.faces.application.ApplicationAssociate; -import com.sun.faces.config.WebConfiguration; import com.sun.faces.el.ELUtils; import com.sun.faces.facelets.util.DevTools; import com.sun.faces.util.FacesLogger; @@ -1219,7 +1218,7 @@ public static String getImageSource(FacesContext context, UIComponent component, ResourceHandler handler = context.getApplication().getResourceHandler(); if (resName != null) { String libName = (String) component.getAttributes().get("library"); - + if (libName == null && ApplicationAssociate.getInstance(context).getResourceManager().isContractsResource(resName)) { if (context.isProjectStage(ProjectStage.Development)) { String msg = "Illegal path, direct contract references are not allowed: " + resName; @@ -1245,8 +1244,7 @@ public static String getImageSource(FacesContext context, UIComponent component, if (value == null || value.length() == 0) { return ""; } - WebConfiguration webConfig = WebConfiguration.getInstance(); - if (value.startsWith(webConfig.getOptionValue(WebConfiguration.WebContextInitParameter.WebAppContractsDirectory))) { + if (ApplicationAssociate.getInstance(context).getResourceManager().isContractsResource(value)) { if (context.isProjectStage(ProjectStage.Development)) { String msg = "Illegal path, direct contract references are not allowed: " + value; context.addMessage(component.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg)); diff --git a/impl/src/main/java/com/sun/faces/renderkit/ResponseStateManagerImpl.java b/impl/src/main/java/com/sun/faces/renderkit/ResponseStateManagerImpl.java index 8125c8de7d..0737a1e82b 100644 --- a/impl/src/main/java/com/sun/faces/renderkit/ResponseStateManagerImpl.java +++ b/impl/src/main/java/com/sun/faces/renderkit/ResponseStateManagerImpl.java @@ -20,13 +20,11 @@ import java.io.IOException; -import com.sun.faces.config.WebConfiguration; -import com.sun.faces.config.WebConfiguration.WebContextInitParameter; import com.sun.faces.renderkit.RenderKitUtils.PredefinedPostbackParameter; import com.sun.faces.util.RequestStateManager; import jakarta.faces.FacesException; -import jakarta.faces.application.StateManager.StateSavingMethod; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.context.FacesContext; import jakarta.faces.render.ResponseStateManager; @@ -39,9 +37,8 @@ public class ResponseStateManagerImpl extends ResponseStateManager { private StateHelper helper; public ResponseStateManagerImpl() { - WebConfiguration webConfig = WebConfiguration.getInstance(); - String stateMode = webConfig.getOptionValue(WebContextInitParameter.StateSavingMethod); - helper = StateSavingMethod.CLIENT.name().equalsIgnoreCase(stateMode) ? new ClientSideStateHelper() : new ServerSideStateHelper(); + FacesContext context = FacesContext.getCurrentInstance(); + helper = ContextParam.STATE_SAVING_METHOD.isDefault(context) ? new ClientSideStateHelper() : new ServerSideStateHelper(); } // --------------------------------------- Methods from ResponseStateManager diff --git a/impl/src/main/java/com/sun/faces/renderkit/ServerSideStateHelper.java b/impl/src/main/java/com/sun/faces/renderkit/ServerSideStateHelper.java index 5e0e271293..7a72f44f85 100644 --- a/impl/src/main/java/com/sun/faces/renderkit/ServerSideStateHelper.java +++ b/impl/src/main/java/com/sun/faces/renderkit/ServerSideStateHelper.java @@ -19,7 +19,6 @@ import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.AutoCompleteOffOnViewState; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableViewStateIdRendering; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.GenerateUniqueServerStateIds; -import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.SerializeServerState; import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.NumberOfLogicalViews; import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.NumberOfViews; import static com.sun.faces.renderkit.RenderKitUtils.PredefinedPostbackParameter.VIEW_STATE_PARAM; @@ -50,6 +49,7 @@ import com.sun.faces.util.Util; import jakarta.faces.FacesException; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.component.UIViewRoot; import jakarta.faces.context.ExternalContext; import jakarta.faces.context.FacesContext; @@ -325,7 +325,7 @@ protected Integer getIntegerConfigValue(WebContextInitParameter param) { * @return If option SerializeServerState is true, serialize and return the state, otherwise, return state unchanged. */ protected Object handleSaveState(Object state) { - if (!webConfig.isOptionEnabled(SerializeServerState)) { + if (!ContextParam.SERIALIZE_SERVER_STATE.isSet(FacesContext.getCurrentInstance())) { return state; } @@ -356,7 +356,7 @@ protected Object handleSaveState(Object state) { * de-serialize the state prior to returning it, otherwise return state as is. */ protected Object handleRestoreState(Object state) { - if (!webConfig.isOptionEnabled(SerializeServerState)) { + if (!ContextParam.SERIALIZE_SERVER_STATE.isSet(FacesContext.getCurrentInstance())) { return state; } diff --git a/impl/src/main/java/jakarta/faces/annotation/FacesConfig.java b/impl/src/main/java/jakarta/faces/annotation/FacesConfig.java index 094fb7c0ba..c8311578b2 100644 --- a/impl/src/main/java/jakarta/faces/annotation/FacesConfig.java +++ b/impl/src/main/java/jakarta/faces/annotation/FacesConfig.java @@ -62,8 +62,9 @@ * The presence of this annotation on a class deployed within an application * guarantees activation of Jakarta Faces and its CDI specific features, even when * {@code /WEB-INF/faces-config.xml} is absent and {@code FacesServlet} is not explicitly registered. - * The attributes can be used to preconfigure the context parameters of your Jakarta Faces application. - * The {@link ContextParam} can be used to obtain the context parameters of your Jakarta Faces application. + *

    + * The attributes can be used to preconfigure the context parameters of your Jakarta Faces application. + * The {@link ContextParam} can be used to obtain the context parameters of your Jakarta Faces application. *

    */ @Qualifier @@ -428,6 +429,7 @@ public int websocketEndpointPort() { /** *

    * Enumeration of all available {@code jakarta.faces.*} context parameters. + * The {@link ContextParam#getValue(FacesContext)} can be used to obtain the value of the context parameter. *

    * * @since 5.0 @@ -659,12 +661,12 @@ public Class getType() { * Returns the value of the context parameter, converted to the expected type as indicated by {@link #getType()}. * This method never returns {@code null}. When the context parameter is not set, a default value is returned. *

    - * The implementation must first look for {@link ExternalContext#getInitParameter(String)} . If it is non-{@code null}, then return it. + * The implementation must first look for {@link ExternalContext#getInitParameter(String)}. If it is non-{@code null}, then return it. * Else look for any {@link FacesConfig} annotation. If present, then return it. Else return the default value. * @param The expected return type. * @param context The involved faces context. * @return The value of the context parameter, converted to the expected type as indicated by {@link #getType()}. - * @throws ClassCastException When inferred T is of wrong type. See {@link #getType()} for the correct type. + * @throws ClassCastException When inferred {@code T} is of wrong type. See {@link #getType()} for the correct type. * @throws IllegalArgumentException When the value of the context parameter cannot be converted to the expected type as indicated by {@link #getType()}. */ @SuppressWarnings("unchecked") @@ -689,7 +691,7 @@ public boolean isSet(FacesContext context) { * @param The expected return type. * @param context The involved faces context. * @return The default value of the context parameter, converted to the expected type as indicated by {@link #getType()}. - * @throws ClassCastException When inferred T is of wrong type. See {@link #getType()} for the correct type. + * @throws ClassCastException When inferred {@code T} is of wrong type. See {@link #getType()} for the correct type. */ @SuppressWarnings("unchecked") public T getDefaultValue(FacesContext context) { diff --git a/impl/src/main/java/jakarta/faces/application/StateManager.java b/impl/src/main/java/jakarta/faces/application/StateManager.java index 31fe1e88d3..8fa41b74ca 100644 --- a/impl/src/main/java/jakarta/faces/application/StateManager.java +++ b/impl/src/main/java/jakarta/faces/application/StateManager.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.util.Map; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.context.FacesContext; import jakarta.faces.context.ResponseWriter; import jakarta.faces.render.RenderKit; @@ -237,16 +238,9 @@ public void writeState(FacesContext context, Object state) throws IOException { * @throws NullPointerException if context is null. */ public boolean isSavingStateInClient(FacesContext context) { - if (savingStateInClient != null) { - return savingStateInClient; + if (savingStateInClient == null) { + savingStateInClient = ContextParam.STATE_SAVING_METHOD.isDefault(context); } - savingStateInClient = false; - - String saveStateParam = context.getExternalContext().getInitParameter(STATE_SAVING_METHOD_PARAM_NAME); - if (StateSavingMethod.CLIENT.name().equalsIgnoreCase(saveStateParam)) { - savingStateInClient = true; - } - return savingStateInClient; } diff --git a/impl/src/main/java/jakarta/faces/component/UIInput.java b/impl/src/main/java/jakarta/faces/component/UIInput.java index 6fbb7dc165..75723042d2 100644 --- a/impl/src/main/java/jakarta/faces/component/UIInput.java +++ b/impl/src/main/java/jakarta/faces/component/UIInput.java @@ -24,10 +24,10 @@ import jakarta.el.ELException; import jakarta.el.ValueExpression; import jakarta.faces.FacesException; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.application.Application; import jakarta.faces.application.FacesMessage; import jakarta.faces.context.ExceptionHandler; -import jakarta.faces.context.ExternalContext; import jakarta.faces.context.FacesContext; import jakarta.faces.convert.Converter; import jakarta.faces.convert.ConverterException; @@ -884,8 +884,7 @@ private boolean isSetAlwaysValidateRequired(FacesContext context) { if (null != bool) { isSetAlwaysValidateRequired = bool; } else { - String val = context.getExternalContext().getInitParameter(ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE); - isSetAlwaysValidateRequired = Boolean.valueOf(val); + isSetAlwaysValidateRequired = ContextParam.ALWAYS_PERFORM_VALIDATION_WHEN_REQUIRED_IS_TRUE.isSet(context); } return isSetAlwaysValidateRequired; @@ -1379,8 +1378,7 @@ private void addConversionErrorMessage(FacesContext context, ConverterException boolean considerEmptyStringNull(FacesContext ctx) { if (emptyStringIsNull == null) { - String val = ctx.getExternalContext().getInitParameter(EMPTY_STRING_AS_NULL_PARAM_NAME); - emptyStringIsNull = Boolean.valueOf(val); + emptyStringIsNull = ContextParam.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL.isSet(ctx); } return emptyStringIsNull; @@ -1390,16 +1388,24 @@ boolean considerEmptyStringNull(FacesContext ctx) { private boolean validateEmptyFields(FacesContext ctx) { if (validateEmptyFields == null) { - ExternalContext extCtx = ctx.getExternalContext(); - String val = extCtx.getInitParameter(VALIDATE_EMPTY_FIELDS_PARAM_NAME); + ValidateEmptyFields val = null; - if (null == val) { - val = (String) extCtx.getApplicationMap().get(VALIDATE_EMPTY_FIELDS_PARAM_NAME); + if (!ContextParam.VALIDATE_EMPTY_FIELDS.isSet(ctx)) { + String appVal = (String) ctx.getExternalContext().getApplicationMap().get(VALIDATE_EMPTY_FIELDS_PARAM_NAME); + + if (appVal != null) { + val = ValidateEmptyFields.valueOf(appVal.toUpperCase()); + } + } + + if (val == null) { + val = ContextParam.VALIDATE_EMPTY_FIELDS.getValue(ctx); } - if (val == null || ValidateEmptyFields.AUTO.name().equalsIgnoreCase(val)) { + + if (val == ValidateEmptyFields.AUTO) { validateEmptyFields = isBeansValidationAvailable(ctx); } else { - validateEmptyFields = Boolean.valueOf(val); + validateEmptyFields = val == ValidateEmptyFields.TRUE; } } diff --git a/impl/src/main/java/jakarta/faces/component/UINamingContainer.java b/impl/src/main/java/jakarta/faces/component/UINamingContainer.java index 668561ba92..eb5bea3186 100644 --- a/impl/src/main/java/jakarta/faces/component/UINamingContainer.java +++ b/impl/src/main/java/jakarta/faces/component/UINamingContainer.java @@ -24,6 +24,7 @@ import java.util.Collection; import java.util.logging.Logger; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.component.visit.VisitCallback; import jakarta.faces.component.visit.VisitContext; import jakarta.faces.context.FacesContext; @@ -113,15 +114,7 @@ public static char getSeparatorChar(FacesContext context) { Character separatorChar = (Character) context.getAttributes().get(SEPARATOR_CHAR_PARAM_NAME); if (separatorChar == null) { - String initParam = context.getExternalContext().getInitParameter(SEPARATOR_CHAR_PARAM_NAME); - separatorChar = SEPARATOR_CHAR; - if (initParam != null) { - initParam = initParam.trim(); - if (initParam.length() != 0) { - separatorChar = initParam.charAt(0); - } - } - + separatorChar = ContextParam.SEPARATOR_CHAR.getValue(context); context.getAttributes().put(SEPARATOR_CHAR_PARAM_NAME, separatorChar); } diff --git a/impl/src/main/java/jakarta/faces/component/UIWebsocket.java b/impl/src/main/java/jakarta/faces/component/UIWebsocket.java index 735329604c..5128d5fb0a 100644 --- a/impl/src/main/java/jakarta/faces/component/UIWebsocket.java +++ b/impl/src/main/java/jakarta/faces/component/UIWebsocket.java @@ -25,8 +25,8 @@ import java.util.regex.Pattern; import jakarta.el.ValueExpression; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.component.behavior.ClientBehaviorHolder; -import jakarta.faces.context.ExternalContext; import jakarta.faces.context.FacesContext; import jakarta.faces.push.Push; import jakarta.faces.push.PushContext; @@ -97,9 +97,7 @@ enum PropertyKeys { * @throws IllegalStateException When Websocket endpoint is not enabled. */ public UIWebsocket() { - ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext(); - - if (!Boolean.parseBoolean(externalContext.getInitParameter(ENABLE_WEBSOCKET_ENDPOINT_PARAM_NAME))) { + if (!ContextParam.ENABLE_WEBSOCKET_ENDPOINT.isSet(FacesContext.getCurrentInstance())) { throw new IllegalStateException(ERROR_ENDPOINT_NOT_ENABLED); } } diff --git a/impl/src/main/java/jakarta/faces/validator/MethodExpressionValidator.java b/impl/src/main/java/jakarta/faces/validator/MethodExpressionValidator.java index 160b688d65..cfc216390a 100644 --- a/impl/src/main/java/jakarta/faces/validator/MethodExpressionValidator.java +++ b/impl/src/main/java/jakarta/faces/validator/MethodExpressionValidator.java @@ -16,14 +16,17 @@ package jakarta.faces.validator; +import static jakarta.faces.component.UIInput.VALIDATE_EMPTY_FIELDS_PARAM_NAME; + import java.util.Map; import jakarta.el.ELContext; import jakarta.el.ELException; import jakarta.el.MethodExpression; +import jakarta.faces.annotation.FacesConfig.ContextParam; import jakarta.faces.component.StateHolder; import jakarta.faces.component.UIComponent; -import jakarta.faces.context.ExternalContext; +import jakarta.faces.component.UIInput.ValidateEmptyFields; import jakarta.faces.context.FacesContext; /** @@ -38,8 +41,6 @@ public class MethodExpressionValidator implements Validator, StateHolder { private static final String BEANS_VALIDATION_AVAILABLE = "jakarta.faces.private.BEANS_VALIDATION_AVAILABLE"; - private static final String VALIDATE_EMPTY_FIELDS_PARAM_NAME = "jakarta.faces.VALIDATE_EMPTY_FIELDS"; - // ------------------------------------------------------ Instance Variables private MethodExpression methodExpression = null; @@ -137,16 +138,24 @@ public void setTransient(boolean transientValue) { private boolean validateEmptyFields(FacesContext ctx) { if (validateEmptyFields == null) { - ExternalContext extCtx = ctx.getExternalContext(); - String val = extCtx.getInitParameter(VALIDATE_EMPTY_FIELDS_PARAM_NAME); + ValidateEmptyFields val = null; + + if (!ContextParam.VALIDATE_EMPTY_FIELDS.isSet(ctx)) { + String appVal = (String) ctx.getExternalContext().getApplicationMap().get(VALIDATE_EMPTY_FIELDS_PARAM_NAME); + + if (appVal != null) { + val = ValidateEmptyFields.valueOf(appVal.toUpperCase()); + } + } - if (null == val) { - val = (String) extCtx.getApplicationMap().get(VALIDATE_EMPTY_FIELDS_PARAM_NAME); + if (val == null) { + val = ContextParam.VALIDATE_EMPTY_FIELDS.getValue(ctx); } - if (val == null || "auto".equals(val)) { + + if (val == ValidateEmptyFields.AUTO) { validateEmptyFields = isBeansValidationAvailable(ctx); } else { - validateEmptyFields = Boolean.valueOf(val); + validateEmptyFields = val == ValidateEmptyFields.TRUE; } } From a1016c73466a83b3d8d19454fc75e4079381020a Mon Sep 17 00:00:00 2001 From: Bauke Scholtz Date: Sat, 28 Oct 2023 08:38:01 -0400 Subject: [PATCH 4/4] Fixed broken tests after adding new FacesConfig.ContextParam enum https://github.com/jakartaee/faces/issues/1416 --- impl/src/test/java/com/sun/faces/el/ELUtilsTest.java | 2 +- .../test/java/com/sun/faces/mock/MockBeanManager.java | 10 ++++++---- .../test/java/com/sun/faces/mock/MockFacesContext.java | 2 ++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/impl/src/test/java/com/sun/faces/el/ELUtilsTest.java b/impl/src/test/java/com/sun/faces/el/ELUtilsTest.java index 2eca310586..461e50652e 100644 --- a/impl/src/test/java/com/sun/faces/el/ELUtilsTest.java +++ b/impl/src/test/java/com/sun/faces/el/ELUtilsTest.java @@ -46,12 +46,12 @@ public URL getResource(String path) { "com.sun.faces.mock.MockRenderKitFactory"); new FacesContextImpl(externalContext, new LifecycleImpl()); + FacesContext.getCurrentInstance().getAttributes().put(RIConstants.CDI_BEAN_MANAGER, new MockBeanManager()); new ApplicationImpl(); applicationAssociate = (ApplicationAssociate) externalContext.getApplicationMap() .get(RIConstants.FACES_PREFIX + "ApplicationAssociate"); - FacesContext.getCurrentInstance().getAttributes().put(RIConstants.CDI_BEAN_MANAGER, new MockBeanManager()); } @Test diff --git a/impl/src/test/java/com/sun/faces/mock/MockBeanManager.java b/impl/src/test/java/com/sun/faces/mock/MockBeanManager.java index 6eda0eb22c..b651643062 100644 --- a/impl/src/test/java/com/sun/faces/mock/MockBeanManager.java +++ b/impl/src/test/java/com/sun/faces/mock/MockBeanManager.java @@ -16,6 +16,8 @@ package com.sun.faces.mock; +import static java.util.Collections.emptySet; + import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.List; @@ -71,12 +73,12 @@ public CreationalContext createCreationalContext(Contextual contextual @Override public Set> getBeans(Type beanType, Annotation... qualifiers) { - return null; + return emptySet(); } @Override public Set> getBeans(String name) { - return null; + return emptySet(); } @Override @@ -156,12 +158,12 @@ public boolean isPassivatingScope(Class annotationType) { @Override public Set getInterceptorBindingDefinition(Class bindingType) { - return null; + return emptySet(); } @Override public Set getStereotypeDefinition(Class stereotype) { - return null; + return emptySet(); } @Override diff --git a/impl/src/test/java/com/sun/faces/mock/MockFacesContext.java b/impl/src/test/java/com/sun/faces/mock/MockFacesContext.java index 8d1893d42a..d4f0e3318e 100644 --- a/impl/src/test/java/com/sun/faces/mock/MockFacesContext.java +++ b/impl/src/test/java/com/sun/faces/mock/MockFacesContext.java @@ -24,6 +24,7 @@ import java.util.Locale; import java.util.Map; +import com.sun.faces.RIConstants; import com.sun.faces.context.ExceptionHandlerFactoryImpl; import com.sun.faces.renderkit.RenderKitUtils; @@ -62,6 +63,7 @@ public class MockFacesContext extends FacesContext { public MockFacesContext() { super(); setCurrentInstance(this); + getAttributes().put(RIConstants.CDI_BEAN_MANAGER, new MockBeanManager()); } public MockFacesContext(ExternalContext externalContext) {