Skip to content

Commit

Permalink
Merge pull request #5393 from eclipse-ee4j/mojarra_issue_5380_add_ses…
Browse files Browse the repository at this point in the history
…sion_mutex

Add session mutex
  • Loading branch information
BalusC authored Mar 2, 2024
2 parents 5d700b3 + 039c661 commit e727ed4
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static com.sun.faces.application.view.ViewScopeManager.VIEW_MAP_ID;
import static com.sun.faces.cdi.CdiUtils.getBeanReference;
import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableDistributable;
import static com.sun.faces.context.SessionMap.getMutex;
import static com.sun.faces.util.Util.getCdiBeanManager;
import static java.util.logging.Level.FINEST;
import static java.util.logging.Level.WARNING;
Expand Down Expand Up @@ -95,7 +96,7 @@ public void clear(FacesContext facesContext, Map<String, Object> viewMap) {
LOGGER.log(WARNING, "Cannot locate the view map to clear in the active maps: {0}", viewMap);
}
}

/**
* Clear the given view map.
*
Expand Down Expand Up @@ -247,7 +248,7 @@ private Map<String, ViewScopeContextObject> getContextMap(FacesContext facesCont
String viewMapId = (String) facesContext.getViewRoot().getTransientStateHelper().getTransient(VIEW_MAP_ID);

if (activeViewScopeContexts == null && create) {
synchronized (session) {
synchronized (getMutex(session)) {
activeViewScopeContexts = new ConcurrentHashMap<>();
sessionMap.put(ACTIVE_VIEW_CONTEXTS, activeViewScopeContexts);
}
Expand Down Expand Up @@ -332,7 +333,7 @@ public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {

HttpSession session = httpSessionEvent.getSession();

Map<Object, Map<String, ViewScopeContextObject>> activeViewScopeContexts = (Map<Object, Map<String, ViewScopeContextObject>>)
Map<Object, Map<String, ViewScopeContextObject>> activeViewScopeContexts = (Map<Object, Map<String, ViewScopeContextObject>>)
session.getAttribute(ACTIVE_VIEW_CONTEXTS);
if (activeViewScopeContexts != null) {
Map<String, Object> activeViewMaps = (Map<String, Object>) session.getAttribute(ViewScopeManager.ACTIVE_VIEW_MAPS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableDistributable;
import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.NumberOfClientWindows;
import static com.sun.faces.context.SessionMap.getMutex;
import static java.util.logging.Level.FINEST;

import java.util.Collections;
Expand Down Expand Up @@ -157,7 +158,7 @@ private Map<String, ClientWindowScopeContextObject> getContextMap(FacesContext f
numberOfClientWindows = Integer.valueOf(NumberOfClientWindows.getDefaultValue());
}

synchronized (session) {
synchronized (getMutex(session)) {
sessionMap.put(CLIENT_WINDOW_CONTEXTS, Collections.synchronizedMap(new LRUMap<String, Object>(numberOfClientWindows)));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.ForceLoadFacesConfigFiles;
import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.VerifyFacesConfigObjects;
import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.JakartaFacesProjectStage;
import static com.sun.faces.context.SessionMap.createMutex;
import static com.sun.faces.context.SessionMap.removeMutex;
import static com.sun.faces.push.WebsocketEndpoint.URI_TEMPLATE;
import static java.lang.Boolean.TRUE;
import static java.text.MessageFormat.format;
Expand Down Expand Up @@ -350,13 +352,17 @@ public void requestInitialized(ServletRequestEvent event) {

@Override
public void sessionCreated(HttpSessionEvent event) {
createMutex(event.getSession());

if (webAppListener != null) {
webAppListener.sessionCreated(event);
}
}

@Override
public void sessionDestroyed(HttpSessionEvent event) {
removeMutex(event.getSession());

if (webAppListener != null) {
webAppListener.sessionDestroyed(event);
}
Expand Down
21 changes: 21 additions & 0 deletions impl/src/main/java/com/sun/faces/context/SessionMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.sun.faces.context;

import static java.util.Optional.ofNullable;

import java.io.Serializable;
import java.util.Collections;
import java.util.Enumeration;
Expand All @@ -37,6 +39,7 @@
public class SessionMap extends BaseContextMap<Object> {

private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger();
private static final String MUTEX = Mutex.class.getName();

private final HttpServletRequest request;
private final ProjectStage stage;
Expand Down Expand Up @@ -189,4 +192,22 @@ protected HttpSession getSession(boolean createNew) {
return request.getSession(createNew);
}

// ----------------------------------------------------------- Session Mutex

private static final class Mutex implements Serializable {
private static final long serialVersionUID = 1L;
}

public static void createMutex(HttpSession session) {
session.setAttribute(MUTEX, new Mutex());
}

public static Object getMutex(Object session) {
return session instanceof HttpSession ? ofNullable(((HttpSession) session).getAttribute(MUTEX)).orElse(session) : session;
}

public static void removeMutex(HttpSession session) {
session.removeAttribute(MUTEX);
}

} // END SessionMap
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.sun.faces.lifecycle;

import static com.sun.faces.context.SessionMap.getMutex;
import static com.sun.faces.renderkit.RenderKitUtils.PredefinedPostbackParameter.CLIENT_WINDOW_PARAM;

import java.util.Map;
Expand Down Expand Up @@ -56,7 +57,7 @@ public void decode(FacesContext context) {
}

private String calculateClientWindow(FacesContext context) {
synchronized (context.getExternalContext().getSession(true)) {
synchronized (getMutex(context.getExternalContext().getSession(true))) {
final String clientWindowCounterKey = "com.sun.faces.lifecycle.ClientWindowCounterKey";
ExternalContext extContext = context.getExternalContext();
Map<String, Object> sessionAttrs = extContext.getSessionMap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.SerializeServerState;
import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.NumberOfLogicalViews;
import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.NumberOfViews;
import static com.sun.faces.context.SessionMap.getMutex;
import static com.sun.faces.renderkit.RenderKitUtils.PredefinedPostbackParameter.VIEW_STATE_PARAM;
import static com.sun.faces.util.Util.notNull;
import static java.util.logging.Level.FINE;
Expand Down Expand Up @@ -149,7 +150,7 @@ public void writeState(FacesContext ctx, Object state, StringBuilder stateCaptur
Object sessionObj = externalContext.getSession(true);
Map<String, Object> sessionMap = externalContext.getSessionMap();

synchronized (sessionObj) {
synchronized (getMutex(sessionObj)) {
Map<String, Map> logicalMap = TypedCollections.dynamicallyCastMap((Map) sessionMap.get(LOGICAL_VIEW_MAP), String.class, Map.class);
if (logicalMap == null) {
logicalMap = Collections.synchronizedMap(new LRUMap<String, Map>(numberOfLogicalViews));
Expand Down Expand Up @@ -262,7 +263,7 @@ public Object getState(FacesContext ctx, String viewId) {
}

// noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (sessionObj) {
synchronized (getMutex(sessionObj)) {
Map logicalMap = (Map) externalCtx.getSessionMap().get(LOGICAL_VIEW_MAP);
if (logicalMap != null) {
Map actualMap = (Map) logicalMap.get(idInLogicalMap);
Expand Down Expand Up @@ -328,7 +329,7 @@ protected Object handleSaveState(Object state) {
if (!webConfig.isOptionEnabled(SerializeServerState)) {
return state;
}

ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
ObjectOutputStream oas = null;
try {
Expand All @@ -346,7 +347,7 @@ protected Object handleSaveState(Object state) {
}
}
}

return baos.toByteArray();
}

Expand All @@ -359,7 +360,7 @@ protected Object handleRestoreState(Object state) {
if (!webConfig.isOptionEnabled(SerializeServerState)) {
return state;
}

try (ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) state);
ObjectInputStream ois = serialProvider.createObjectInputStream(compressViewState ? new GZIPInputStream(bais, 1024) : bais);) {
return ois.readObject();
Expand Down Expand Up @@ -402,7 +403,7 @@ public boolean isStateless(FacesContext facesContext, String viewId) throws Ille
if (!facesContext.isPostback()) {
throw new IllegalStateException("Cannot determine whether or not the request is stateless");
}

String compoundId = getStateParamValue(facesContext);
return compoundId != null && "stateless".equals(compoundId);
}
Expand Down

0 comments on commit e727ed4

Please sign in to comment.