From db53027b3148fe37e9ceaa36b92e2bc01042abb0 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sat, 20 May 2023 09:51:17 -0400
Subject: [PATCH 01/44] Fix #5232: fail fast when CDI is unavailable
---
impl/src/main/java/com/sun/faces/config/FacesInitializer.java | 3 +++
1 file changed, 3 insertions(+)
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 e56a2bc78d..b38534d356 100644
--- a/impl/src/main/java/com/sun/faces/config/FacesInitializer.java
+++ b/impl/src/main/java/com/sun/faces/config/FacesInitializer.java
@@ -27,6 +27,8 @@
import java.util.Map;
import java.util.Set;
+import com.sun.faces.util.Util;
+
import jakarta.faces.annotation.FacesConfig;
import jakarta.faces.application.ResourceDependencies;
import jakarta.faces.application.ResourceDependency;
@@ -104,6 +106,7 @@ public void onStartup(Set> classes, ServletContext servletContext) thro
if (appHasFacesContent || appHasFacesServlet) {
addAnnotatedClasses(classes, servletContext);
InitFacesContext initFacesContext = new InitFacesContext(servletContext);
+ Util.getCdiBeanManager(initFacesContext); // #5232 Fail fast when CDI is really not available.
try {
if (appHasFacesContent) {
From db7f686b4e31a759d70af17eae472c16f823cb86 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sat, 20 May 2023 09:51:51 -0400
Subject: [PATCH 02/44] Fix #5232: force Weld to reinitialize when it skipped
initialization (usually due to empty BDA)
---
impl/src/main/java/com/sun/faces/util/Util.java | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/impl/src/main/java/com/sun/faces/util/Util.java b/impl/src/main/java/com/sun/faces/util/Util.java
index cacd9f20dc..e6dcb980e7 100644
--- a/impl/src/main/java/com/sun/faces/util/Util.java
+++ b/impl/src/main/java/com/sun/faces/util/Util.java
@@ -30,6 +30,7 @@
import static java.util.Collections.emptyList;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.SEVERE;
+import static java.util.logging.Level.WARNING;
import java.beans.FeatureDescriptor;
import java.io.IOException;
@@ -100,6 +101,7 @@
import jakarta.faces.event.AbortProcessingException;
import jakarta.faces.render.ResponseStateManager;
import jakarta.faces.webapp.FacesServlet;
+import jakarta.servlet.ServletContainerInitializer;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletRegistration;
import jakarta.servlet.http.HttpServletMapping;
@@ -1482,6 +1484,19 @@ public static BeanManager getCdiBeanManager(FacesContext facesContext) {
if (result == null && facesContext != null) {
Map applicationMap = facesContext.getExternalContext().getApplicationMap();
result = (BeanManager) applicationMap.get("org.jboss.weld.environment.servlet.jakarta.enterprise.inject.spi.BeanManager");
+
+ if (result == null && applicationMap.get("org.jboss.weld.environment.servlet.enhancedListenerUsed") == Boolean.TRUE) {
+ LOGGER.log(WARNING, "Weld skipped initialization - forcing it to reinitialize");
+ try {
+ ServletContext servletContext = (ServletContext) facesContext.getExternalContext().getContext();
+ servletContext.setInitParameter("org.jboss.weld.environment.servlet.archive.isolation", "false");
+ ServletContainerInitializer weld = (ServletContainerInitializer) Class.forName("org.jboss.weld.environment.servlet.EnhancedListener").getConstructor().newInstance();
+ weld.onStartup(null, servletContext);
+ result = (BeanManager) applicationMap.get("org.jboss.weld.environment.servlet.jakarta.enterprise.inject.spi.BeanManager");
+ } catch (Exception | LinkageError e) {
+ LOGGER.log(WARNING, "Reinitializing Weld failed", e);
+ }
+ }
}
if (result != null && facesContext != null) {
From bda4b77b6bfbc1e087ee1f832bbac5a38bc3036a Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sat, 20 May 2023 10:01:13 -0400
Subject: [PATCH 03/44] Improve #5232: add hint how to fix Weld init fail on
your own
---
impl/src/main/java/com/sun/faces/util/Util.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/impl/src/main/java/com/sun/faces/util/Util.java b/impl/src/main/java/com/sun/faces/util/Util.java
index e6dcb980e7..8e14d63b11 100644
--- a/impl/src/main/java/com/sun/faces/util/Util.java
+++ b/impl/src/main/java/com/sun/faces/util/Util.java
@@ -1494,7 +1494,7 @@ public static BeanManager getCdiBeanManager(FacesContext facesContext) {
weld.onStartup(null, servletContext);
result = (BeanManager) applicationMap.get("org.jboss.weld.environment.servlet.jakarta.enterprise.inject.spi.BeanManager");
} catch (Exception | LinkageError e) {
- LOGGER.log(WARNING, "Reinitializing Weld failed", e);
+ LOGGER.log(WARNING, "Reinitializing Weld failed - giving up, please make sure your project has at least one @Named bean and retry", e);
}
}
}
From 8d59b3de2b64229299f04880fd75310f03aafda0 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sun, 9 Jul 2023 10:41:07 -0400
Subject: [PATCH 04/44] https://github.com/eclipse-ee4j/mojarra/issues/5232
Improved warning message
---
impl/src/main/java/com/sun/faces/util/Util.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/impl/src/main/java/com/sun/faces/util/Util.java b/impl/src/main/java/com/sun/faces/util/Util.java
index 438ae16ee8..48e26e1d96 100644
--- a/impl/src/main/java/com/sun/faces/util/Util.java
+++ b/impl/src/main/java/com/sun/faces/util/Util.java
@@ -1486,7 +1486,7 @@ public static BeanManager getCdiBeanManager(FacesContext facesContext) {
weld.onStartup(null, servletContext);
result = (BeanManager) applicationMap.get("org.jboss.weld.environment.servlet.jakarta.enterprise.inject.spi.BeanManager");
} catch (Exception | LinkageError e) {
- LOGGER.log(WARNING, "Reinitializing Weld failed - giving up, please make sure your project has at least one @Named bean and retry", e);
+ LOGGER.log(WARNING, "Reinitializing Weld failed - giving up, please make sure your project contains at least one bean class with a bean defining annotation and retry", e);
}
}
}
From d324508fe83987d9559c717511c4d4cf6a9759f1 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sun, 9 Jul 2023 11:50:43 -0400
Subject: [PATCH 05/44] https://github.com/eclipse-ee4j/mojarra/issues/5232
'Fail fast' line should be in ConfigureListener because ordering of
ServletContainerInitializer is undefined
---
impl/src/main/java/com/sun/faces/config/ConfigureListener.java | 1 +
impl/src/main/java/com/sun/faces/config/FacesInitializer.java | 3 ---
2 files changed, 1 insertion(+), 3 deletions(-)
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 fa975e1f73..684baa88bb 100644
--- a/impl/src/main/java/com/sun/faces/config/ConfigureListener.java
+++ b/impl/src/main/java/com/sun/faces/config/ConfigureListener.java
@@ -121,6 +121,7 @@ public void contextInitialized(ServletContextEvent servletContextEvent) {
}
InitFacesContext initFacesContext = new InitFacesContext(servletContext);
+ Util.getCdiBeanManager(initFacesContext); // #5232 Fail fast when CDI is really not available.
LOGGER.log(FINE, () -> format("ConfigureListener.contextInitialized({0})", servletContext.getContextPath()));
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 b38534d356..e56a2bc78d 100644
--- a/impl/src/main/java/com/sun/faces/config/FacesInitializer.java
+++ b/impl/src/main/java/com/sun/faces/config/FacesInitializer.java
@@ -27,8 +27,6 @@
import java.util.Map;
import java.util.Set;
-import com.sun.faces.util.Util;
-
import jakarta.faces.annotation.FacesConfig;
import jakarta.faces.application.ResourceDependencies;
import jakarta.faces.application.ResourceDependency;
@@ -106,7 +104,6 @@ public void onStartup(Set> classes, ServletContext servletContext) thro
if (appHasFacesContent || appHasFacesServlet) {
addAnnotatedClasses(classes, servletContext);
InitFacesContext initFacesContext = new InitFacesContext(servletContext);
- Util.getCdiBeanManager(initFacesContext); // #5232 Fail fast when CDI is really not available.
try {
if (appHasFacesContent) {
From 4f8d049563d59159d1e1a2ce375f8dab6a27b663 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sun, 23 Jul 2023 10:45:55 -0400
Subject: [PATCH 06/44] https://github.com/eclipse-ee4j/mojarra/issues/5213
RowIndex/DataModel of UIData doesn't need to be reset when broadcasted row
index is same as current row index; noticed same thing on UIRepeat as well so
also improved over there
---
.../com/sun/faces/facelets/component/UIRepeat.java | 10 +++++++---
.../main/java/javax/faces/component/UIData.java | 14 ++++++++++----
2 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/impl/src/main/java/com/sun/faces/facelets/component/UIRepeat.java b/impl/src/main/java/com/sun/faces/facelets/component/UIRepeat.java
index cd26b01803..7eb37027bd 100644
--- a/impl/src/main/java/com/sun/faces/facelets/component/UIRepeat.java
+++ b/impl/src/main/java/com/sun/faces/facelets/component/UIRepeat.java
@@ -967,13 +967,15 @@ public void broadcast(FacesEvent event) throws AbortProcessingException {
FacesEvent target = idxEvent.getTarget();
FacesContext ctx = target.getFacesContext();
this.resetDataModel(ctx);
+ int idx = idxEvent.getIndex();
int prevIndex = this.index;
UIComponent source = target.getComponent();
UIComponent compositeParent = null;
try {
int rowCount = getDataModel().getRowCount();
- int idx = idxEvent.getIndex();
- this.setIndex(ctx, idx);
+ if (idx != prevIndex) {
+ this.setIndex(ctx, idx);
+ }
Integer begin = this.getBegin();
Integer end = this.getEnd();
Integer step = this.getStep();
@@ -1005,7 +1007,9 @@ public void broadcast(FacesEvent event) throws AbortProcessingException {
compositeParent.popComponentFromEL(ctx);
}
this.updateIterationStatus(ctx, null);
- this.setIndex(ctx, prevIndex);
+ if (idx != prevIndex) {
+ this.setIndex(ctx, prevIndex);
+ }
}
} else {
super.broadcast(event);
diff --git a/impl/src/main/java/javax/faces/component/UIData.java b/impl/src/main/java/javax/faces/component/UIData.java
index c0e1157bbb..e32744076e 100644
--- a/impl/src/main/java/javax/faces/component/UIData.java
+++ b/impl/src/main/java/javax/faces/component/UIData.java
@@ -18,7 +18,6 @@
import static com.sun.faces.util.Util.extractFirstNumericSegment;
import static com.sun.faces.util.Util.isNestedInIterator;
-import static java.lang.Character.isDigit;
import java.io.IOException;
import java.io.Serializable;
@@ -1102,8 +1101,13 @@ public void broadcast(FacesEvent event)
if (isNestedWithinIterator(context)) {
setDataModel(null);
}
- int oldRowIndex = getRowIndex();
- setRowIndex(revent.getRowIndex());
+ int currentRowIndex = getRowIndex();
+ int broadcastedRowIndex = revent.getRowIndex();
+
+ if (currentRowIndex != broadcastedRowIndex) {
+ setRowIndex(broadcastedRowIndex);
+ }
+
FacesEvent rowEvent = revent.getFacesEvent();
UIComponent source = rowEvent.getComponent();
UIComponent compositeParent = null;
@@ -1122,8 +1126,10 @@ public void broadcast(FacesEvent event)
compositeParent.popComponentFromEL(context);
}
}
- setRowIndex(oldRowIndex);
+ if (currentRowIndex != broadcastedRowIndex) {
+ setRowIndex(currentRowIndex);
+ }
}
/**
From 37eaf36748f204021d94d4b272a98f47605c61c4 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sat, 29 Jul 2023 08:43:29 -0400
Subject: [PATCH 07/44] https://github.com/eclipse-ee4j/mojarra/issues/5213
Further improved to only skip index setting when old+new are both -1
---
.../main/java/com/sun/faces/facelets/component/UIRepeat.java | 5 +++--
impl/src/main/java/javax/faces/component/UIData.java | 5 +++--
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/impl/src/main/java/com/sun/faces/facelets/component/UIRepeat.java b/impl/src/main/java/com/sun/faces/facelets/component/UIRepeat.java
index 7eb37027bd..3fc96c8d5e 100644
--- a/impl/src/main/java/com/sun/faces/facelets/component/UIRepeat.java
+++ b/impl/src/main/java/com/sun/faces/facelets/component/UIRepeat.java
@@ -969,11 +969,12 @@ public void broadcast(FacesEvent event) throws AbortProcessingException {
this.resetDataModel(ctx);
int idx = idxEvent.getIndex();
int prevIndex = this.index;
+ boolean needsToSetIndex = idx != -1 || prevIndex != -1; // #5213
UIComponent source = target.getComponent();
UIComponent compositeParent = null;
try {
int rowCount = getDataModel().getRowCount();
- if (idx != prevIndex) {
+ if (needsToSetIndex) {
this.setIndex(ctx, idx);
}
Integer begin = this.getBegin();
@@ -1007,7 +1008,7 @@ public void broadcast(FacesEvent event) throws AbortProcessingException {
compositeParent.popComponentFromEL(ctx);
}
this.updateIterationStatus(ctx, null);
- if (idx != prevIndex) {
+ if (needsToSetIndex) {
this.setIndex(ctx, prevIndex);
}
}
diff --git a/impl/src/main/java/javax/faces/component/UIData.java b/impl/src/main/java/javax/faces/component/UIData.java
index e32744076e..6c810be48e 100644
--- a/impl/src/main/java/javax/faces/component/UIData.java
+++ b/impl/src/main/java/javax/faces/component/UIData.java
@@ -1103,8 +1103,9 @@ public void broadcast(FacesEvent event)
}
int currentRowIndex = getRowIndex();
int broadcastedRowIndex = revent.getRowIndex();
+ boolean needsToSetIndex = currentRowIndex != -1 || broadcastedRowIndex != -1; // #5213
- if (currentRowIndex != broadcastedRowIndex) {
+ if (needsToSetIndex) {
setRowIndex(broadcastedRowIndex);
}
@@ -1127,7 +1128,7 @@ public void broadcast(FacesEvent event)
}
}
- if (currentRowIndex != broadcastedRowIndex) {
+ if (needsToSetIndex) {
setRowIndex(currentRowIndex);
}
}
From e0cd6ecd7d328837e28b14bc62c4f60e8a64eaff Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sat, 29 Jul 2023 08:57:25 -0400
Subject: [PATCH 08/44] https://github.com/eclipse-ee4j/mojarra/issues/5291
jakarta.faces.NUMBER_OF_CLIENT_WINDOWS was not considered as context param
---
.../ClientWindowScopeContextManager.java | 40 ++++++++++++-------
.../sun/faces/config/WebConfiguration.java | 1 +
2 files changed, 27 insertions(+), 14 deletions(-)
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 7c448c1c00..5a2a9d4c90 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
@@ -17,26 +17,28 @@
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;
import com.sun.faces.util.FacesLogger;
import com.sun.faces.util.LRUMap;
+
import jakarta.enterprise.context.spi.Contextual;
import jakarta.enterprise.context.spi.CreationalContext;
import jakarta.enterprise.inject.spi.PassivationCapable;
import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext;
-import jakarta.faces.lifecycle.ClientWindow;
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.http.HttpSessionEvent;
-import java.util.Collections;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.logging.Logger;
-
-import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableDistributable;
-import static java.util.logging.Level.FINEST;
-
/**
* The manager that deals with CDI ClientWindowScoped beans.
*/
@@ -141,12 +143,22 @@ private Map getContextMap(FacesContext f
String clientWindowId = getCurrentClientWindowId(facesContext);
if (clientWindowScopeContexts == null && create) {
- synchronized (session) {
- Integer size = (Integer) sessionMap.get(ClientWindow.NUMBER_OF_CLIENT_WINDOWS_PARAM_NAME);
- if (size == null) {
- size = 10;
+ 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());
}
- sessionMap.put(CLIENT_WINDOW_CONTEXTS, Collections.synchronizedMap(new LRUMap(size)));
+ }
+
+ if (numberOfClientWindows == null) {
+ numberOfClientWindows = Integer.valueOf(NumberOfClientWindows.getDefaultValue());
+ }
+
+ synchronized (session) {
+ sessionMap.put(CLIENT_WINDOW_CONTEXTS, Collections.synchronizedMap(new LRUMap(numberOfClientWindows)));
}
}
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 f66dd7d28a..da43ad076e 100644
--- a/impl/src/main/java/com/sun/faces/config/WebConfiguration.java
+++ b/impl/src/main/java/com/sun/faces/config/WebConfiguration.java
@@ -756,6 +756,7 @@ public enum WebContextInitParameter {
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"),
From 1f6939988743b1f04688b54111d18a03423d4d70 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sun, 30 Jul 2023 10:23:44 -0400
Subject: [PATCH 09/44] https://github.com/jakartaee/faces/issues/1567 Improved
impl of "retargeted ajax behavior"
---
.../tag/composite/RetargetedAjaxBehavior.java | 229 ++++++++++++++++++
.../facelets/tag/jsf/core/AjaxHandler.java | 2 +
.../html_basic/AjaxBehaviorRenderer.java | 21 +-
3 files changed, 237 insertions(+), 15 deletions(-)
create mode 100644 impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
diff --git a/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java b/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
new file mode 100644
index 0000000000..e33860c579
--- /dev/null
+++ b/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.faces.facelets.tag.composite;
+
+import java.util.Collection;
+import java.util.Set;
+
+import javax.el.ValueExpression;
+import javax.faces.component.UIComponent;
+import javax.faces.component.behavior.AjaxBehavior;
+import javax.faces.component.behavior.ClientBehaviorContext;
+import javax.faces.component.behavior.ClientBehaviorHint;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.AjaxBehaviorListener;
+import javax.faces.event.BehaviorEvent;
+
+/**
+ * Basically represents which is retargeted by in AjaxHandler and checked in AjaxBehaviorRenderer.
+ *
+ * @see https://github.com/jakartaee/faces/issues/1567
+ */
+public class RetargetedAjaxBehavior extends AjaxBehavior {
+
+ private AjaxBehavior retargeted;
+
+ public RetargetedAjaxBehavior(AjaxBehavior retargeted) {
+ this.retargeted = retargeted;
+ }
+
+ @Override
+ public String getScript(ClientBehaviorContext behaviorContext) {
+ return retargeted.getScript(behaviorContext);
+ }
+
+ @Override
+ public void broadcast(BehaviorEvent event) throws AbortProcessingException {
+ retargeted.broadcast(event);
+ }
+
+ @Override
+ public int hashCode() {
+ return retargeted.hashCode();
+ }
+
+ @Override
+ public String getRendererType() {
+ return retargeted.getRendererType();
+ }
+
+ @Override
+ public void decode(FacesContext context, UIComponent component) {
+ retargeted.decode(context, component);
+ }
+
+ @Override
+ public boolean isTransient() {
+ return retargeted.isTransient();
+ }
+
+ @Override
+ public Set getHints() {
+ return retargeted.getHints();
+ }
+
+ @Override
+ public void setTransient(boolean transientFlag) {
+ retargeted.setTransient(transientFlag);
+ }
+
+ @Override
+ public String getOnerror() {
+ return retargeted.getOnerror();
+ }
+
+ @Override
+ public void setOnerror(String onerror) {
+ retargeted.setOnerror(onerror);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return retargeted.equals(obj);
+ }
+
+ @Override
+ public String getOnevent() {
+ return retargeted.getOnevent();
+ }
+
+ @Override
+ public void setOnevent(String onevent) {
+ retargeted.setOnevent(onevent);
+ }
+
+ @Override
+ public void markInitialState() {
+ retargeted.markInitialState();
+ }
+
+ @Override
+ public boolean initialStateMarked() {
+ return retargeted.initialStateMarked();
+ }
+
+ @Override
+ public Collection getExecute() {
+ return retargeted.getExecute();
+ }
+
+ @Override
+ public void clearInitialState() {
+ retargeted.clearInitialState();
+ }
+
+ @Override
+ public void setExecute(Collection execute) {
+ retargeted.setExecute(execute);
+ }
+
+ @Override
+ public String getDelay() {
+ return retargeted.getDelay();
+ }
+
+ @Override
+ public void setDelay(String delay) {
+ retargeted.setDelay(delay);
+ }
+
+ @Override
+ public Collection getRender() {
+ return retargeted.getRender();
+ }
+
+ @Override
+ public void setRender(Collection render) {
+ retargeted.setRender(render);
+ }
+
+ @Override
+ public boolean isResetValues() {
+ return retargeted.isResetValues();
+ }
+
+ @Override
+ public void setResetValues(boolean resetValues) {
+ retargeted.setResetValues(resetValues);
+ }
+
+ @Override
+ public boolean isDisabled() {
+ return retargeted.isDisabled();
+ }
+
+ @Override
+ public void setDisabled(boolean disabled) {
+ retargeted.setDisabled(disabled);
+ }
+
+ @Override
+ public boolean isImmediate() {
+ return retargeted.isImmediate();
+ }
+
+ @Override
+ public void setImmediate(boolean immediate) {
+ retargeted.setImmediate(immediate);
+ }
+
+ @Override
+ public boolean isImmediateSet() {
+ return retargeted.isImmediateSet();
+ }
+
+ @Override
+ public String toString() {
+ return retargeted.toString();
+ }
+
+ @Override
+ public boolean isResetValuesSet() {
+ return retargeted.isResetValuesSet();
+ }
+
+ @Override
+ public ValueExpression getValueExpression(String name) {
+ return retargeted.getValueExpression(name);
+ }
+
+ @Override
+ public void setValueExpression(String name, ValueExpression binding) {
+ retargeted.setValueExpression(name, binding);
+ }
+
+ @Override
+ public void addAjaxBehaviorListener(AjaxBehaviorListener listener) {
+ retargeted.addAjaxBehaviorListener(listener);
+ }
+
+ @Override
+ public void removeAjaxBehaviorListener(AjaxBehaviorListener listener) {
+ retargeted.removeAjaxBehaviorListener(listener);
+ }
+
+ @Override
+ public Object saveState(FacesContext context) {
+ return retargeted.saveState(context);
+ }
+
+ @Override
+ public void restoreState(FacesContext context, Object state) {
+ retargeted.restoreState(context, state);
+ }
+}
diff --git a/impl/src/main/java/com/sun/faces/facelets/tag/jsf/core/AjaxHandler.java b/impl/src/main/java/com/sun/faces/facelets/tag/jsf/core/AjaxHandler.java
index ba056209fe..7c77b02ea4 100644
--- a/impl/src/main/java/com/sun/faces/facelets/tag/jsf/core/AjaxHandler.java
+++ b/impl/src/main/java/com/sun/faces/facelets/tag/jsf/core/AjaxHandler.java
@@ -56,6 +56,7 @@
import com.sun.faces.component.behavior.AjaxBehaviors;
import com.sun.faces.facelets.tag.TagHandlerImpl;
import com.sun.faces.facelets.tag.composite.BehaviorHolderWrapper;
+import com.sun.faces.facelets.tag.composite.RetargetedAjaxBehavior;
import com.sun.faces.facelets.tag.jsf.CompositeComponentTagHandler;
import com.sun.faces.renderkit.RenderKitUtils;
@@ -345,6 +346,7 @@ private AjaxBehavior createAjaxBehavior(FaceletContext ctx, UIComponent parent,
executeClientIds.remove("@this");
stream(targetClientIds.trim().split(" +")).map(id -> "@this" + separatorChar + id).forEach(executeClientIds::add);
behavior.setExecute(executeClientIds);
+ behavior = new RetargetedAjaxBehavior(behavior);
}
}
}
diff --git a/impl/src/main/java/com/sun/faces/renderkit/html_basic/AjaxBehaviorRenderer.java b/impl/src/main/java/com/sun/faces/renderkit/html_basic/AjaxBehaviorRenderer.java
index 92e0a96e0c..d54067e66c 100644
--- a/impl/src/main/java/com/sun/faces/renderkit/html_basic/AjaxBehaviorRenderer.java
+++ b/impl/src/main/java/com/sun/faces/renderkit/html_basic/AjaxBehaviorRenderer.java
@@ -43,7 +43,7 @@
import javax.faces.event.PhaseId;
import javax.faces.render.ClientBehaviorRenderer;
-import com.sun.faces.facelets.tag.composite.InsertChildrenHandler;
+import com.sun.faces.facelets.tag.composite.RetargetedAjaxBehavior;
import com.sun.faces.renderkit.RenderKitUtils;
import com.sun.faces.util.FacesLogger;
@@ -238,9 +238,9 @@ private static String buildAjaxCommand(ClientBehaviorContext behaviorContext,
ajaxCommand.append(eventName);
ajaxCommand.append("',");
- appendIds(behaviorContext.getFacesContext(), component, ajaxCommand, execute);
+ appendIds(behaviorContext.getFacesContext(), component, ajaxBehavior, ajaxCommand, execute);
ajaxCommand.append(",");
- appendIds(behaviorContext.getFacesContext(), component, ajaxCommand, render);
+ appendIds(behaviorContext.getFacesContext(), component, ajaxBehavior, ajaxCommand, render);
if ((onevent != null) || (onerror != null) || (delay != null) ||
(resetValues != null) || !params.isEmpty()) {
@@ -303,6 +303,7 @@ private static String buildAjaxCommand(ClientBehaviorContext behaviorContext,
// Appends an ids argument to the ajax command
private static void appendIds(FacesContext facesContext,
UIComponent component,
+ AjaxBehavior ajaxBehavior,
StringBuilder builder,
Collection ids) {
@@ -318,7 +319,7 @@ private static void appendIds(FacesContext facesContext,
boolean first = true;
- UIComponent composite = UIComponent.getCompositeComponentParent(component);
+ UIComponent composite = (ajaxBehavior instanceof RetargetedAjaxBehavior) ? UIComponent.getCompositeComponentParent(component) : null;
String separatorChar = String.valueOf(getSeparatorChar(facesContext));
for (String id : ids) {
@@ -335,7 +336,7 @@ private static void appendIds(FacesContext facesContext,
boolean clientResolveableExpression = expression.equals("@all") || expression.equals("@none") || expression.equals("@form") || expression.equals("@this");
- if (composite != null && !isHandledByInsertChildren(component, composite) && (expression.equals("@this") || expression.startsWith("@this" + separatorChar))) {
+ if (composite != null && (expression.equals("@this") || expression.startsWith("@this" + separatorChar))) {
expression = expression.replaceFirst("@this", separatorChar + composite.getClientId(facesContext));
clientResolveableExpression = false;
}
@@ -372,16 +373,6 @@ private static void appendIds(FacesContext facesContext,
builder.append("'");
}
- private static boolean isHandledByInsertChildren(UIComponent component, UIComponent composite) {
- for (UIComponent parent = component.getParent(); parent != null && !parent.equals(composite); parent = parent.getParent()) {
- if (parent.getAttributes().containsKey(InsertChildrenHandler.INDEX_ATTRIBUTE)) {
- return true;
- }
- }
-
- return false;
- }
-
// Returns the resolved (client id) for a particular id.
private static String getResolvedId(UIComponent component, String id) {
From db8b436c9f393995fa8dd15c0e91cd7d7fa17f57 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sun, 30 Jul 2023 10:27:02 -0400
Subject: [PATCH 10/44] Improved javadoc comment
---
.../faces/facelets/tag/composite/RetargetedAjaxBehavior.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java b/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
index e33860c579..b8a4a76d02 100644
--- a/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
+++ b/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
@@ -31,6 +31,8 @@
/**
* Basically represents which is retargeted by in AjaxHandler and checked in AjaxBehaviorRenderer.
+ *
+ * We should probably introduce AjaxBehaviorWrapper in Faces.next to reduce boilerplate like this.
*
* @see https://github.com/jakartaee/faces/issues/1567
*/
From 6a11c61de20c65945c4e2ef1e4497fd9ad7a919b Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sun, 30 Jul 2023 10:35:03 -0400
Subject: [PATCH 11/44] Fixed comment references
---
.../sun/faces/facelets/tag/composite/InsertChildrenHandler.java | 2 +-
.../faces/facelets/tag/composite/RetargetedAjaxBehavior.java | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/impl/src/main/java/com/sun/faces/facelets/tag/composite/InsertChildrenHandler.java b/impl/src/main/java/com/sun/faces/facelets/tag/composite/InsertChildrenHandler.java
index 3cabe6acc3..62663ef408 100644
--- a/impl/src/main/java/com/sun/faces/facelets/tag/composite/InsertChildrenHandler.java
+++ b/impl/src/main/java/com/sun/faces/facelets/tag/composite/InsertChildrenHandler.java
@@ -108,7 +108,7 @@ private class RelocateChildrenListener extends RelocateListener {
this.ctx = ctx;
this.component = component;
if (!component.getAttributes().containsKey(INDEX_ATTRIBUTE)) {
- component.getAttributes().put(INDEX_ATTRIBUTE, idx); // NOTE: this is also used by AjaxBehaviorRenderer in order to detect if f:ajax was handled by cc:insertChildren. See also #5032
+ component.getAttributes().put(INDEX_ATTRIBUTE, idx);
}
this.idx = idx;
this.location = location;
diff --git a/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java b/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
index b8a4a76d02..8e05be622b 100644
--- a/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
+++ b/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
@@ -35,6 +35,7 @@
* We should probably introduce AjaxBehaviorWrapper in Faces.next to reduce boilerplate like this.
*
* @see https://github.com/jakartaee/faces/issues/1567
+ * @see https://github.com/eclipse-ee4j/mojarra/issues/5032
*/
public class RetargetedAjaxBehavior extends AjaxBehavior {
From ffe1e111f531e1a0ff827f9c86cb2c5f55c2316e Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Thu, 7 Sep 2023 06:21:06 -0400
Subject: [PATCH 12/44] Fix #5308 ambiguous resolution during release of
FacesContext when there is more than one implementation of FacesContext known
to CDI in bean-discovery-mode=all state
---
.../main/java/com/sun/faces/context/FacesContextImpl.java | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/impl/src/main/java/com/sun/faces/context/FacesContextImpl.java b/impl/src/main/java/com/sun/faces/context/FacesContextImpl.java
index d750d15f16..a75013b10d 100644
--- a/impl/src/main/java/com/sun/faces/context/FacesContextImpl.java
+++ b/impl/src/main/java/com/sun/faces/context/FacesContextImpl.java
@@ -16,6 +16,8 @@
package com.sun.faces.context;
+import static java.util.stream.Collectors.toSet;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -24,9 +26,11 @@
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
+import com.sun.faces.cdi.CdiExtension;
import com.sun.faces.el.ELContextImpl;
import com.sun.faces.renderkit.RenderKitUtils;
import com.sun.faces.util.FacesLogger;
@@ -556,7 +560,8 @@ public void release() {
DEFAULT_FACES_CONTEXT.remove();
// Destroy our instance produced by FacesContextProducer.
- Bean> bean = beanManager.resolve(beanManager.getBeans(FacesContext.class));
+ Set> beans = beanManager.getBeans(FacesContext.class).stream().filter(bean -> CdiExtension.class.isAssignableFrom(bean.getBeanClass())).collect(toSet());
+ Bean> bean = beanManager.resolve(beans);
((AlterableContext) beanManager.getContext(bean.getScope())).destroy(bean);
}
From 787ee5b208d1d7b6e3baa5a1da581620995872a3 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Thu, 7 Sep 2023 14:33:47 -0400
Subject: [PATCH 13/44] Fixed merge error during
https://github.com/eclipse-ee4j/mojarra/commit/119fa9fbdbe490b7e19d4331f7d414926690f07b
---
.../facelets/tag/faces/core/AjaxHandler.java | 22 +++++++++----------
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/impl/src/main/java/com/sun/faces/facelets/tag/faces/core/AjaxHandler.java b/impl/src/main/java/com/sun/faces/facelets/tag/faces/core/AjaxHandler.java
index 38a4273415..dda42ad98d 100644
--- a/impl/src/main/java/com/sun/faces/facelets/tag/faces/core/AjaxHandler.java
+++ b/impl/src/main/java/com/sun/faces/facelets/tag/faces/core/AjaxHandler.java
@@ -67,6 +67,7 @@
* values.
The events attribute for this tag that can be a
* ValueExpression must be evaluated at tag execution time since the event name is used in the process of
* Behavior creation.
If this tag is nested within a single {@link ClientBehaviorHolder} component:
+ *
*
*
If the events attribute value is not specified, obtain the default event name by calling
* {@link ClientBehaviorHolder#getDefaultEventName}. If that returns null throw an
@@ -77,21 +78,18 @@
*
Add the {@link AjaxBehavior} instance to the {@link ClientBehaviorHolder} component by calling
* {@link ClientBehaviorHolder#addClientBehavior} passing event and the {@link AjaxBehavior} instance.
*
- *
- *
+ *
* Check for the existence of the Ajax resource by calling UIViewRoot.getComponentResources(). If the Ajax
* resource does not exist, create a UIOutput component instance and set the renderer type to
* jakarta.faces.resource.Script. Set the the following attributes in the component's attribute
- * Map: library with the value {@value ResourceHandler#JSF_SCRIPT_LIBRARY_NAME} and
- * name with the value {@value ResourceHandler#JSF_SCRIPT_RESOURCE_NAME}. Install the component resource
+ * Map: library with the value {@value ResourceHandler#FACES_SCRIPT_LIBRARY_NAME} and
+ * name with the value {@value ResourceHandler#FACES_SCRIPT_RESOURCE_NAME}. Install the component resource
* using UIViewRoot.addComponentResource() and specifying head as the target
* argument.
- *
- *
+ *
* If this tag has component children, add the {@link AjaxBehavior} to {@link AjaxBehaviors} by calling
* {@link AjaxBehaviors#pushBehavior}. As subsequent child components that implement the {@link ClientBehaviorHolder}
* interface are evaluated this {@link AjaxBehavior} instance must be added as a behavior to the component.
- *
*
* @version $Id: AjaxHandler.java 5369 2008-09-08 19:53:45Z rogerk $
*/
@@ -304,10 +302,10 @@ private AjaxBehavior createAjaxBehavior(FaceletContext ctx, UIComponent parent,
if (parent instanceof BehaviorHolderWrapper) {
ValueExpression targets = ((BehaviorHolderWrapper) parent).getTargets();
-
+
if (targets != null) {
String targetClientIds = (String) targets.getValue(ctx);
-
+
if (targetClientIds != null) {
Collection executeClientIds = new ArrayList<>(behavior.getExecute());
@@ -324,15 +322,15 @@ private AjaxBehavior createAjaxBehavior(FaceletContext ctx, UIComponent parent,
if (null != listener) {
behavior.addAjaxBehaviorListener(
- new AjaxBehaviorListenerImpl(listener.getMethodExpression(ctx, Object.class, new Class[] { AjaxBehaviorEvent.class }),
- listener.getMethodExpression(ctx, Object.class, new Class[] {})));
+ new AjaxBehaviorListenerImpl(listener.getMethodExpression(ctx, Object.class, new Class>[] { AjaxBehaviorEvent.class }),
+ listener.getMethodExpression(ctx, Object.class, new Class>[] {})));
}
return behavior;
}
// Sets the value from the TagAttribute on the behavior
- private void setBehaviorAttribute(FaceletContext ctx, AjaxBehavior behavior, TagAttribute attr, Class type) {
+ private void setBehaviorAttribute(FaceletContext ctx, AjaxBehavior behavior, TagAttribute attr, Class> type) {
if (attr != null) {
behavior.setValueExpression(attr.getLocalName(), attr.getValueExpression(ctx, type));
From 963d3cf2e644ed37f980cb77cf2182428bc43d86 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Thu, 7 Sep 2023 14:37:59 -0400
Subject: [PATCH 14/44] Fix javadoc errors on #5032 (com.sun.faces.* is also
checked in 4.0)
---
.../facelets/tag/composite/RetargetedAjaxBehavior.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java b/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
index 8e05be622b..2937244c65 100644
--- a/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
+++ b/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
@@ -30,12 +30,12 @@
import javax.faces.event.BehaviorEvent;
/**
- * Basically represents which is retargeted by in AjaxHandler and checked in AjaxBehaviorRenderer.
+ * Basically represents {@code } which is retargeted by {@code } in {@code AjaxHandler} and checked in {@code AjaxBehaviorRenderer}.
*
- * We should probably introduce AjaxBehaviorWrapper in Faces.next to reduce boilerplate like this.
+ * We should probably introduce {@code AjaxBehaviorWrapper} in Faces.next to reduce boilerplate like this.
*
- * @see https://github.com/jakartaee/faces/issues/1567
- * @see https://github.com/eclipse-ee4j/mojarra/issues/5032
+ * - https://github.com/jakartaee/faces/issues/1567
+ * - https://github.com/eclipse-ee4j/mojarra/issues/5032
*/
public class RetargetedAjaxBehavior extends AjaxBehavior {
From d7029ed9545bdf809d88868188f58ef3a5c894bb Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Fri, 8 Sep 2023 06:49:44 -0400
Subject: [PATCH 15/44] https://github.com/jakartaee/faces/issues/1567 Fixed
regression error which caused spec1567IT to fail; the composite instance is
needed further down in ComponentNotFoundException block
---
.../sun/faces/renderkit/html_basic/AjaxBehaviorRenderer.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/impl/src/main/java/com/sun/faces/renderkit/html_basic/AjaxBehaviorRenderer.java b/impl/src/main/java/com/sun/faces/renderkit/html_basic/AjaxBehaviorRenderer.java
index d54067e66c..943547fac7 100644
--- a/impl/src/main/java/com/sun/faces/renderkit/html_basic/AjaxBehaviorRenderer.java
+++ b/impl/src/main/java/com/sun/faces/renderkit/html_basic/AjaxBehaviorRenderer.java
@@ -319,7 +319,7 @@ private static void appendIds(FacesContext facesContext,
boolean first = true;
- UIComponent composite = (ajaxBehavior instanceof RetargetedAjaxBehavior) ? UIComponent.getCompositeComponentParent(component) : null;
+ UIComponent composite = UIComponent.getCompositeComponentParent(component);
String separatorChar = String.valueOf(getSeparatorChar(facesContext));
for (String id : ids) {
@@ -336,7 +336,7 @@ private static void appendIds(FacesContext facesContext,
boolean clientResolveableExpression = expression.equals("@all") || expression.equals("@none") || expression.equals("@form") || expression.equals("@this");
- if (composite != null && (expression.equals("@this") || expression.startsWith("@this" + separatorChar))) {
+ if (composite != null && (ajaxBehavior instanceof RetargetedAjaxBehavior) && (expression.equals("@this") || expression.startsWith("@this" + separatorChar))) {
expression = expression.replaceFirst("@this", separatorChar + composite.getClientId(facesContext));
clientResolveableExpression = false;
}
From 1d2268cecfc453e7d2a834bcad50cd1e7d28e38f Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Fri, 8 Sep 2023 07:23:37 -0400
Subject: [PATCH 16/44] Fixed regression error which caused 3rd form of
spec1567IT to fail; the 'this' instance being passed into getScript() was the
wrong one
---
.../faces/facelets/tag/composite/RetargetedAjaxBehavior.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java b/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
index 2937244c65..980c8b15cf 100644
--- a/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
+++ b/impl/src/main/java/com/sun/faces/facelets/tag/composite/RetargetedAjaxBehavior.java
@@ -28,6 +28,7 @@
import javax.faces.event.AbortProcessingException;
import javax.faces.event.AjaxBehaviorListener;
import javax.faces.event.BehaviorEvent;
+import javax.faces.render.ClientBehaviorRenderer;
/**
* Basically represents {@code } which is retargeted by {@code } in {@code AjaxHandler} and checked in {@code AjaxBehaviorRenderer}.
@@ -47,7 +48,8 @@ public RetargetedAjaxBehavior(AjaxBehavior retargeted) {
@Override
public String getScript(ClientBehaviorContext behaviorContext) {
- return retargeted.getScript(behaviorContext);
+ ClientBehaviorRenderer renderer = getRenderer(behaviorContext.getFacesContext());
+ return renderer != null ? renderer.getScript(behaviorContext, this) : null;
}
@Override
From 5256df0e6f53d886427d8efc28e73dabb62b46fe Mon Sep 17 00:00:00 2001
From: Eclipse Mojarra Bot
Date: Fri, 8 Sep 2023 14:45:18 +0000
Subject: [PATCH 17/44] Prepare release org.glassfish:mojarra-parent:4.0.4
---
action/pom.xml | 2 +-
cdi/pom.xml | 2 +-
impl/pom.xml | 2 +-
pom.xml | 2 +-
rest/pom.xml | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/action/pom.xml b/action/pom.xml
index f5fd8afa1b..e26fedbc01 100644
--- a/action/pom.xml
+++ b/action/pom.xml
@@ -22,7 +22,7 @@
org.glassfishmojarra-parent
- 4.0.4-SNAPSHOT
+ 4.0.4org.eclipse.mojarra
diff --git a/cdi/pom.xml b/cdi/pom.xml
index f2d602fcbf..58be26230a 100644
--- a/cdi/pom.xml
+++ b/cdi/pom.xml
@@ -22,7 +22,7 @@
org.glassfishmojarra-parent
- 4.0.4-SNAPSHOT
+ 4.0.4org.eclipse.mojarra
diff --git a/impl/pom.xml b/impl/pom.xml
index 6fdeed619a..39f631bf10 100644
--- a/impl/pom.xml
+++ b/impl/pom.xml
@@ -29,7 +29,7 @@
org.glassfishmojarra-parent
- 4.0.4-SNAPSHOT
+ 4.0.4jakarta.faces
diff --git a/pom.xml b/pom.xml
index 7e5bf323ec..3b1e305b75 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
org.glassfishmojarra-parent
- 4.0.4-SNAPSHOT
+ 4.0.4pomMojarra ${project.version} - Project
diff --git a/rest/pom.xml b/rest/pom.xml
index 1cdd181430..ae79c04c0b 100644
--- a/rest/pom.xml
+++ b/rest/pom.xml
@@ -22,7 +22,7 @@
org.glassfishmojarra-parent
- 4.0.4-SNAPSHOT
+ 4.0.4org.eclipse.mojarra
From 606b3c7da9af96d26565d288ec8d5287d8ce4206 Mon Sep 17 00:00:00 2001
From: Eclipse Mojarra Bot
Date: Fri, 8 Sep 2023 14:47:37 +0000
Subject: [PATCH 18/44] Prepare next development cycle for 4.0.5-SNAPSHOT
---
action/pom.xml | 2 +-
cdi/pom.xml | 2 +-
impl/pom.xml | 2 +-
pom.xml | 2 +-
rest/pom.xml | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/action/pom.xml b/action/pom.xml
index e26fedbc01..0739f3729e 100644
--- a/action/pom.xml
+++ b/action/pom.xml
@@ -22,7 +22,7 @@
org.glassfishmojarra-parent
- 4.0.4
+ 4.0.5-SNAPSHOTorg.eclipse.mojarra
diff --git a/cdi/pom.xml b/cdi/pom.xml
index 58be26230a..9726b77270 100644
--- a/cdi/pom.xml
+++ b/cdi/pom.xml
@@ -22,7 +22,7 @@
org.glassfishmojarra-parent
- 4.0.4
+ 4.0.5-SNAPSHOTorg.eclipse.mojarra
diff --git a/impl/pom.xml b/impl/pom.xml
index 39f631bf10..49bf07d410 100644
--- a/impl/pom.xml
+++ b/impl/pom.xml
@@ -29,7 +29,7 @@
org.glassfishmojarra-parent
- 4.0.4
+ 4.0.5-SNAPSHOTjakarta.faces
diff --git a/pom.xml b/pom.xml
index 3b1e305b75..7ce609e63f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
org.glassfishmojarra-parent
- 4.0.4
+ 4.0.5-SNAPSHOTpomMojarra ${project.version} - Project
diff --git a/rest/pom.xml b/rest/pom.xml
index ae79c04c0b..7dcc5989a1 100644
--- a/rest/pom.xml
+++ b/rest/pom.xml
@@ -22,7 +22,7 @@
org.glassfishmojarra-parent
- 4.0.4
+ 4.0.5-SNAPSHOTorg.eclipse.mojarra
From e21dd15ac1bb12e1fa344e2aeb57165cf162218d Mon Sep 17 00:00:00 2001
From: Eclipse Mojarra Bot
Date: Fri, 8 Sep 2023 15:00:08 +0000
Subject: [PATCH 19/44] Prepare release org.glassfish:mojarra-parent:2.3.21
---
impl/pom.xml | 2 +-
pom.xml | 2 +-
test/pom.xml | 2 +-
util/pom.xml | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/impl/pom.xml b/impl/pom.xml
index 827c05871b..35deebf9f1 100644
--- a/impl/pom.xml
+++ b/impl/pom.xml
@@ -27,7 +27,7 @@
org.glassfishmojarra-parent
- 2.3.21-SNAPSHOT
+ 2.3.21jakarta.faces
diff --git a/pom.xml b/pom.xml
index c6fff1635f..bc3a61b04a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,7 +27,7 @@
org.glassfishmojarra-parent
- 2.3.21-SNAPSHOT
+ 2.3.21pomMojarra ${project.version} - Project
diff --git a/test/pom.xml b/test/pom.xml
index 2b3051d2ce..8bc8dc1f17 100644
--- a/test/pom.xml
+++ b/test/pom.xml
@@ -193,7 +193,7 @@
com.sun.facesutil
- 2.3.21-SNAPSHOT
+ 2.3.21test
diff --git a/util/pom.xml b/util/pom.xml
index ed3fe7a2ef..653da890bc 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -24,7 +24,7 @@
org.glassfishmojarra-parent
- 2.3.21-SNAPSHOT
+ 2.3.21com.sun.faces
From f4b475f38e63b0fec2a60706e27d6cb082f912b0 Mon Sep 17 00:00:00 2001
From: Eclipse Mojarra Bot
Date: Fri, 8 Sep 2023 15:02:15 +0000
Subject: [PATCH 20/44] Prepare next development cycle for 2.3.22-SNAPSHOT
---
impl/pom.xml | 2 +-
pom.xml | 2 +-
test/pom.xml | 2 +-
util/pom.xml | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/impl/pom.xml b/impl/pom.xml
index 35deebf9f1..282f43f929 100644
--- a/impl/pom.xml
+++ b/impl/pom.xml
@@ -27,7 +27,7 @@
org.glassfishmojarra-parent
- 2.3.21
+ 2.3.22-SNAPSHOTjakarta.faces
diff --git a/pom.xml b/pom.xml
index bc3a61b04a..8370769588 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,7 +27,7 @@
org.glassfishmojarra-parent
- 2.3.21
+ 2.3.22-SNAPSHOTpomMojarra ${project.version} - Project
diff --git a/test/pom.xml b/test/pom.xml
index 8bc8dc1f17..5d6fd2834d 100644
--- a/test/pom.xml
+++ b/test/pom.xml
@@ -193,7 +193,7 @@
com.sun.facesutil
- 2.3.21
+ 2.3.22-SNAPSHOTtest
diff --git a/util/pom.xml b/util/pom.xml
index 653da890bc..f494ccabf3 100644
--- a/util/pom.xml
+++ b/util/pom.xml
@@ -24,7 +24,7 @@
org.glassfishmojarra-parent
- 2.3.21
+ 2.3.22-SNAPSHOTcom.sun.faces
From 1f272e5e6842f21137a37a7730fef0f2889ec160 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sat, 9 Sep 2023 11:54:19 -0400
Subject: [PATCH 21/44] Composite component can't find reparented child when
it's in turn in another NamingContainer within the composite such as h:form
or h:dataTable; upon code analysis I found a line which seemed completely
unnecessary so I have removed it and it works again for me.
https://github.com/eclipse-ee4j/mojarra/issues/5214
---
.../facelets/tag/faces/ComponentTagHandlerDelegateImpl.java | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/impl/src/main/java/com/sun/faces/facelets/tag/faces/ComponentTagHandlerDelegateImpl.java b/impl/src/main/java/com/sun/faces/facelets/tag/faces/ComponentTagHandlerDelegateImpl.java
index 4a9b9c1637..3a58883cce 100644
--- a/impl/src/main/java/com/sun/faces/facelets/tag/faces/ComponentTagHandlerDelegateImpl.java
+++ b/impl/src/main/java/com/sun/faces/facelets/tag/faces/ComponentTagHandlerDelegateImpl.java
@@ -462,10 +462,7 @@ protected UIComponent findChild(FaceletContext ctx, UIComponent parent, String t
protected UIComponent findReparentedComponent(FaceletContext ctx, UIComponent parent, String tagId) {
UIComponent facet = parent.getFacets().get(UIComponent.COMPOSITE_FACET_NAME);
if (facet != null) {
- UIComponent newParent = facet.findComponent((String) parent.getAttributes().get(tagId));
- if (newParent != null) {
- return ComponentSupport.findChildByTagId(ctx.getFacesContext(), newParent, tagId);
- }
+ return findChild(ctx, facet, tagId);
}
return null;
}
From 6e8224e8daf0af16e4a682d9d85aebd6f18dae4e Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sat, 30 Sep 2023 11:01:23 -0400
Subject: [PATCH 22/44] Move back weld reinit from ConfigureListener into
FacesInitializer https://github.com/eclipse-ee4j/mojarra/issues/5321
---
.../sun/faces/config/FacesInitializer.java | 43 +++++++++++++++++++
.../main/java/com/sun/faces/util/Util.java | 15 -------
2 files changed, 43 insertions(+), 15 deletions(-)
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 e56a2bc78d..c01c0aa277 100644
--- a/impl/src/main/java/com/sun/faces/config/FacesInitializer.java
+++ b/impl/src/main/java/com/sun/faces/config/FacesInitializer.java
@@ -22,11 +22,16 @@
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;
import java.util.Map;
import java.util.Set;
+import java.util.logging.Logger;
+import com.sun.faces.util.FacesLogger;
+
+import jakarta.enterprise.inject.spi.BeanManager;
import jakarta.faces.annotation.FacesConfig;
import jakarta.faces.application.ResourceDependencies;
import jakarta.faces.application.ResourceDependency;
@@ -84,6 +89,8 @@
public class FacesInitializer implements ServletContainerInitializer {
// NOTE: Logging should not be used with this class.
+ // NOTE: It can, we only need to ensure that the logger is only invoked when there's a (Init)FacesContext.
+ private static final Logger LOGGER = FacesLogger.CONFIG.getLogger();
public static final String FACES_PACKAGE_PREFIX = "jakarta.faces.";
public static final String MOJARRA_PACKAGE_PREFIX = "com.sun.faces.";
@@ -112,6 +119,7 @@ public void onStartup(Set> classes, ServletContext servletContext) thro
}
// Other concerns also handled if there is an existing Faces Servlet mapping
+ handleCdiConcerns(servletContext);
handleWebSocketConcerns(servletContext);
// The Configure listener will do the bulk of initializing (configuring) Faces in a later phase.
@@ -204,6 +212,41 @@ private static void handleMappingConcerns(ServletContext servletContext) throws
servletContext.setAttribute(FACES_SERVLET_REGISTRATION, newFacesServletRegistration);
}
+ private static void handleCdiConcerns(ServletContext context) throws ServletException {
+ // If Weld is used as CDI impl then make sure it doesn't skip initialization when there's no BDA. See also #5232 and #5321
+
+ if (context.getAttribute("org.jboss.weld.environment.servlet.jakarta.enterprise.inject.spi.BeanManager") instanceof BeanManager) {
+ // Already initialized.
+ return;
+ }
+
+ ClassLoader cl = context.getClassLoader();
+ Class> weldInitializerClass;
+
+ try {
+ weldInitializerClass = cl.loadClass("org.jboss.weld.environment.servlet.EnhancedListener");
+ }
+ catch (ClassNotFoundException ignore) {
+ // Weld is actually not being used. That's OK for now, so just continue as usual.
+ return;
+ }
+
+ // Weld is being used so let's make sure it doesn't skip initialization when there's no BDA.
+ context.setInitParameter("org.jboss.weld.environment.servlet.archive.isolation", "false");
+
+ if (context.getAttribute("org.jboss.weld.environment.servlet.enhancedListenerUsed") == Boolean.TRUE) {
+ try {
+ LOGGER.log(WARNING, "Weld skipped initialization - forcing it to reinitialize");
+ ServletContainerInitializer weldInitializer = (ServletContainerInitializer) weldInitializerClass.getConstructor().newInstance();
+ weldInitializer.onStartup(null, context);
+ }
+ catch (Exception | LinkageError e) {
+ // Weld is being used but it failed for unclear reason while CDI should be enabled. That's not OK, so rethrow as ServletException.
+ throw new ServletException("Reinitializing Weld failed - giving up, please make sure your project contains at least one bean class with a bean defining annotation and retry", e);
+ }
+ }
+ }
+
private static void handleWebSocketConcerns(ServletContext context) throws ServletException {
if (context.getAttribute(ServerContainer.class.getName()) != null) {
// Already initialized
diff --git a/impl/src/main/java/com/sun/faces/util/Util.java b/impl/src/main/java/com/sun/faces/util/Util.java
index 48e26e1d96..14c62e2db7 100644
--- a/impl/src/main/java/com/sun/faces/util/Util.java
+++ b/impl/src/main/java/com/sun/faces/util/Util.java
@@ -30,7 +30,6 @@
import static java.util.Collections.emptyList;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.SEVERE;
-import static java.util.logging.Level.WARNING;
import java.beans.FeatureDescriptor;
import java.io.IOException;
@@ -101,7 +100,6 @@
import jakarta.faces.event.AbortProcessingException;
import jakarta.faces.render.ResponseStateManager;
import jakarta.faces.webapp.FacesServlet;
-import jakarta.servlet.ServletContainerInitializer;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletRegistration;
import jakarta.servlet.http.HttpServletMapping;
@@ -1476,19 +1474,6 @@ public static BeanManager getCdiBeanManager(FacesContext facesContext) {
if (result == null && facesContext != null) {
Map applicationMap = facesContext.getExternalContext().getApplicationMap();
result = (BeanManager) applicationMap.get("org.jboss.weld.environment.servlet.jakarta.enterprise.inject.spi.BeanManager");
-
- if (result == null && applicationMap.get("org.jboss.weld.environment.servlet.enhancedListenerUsed") == Boolean.TRUE) {
- LOGGER.log(WARNING, "Weld skipped initialization - forcing it to reinitialize");
- try {
- ServletContext servletContext = (ServletContext) facesContext.getExternalContext().getContext();
- servletContext.setInitParameter("org.jboss.weld.environment.servlet.archive.isolation", "false");
- ServletContainerInitializer weld = (ServletContainerInitializer) Class.forName("org.jboss.weld.environment.servlet.EnhancedListener").getConstructor().newInstance();
- weld.onStartup(null, servletContext);
- result = (BeanManager) applicationMap.get("org.jboss.weld.environment.servlet.jakarta.enterprise.inject.spi.BeanManager");
- } catch (Exception | LinkageError e) {
- LOGGER.log(WARNING, "Reinitializing Weld failed - giving up, please make sure your project contains at least one bean class with a bean defining annotation and retry", e);
- }
- }
}
if (result != null && facesContext != null) {
From 08997dea23d86e499fb9748c0cb365c1f867889e Mon Sep 17 00:00:00 2001
From: Manfred Riem
Date: Sun, 1 Oct 2023 08:07:55 -0500
Subject: [PATCH 23/44] Fixes #5316 - ClientWindow: Custom
PrimeClientWindowFactory not being respected (#5323)
Co-authored-by: Manfred Riem
---
.../sun/faces/lifecycle/LifecycleImpl.java | 28 -------------------
1 file changed, 28 deletions(-)
diff --git a/impl/src/main/java/com/sun/faces/lifecycle/LifecycleImpl.java b/impl/src/main/java/com/sun/faces/lifecycle/LifecycleImpl.java
index 42a6b9577a..9811f3620a 100644
--- a/impl/src/main/java/com/sun/faces/lifecycle/LifecycleImpl.java
+++ b/impl/src/main/java/com/sun/faces/lifecycle/LifecycleImpl.java
@@ -66,46 +66,18 @@ public class LifecycleImpl extends Lifecycle {
// List for registered PhaseListeners
private List listeners = new CopyOnWriteArrayList<>();
- private boolean isClientWindowEnabled = false;
- private WebConfiguration config;
public LifecycleImpl() {
-
}
public LifecycleImpl(FacesContext context) {
- ExternalContext extContext = context.getExternalContext();
- config = WebConfiguration.getInstance(extContext);
- context.getApplication().subscribeToEvent(PostConstructApplicationEvent.class, Application.class, new PostConstructApplicationListener());
-
- }
-
- private class PostConstructApplicationListener implements SystemEventListener {
-
- @Override
- public boolean isListenerForSource(Object source) {
- return source instanceof Application;
- }
-
- @Override
- public void processEvent(SystemEvent event) throws AbortProcessingException {
- postConstructApplicationInitialization();
- }
-
}
- private void postConstructApplicationInitialization() {
- String optionValue = config.getOptionValue(WebConfiguration.WebContextInitParameter.ClientWindowMode);
- isClientWindowEnabled = null != optionValue && !optionValue.equals(WebConfiguration.WebContextInitParameter.ClientWindowMode.getDefaultValue());
- }
// ------------------------------------------------------- Lifecycle Methods
@Override
public void attachWindow(FacesContext context) {
- if (!isClientWindowEnabled) {
- return;
- }
if (context == null) {
throw new NullPointerException(MessageUtils.getExceptionMessageString(MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "context"));
}
From ac296492a5f406f34cf8a699e0ed53b106c50e7a Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sun, 8 Oct 2023 12:04:07 -0400
Subject: [PATCH 24/44] Refactor retrieval and validation of webapp contracts
directory into a single place and fixed a couple of misassumptions about it
always being an absolute path
https://github.com/eclipse-ee4j/mojarra/issues/5329
---
.../application/ApplicationAssociate.java | 11 ++++++----
.../resource/FaceletWebappResourceHelper.java | 13 +++++------
.../application/resource/ResourceManager.java | 19 +++++++++++++---
.../sun/faces/config/WebConfiguration.java | 4 ++--
.../faces/facelets/impl/DefaultFacelet.java | 21 ++++++++++--------
.../facelets/impl/DefaultFaceletFactory.java | 22 +++++++++++++++++++
.../facelets/tag/ui/CompositionHandler.java | 7 +-----
.../facelets/tag/ui/DecorateHandler.java | 7 +-----
.../faces/facelets/tag/ui/IncludeHandler.java | 7 +-----
.../sun/faces/renderkit/RenderKitUtils.java | 6 ++---
.../html_basic/ScriptStyleBaseRenderer.java | 6 ++---
11 files changed, 73 insertions(+), 50 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 8b9f6b1440..9ac13faae4 100644
--- a/impl/src/main/java/com/sun/faces/application/ApplicationAssociate.java
+++ b/impl/src/main/java/com/sun/faces/application/ApplicationAssociate.java
@@ -201,12 +201,15 @@ public static ApplicationAssociate getCurrentInstance() {
}
public static ApplicationAssociate getInstance() {
- FacesContext facesContext = FacesContext.getCurrentInstance();
+ return getInstance(FacesContext.getCurrentInstance());
+ }
+
+ public static ApplicationAssociate getInstance(FacesContext facesContext) {
if (facesContext == null) {
- return null;
- }
+ return null;
+ }
- return ApplicationAssociate.getInstance(facesContext.getExternalContext());
+ return ApplicationAssociate.getInstance(facesContext.getExternalContext());
}
public static ApplicationAssociate getInstance(ExternalContext externalContext) {
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 513fbb8cc7..2d5508650e 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
@@ -19,7 +19,6 @@
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.config.WebConfiguration.WebContextInitParameter.WebAppContractsDirectory;
import static jakarta.faces.application.ResourceVisitOption.TOP_LEVEL_VIEWS_ONLY;
import static java.util.Spliterator.DISTINCT;
import static java.util.Spliterators.spliteratorUnknownSize;
@@ -48,12 +47,12 @@ public class FaceletWebappResourceHelper extends ResourceHelper {
private static final String[] RESTRICTED_DIRECTORIES = { "/WEB-INF/", "/META-INF/" };
- private final String webAppContractsDirectory;
+ private final ResourceHelper webappResourceHelper;
private final String[] configuredExtensions;
- public FaceletWebappResourceHelper() {
+ public FaceletWebappResourceHelper(WebappResourceHelper webappResourceHelper) {
+ this.webappResourceHelper = webappResourceHelper;
WebConfiguration webConfig = WebConfiguration.getInstance();
- webAppContractsDirectory = webConfig.getOptionValue(WebAppContractsDirectory);
configuredExtensions = webConfig.getOptionValue(FaceletsSuffix, " ");
}
@@ -150,9 +149,9 @@ private URL findResourceInfoConsideringContracts(FacesContext ctx, String baseRe
for (String contract : contracts) {
if (baseResourceName.startsWith("/")) {
- resourceName = webAppContractsDirectory + "/" + contract + baseResourceName;
+ resourceName = getBaseContractsPath() + "/" + contract + baseResourceName;
} else {
- resourceName = webAppContractsDirectory + "/" + contract + "/" + baseResourceName;
+ resourceName = getBaseContractsPath() + "/" + contract + "/" + baseResourceName;
}
url = Resource.getResourceUrl(ctx, resourceName);
@@ -226,7 +225,7 @@ public String getBaseResourcePath() {
@Override
public String getBaseContractsPath() {
- return webAppContractsDirectory;
+ return webappResourceHelper.getBaseContractsPath();
}
@Override
diff --git a/impl/src/main/java/com/sun/faces/application/resource/ResourceManager.java b/impl/src/main/java/com/sun/faces/application/resource/ResourceManager.java
index 2a491fa2b8..2d3b3ea631 100644
--- a/impl/src/main/java/com/sun/faces/application/resource/ResourceManager.java
+++ b/impl/src/main/java/com/sun/faces/application/resource/ResourceManager.java
@@ -16,6 +16,8 @@
package com.sun.faces.application.resource;
+import static com.sun.faces.util.Util.ensureLeadingSlash;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -57,12 +59,15 @@ public class ResourceManager {
*/
private static final Pattern CONFIG_MIMETYPE_PATTERN = Pattern.compile("[a-z-]*/[a-z0-9.\\*-]*");
- private FaceletWebappResourceHelper faceletWebappResourceHelper = new FaceletWebappResourceHelper();
-
/**
* {@link ResourceHelper} used for looking up webapp-based resources.
*/
- private ResourceHelper webappResourceHelper = new WebappResourceHelper();
+ private WebappResourceHelper webappResourceHelper = new WebappResourceHelper();
+
+ /**
+ * {@link ResourceHelper} used for looking up webapp-based facelets resources.
+ */
+ private FaceletWebappResourceHelper faceletWebappResourceHelper = new FaceletWebappResourceHelper(webappResourceHelper);
/**
* {@link ResourceHelper} used for looking up classpath-based resources.
@@ -175,6 +180,14 @@ public ResourceInfo findResource(String libraryName, String resourceName, String
public Stream getViewResources(FacesContext facesContext, String path, int maxDepth, ResourceVisitOption... options) {
return faceletWebappResourceHelper.getViewResources(facesContext, path, maxDepth, options);
}
+
+ public String getBaseContractsPath() {
+ return faceletWebappResourceHelper.getBaseContractsPath();
+ }
+
+ public boolean isContractsResource(String path) {
+ return ensureLeadingSlash(path).startsWith(getBaseContractsPath());
+ }
// ----------------------------------------------------- Private Methods
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 da43ad076e..7b72496284 100644
--- a/impl/src/main/java/com/sun/faces/config/WebConfiguration.java
+++ b/impl/src/main/java/com/sun/faces/config/WebConfiguration.java
@@ -396,7 +396,8 @@ private void discoverResourceLibraryContracts() {
Set candidates;
// Scan for "contractMappings" in the web app root
- String contractsDirName = getOptionValue(WebContextInitParameter.WebAppContractsDirectory);
+ ApplicationAssociate associate = ApplicationAssociate.getCurrentInstance();
+ String contractsDirName = associate.getResourceManager().getBaseContractsPath();
assert null != contractsDirName;
candidates = extContex.getResourcePaths(contractsDirName);
if (null != candidates) {
@@ -437,7 +438,6 @@ private void discoverResourceLibraryContracts() {
Map> contractMappings = new HashMap<>();
- ApplicationAssociate associate = ApplicationAssociate.getCurrentInstance();
Map> contractsFromConfig = associate.getResourceLibraryContracts();
List contractsToExpose;
diff --git a/impl/src/main/java/com/sun/faces/facelets/impl/DefaultFacelet.java b/impl/src/main/java/com/sun/faces/facelets/impl/DefaultFacelet.java
index 83ae43e195..824a8c42a5 100644
--- a/impl/src/main/java/com/sun/faces/facelets/impl/DefaultFacelet.java
+++ b/impl/src/main/java/com/sun/faces/facelets/impl/DefaultFacelet.java
@@ -230,14 +230,14 @@ public long getCreateTime() {
}
/**
- * Delegates resolution to DefaultFaceletFactory reference. Also, caches URLs for relative paths.
+ * Delegates resolution to DefaultFaceletFactory reference. Also, caches URLs for absolute paths.
*
- * @param path a relative url path
+ * @param relativePath a relative url path
* @return URL pointing to destination
* @throws IOException if there is a problem creating the URL for the path specified
*/
- private URL getRelativePath(String path) throws IOException {
- return factory.resolveURL(src, path);
+ private URL resolveURL(String relativePath) throws IOException {
+ return factory.resolveURL(src, relativePath);
}
/**
@@ -268,21 +268,21 @@ private void include(DefaultFaceletContext ctx, UIComponent parent) throws IOExc
/**
* Used for delegation by the DefaultFaceletContext. First pulls the URL from {@link #getRelativePath(String)
- * getRelativePath(String)}, then calls
+ * getRelativePath(String)}, then validates that the path does not represent a contracts resource, then calls
* {@link #include(DefaultFaceletContext, jakarta.faces.component.UIComponent, String)}.
*
* @see FaceletContext#includeFacelet(UIComponent, String)
* @param ctx FaceletContext to pass to the included Facelet
* @param parent UIComponent to apply changes to
- * @param path relative path to the desired Facelet from the FaceletContext
+ * @param relativePath relative path to the desired Facelet from the FaceletContext
* @throws IOException
* @throws FacesException
* @throws FaceletException
* @throws ELException
*/
- public void include(DefaultFaceletContext ctx, UIComponent parent, String path) throws IOException {
+ public void include(DefaultFaceletContext ctx, UIComponent parent, String relativePath) throws IOException {
URL url;
- if (path.equals(JAKARTA_FACES_ERROR_XHTML)) {
+ if (relativePath.equals(JAKARTA_FACES_ERROR_XHTML)) {
if (isDevelopment(ctx)) {
// try using this class' ClassLoader
url = getErrorFacelet(DefaultFacelet.class.getClassLoader());
@@ -293,7 +293,10 @@ public void include(DefaultFaceletContext ctx, UIComponent parent, String path)
return;
}
} else {
- url = getRelativePath(path);
+ url = resolveURL(relativePath);
+ if (factory.isContractsResource(url)) {
+ throw new IOException("Contract resources cannot be accessed this way");
+ }
}
this.include(ctx, parent, url);
}
diff --git a/impl/src/main/java/com/sun/faces/facelets/impl/DefaultFaceletFactory.java b/impl/src/main/java/com/sun/faces/facelets/impl/DefaultFaceletFactory.java
index b0678ebcb4..082208d22c 100644
--- a/impl/src/main/java/com/sun/faces/facelets/impl/DefaultFaceletFactory.java
+++ b/impl/src/main/java/com/sun/faces/facelets/impl/DefaultFaceletFactory.java
@@ -44,6 +44,8 @@
import java.util.regex.Pattern;
import com.sun.faces.RIConstants;
+import com.sun.faces.application.ApplicationAssociate;
+import com.sun.faces.application.resource.ResourceManager;
import com.sun.faces.config.WebConfiguration;
import com.sun.faces.context.FacesFileNotFoundException;
import com.sun.faces.facelets.compiler.Compiler;
@@ -81,7 +83,9 @@ public class DefaultFaceletFactory {
// provides a custom one. The DefaultResourceResolver simply uses
// the ResourceHandler to do its work.
private DefaultResourceResolver resolver;
+ private ResourceManager manager;
private URL baseUrl;
+ private String baseUrlAsString;
private long refreshPeriod;
private FaceletCache cache;
private ConcurrentMap> cachePerContract;
@@ -104,7 +108,9 @@ public final void init(FacesContext facesContext, Compiler compiler, DefaultReso
this.compiler = compiler;
cachePerContract = new ConcurrentHashMap<>();
this.resolver = resolver;
+ this.manager = ApplicationAssociate.getInstance(externalContext).getResourceManager();
baseUrl = resolver.resolveUrl("/");
+ baseUrlAsString = baseUrl.toExternalForm();
this.idMappers = config.isOptionEnabled(UseFaceletsID) ? null : new Cache<>(new IdMapperFactory());
refreshPeriod = refreshPeriod >= 0 ? refreshPeriod * 1000 : -1;
this.refreshPeriod = refreshPeriod;
@@ -167,6 +173,22 @@ public URL resolveURL(URL source, String path) throws IOException {
return new URL(source, path);
}
+ /**
+ * Returns true if given url is a contracts resource.
+ * @param url source url
+ * @return true if given url is a contracts resource.
+ */
+ public boolean isContractsResource(URL url) {
+ String urlAsString = url.toExternalForm();
+
+ if (!urlAsString.startsWith(baseUrlAsString)) {
+ return false;
+ }
+
+ String path = urlAsString.substring(baseUrlAsString.length());
+ return manager.isContractsResource(path);
+ }
+
/**
* Create a Facelet from the passed URL. This method checks if the cached Facelet needs to be refreshed before
* returning. If so, uses the passed URL to build a new instance;
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 075c1d3ae4..cf004f77a4 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
@@ -25,7 +25,6 @@
import java.util.logging.Level;
import java.util.logging.Logger;
-import com.sun.faces.config.WebConfiguration;
import com.sun.faces.facelets.FaceletContextImplBase;
import com.sun.faces.facelets.TemplateClient;
import com.sun.faces.facelets.el.VariableMapperWrapper;
@@ -127,16 +126,12 @@ public void apply(FaceletContext ctxObj, UIComponent parent) throws IOException
if (path.trim().length() == 0) {
throw new TagAttributeException(tag, template, "Invalid path : " + path);
}
- WebConfiguration webConfig = WebConfiguration.getInstance();
- if (path.startsWith(webConfig.getOptionValue(WebConfiguration.WebContextInitParameter.WebAppContractsDirectory))) {
- throw new TagAttributeException(tag, template, "Invalid path, contract resources cannot be accessed this way : " + path);
- }
ctx.includeFacelet(parent, path);
} catch (IOException e) {
if (log.isLoggable(Level.FINE)) {
log.log(Level.FINE, e.toString(), e);
}
- throw new TagAttributeException(tag, template, "Invalid path : " + path);
+ throw new TagAttributeException(tag, template, "Invalid path : " + path, e);
} finally {
ctx.popClient(this);
ctx.setVariableMapper(orig);
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 0d500e5dd6..7af0fbf184 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
@@ -25,7 +25,6 @@
import java.util.logging.Level;
import java.util.logging.Logger;
-import com.sun.faces.config.WebConfiguration;
import com.sun.faces.facelets.FaceletContextImplBase;
import com.sun.faces.facelets.TemplateClient;
import com.sun.faces.facelets.el.VariableMapperWrapper;
@@ -108,16 +107,12 @@ public void apply(FaceletContext ctxObj, UIComponent parent) throws IOException
if (path.trim().length() == 0) {
throw new TagAttributeException(tag, template, "Invalid path : " + path);
}
- WebConfiguration webConfig = WebConfiguration.getInstance();
- if (path.startsWith(webConfig.getOptionValue(WebConfiguration.WebContextInitParameter.WebAppContractsDirectory))) {
- throw new TagAttributeException(tag, template, "Invalid path, contract resources cannot be accessed this way : " + path);
- }
ctx.includeFacelet(parent, path);
} catch (IOException e) {
if (log.isLoggable(Level.FINE)) {
log.log(Level.FINE, e.toString(), e);
}
- throw new TagAttributeException(tag, template, "Invalid path : " + path);
+ throw new TagAttributeException(tag, template, "Invalid path : " + path, e);
} finally {
ctx.setVariableMapper(orig);
ctx.popClient(this);
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 f78c6dacae..0704901d5d 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
@@ -20,7 +20,6 @@
import java.util.logging.Level;
import java.util.logging.Logger;
-import com.sun.faces.config.WebConfiguration;
import com.sun.faces.facelets.el.VariableMapperWrapper;
import com.sun.faces.facelets.tag.TagHandlerImpl;
import com.sun.faces.util.FacesLogger;
@@ -76,16 +75,12 @@ public void apply(FaceletContext ctx, UIComponent parent) throws IOException {
ctx.setVariableMapper(new VariableMapperWrapper(orig));
try {
nextHandler.apply(ctx, null);
- WebConfiguration webConfig = WebConfiguration.getInstance();
- if (path.startsWith(webConfig.getOptionValue(WebConfiguration.WebContextInitParameter.WebAppContractsDirectory))) {
- throw new TagAttributeException(tag, src, "Invalid src, contract resources cannot be accessed this way : " + path);
- }
ctx.includeFacelet(parent, path);
} catch (IOException e) {
if (log.isLoggable(Level.FINE)) {
log.log(Level.FINE, e.toString(), e);
}
- throw new TagAttributeException(tag, src, "Invalid path : " + path);
+ throw new TagAttributeException(tag, src, "Invalid path : " + path, e);
} finally {
ctx.setVariableMapper(orig);
}
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 36b57a3b43..a1bbd394cd 100644
--- a/impl/src/main/java/com/sun/faces/renderkit/RenderKitUtils.java
+++ b/impl/src/main/java/com/sun/faces/renderkit/RenderKitUtils.java
@@ -37,6 +37,7 @@
import java.util.logging.Logger;
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;
@@ -1219,9 +1220,8 @@ public static String getImageSource(FacesContext context, UIComponent component,
ResourceHandler handler = context.getApplication().getResourceHandler();
if (resName != null) {
String libName = (String) component.getAttributes().get("library");
- WebConfiguration webConfig = WebConfiguration.getInstance();
-
- if (libName == null && resName.startsWith(webConfig.getOptionValue(WebConfiguration.WebContextInitParameter.WebAppContractsDirectory))) {
+
+ 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;
context.addMessage(component.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg));
diff --git a/impl/src/main/java/com/sun/faces/renderkit/html_basic/ScriptStyleBaseRenderer.java b/impl/src/main/java/com/sun/faces/renderkit/html_basic/ScriptStyleBaseRenderer.java
index 39dc2b9fd9..838c722ae8 100644
--- a/impl/src/main/java/com/sun/faces/renderkit/html_basic/ScriptStyleBaseRenderer.java
+++ b/impl/src/main/java/com/sun/faces/renderkit/html_basic/ScriptStyleBaseRenderer.java
@@ -21,7 +21,7 @@
import java.util.Map;
import java.util.logging.Logger;
-import com.sun.faces.config.WebConfiguration;
+import com.sun.faces.application.ApplicationAssociate;
import com.sun.faces.util.FacesLogger;
import jakarta.faces.application.FacesMessage;
@@ -194,9 +194,7 @@ public void encodeEnd(FacesContext context, UIComponent component) throws IOExce
ResponseWriter writer = context.getResponseWriter();
startExternalElement(context, writer, component);
- WebConfiguration webConfig = WebConfiguration.getInstance();
-
- if (library == null && name != null && name.startsWith(webConfig.getOptionValue(WebConfiguration.WebContextInitParameter.WebAppContractsDirectory))) {
+ if (library == null && name != null && ApplicationAssociate.getInstance(context).getResourceManager().isContractsResource(name)) {
if (context.isProjectStage(ProjectStage.Development)) {
String msg = "Illegal path, direct contract references are not allowed: " + name;
context.addMessage(component.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg));
From 9f72851c7602fc2e6d7afeb7547fde1327bc4338 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sun, 8 Oct 2023 12:07:40 -0400
Subject: [PATCH 25/44] Fixed creepy whitespace after self-review
---
.../com/sun/faces/application/ApplicationAssociate.java | 6 +++---
1 file changed, 3 insertions(+), 3 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 9ac13faae4..36d61b5bcb 100644
--- a/impl/src/main/java/com/sun/faces/application/ApplicationAssociate.java
+++ b/impl/src/main/java/com/sun/faces/application/ApplicationAssociate.java
@@ -201,15 +201,15 @@ public static ApplicationAssociate getCurrentInstance() {
}
public static ApplicationAssociate getInstance() {
- return getInstance(FacesContext.getCurrentInstance());
+ return getInstance(FacesContext.getCurrentInstance());
}
public static ApplicationAssociate getInstance(FacesContext facesContext) {
if (facesContext == null) {
return null;
- }
+ }
- return ApplicationAssociate.getInstance(facesContext.getExternalContext());
+ return ApplicationAssociate.getInstance(facesContext.getExternalContext());
}
public static ApplicationAssociate getInstance(ExternalContext externalContext) {
From f45d5ae8218aec3ba7985b4d1b93f523110b6797 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sat, 14 Oct 2023 14:09:59 -0400
Subject: [PATCH 26/44] Remove unused constants for com.sun.faces.* context
params https://github.com/eclipse-ee4j/mojarra/issues/5331
---
.../main/java/com/sun/faces/config/WebConfiguration.java | 8 --------
1 file changed, 8 deletions(-)
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 7b72496284..1c4379aa72 100644
--- a/impl/src/main/java/com/sun/faces/config/WebConfiguration.java
+++ b/impl/src/main/java/com/sun/faces/config/WebConfiguration.java
@@ -749,7 +749,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.
- ManagedBeanFactoryDecorator("com.sun.faces.managedBeanFactoryDecoratorClass", ""),
StateSavingMethod(StateManager.STATE_SAVING_METHOD_PARAM_NAME, "server"),
FaceletsSuffix(ViewHandler.FACELETS_SUFFIX_PARAM_NAME, ViewHandler.DEFAULT_FACELETS_SUFFIX),
JakartaFacesConfigFiles(FacesServlet.CONFIG_FILES_ATTR, ""),
@@ -767,7 +766,6 @@ public enum WebContextInitParameter {
FaceletsBufferSize(ViewHandler.FACELETS_BUFFER_SIZE_PARAM_NAME, "1024"),
ClientStateWriteBufferSize("com.sun.faces.clientStateWriteBufferSize", "8192"),
ResourceBufferSize("com.sun.faces.resourceBufferSize", "2048"),
- ExpressionFactory("com.sun.faces.expressionFactory", "com.sun.el.ExpressionFactoryImpl"),
ClientStateTimeout("com.sun.faces.clientStateTimeout", ""),
DefaultResourceMaxAge("com.sun.faces.defaultResourceMaxAge", "604800000"), // 7 days
ResourceUpdateCheckPeriod("com.sun.faces.resourceUpdateCheckPeriod", "5"), // in minutes
@@ -859,16 +857,12 @@ public enum BooleanWebContextInitParameter {
DisableFacesServletAutomaticMapping(FacesServlet.DISABLE_FACESSERVLET_TO_XHTML_PARAM_NAME, false),
AutomaticExtensionlessMapping(FacesServlet.AUTOMATIC_EXTENSIONLESS_MAPPING_PARAM_NAME, false),
EnableClientStateDebugging("com.sun.faces.enableClientStateDebugging", false),
- EnableHtmlTagLibraryValidator("com.sun.faces.enableHtmlTagLibValidator", false),
- EnableCoreTagLibraryValidator("com.sun.faces.enableCoreTagLibValidator", false),
PreferXHTMLContentType("com.sun.faces.preferXHTML", false),
CompressViewState("com.sun.faces.compressViewState", true),
- CompressJavaScript("com.sun.faces.compressJavaScript", true),
EnableJSStyleHiding("com.sun.faces.enableJSStyleHiding", false),
EnableScriptInAttributeValue("com.sun.faces.enableScriptsInAttributeValues", true),
WriteStateAtFormEnd("com.sun.faces.writeStateAtFormEnd", true),
EnableLazyBeanValidation("com.sun.faces.enableLazyBeanValidation", true),
- EnableLoadBundle11Compatibility("com.sun.faces.enabledLoadBundle11Compatibility", false),
SerializeServerState(StateManager.SERIALIZE_SERVER_STATE_PARAM_NAME, false),
EnableViewStateIdRendering("com.sun.faces.enableViewStateIdRendering", true),
RegisterConverterPropertyEditors("com.sun.faces.registerConverterPropertyEditors", false),
@@ -883,9 +877,7 @@ public enum BooleanWebContextInitParameter {
EnableThreading("com.sun.faces.enableThreading", false),
AllowTextChildren("com.sun.faces.allowTextChildren", false),
CacheResourceModificationTimestamp("com.sun.faces.cacheResourceModificationTimestamp", false),
- EnableAgressiveSessionDirtying("com.sun.faces.enableAgressiveSessionDirtying", false),
EnableDistributable("com.sun.faces.enableDistributable", false),
- EnableFaceletsResourceResolverResolveCompositeComponents("com.sun.faces.enableFaceletsResourceResolverCompositeComponents", false),
EnableMissingResourceLibraryDetection("com.sun.faces.enableMissingResourceLibraryDetection", false),
DisableIdUniquenessCheck("com.sun.faces.disableIdUniquenessCheck", false),
EnableTransitionTimeNoOpFlash("com.sun.faces.enableTransitionTimeNoOpFlash", false),
From 0ae839a8d0fbe597f28a76227b98db7e63f80caf Mon Sep 17 00:00:00 2001
From: Jason Lee
Date: Thu, 19 Oct 2023 16:41:05 -0500
Subject: [PATCH 27/44] [MOJARRA_5341] UnsupportedOperationException in
InitFacesContext
Provide an ExceptionHandler in getExceptionHandler()
---
.../main/java/com/sun/faces/config/InitFacesContext.java | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/impl/src/main/java/com/sun/faces/config/InitFacesContext.java b/impl/src/main/java/com/sun/faces/config/InitFacesContext.java
index 96c3312dec..0de180d621 100644
--- a/impl/src/main/java/com/sun/faces/config/InitFacesContext.java
+++ b/impl/src/main/java/com/sun/faces/config/InitFacesContext.java
@@ -32,6 +32,7 @@
import com.sun.faces.config.initfacescontext.NoOpFacesContext;
import com.sun.faces.config.initfacescontext.ServletContextAdapter;
import com.sun.faces.context.ApplicationMap;
+import com.sun.faces.context.ExceptionHandlerImpl;
import com.sun.faces.util.FacesLogger;
import com.sun.faces.util.Util;
@@ -41,6 +42,7 @@
import jakarta.faces.application.ApplicationFactory;
import jakarta.faces.application.ProjectStage;
import jakarta.faces.component.UIViewRoot;
+import jakarta.faces.context.ExceptionHandler;
import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext;
import jakarta.servlet.ServletContext;
@@ -109,6 +111,11 @@ public Application getApplication() {
return factory.getApplication();
}
+ @Override
+ public ExceptionHandler getExceptionHandler() {
+ return new ExceptionHandlerImpl(false);
+ }
+
@Override
public boolean isProjectStage(ProjectStage stage) {
if (stage == null) {
From 14dc7d72e59f5b9b6e758ceb4c3b3e5844afca48 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sat, 21 Oct 2023 09:37:26 -0400
Subject: [PATCH 28/44] Improved impl of #5339
---
.../sun/faces/config/manager/Documents.java | 3 +-
.../FacesFlowDefinitionConfigProcessor.java | 3 +-
.../main/java/com/sun/faces/util/Util.java | 30 ++++++++++++++++++-
.../FacesConfigNamespaceContextTest.java | 3 +-
.../faces/FacesConfigOrderingTestCase.java | 11 +++----
5 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/impl/src/main/java/com/sun/faces/config/manager/Documents.java b/impl/src/main/java/com/sun/faces/config/manager/Documents.java
index e90fd44df6..218445a90e 100644
--- a/impl/src/main/java/com/sun/faces/config/manager/Documents.java
+++ b/impl/src/main/java/com/sun/faces/config/manager/Documents.java
@@ -18,6 +18,7 @@
import static com.sun.faces.RIConstants.DOCUMENT_NAMESPACE;
import static com.sun.faces.RIConstants.DOCUMENT_VERSION;
+import static com.sun.faces.util.Util.createLocalDocumentBuilderFactory;
import static com.sun.faces.util.Util.isEmpty;
import static java.util.Arrays.asList;
import static java.util.logging.Level.INFO;
@@ -231,7 +232,7 @@ public static DocumentInfo[] sortDocuments(DocumentInfo[] facesDocuments, FacesC
}
private static DOMImplementation createDOMImplementation() throws ParserConfigurationException {
- DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilderFactory documentBuilderFactory = createLocalDocumentBuilderFactory();
documentBuilderFactory.setNamespaceAware(true);
return documentBuilderFactory.newDocumentBuilder().getDOMImplementation();
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 77da79922c..3ac07b6f51 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
@@ -16,6 +16,7 @@
package com.sun.faces.config.processor;
+import static com.sun.faces.util.Util.createLocalDocumentBuilderFactory;
import static com.sun.faces.util.Util.notNull;
import java.net.MalformedURLException;
@@ -127,7 +128,7 @@ public static Document synthesizeEmptyFlowDefinition(URI uri) throws ParserConfi
}
String flowName = segments[segments.length - 2];
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilderFactory dbf = createLocalDocumentBuilderFactory();
dbf.setNamespaceAware(true);
DocumentBuilder builder = dbf.newDocumentBuilder();
DOMImplementation domImpl = builder.getDOMImplementation();
diff --git a/impl/src/main/java/com/sun/faces/util/Util.java b/impl/src/main/java/com/sun/faces/util/Util.java
index 14c62e2db7..7ae95e534d 100644
--- a/impl/src/main/java/com/sun/faces/util/Util.java
+++ b/impl/src/main/java/com/sun/faces/util/Util.java
@@ -62,6 +62,7 @@
import javax.naming.InitialContext;
import javax.naming.NamingException;
+import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -269,12 +270,27 @@ public static boolean isUnitTestModeEnabled() {
return unitTestModeEnabled;
}
+ public static interface ThrowingBiConsumer {
+ void accept(T t, U u) throws Exception;
+ }
+
+ private static void setPossiblyUnsupportedFeature(ThrowingBiConsumer setter, F feature, Boolean flag) {
+ try {
+ setter.accept(feature, flag);
+ } catch (Exception e) {
+ throw new IllegalStateException("The feature '" + feature + "' is not supported by your XML processor.", e);
+ }
+ }
+
public static TransformerFactory createTransformerFactory() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
TransformerFactory factory;
try {
Thread.currentThread().setContextClassLoader(Util.class.getClassLoader());
factory = TransformerFactory.newInstance();
+ factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+ factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
+ setPossiblyUnsupportedFeature(factory::setFeature, XMLConstants.FEATURE_SECURE_PROCESSING, true);
} finally {
Thread.currentThread().setContextClassLoader(cl);
}
@@ -298,13 +314,25 @@ public static DocumentBuilderFactory createDocumentBuilderFactory() {
DocumentBuilderFactory factory;
try {
Thread.currentThread().setContextClassLoader(Util.class.getClassLoader());
- factory = DocumentBuilderFactory.newInstance();
+ factory = createLocalDocumentBuilderFactory();
} finally {
Thread.currentThread().setContextClassLoader(cl);
}
return factory;
}
+ public static DocumentBuilderFactory createLocalDocumentBuilderFactory() {
+ DocumentBuilderFactory factory;
+ factory = DocumentBuilderFactory.newInstance();
+ setPossiblyUnsupportedFeature(factory::setFeature, "http://xml.org/sax/features/external-parameter-entities", false);
+ setPossiblyUnsupportedFeature(factory::setFeature, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+ setPossiblyUnsupportedFeature(factory::setFeature, "http://xml.org/sax/features/external-general-entities", false);
+ factory.setXIncludeAware(false);
+ factory.setExpandEntityReferences(false);
+ setPossiblyUnsupportedFeature(factory::setFeature, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ return factory;
+ }
+
public static SchemaFactory createSchemaFactory(String uri) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
SchemaFactory factory;
diff --git a/impl/src/test/java/com/sun/faces/config/processor/FacesConfigNamespaceContextTest.java b/impl/src/test/java/com/sun/faces/config/processor/FacesConfigNamespaceContextTest.java
index d4d1150b59..cb59988b72 100644
--- a/impl/src/test/java/com/sun/faces/config/processor/FacesConfigNamespaceContextTest.java
+++ b/impl/src/test/java/com/sun/faces/config/processor/FacesConfigNamespaceContextTest.java
@@ -16,6 +16,7 @@
package com.sun.faces.config.processor;
+import static com.sun.faces.util.Util.createLocalDocumentBuilderFactory;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -79,7 +80,7 @@ public void testJakartaEENSWithParameter() throws ParserConfigurationException,
private Document createFacesConfig(String flowName, String namespace, String version)
throws ParserConfigurationException {
- DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilderFactory documentBuilderFactory = createLocalDocumentBuilderFactory();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document docFlowConfig = documentBuilder.newDocument();
diff --git a/impl/src/test/java/jakarta/faces/FacesConfigOrderingTestCase.java b/impl/src/test/java/jakarta/faces/FacesConfigOrderingTestCase.java
index c5c7187bfb..c072c4fd98 100644
--- a/impl/src/test/java/jakarta/faces/FacesConfigOrderingTestCase.java
+++ b/impl/src/test/java/jakarta/faces/FacesConfigOrderingTestCase.java
@@ -16,6 +16,8 @@
package jakarta.faces;
+import static com.sun.faces.util.Util.createLocalDocumentBuilderFactory;
+
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
@@ -25,10 +27,6 @@
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -36,6 +34,9 @@
import com.sun.faces.config.manager.documents.DocumentOrderingWrapper;
import jakarta.faces.context.FacesContext;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
public class FacesConfigOrderingTestCase extends TestCase {
@@ -391,7 +392,7 @@ private void populateIds(String elementName, List ids, String ns,
private Document newDocument() throws ParserConfigurationException {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilderFactory factory = createLocalDocumentBuilderFactory();
factory.setValidating(false);
factory.setNamespaceAware(true);
return factory.newDocumentBuilder().newDocument();
From 886f1bcae9315e67f7eefa39a6125aef1040e519 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sun, 22 Oct 2023 10:17:51 -0400
Subject: [PATCH 29/44] Further improved impl of #5339
---
.../main/java/com/sun/faces/util/Util.java | 27 ++++++++++++-------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/impl/src/main/java/com/sun/faces/util/Util.java b/impl/src/main/java/com/sun/faces/util/Util.java
index 7ae95e534d..57e2863a38 100644
--- a/impl/src/main/java/com/sun/faces/util/Util.java
+++ b/impl/src/main/java/com/sun/faces/util/Util.java
@@ -21,6 +21,7 @@
import static com.sun.faces.RIConstants.FACES_SERVLET_MAPPINGS;
import static com.sun.faces.RIConstants.FACES_SERVLET_REGISTRATION;
+import static com.sun.faces.RIConstants.NO_VALUE;
import static com.sun.faces.util.MessageUtils.ILLEGAL_ATTEMPT_SETTING_APPLICATION_ARTIFACT_ID;
import static com.sun.faces.util.MessageUtils.NAMED_OBJECT_NOT_FOUND_ERROR_MESSAGE_ID;
import static com.sun.faces.util.MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID;
@@ -274,11 +275,19 @@ public static interface ThrowingBiConsumer {
void accept(T t, U u) throws Exception;
}
- private static void setPossiblyUnsupportedFeature(ThrowingBiConsumer setter, F feature, Boolean flag) {
+ private static void setFeature(ThrowingBiConsumer setter, F feature, Boolean flag) {
try {
setter.accept(feature, flag);
} catch (Exception e) {
- throw new IllegalStateException("The feature '" + feature + "' is not supported by your XML processor.", e);
+ throw new IllegalArgumentException("The feature '" + feature + "' is not supported by your XML processor.", e);
+ }
+ }
+
+ private static void setPossiblyUnsupportedFeature(ThrowingBiConsumer setter, F feature, Boolean flag) {
+ try {
+ setFeature(setter, feature, flag);
+ } catch (IllegalArgumentException e) {
+ LOGGER.log(Level.FINE, e.getMessage(), e);
}
}
@@ -288,9 +297,9 @@ public static TransformerFactory createTransformerFactory() {
try {
Thread.currentThread().setContextClassLoader(Util.class.getClassLoader());
factory = TransformerFactory.newInstance();
- factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
- factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
- setPossiblyUnsupportedFeature(factory::setFeature, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, NO_VALUE);
+ factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, NO_VALUE);
+ setFeature(factory::setFeature, XMLConstants.FEATURE_SECURE_PROCESSING, true);
} finally {
Thread.currentThread().setContextClassLoader(cl);
}
@@ -324,12 +333,12 @@ public static DocumentBuilderFactory createDocumentBuilderFactory() {
public static DocumentBuilderFactory createLocalDocumentBuilderFactory() {
DocumentBuilderFactory factory;
factory = DocumentBuilderFactory.newInstance();
- setPossiblyUnsupportedFeature(factory::setFeature, "http://xml.org/sax/features/external-parameter-entities", false);
- setPossiblyUnsupportedFeature(factory::setFeature, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
- setPossiblyUnsupportedFeature(factory::setFeature, "http://xml.org/sax/features/external-general-entities", false);
factory.setXIncludeAware(false);
factory.setExpandEntityReferences(false);
- setPossiblyUnsupportedFeature(factory::setFeature, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ setFeature(factory::setFeature, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ setPossiblyUnsupportedFeature(factory::setFeature, "http://xml.org/sax/features/external-general-entities", false);
+ setPossiblyUnsupportedFeature(factory::setFeature, "http://xml.org/sax/features/external-parameter-entities", false);
+ setPossiblyUnsupportedFeature(factory::setFeature, "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
return factory;
}
From 7f3e5227fbc83f319d8c28ffe3eb17ebcc78f0a8 Mon Sep 17 00:00:00 2001
From: Paul Ferraro
Date: Tue, 31 Oct 2023 18:33:34 -0400
Subject: [PATCH 30/44] [5345] Do not override application-specified
"com.sun.faces.enableDistributable" value.
---
.../main/java/com/sun/faces/config/ConfigureListener.java | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
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 684baa88bb..7775923b4c 100644
--- a/impl/src/main/java/com/sun/faces/config/ConfigureListener.java
+++ b/impl/src/main/java/com/sun/faces/config/ConfigureListener.java
@@ -150,8 +150,11 @@ public void contextInitialized(ServletContextEvent servletContextEvent) {
}
}
- if (webXmlProcessor.isDistributablePresent()) {
- webConfig.setOptionEnabled(WebConfiguration.BooleanWebContextInitParameter.EnableDistributable, true);
+ // Do not override if already defined
+ if (!webConfig.isSet(WebConfiguration.BooleanWebContextInitParameter.EnableDistributable)) {
+ webConfig.setOptionEnabled(WebConfiguration.BooleanWebContextInitParameter.EnableDistributable, webXmlProcessor.isDistributablePresent());
+ }
+ if (webConfig.isOptionEnabled(WebConfiguration.BooleanWebContextInitParameter.EnableDistributable)) {
servletContext.setAttribute(WebConfiguration.BooleanWebContextInitParameter.EnableDistributable.getQualifiedName(), TRUE);
}
From fbeee0c0747770884314419686cbbee0ebb9e87a Mon Sep 17 00:00:00 2001
From: Eclipse Mojarra Bot
Date: Wed, 1 Nov 2023 15:07:47 +0000
Subject: [PATCH 31/44] Prepare release org.glassfish:mojarra-parent:4.0.5
---
action/pom.xml | 2 +-
cdi/pom.xml | 2 +-
impl/pom.xml | 2 +-
pom.xml | 2 +-
rest/pom.xml | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/action/pom.xml b/action/pom.xml
index 0739f3729e..7e88ebfc4e 100644
--- a/action/pom.xml
+++ b/action/pom.xml
@@ -22,7 +22,7 @@
org.glassfishmojarra-parent
- 4.0.5-SNAPSHOT
+ 4.0.5org.eclipse.mojarra
diff --git a/cdi/pom.xml b/cdi/pom.xml
index 9726b77270..11ba603330 100644
--- a/cdi/pom.xml
+++ b/cdi/pom.xml
@@ -22,7 +22,7 @@
org.glassfishmojarra-parent
- 4.0.5-SNAPSHOT
+ 4.0.5org.eclipse.mojarra
diff --git a/impl/pom.xml b/impl/pom.xml
index 49bf07d410..c9fae9cfcd 100644
--- a/impl/pom.xml
+++ b/impl/pom.xml
@@ -29,7 +29,7 @@
org.glassfishmojarra-parent
- 4.0.5-SNAPSHOT
+ 4.0.5jakarta.faces
diff --git a/pom.xml b/pom.xml
index 7ce609e63f..58d15df541 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
org.glassfishmojarra-parent
- 4.0.5-SNAPSHOT
+ 4.0.5pomMojarra ${project.version} - Project
diff --git a/rest/pom.xml b/rest/pom.xml
index 7dcc5989a1..4e21003c14 100644
--- a/rest/pom.xml
+++ b/rest/pom.xml
@@ -22,7 +22,7 @@
org.glassfishmojarra-parent
- 4.0.5-SNAPSHOT
+ 4.0.5org.eclipse.mojarra
From ab8cbc1e604bdd25e4988c999aafc4f2149443c2 Mon Sep 17 00:00:00 2001
From: Eclipse Mojarra Bot
Date: Wed, 1 Nov 2023 15:10:47 +0000
Subject: [PATCH 32/44] Prepare next development cycle for 4.0.6-SNAPSHOT
---
action/pom.xml | 2 +-
cdi/pom.xml | 2 +-
impl/pom.xml | 2 +-
pom.xml | 2 +-
rest/pom.xml | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/action/pom.xml b/action/pom.xml
index 7e88ebfc4e..74c546d04b 100644
--- a/action/pom.xml
+++ b/action/pom.xml
@@ -22,7 +22,7 @@
org.glassfishmojarra-parent
- 4.0.5
+ 4.0.6-SNAPSHOTorg.eclipse.mojarra
diff --git a/cdi/pom.xml b/cdi/pom.xml
index 11ba603330..ba689d85a4 100644
--- a/cdi/pom.xml
+++ b/cdi/pom.xml
@@ -22,7 +22,7 @@
org.glassfishmojarra-parent
- 4.0.5
+ 4.0.6-SNAPSHOTorg.eclipse.mojarra
diff --git a/impl/pom.xml b/impl/pom.xml
index c9fae9cfcd..9f0d5182fb 100644
--- a/impl/pom.xml
+++ b/impl/pom.xml
@@ -29,7 +29,7 @@
org.glassfishmojarra-parent
- 4.0.5
+ 4.0.6-SNAPSHOTjakarta.faces
diff --git a/pom.xml b/pom.xml
index 58d15df541..29057a36ba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
org.glassfishmojarra-parent
- 4.0.5
+ 4.0.6-SNAPSHOTpomMojarra ${project.version} - Project
diff --git a/rest/pom.xml b/rest/pom.xml
index 4e21003c14..18d61ee230 100644
--- a/rest/pom.xml
+++ b/rest/pom.xml
@@ -22,7 +22,7 @@
org.glassfishmojarra-parent
- 4.0.5
+ 4.0.6-SNAPSHOTorg.eclipse.mojarra
From 460e797f730928150745ab1d562e9fbcffd87530 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sun, 26 Nov 2023 11:48:31 -0400
Subject: [PATCH 33/44] Make sure that ViewHandler#getViews() also returns
programmatic facelets https://github.com/eclipse-ee4j/mojarra/issues/5362
---
.../resource/FaceletWebappResourceHelper.java | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
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..a79c490b26 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
@@ -31,13 +31,16 @@
import java.util.Enumeration;
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.Objects;
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.enterprise.inject.Any;
import jakarta.faces.FacesException;
+import jakarta.faces.annotation.View;
import jakarta.faces.application.ResourceVisitOption;
import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext;
@@ -113,9 +116,16 @@ public ResourceInfo findResource(LibraryInfo library, String resourceName, Strin
}
public Stream getViewResources(FacesContext facesContext, String path, int maxDepth, ResourceVisitOption... options) {
- return stream(spliteratorUnknownSize(
+ Stream physicalViewResources = stream(spliteratorUnknownSize(
new ResourcePathsIterator(path, maxDepth, configuredExtensions, getRestrictedDirectories(options), facesContext.getExternalContext()),
DISTINCT), false);
+ Stream programmaticViewResources = Util.getCdiBeanManager(facesContext)
+ .getBeans(Object.class, Any.Literal.INSTANCE).stream() // The value is not @Nonbinding. Only in 4.1 we can use View.Literal.INSTANCE as qualifier.
+ .map(bean -> bean.getBeanClass().getAnnotation(View.class))
+ .filter(Objects::nonNull)
+ .map(View::value);
+
+ return Stream.concat(physicalViewResources, programmaticViewResources);
}
private static String[] getRestrictedDirectories(final ResourceVisitOption... options) {
From 377c749c7747084e48f230900ff4b7bca123e1c7 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sun, 26 Nov 2023 14:39:17 -0400
Subject: [PATCH 34/44] Remove jakarta.faces.visit.SKIP_ITERATION
https://github.com/eclipse-ee4j/mojarra/issues/5355
---
.../FaceletFullStateManagementStrategy.java | 141 ++++++++----------
...FaceletPartialStateManagementStrategy.java | 110 +++++++-------
.../application/view/FormOmittedChecker.java | 31 ++--
.../sun/faces/lifecycle/RestoreViewPhase.java | 18 +--
4 files changed, 128 insertions(+), 172 deletions(-)
diff --git a/impl/src/main/java/com/sun/faces/application/view/FaceletFullStateManagementStrategy.java b/impl/src/main/java/com/sun/faces/application/view/FaceletFullStateManagementStrategy.java
index 96b7b8be92..4b50125348 100644
--- a/impl/src/main/java/com/sun/faces/application/view/FaceletFullStateManagementStrategy.java
+++ b/impl/src/main/java/com/sun/faces/application/view/FaceletFullStateManagementStrategy.java
@@ -82,7 +82,7 @@ public class FaceletFullStateManagementStrategy extends StateManagementStrategy
/**
* Stores the skip hint.
*/
- private static final String SKIP_ITERATION_HINT = "jakarta.faces.visit.SKIP_ITERATION";
+ private static final Set SKIP_ITERATION_HINT = EnumSet.of(SKIP_ITERATION);
/**
* Stores the class map.
@@ -185,41 +185,34 @@ private UIComponent locateComponentByClientId(final FacesContext context, final
final List found = new ArrayList<>();
UIComponent result = null;
- try {
- context.getAttributes().put(SKIP_ITERATION_HINT, true);
- Set hints = EnumSet.of(VisitHint.SKIP_ITERATION);
-
- VisitContext visitContext = VisitContext.createVisitContext(context, null, hints);
- subTree.visitTree(visitContext, (visitContext1, component) -> {
- VisitResult result1 = ACCEPT;
- if (component.getClientId(visitContext1.getFacesContext()).equals(clientId)) {
- /*
- * If the client id matches up we have found our match.
- */
- found.add(component);
- result1 = COMPLETE;
- } else if (component instanceof UIForm) {
- /*
- * If the component is a UIForm and it is prepending its id then we can short circuit out of here if the the client id
- * of the component we are trying to find does not begin with the id of the UIForm.
- */
- UIForm form = (UIForm) component;
- if (form.isPrependId() && !clientId.startsWith(form.getClientId(visitContext1.getFacesContext()))) {
- result1 = REJECT;
- }
- } else if (component instanceof NamingContainer && !clientId.startsWith(component.getClientId(visitContext1.getFacesContext()))) {
- /*
- * If the component is a naming container then assume it is prepending its id so if our client id we are looking for
- * does not start with the naming container id we can skip visiting this tree.
- */
+ VisitContext visitContext = VisitContext.createVisitContext(context, null, SKIP_ITERATION_HINT);
+ subTree.visitTree(visitContext, (visitContext1, component) -> {
+ VisitResult result1 = ACCEPT;
+ if (component.getClientId(visitContext1.getFacesContext()).equals(clientId)) {
+ /*
+ * If the client id matches up we have found our match.
+ */
+ found.add(component);
+ result1 = COMPLETE;
+ } else if (component instanceof UIForm) {
+ /*
+ * If the component is a UIForm and it is prepending its id then we can short circuit out of here if the the client id
+ * of the component we are trying to find does not begin with the id of the UIForm.
+ */
+ UIForm form = (UIForm) component;
+ if (form.isPrependId() && !clientId.startsWith(form.getClientId(visitContext1.getFacesContext()))) {
result1 = REJECT;
}
+ } else if (component instanceof NamingContainer && !clientId.startsWith(component.getClientId(visitContext1.getFacesContext()))) {
+ /*
+ * If the component is a naming container then assume it is prepending its id so if our client id we are looking for
+ * does not start with the naming container id we can skip visiting this tree.
+ */
+ result1 = REJECT;
+ }
- return result1;
- });
- } finally {
- context.getAttributes().remove(SKIP_ITERATION_HINT);
- }
+ return result1;
+ });
if (!found.isEmpty()) {
result = found.get(0);
@@ -311,36 +304,30 @@ private void restoreComponentState(final FacesContext context, final HashMap hints = EnumSet.of(SKIP_ITERATION);
- VisitContext visitContext = VisitContext.createVisitContext(context, null, hints);
+ VisitContext visitContext = VisitContext.createVisitContext(context, null, SKIP_ITERATION_HINT);
- viewRoot.visitTree(visitContext, (visitContext1, component) -> {
- VisitResult result = ACCEPT;
+ viewRoot.visitTree(visitContext, (visitContext1, component) -> {
+ VisitResult result = ACCEPT;
- String clientId = component.getClientId(context);
- Object stateObj = state.get(clientId);
+ String clientId = component.getClientId(context);
+ Object stateObj = state.get(clientId);
- if (stateObj != null && !stateContext.componentAddedDynamically(component)) {
- boolean restoreStateNow = true;
- if (stateObj instanceof StateHolderSaver) {
- restoreStateNow = !((StateHolderSaver) stateObj).componentAddedDynamically();
- }
- if (restoreStateNow) {
- try {
- component.restoreState(context, stateObj);
- } catch (Exception e) {
- throw new FacesException(e);
- }
+ if (stateObj != null && !stateContext.componentAddedDynamically(component)) {
+ boolean restoreStateNow = true;
+ if (stateObj instanceof StateHolderSaver) {
+ restoreStateNow = !((StateHolderSaver) stateObj).componentAddedDynamically();
+ }
+ if (restoreStateNow) {
+ try {
+ component.restoreState(context, stateObj);
+ } catch (Exception e) {
+ throw new FacesException(e);
}
}
+ }
- return result;
- });
- } finally {
- context.getAttributes().remove(SKIP_ITERATION_HINT);
- }
+ return result;
+ });
}
/**
@@ -592,33 +579,27 @@ private Object saveComponentState(FacesContext context) {
final UIViewRoot viewRoot = context.getViewRoot();
final FacesContext finalContext = context;
- context.getAttributes().put(SKIP_ITERATION_HINT, true);
- Set hints = EnumSet.of(SKIP_ITERATION);
- VisitContext visitContext = VisitContext.createVisitContext(context, null, hints);
+ VisitContext visitContext = VisitContext.createVisitContext(context, null, SKIP_ITERATION_HINT);
- try {
- viewRoot.visitTree(visitContext, (context1, component) -> {
- VisitResult result = ACCEPT;
- Object stateObj;
- if (!component.isTransient()) {
- if (stateContext.componentAddedDynamically(component)) {
- component.getAttributes().put(DYNAMIC_COMPONENT, new Integer(getProperChildIndex(component)));
- stateObj = new StateHolderSaver(finalContext, component);
- } else {
- stateObj = component.saveState(finalContext);
- }
- if (stateObj != null) {
- stateMap.put(component.getClientId(finalContext), stateObj);
- }
+ viewRoot.visitTree(visitContext, (context1, component) -> {
+ VisitResult result = ACCEPT;
+ Object stateObj;
+ if (!component.isTransient()) {
+ if (stateContext.componentAddedDynamically(component)) {
+ component.getAttributes().put(DYNAMIC_COMPONENT, new Integer(getProperChildIndex(component)));
+ stateObj = new StateHolderSaver(finalContext, component);
} else {
- result = REJECT;
+ stateObj = component.saveState(finalContext);
}
+ if (stateObj != null) {
+ stateMap.put(component.getClientId(finalContext), stateObj);
+ }
+ } else {
+ result = REJECT;
+ }
- return result;
- });
- } finally {
- context.getAttributes().remove(SKIP_ITERATION_HINT);
- }
+ return result;
+ });
return stateMap;
}
diff --git a/impl/src/main/java/com/sun/faces/application/view/FaceletPartialStateManagementStrategy.java b/impl/src/main/java/com/sun/faces/application/view/FaceletPartialStateManagementStrategy.java
index 29e763978f..6faf35945e 100644
--- a/impl/src/main/java/com/sun/faces/application/view/FaceletPartialStateManagementStrategy.java
+++ b/impl/src/main/java/com/sun/faces/application/view/FaceletPartialStateManagementStrategy.java
@@ -68,10 +68,16 @@ public class FaceletPartialStateManagementStrategy extends StateManagementStrate
* Stores the logger.
*/
private static final Logger LOGGER = FacesLogger.APPLICATION_VIEW.getLogger();
+
/**
* Stores the skip hint.
*/
- private static final String SKIP_ITERATION_HINT = "jakarta.faces.visit.SKIP_ITERATION";
+ private static final Set SKIP_ITERATION_HINT = EnumSet.of(SKIP_ITERATION);
+
+ /**
+ * Stores the skip and lifecycle hints.
+ */
+ private static final Set SKIP_ITERATION_AND_EXECUTE_LIFECYCLE_HINTS = EnumSet.of(VisitHint.SKIP_ITERATION, VisitHint.EXECUTE_LIFECYCLE);
/**
* Constructor.
@@ -102,41 +108,34 @@ private UIComponent locateComponentByClientId(final FacesContext context, final
final List found = new ArrayList<>();
UIComponent result = null;
- try {
- context.getAttributes().put(SKIP_ITERATION_HINT, true);
- Set hints = EnumSet.of(SKIP_ITERATION);
-
- VisitContext visitContext = VisitContext.createVisitContext(context, null, hints);
- subTree.visitTree(visitContext, (visitContext1, component) -> {
- VisitResult result1 = ACCEPT;
- if (component.getClientId(visitContext1.getFacesContext()).equals(clientId)) {
- /*
- * If the client id matches up we have found our match.
- */
- found.add(component);
- result1 = COMPLETE;
- } else if (component instanceof UIForm) {
- /*
- * If the component is a UIForm and it is prepending its id then we can short circuit out of here if the the client id
- * of the component we are trying to find does not begin with the id of the UIForm.
- */
- UIForm form = (UIForm) component;
- if (form.isPrependId() && !clientId.startsWith(form.getClientId(visitContext1.getFacesContext()))) {
- result1 = REJECT;
- }
- } else if (component instanceof NamingContainer && !clientId.startsWith(component.getClientId(visitContext1.getFacesContext()))) {
- /*
- * If the component is a naming container then assume it is prepending its id so if our client id we are looking for
- * does not start with the naming container id we can skip visiting this tree.
- */
+ VisitContext visitContext = VisitContext.createVisitContext(context, null, SKIP_ITERATION_HINT);
+ subTree.visitTree(visitContext, (visitContext1, component) -> {
+ VisitResult result1 = ACCEPT;
+ if (component.getClientId(visitContext1.getFacesContext()).equals(clientId)) {
+ /*
+ * If the client id matches up we have found our match.
+ */
+ found.add(component);
+ result1 = COMPLETE;
+ } else if (component instanceof UIForm) {
+ /*
+ * If the component is a UIForm and it is prepending its id then we can short circuit out of here if the the client id
+ * of the component we are trying to find does not begin with the id of the UIForm.
+ */
+ UIForm form = (UIForm) component;
+ if (form.isPrependId() && !clientId.startsWith(form.getClientId(visitContext1.getFacesContext()))) {
result1 = REJECT;
}
+ } else if (component instanceof NamingContainer && !clientId.startsWith(component.getClientId(visitContext1.getFacesContext()))) {
+ /*
+ * If the component is a naming container then assume it is prepending its id so if our client id we are looking for
+ * does not start with the naming container id we can skip visiting this tree.
+ */
+ result1 = REJECT;
+ }
- return result1;
- });
- } finally {
- context.getAttributes().remove(SKIP_ITERATION_HINT);
- }
+ return result1;
+ });
if (!found.isEmpty()) {
result = found.get(0);
@@ -343,9 +342,7 @@ public UIViewRoot restoreView(FacesContext context, String viewId, String render
try {
stateContext.setTrackViewModifications(false);
- context.getAttributes().put(SKIP_ITERATION_HINT, true);
- Set hints = EnumSet.of(VisitHint.SKIP_ITERATION, VisitHint.EXECUTE_LIFECYCLE);
- VisitContext visitContext = VisitContext.createVisitContext(context, null, hints);
+ VisitContext visitContext = VisitContext.createVisitContext(context, null, SKIP_ITERATION_AND_EXECUTE_LIFECYCLE_HINTS);
viewRoot.visitTree(visitContext, (context1, target) -> {
VisitResult result = VisitResult.ACCEPT;
String cid = target.getClientId(context1.getFacesContext());
@@ -370,7 +367,6 @@ public UIViewRoot restoreView(FacesContext context, String viewId, String render
restoreDynamicActions(context, stateContext, state);
} finally {
stateContext.setTrackViewModifications(true);
- context.getAttributes().remove(SKIP_ITERATION_HINT);
}
} else {
viewRoot = null;
@@ -436,33 +432,27 @@ public Object saveView(FacesContext context) {
final Map stateMap = new HashMap<>();
final StateContext stateContext = StateContext.getStateContext(context);
- context.getAttributes().put(SKIP_ITERATION_HINT, true);
- Set hints = EnumSet.of(VisitHint.SKIP_ITERATION);
- VisitContext visitContext = VisitContext.createVisitContext(context, null, hints);
+ VisitContext visitContext = VisitContext.createVisitContext(context, null, SKIP_ITERATION_HINT);
final FacesContext finalContext = context;
- try {
- viewRoot.visitTree(visitContext, (context1, target) -> {
- VisitResult result = VisitResult.ACCEPT;
- Object stateObj;
- if (!target.isTransient()) {
- if (stateContext.componentAddedDynamically(target)) {
- target.getAttributes().put(DYNAMIC_COMPONENT, target.getParent().getChildren().indexOf(target));
- stateObj = new StateHolderSaver(finalContext, target);
- } else {
- stateObj = target.saveState(context1.getFacesContext());
- }
- if (stateObj != null) {
- stateMap.put(target.getClientId(context1.getFacesContext()), stateObj);
- }
+ viewRoot.visitTree(visitContext, (context1, target) -> {
+ VisitResult result = VisitResult.ACCEPT;
+ Object stateObj;
+ if (!target.isTransient()) {
+ if (stateContext.componentAddedDynamically(target)) {
+ target.getAttributes().put(DYNAMIC_COMPONENT, target.getParent().getChildren().indexOf(target));
+ stateObj = new StateHolderSaver(finalContext, target);
} else {
- return VisitResult.REJECT;
+ stateObj = target.saveState(context1.getFacesContext());
}
- return result;
- });
- } finally {
- context.getAttributes().remove(SKIP_ITERATION_HINT);
- }
+ if (stateObj != null) {
+ stateMap.put(target.getClientId(context1.getFacesContext()), stateObj);
+ }
+ } else {
+ return VisitResult.REJECT;
+ }
+ return result;
+ });
saveDynamicActions(context, stateContext, stateMap);
StateContext.release(context);
diff --git a/impl/src/main/java/com/sun/faces/application/view/FormOmittedChecker.java b/impl/src/main/java/com/sun/faces/application/view/FormOmittedChecker.java
index 1375e70e9d..2463b52c39 100644
--- a/impl/src/main/java/com/sun/faces/application/view/FormOmittedChecker.java
+++ b/impl/src/main/java/com/sun/faces/application/view/FormOmittedChecker.java
@@ -16,6 +16,8 @@
package com.sun.faces.application.view;
+import static jakarta.faces.component.visit.VisitHint.SKIP_ITERATION;
+
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
@@ -42,7 +44,7 @@ class FormOmittedChecker {
/**
* Stores the skip hint.
*/
- private static String SKIP_ITERATION_HINT = "jakarta.faces.visit.SKIP_ITERATION";
+ private static final Set SKIP_ITERATION_HINT = EnumSet.of(SKIP_ITERATION);
/**
* Constructor.
@@ -61,24 +63,17 @@ public static void check(FacesContext context) {
List children = viewRoot.getChildren();
for (UIComponent child : children) {
- try {
- context.getAttributes().put(SKIP_ITERATION_HINT, true);
- Set hints = EnumSet.of(VisitHint.SKIP_ITERATION);
-
- VisitContext visitContext = VisitContext.createVisitContext(context, null, hints);
- child.visitTree(visitContext, (visitContext1, component) -> {
- VisitResult result = VisitResult.ACCEPT;
+ VisitContext visitContext = VisitContext.createVisitContext(context, null, SKIP_ITERATION_HINT);
+ child.visitTree(visitContext, (visitContext1, component) -> {
+ VisitResult result = VisitResult.ACCEPT;
- if (isForm(component)) {
- result = VisitResult.REJECT;
- } else if (isInNeedOfForm(component)) {
- addFormOmittedMessage(finalContext, component);
- }
- return result;
- });
- } finally {
- context.getAttributes().remove(SKIP_ITERATION_HINT);
- }
+ if (isForm(component)) {
+ result = VisitResult.REJECT;
+ } else if (isInNeedOfForm(component)) {
+ addFormOmittedMessage(finalContext, component);
+ }
+ return result;
+ });
}
}
diff --git a/impl/src/main/java/com/sun/faces/lifecycle/RestoreViewPhase.java b/impl/src/main/java/com/sun/faces/lifecycle/RestoreViewPhase.java
index a869c08382..2e335c0190 100644
--- a/impl/src/main/java/com/sun/faces/lifecycle/RestoreViewPhase.java
+++ b/impl/src/main/java/com/sun/faces/lifecycle/RestoreViewPhase.java
@@ -25,6 +25,7 @@
import static com.sun.faces.util.MessageUtils.getExceptionMessageString;
import static com.sun.faces.util.Util.getViewHandler;
import static com.sun.faces.util.Util.isOneOf;
+import static jakarta.faces.component.visit.VisitHint.SKIP_ITERATION;
import static jakarta.faces.event.PhaseId.RESTORE_VIEW;
import static jakarta.faces.render.ResponseStateManager.NON_POSTBACK_VIEW_TOKEN_PARAM;
import static jakarta.faces.view.ViewMetadata.hasMetadata;
@@ -80,7 +81,7 @@ public class RestoreViewPhase extends Phase {
private static final String WEBAPP_ERROR_PAGE_MARKER = "jakarta.servlet.error.message";
private static final Logger LOGGER = FacesLogger.LIFECYCLE.getLogger();
- private static String SKIP_ITERATION_HINT = "jakarta.faces.visit.SKIP_ITERATION";
+ private static final Set SKIP_ITERATION_HINT = EnumSet.of(SKIP_ITERATION);
// ---------------------------------------------------------- Public Methods
@@ -101,7 +102,7 @@ public void doPhase(FacesContext context, Lifecycle lifecycle, ListIterator
- *
+ *
* POSTCONDITION: The facesContext has been initialized with a tree.
*/
@@ -382,14 +383,8 @@ private void deliverPostRestoreStateEvent(FacesContext facesContext) throws Face
UIViewRoot root = facesContext.getViewRoot();
PostRestoreStateEvent postRestoreStateEvent = new PostRestoreStateEvent(root);
try {
- // PENDING: This is included for those component frameworks that don't utilize the
- // new VisitHint(s) yet - but still wish to know that they should be non-iterating
- // during state saving. It should be removed at some point.
- facesContext.getAttributes().put(SKIP_ITERATION_HINT, true);
facesContext.getApplication().publishEvent(facesContext, PostRestoreStateEvent.class, root);
-
- Set hints = EnumSet.of(VisitHint.SKIP_ITERATION);
- VisitContext visitContext = VisitContext.createVisitContext(facesContext, null, hints);
+ VisitContext visitContext = VisitContext.createVisitContext(facesContext, null, SKIP_ITERATION_HINT);
root.visitTree(visitContext, (context, target) -> {
postRestoreStateEvent.setComponent(target);
target.processEvent(postRestoreStateEvent);
@@ -401,11 +396,6 @@ private void deliverPostRestoreStateEvent(FacesContext facesContext) throws Face
.publishEvent(
facesContext, ExceptionQueuedEvent.class,
new ExceptionQueuedEventContext(facesContext, e, null, PhaseId.RESTORE_VIEW));
- } finally {
- // PENDING: This is included for those component frameworks that don't utilize the
- // new VisitHint(s) yet - but still wish to know that they should be non-iterating
- // during state saving. It should be removed at some point.
- facesContext.getAttributes().remove(SKIP_ITERATION_HINT);
}
}
From d59442dbc4dc9e2523e41c2251622fee9747e32a Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Thu, 30 Nov 2023 07:36:22 -0400
Subject: [PATCH 35/44] Remove comment
---
.../faces/application/resource/FaceletWebappResourceHelper.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 a79c490b26..33f708b208 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
@@ -120,7 +120,7 @@ public Stream getViewResources(FacesContext facesContext, String path, i
new ResourcePathsIterator(path, maxDepth, configuredExtensions, getRestrictedDirectories(options), facesContext.getExternalContext()),
DISTINCT), false);
Stream programmaticViewResources = Util.getCdiBeanManager(facesContext)
- .getBeans(Object.class, Any.Literal.INSTANCE).stream() // The value is not @Nonbinding. Only in 4.1 we can use View.Literal.INSTANCE as qualifier.
+ .getBeans(Object.class, Any.Literal.INSTANCE).stream()
.map(bean -> bean.getBeanClass().getAnnotation(View.class))
.filter(Objects::nonNull)
.map(View::value);
From aedf85725413c0e58c893b3ae187092898f11910 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sat, 20 Jan 2024 12:40:44 -0400
Subject: [PATCH 36/44] Remove hardcoded string constant representing "UTF-8"
where possible
---
.../main/java/com/sun/faces/RIConstants.java | 4 ++-
.../ConverterPropertyEditorFactory.java | 14 ++------
.../faces/context/ExternalContextImpl.java | 32 +++----------------
.../faces/context/PartialViewContextImpl.java | 11 ++-----
.../com/sun/faces/context/flash/ELFlash.java | 22 +++----------
.../sun/faces/facelets/util/Classpath.java | 13 +++-----
.../sun/faces/lifecycle/RestoreViewPhase.java | 13 ++------
.../com/sun/faces/renderkit/StateHelper.java | 12 ++-----
.../html_basic/OutputLinkRenderer.java | 9 +++---
.../faces/context/PartialResponseWriter.java | 5 ++-
10 files changed, 35 insertions(+), 100 deletions(-)
diff --git a/impl/src/main/java/com/sun/faces/RIConstants.java b/impl/src/main/java/com/sun/faces/RIConstants.java
index 62b400c6b4..cffc4e0ec5 100644
--- a/impl/src/main/java/com/sun/faces/RIConstants.java
+++ b/impl/src/main/java/com/sun/faces/RIConstants.java
@@ -17,6 +17,8 @@
package com.sun.faces;
+import java.nio.charset.StandardCharsets;
+
import com.sun.faces.config.manager.FacesSchema;
import jakarta.faces.render.RenderKitFactory;
@@ -58,7 +60,7 @@ public class RIConstants {
public static final String APPLICATION_XML_CONTENT_TYPE = "application/xml";
public static final String TEXT_XML_CONTENT_TYPE = "text/xml";
public static final String ALL_MEDIA = "*/*";
- public static final String CHAR_ENCODING = "UTF-8";
+ public static final String CHAR_ENCODING = StandardCharsets.UTF_8.name();
public static final String FACELETS_ENCODING_KEY = "facelets.Encoding";
public static final String DEFAULT_LIFECYCLE = FACES_PREFIX + "DefaultLifecycle";
public static final String DEFAULT_STATEMANAGER = FACES_PREFIX + "DefaultStateManager";
diff --git a/impl/src/main/java/com/sun/faces/application/ConverterPropertyEditorFactory.java b/impl/src/main/java/com/sun/faces/application/ConverterPropertyEditorFactory.java
index 660e566abb..9f9d08b41d 100644
--- a/impl/src/main/java/com/sun/faces/application/ConverterPropertyEditorFactory.java
+++ b/impl/src/main/java/com/sun/faces/application/ConverterPropertyEditorFactory.java
@@ -16,6 +16,7 @@
package com.sun.faces.application;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.FINEST;
import static java.util.logging.Level.WARNING;
@@ -23,7 +24,6 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -80,7 +80,6 @@ private static class Utf8InfoRef {
int length;
public Utf8InfoRef(int index, int length) {
- super();
this.index = index;
this.length = length;
}
@@ -102,7 +101,6 @@ private static class Utf8InfoReplacement implements Comparable c) {
* @return the bytes for the UTF8Info constant pool entry, including the tag, length, and utf8 content.
*/
private static byte[] getUtf8InfoBytes(String text) {
- byte[] utf8;
- try {
- utf8 = text.getBytes("UTF-8");
- } catch (UnsupportedEncodingException e) {
- // The DM_DEFAULT_ENCODING warning is acceptable here
- // because we explicitly *want* to use the Java runtime's
- // default encoding.
- utf8 = text.getBytes();
- }
+ byte[] utf8 = text.getBytes(UTF_8);
byte[] info = new byte[utf8.length + 3];
info[0] = 1;
info[1] = (byte) (utf8.length >> 8 & 0xff);
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 13e505874b..935754bf91 100644
--- a/impl/src/main/java/com/sun/faces/context/ExternalContextImpl.java
+++ b/impl/src/main/java/com/sun/faces/context/ExternalContextImpl.java
@@ -654,9 +654,8 @@ public void redirect(String requestURI) throws IOException {
pwriter = ctx.getPartialViewContext().getPartialResponseWriter();
}
setResponseContentType(RIConstants.TEXT_XML_CONTENT_TYPE);
- setResponseCharacterEncoding("UTF-8");
+ setResponseCharacterEncoding(RIConstants.CHAR_ENCODING);
addResponseHeader("Cache-Control", "no-cache");
-// pwriter.writePreamble("\n");
pwriter.startDocument();
pwriter.redirect(requestURI);
pwriter.endDocument();
@@ -974,14 +973,7 @@ public boolean isSecure() {
@Override
public String encodeBookmarkableURL(String baseUrl, Map> parameters) {
- FacesContext context = FacesContext.getCurrentInstance();
- String encodingFromContext = (String) context.getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
- if (null == encodingFromContext) {
- encodingFromContext = (String) context.getViewRoot().getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
- }
-
- String currentResponseEncoding = null != encodingFromContext ? encodingFromContext : getResponseCharacterEncoding();
-
+ String currentResponseEncoding = Util.getResponseEncoding(FacesContext.getCurrentInstance());
UrlBuilder builder = new UrlBuilder(baseUrl, currentResponseEncoding);
builder.addParameters(parameters);
return builder.createUrl();
@@ -990,14 +982,7 @@ public String encodeBookmarkableURL(String baseUrl, Map> pa
@Override
public String encodeRedirectURL(String baseUrl, Map> parameters) {
- FacesContext context = FacesContext.getCurrentInstance();
- String encodingFromContext = (String) context.getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
- if (null == encodingFromContext) {
- encodingFromContext = (String) context.getViewRoot().getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
- }
-
- String currentResponseEncoding = null != encodingFromContext ? encodingFromContext : getResponseCharacterEncoding();
-
+ String currentResponseEncoding = Util.getResponseEncoding(FacesContext.getCurrentInstance());
UrlBuilder builder = new UrlBuilder(baseUrl, currentResponseEncoding);
builder.addParameters(parameters);
return builder.createUrl();
@@ -1013,14 +998,7 @@ public String encodePartialActionURL(String url) {
String message = MessageUtils.getExceptionMessageString(MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "url");
throw new NullPointerException(message);
}
- FacesContext context = FacesContext.getCurrentInstance();
- String encodingFromContext = (String) context.getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
- if (null == encodingFromContext) {
- encodingFromContext = (String) context.getViewRoot().getAttributes().get(RIConstants.FACELETS_ENCODING_KEY);
- }
-
- String currentResponseEncoding = null != encodingFromContext ? encodingFromContext : getResponseCharacterEncoding();
-
+ String currentResponseEncoding = Util.getResponseEncoding(FacesContext.getCurrentInstance());
UrlBuilder builder = new UrlBuilder(url, currentResponseEncoding);
return ((HttpServletResponse) response).encodeURL(builder.createUrl());
}
@@ -1078,7 +1056,7 @@ private void pushIfPossibleAndNecessary(String result) {
private PushBuilder getPushBuilder(FacesContext context) {
ExternalContext extContext = context.getExternalContext();
-
+
if (extContext.getRequest() instanceof HttpServletRequest) {
HttpServletRequest hreq = (HttpServletRequest) extContext.getRequest();
diff --git a/impl/src/main/java/com/sun/faces/context/PartialViewContextImpl.java b/impl/src/main/java/com/sun/faces/context/PartialViewContextImpl.java
index f9b379ff53..bbf59f37c8 100644
--- a/impl/src/main/java/com/sun/faces/context/PartialViewContextImpl.java
+++ b/impl/src/main/java/com/sun/faces/context/PartialViewContextImpl.java
@@ -19,9 +19,9 @@
import static com.sun.faces.renderkit.RenderKitUtils.PredefinedPostbackParameter.PARTIAL_EXECUTE_PARAM;
import static com.sun.faces.renderkit.RenderKitUtils.PredefinedPostbackParameter.PARTIAL_RENDER_PARAM;
import static com.sun.faces.renderkit.RenderKitUtils.PredefinedPostbackParameter.PARTIAL_RESET_VALUES_PARAM;
+import static jakarta.faces.FactoryFinder.VISIT_CONTEXT_FACTORY;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.WARNING;
-import static jakarta.faces.FactoryFinder.VISIT_CONTEXT_FACTORY;
import java.io.IOException;
import java.io.Writer;
@@ -281,11 +281,6 @@ public void processPartial(PhaseId phaseId) {
exContext.setResponseContentType(RIConstants.TEXT_XML_CONTENT_TYPE);
exContext.addResponseHeader("Cache-Control", "no-cache");
-// String encoding = writer.getCharacterEncoding( );
-// if( encoding == null ) {
-// encoding = "UTF-8";
-// }
-// writer.writePreamble("\n");
writer.startDocument();
if (isResetValues()) {
@@ -322,7 +317,7 @@ public void processPartial(PhaseId phaseId) {
}
}
}
-
+
private void doFlashPostPhaseActions(FacesContext ctx) {
try {
ctx.getExternalContext().getFlash().doPostPhaseActions(ctx);
@@ -630,7 +625,7 @@ public DelayedInitPartialResponseWriter(PartialViewContextImpl ctx) {
super(null);
this.ctx = ctx;
ExternalContext extCtx = ctx.ctx.getExternalContext();
-
+
if (extCtx.isResponseCommitted()) {
LOGGER.log(WARNING, "Response is already committed - cannot reconfigure it anymore");
}
diff --git a/impl/src/main/java/com/sun/faces/context/flash/ELFlash.java b/impl/src/main/java/com/sun/faces/context/flash/ELFlash.java
index 85a728229f..c653e4627d 100644
--- a/impl/src/main/java/com/sun/faces/context/flash/ELFlash.java
+++ b/impl/src/main/java/com/sun/faces/context/flash/ELFlash.java
@@ -18,8 +18,8 @@
import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableDistributable;
import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.ForceAlwaysWriteFlashCookie;
+import static java.nio.charset.StandardCharsets.UTF_8;
-import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
@@ -640,7 +640,7 @@ public void doPostPhaseActions(FacesContext context) {
* necessary because the call to extContext.flushBuffer() is too late, the response has already been committed by that
* point. outgoingResponseIsRedirect is false.
*
- *
+ *
* @param context the involved faces context
* @param outgoingResponseIsRedirect whether outgoing response is redirect
*/
@@ -1313,15 +1313,7 @@ void expireNext_MovePreviousToNext() {
void decode(FacesContext context, ELFlash flash, Cookie cookie) throws InvalidKeyException {
String temp;
String value;
-
- String urlDecodedValue = null;
-
- try {
- urlDecodedValue = URLDecoder.decode(cookie.getValue(), "UTF-8");
- } catch (UnsupportedEncodingException uee) {
- urlDecodedValue = cookie.getValue();
- }
-
+ String urlDecodedValue = URLDecoder.decode(cookie.getValue(), UTF_8);
value = guard.decrypt(urlDecodedValue);
try {
@@ -1390,16 +1382,10 @@ void decode(FacesContext context, ELFlash flash, Cookie cookie) throws InvalidKe
*
*/
Cookie encode() {
- Cookie result = null;
-
String value = (null != previousRequestFlashInfo ? previousRequestFlashInfo.encode() : "") + "_"
+ (null != nextRequestFlashInfo ? nextRequestFlashInfo.encode() : "");
String encryptedValue = guard.encrypt(value);
- try {
- result = new Cookie(FLASH_COOKIE_NAME, URLEncoder.encode(encryptedValue, "UTF-8"));
- } catch (UnsupportedEncodingException uee) {
- result = new Cookie(FLASH_COOKIE_NAME, encryptedValue);
- }
+ Cookie result = new Cookie(FLASH_COOKIE_NAME, URLEncoder.encode(encryptedValue, UTF_8));
if (1 == value.length()) {
result.setMaxAge(0);
diff --git a/impl/src/main/java/com/sun/faces/facelets/util/Classpath.java b/impl/src/main/java/com/sun/faces/facelets/util/Classpath.java
index ac2bbce3b3..829cf0c20f 100644
--- a/impl/src/main/java/com/sun/faces/facelets/util/Classpath.java
+++ b/impl/src/main/java/com/sun/faces/facelets/util/Classpath.java
@@ -16,6 +16,8 @@
package com.sun.faces.facelets.util;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -45,13 +47,6 @@ public final class Classpath {
private static final String[] PREFIXES_TO_EXCLUDE = { "rar:", "sar:" };
private static final String[] EXTENSIONS_TO_EXCLUDE = { ".rar", ".sar" };
- /**
- *
- */
- public Classpath() {
- super();
- }
-
public enum SearchAdvice {
FirstMatchOnly, AllMatches
}
@@ -93,7 +88,7 @@ public static URL[] search(ClassLoader cl, String prefix, String suffix, SearchA
if (jarFile != null) {
searchJar(cl, all, jarFile, prefix, suffix, advice);
} else {
- boolean searchDone = searchDir(all, new File(URLDecoder.decode(url.getFile(), "UTF-8")), suffix);
+ boolean searchDone = searchDir(all, new File(URLDecoder.decode(url.getFile(), UTF_8)), suffix);
if (!searchDone) {
searchFromURL(all, prefix, suffix, url);
}
@@ -244,7 +239,7 @@ static JarFile getAlternativeJarFile(String urlFile) throws IOException {
// And trim off any "file:" prefix.
if (jarFileUrl.startsWith("file:")) {
jarFileUrl = jarFileUrl.substring("file:".length());
- jarFileUrl = URLDecoder.decode(jarFileUrl, "UTF-8");
+ jarFileUrl = URLDecoder.decode(jarFileUrl, UTF_8);
}
boolean foundExclusion = false;
for (int i = 0; i < PREFIXES_TO_EXCLUDE.length; i++) {
diff --git a/impl/src/main/java/com/sun/faces/lifecycle/RestoreViewPhase.java b/impl/src/main/java/com/sun/faces/lifecycle/RestoreViewPhase.java
index 2e335c0190..74af50b913 100644
--- a/impl/src/main/java/com/sun/faces/lifecycle/RestoreViewPhase.java
+++ b/impl/src/main/java/com/sun/faces/lifecycle/RestoreViewPhase.java
@@ -29,10 +29,10 @@
import static jakarta.faces.event.PhaseId.RESTORE_VIEW;
import static jakarta.faces.render.ResponseStateManager.NON_POSTBACK_VIEW_TOKEN_PARAM;
import static jakarta.faces.view.ViewMetadata.hasMetadata;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.SEVERE;
-import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
@@ -249,16 +249,7 @@ private void maybeTakeProtectedViewAction(FacesContext context, ViewHandler view
String incomingSecretKeyValue = extContext.getRequestParameterMap().get(NON_POSTBACK_VIEW_TOKEN_PARAM);
if (incomingSecretKeyValue != null) {
- try {
- incomingSecretKeyValue = URLEncoder.encode(incomingSecretKeyValue, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- if (LOGGER.isLoggable(SEVERE)) {
- LOGGER.log(SEVERE,
- "Unable to re-encode value of request parameter " + NON_POSTBACK_VIEW_TOKEN_PARAM + ":"
- + incomingSecretKeyValue, e);
- }
- incomingSecretKeyValue = null;
- }
+ incomingSecretKeyValue = URLEncoder.encode(incomingSecretKeyValue, UTF_8);
}
String correctSecretKeyValue = rsm.getCryptographicallyStrongTokenFromSession(context);
diff --git a/impl/src/main/java/com/sun/faces/renderkit/StateHelper.java b/impl/src/main/java/com/sun/faces/renderkit/StateHelper.java
index 6756c4028c..43380f0db1 100644
--- a/impl/src/main/java/com/sun/faces/renderkit/StateHelper.java
+++ b/impl/src/main/java/com/sun/faces/renderkit/StateHelper.java
@@ -21,11 +21,10 @@
import static com.sun.faces.renderkit.RenderKitUtils.PredefinedPostbackParameter.CLIENT_WINDOW_PARAM;
import static com.sun.faces.renderkit.RenderKitUtils.PredefinedPostbackParameter.RENDER_KIT_ID_PARAM;
import static com.sun.faces.renderkit.RenderKitUtils.PredefinedPostbackParameter.VIEW_STATE_PARAM;
+import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
-import java.util.logging.Level;
import java.util.logging.Logger;
import com.sun.faces.RIConstants;
@@ -113,12 +112,7 @@ public static void createAndStoreCryptographicallyStrongTokenInSession(HttpSessi
ByteArrayGuardAESCTR guard = new ByteArrayGuardAESCTR();
String clearText = "" + System.currentTimeMillis();
String result = guard.encrypt(clearText);
- try {
- result = URLEncoder.encode(result, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- LOGGER.log(Level.SEVERE, "Unable to URL encode cryptographically strong token, storing clear text in session instead.", e);
- result = clearText;
- }
+ result = URLEncoder.encode(result, UTF_8);
session.setAttribute(TOKEN_NAME, result);
}
@@ -173,7 +167,7 @@ protected static String getStateParamValue(FacesContext context) {
if (pValue != null && pValue.length() == 0) {
pValue = null;
}
-
+
return pValue;
}
diff --git a/impl/src/main/java/com/sun/faces/renderkit/html_basic/OutputLinkRenderer.java b/impl/src/main/java/com/sun/faces/renderkit/html_basic/OutputLinkRenderer.java
index 2bb779516d..750b7668e4 100644
--- a/impl/src/main/java/com/sun/faces/renderkit/html_basic/OutputLinkRenderer.java
+++ b/impl/src/main/java/com/sun/faces/renderkit/html_basic/OutputLinkRenderer.java
@@ -19,6 +19,7 @@
package com.sun.faces.renderkit.html_basic;
import static com.sun.faces.util.Util.componentIsDisabled;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.logging.Level.FINE;
import java.io.IOException;
@@ -35,7 +36,7 @@
/**
* OutputLinkRenderer is a class ...
- *
+ *
* Lifetime And Scope
*
*/
@@ -133,7 +134,7 @@ protected Object getValue(UIComponent component) {
if (componentIsDisabled(component)) {
return null;
}
-
+
return ((UIOutput) component).getValue();
}
@@ -176,10 +177,10 @@ protected void renderAsActive(FacesContext context, UIComponent component) throw
if (pn != null && pn.length() != 0) {
String pv = paramList[i].value;
sb.append(paramWritten ? '&' : '?');
- sb.append(URLEncoder.encode(pn, "UTF-8"));
+ sb.append(URLEncoder.encode(pn, UTF_8));
sb.append('=');
if (pv != null && pv.length() != 0) {
- sb.append(URLEncoder.encode(pv, "UTF-8"));
+ sb.append(URLEncoder.encode(pv, UTF_8));
}
paramWritten = true;
}
diff --git a/impl/src/main/java/jakarta/faces/context/PartialResponseWriter.java b/impl/src/main/java/jakarta/faces/context/PartialResponseWriter.java
index aa4b4cf893..49a6427519 100644
--- a/impl/src/main/java/jakarta/faces/context/PartialResponseWriter.java
+++ b/impl/src/main/java/jakarta/faces/context/PartialResponseWriter.java
@@ -17,8 +17,11 @@
package jakarta.faces.context;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.Map;
+import com.sun.faces.RIConstants;
+
import jakarta.faces.component.NamingContainer;
import jakarta.faces.component.UIViewRoot;
import jakarta.faces.render.ResponseStateManager;
@@ -97,7 +100,7 @@ public void startDocument() throws IOException {
ResponseWriter writer = getWrapped();
String encoding = writer.getCharacterEncoding();
if (encoding == null) {
- encoding = "utf-8";
+ encoding = RIConstants.CHAR_ENCODING;
}
writer.writePreamble("\n");
writer.startElement("partial-response", null);
From 84f890583e94b9b6780417313fb134b7ada13854 Mon Sep 17 00:00:00 2001
From: Bauke Scholtz
Date: Sat, 20 Jan 2024 15:40:45 -0400
Subject: [PATCH 37/44] Review/cleanup Facelets/Request/Response encoding
implementation https://github.com/eclipse-ee4j/mojarra/issues/5383
---
.../view/FaceletViewHandlingStrategy.java | 71 +++--------------
.../application/view/MultiViewHandler.java | 22 +-----
.../com/sun/faces/context/UrlBuilder.java | 5 +-
.../main/java/com/sun/faces/util/Util.java | 77 ++++++++++++++++++-
.../faces/application/ViewHandler.java | 13 +++-
5 files changed, 100 insertions(+), 88 deletions(-)
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 4075ffb474..444082f30b 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
@@ -43,7 +43,6 @@
import static jakarta.faces.application.Resource.COMPONENT_RESOURCE_KEY;
import static jakarta.faces.application.StateManager.IS_BUILDING_INITIAL_STATE;
import static jakarta.faces.application.StateManager.STATE_SAVING_METHOD_SERVER;
-import static jakarta.faces.application.ViewHandler.CHARACTER_ENCODING_KEY;
import static jakarta.faces.application.ViewHandler.DEFAULT_FACELETS_SUFFIX;
import static jakarta.faces.application.ViewVisitOption.RETURN_AS_MINIMAL_IMPLICIT_OUTCOME;
import static jakarta.faces.component.UIComponent.BEANINFO_KEY;
@@ -72,6 +71,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
@@ -904,26 +904,29 @@ protected ResponseWriter createResponseWriter(FacesContext context) throws IOExc
// get our content type
String contentType = (String) context.getAttributes().get("facelets.ContentType");
- // get the encoding
+ // get the last calculated encoding
String encoding = (String) context.getAttributes().get(FACELETS_ENCODING_KEY);
// Create a dummy ResponseWriter with a bogus writer,
- // so we can figure out what content type the ReponseWriter
+ // so we can figure out what content type and encoding the ReponseWriter
// is really going to ask for
- ResponseWriter writer = renderKit.createResponseWriter(NullWriter.INSTANCE, contentType, encoding);
+ ResponseWriter initWriter = renderKit.createResponseWriter(NullWriter.INSTANCE, contentType, encoding);
- contentType = getResponseContentType(context, writer.getContentType());
- encoding = getResponseEncoding(context, writer.getCharacterEncoding());
+ contentType = getResponseContentType(context, initWriter.getContentType());
+ encoding = Util.getResponseEncoding(context, Optional.ofNullable(initWriter.getCharacterEncoding()));
// apply them to the response
char[] buffer = new char[1028];
- HtmlUtils.writeTextForXML(writer, contentType, buffer);
+ HtmlUtils.writeTextForXML(initWriter, contentType, buffer);
String str = String.valueOf(buffer).trim();
extContext.setResponseContentType(str);
extContext.setResponseCharacterEncoding(encoding);
+ // Save encoding in UIViewRoot for faster consult when Util#getResponseEncoding() is invoked again elsewhere.
+ context.getViewRoot().getAttributes().put(FACELETS_ENCODING_KEY, encoding);
+
// Now, clone with the real writer
- writer = writer.cloneWithWriter(extContext.getResponseOutputWriter());
+ ResponseWriter writer = initWriter.cloneWithWriter(extContext.getResponseOutputWriter());
return writer;
}
@@ -974,58 +977,6 @@ protected void handleFaceletNotFound(FacesContext context, String viewId, String
context.responseComplete();
}
- /**
- * @param context the {@link FacesContext} for the current request
- * @param orig the original encoding
- * @return the encoding to be used for this response
- */
- protected String getResponseEncoding(FacesContext context, String orig) {
- String encoding = orig;
-
- // 1. get it from request
- encoding = context.getExternalContext().getRequestCharacterEncoding();
-
- // 2. get it from the session
- if (encoding == null) {
- if (context.getExternalContext().getSession(false) != null) {
- Map sessionMap = context.getExternalContext().getSessionMap();
- encoding = (String) sessionMap.get(CHARACTER_ENCODING_KEY);
- if (LOGGER.isLoggable(FINEST)) {
- LOGGER.log(FINEST, "Session specified alternate encoding {0}", encoding);
- }
- }
- }
-
- // see if we need to override the encoding
- Map