Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…tering

SECTION: Modified Files
----------------------------
M       jsf-ri/src/main/java/com/sun/faces/util/ByteArrayGuardAESCTR.java

- Make this cluster friendly by adding support for an env-entry to specify the secret key
  for encrypting the flash cookie.

  Here's how you use it.

+    <env-entry>
+        <env-entry-name>jsf/FlashSecretKey</env-entry-name>
+        <env-entry-type>java.lang.String</env-entry-type>
+        <!-- http://www.digitalsanctuary.com/aes-key-generator.php -->
+        <env-entry-value>YeMYsp5+BDTvzL6A5n40IusWI9E8Jqr9q/hk5GU53RE=</env-entry-value>
+    </env-entry>

  If you're going to use client side state saving, you also need this.

+    <env-entry>
+        <env-entry-name>jsf/ClientSideSecretKey</env-entry-name>
+        <env-entry-type>java.lang.String</env-entry-type>
+        <!-- http://www.digitalsanctuary.com/aes-key-generator.php -->
+        <env-entry-value>vxI50oNETIH5iSsUPFBvzP0913W8fy8lwZ/LT6caXyI= </env-entry-value>
+    </env-entry>

M       jsf-ri/src/main/java/com/sun/faces/context/flash/ELFlash.java

- Introduce some cluster awareness.  If we are in a cluster mode, use an
  HttpSessionActivationListener impl, SessionHelper, that essentially
  uses the session to transport the flash data to the other node on
  session activation.  This code is not touched in a non-cluster environment.

A         jsf-ri/src/main/java/com/sun/faces/context/flash/SessionHelper.java

- Uses the HttpSession to store the flashInnerMap in the case of session
  activation.

M       jsf-ri/src/main/java/com/sun/faces/context/flash/FlashELResolver.java

- Remove some incorrect assumptions.

  getValue() should take no action because the ImplicitObjectELResolver
  handles the the case of getValue(null, "flash");

  We should not be storing the flash in the session.  It is an
  application scoped singleton.

M       jsf-ri/src/main/java/com/sun/faces/el/ELConstants.java

- Add FLASH, update values accordingly.

M       jsf-ri/src/main/java/com/sun/faces/el/ImplicitObjectELResolver.java

- add flash to implicitNames.

- Add FLASH to big switch statement.

M       test/cluster/servlet25/flash/pom.xml

- Add basic test, copied from agnostic and improved with
  cluster-exercising capabilities.

M       test/agnostic/flash/basic/nbactions.xml
A       test/servlet30/el/nbactions.xml

- Make it so NetBeans Debug Focused Test works.

A       test/cluster/servlet25/flash/basic
A       test/cluster/servlet25/flash/basic/src
A       test/cluster/servlet25/flash/basic/src/test
A       test/cluster/servlet25/flash/basic/src/test/java
A       test/cluster/servlet25/flash/basic/src/test/java/com
A       test/cluster/servlet25/flash/basic/src/test/java/com/sun
A       test/cluster/servlet25/flash/basic/src/test/java/com/sun/faces
A       test/cluster/servlet25/flash/basic/src/test/java/com/sun/faces/test
A       test/cluster/servlet25/flash/basic/src/test/java/com/sun/faces/test/cluster
A       test/cluster/servlet25/flash/basic/src/test/java/com/sun/faces/test/cluster/flash
A       test/cluster/servlet25/flash/basic/src/test/java/com/sun/faces/test/cluster/flash/basic
A       test/cluster/servlet25/flash/basic/src/test/java/com/sun/faces/test/cluster/flash/basic/FlashMessagesIT.java
A       test/cluster/servlet25/flash/basic/src/test/java/com/sun/faces/test/cluster/flash/basic/FlashViewParamIT.java
A       test/cluster/servlet25/flash/basic/src/test/java/com/sun/faces/test/cluster/flash/basic/Issue2862IT.java
A       test/cluster/servlet25/flash/basic/src/test/java/com/sun/faces/test/cluster/flash/basic/KeepMessagesIT.java
A       test/cluster/servlet25/flash/basic/src/test/java/com/sun/faces/test/cluster/flash/basic/Issue2973IT.java
A       test/cluster/servlet25/flash/basic/src/main
A       test/cluster/servlet25/flash/basic/src/main/webapp
A       test/cluster/servlet25/flash/basic/src/main/webapp/flash02.xhtml
A       test/cluster/servlet25/flash/basic/src/main/webapp/flashDropCookie3.xhtml
A       test/cluster/servlet25/flash/basic/src/main/webapp/messagePage.xhtml
A       test/cluster/servlet25/flash/basic/src/main/webapp/issue2973
A       test/cluster/servlet25/flash/basic/src/main/webapp/issue2973/page1.xhtml
A       test/cluster/servlet25/flash/basic/src/main/webapp/issue2973/page2.xhtml
A       test/cluster/servlet25/flash/basic/src/main/webapp/flashKeepMessages01.xhtml
A       test/cluster/servlet25/flash/basic/src/main/webapp/WEB-INF
A       test/cluster/servlet25/flash/basic/src/main/webapp/WEB-INF/weblogic.xml
A       test/cluster/servlet25/flash/basic/src/main/webapp/WEB-INF/web.xml
A       test/cluster/servlet25/flash/basic/src/main/webapp/WEB-INF/glassfish-web.xml
A       test/cluster/servlet25/flash/basic/src/main/webapp/flashDropCookie.xhtml
A       test/cluster/servlet25/flash/basic/src/main/webapp/flashKeepMessages02.xhtml
A       test/cluster/servlet25/flash/basic/src/main/webapp/keepMessages.xhtml
A       test/cluster/servlet25/flash/basic/src/main/webapp/flash01.xhtml
A       test/cluster/servlet25/flash/basic/src/main/webapp/flashDropCookie2.xhtml
A       test/cluster/servlet25/flash/basic/src/main/java
A       test/cluster/servlet25/flash/basic/src/main/java/com
A       test/cluster/servlet25/flash/basic/src/main/java/com/sun
A       test/cluster/servlet25/flash/basic/src/main/java/com/sun/faces
A       test/cluster/servlet25/flash/basic/src/main/java/com/sun/faces/test
A       test/cluster/servlet25/flash/basic/src/main/java/com/sun/faces/test/cluster
A       test/cluster/servlet25/flash/basic/src/main/java/com/sun/faces/test/cluster/flash
A       test/cluster/servlet25/flash/basic/src/main/java/com/sun/faces/test/cluster/flash/basic
A       test/cluster/servlet25/flash/basic/src/main/java/com/sun/faces/test/cluster/flash/basic/FlashMessagesBean.java
A       test/cluster/servlet25/flash/basic/src/main/java/com/sun/faces/test/cluster/flash/basic/FlashDropCookieBean.java
A       test/cluster/servlet25/flash/basic/src/main/java/com/sun/faces/test/cluster/flash/basic/AddMessageBean.java
A       test/cluster/servlet25/flash/basic/src/main/java/com/sun/faces/test/cluster/flash/issue2973
A       test/cluster/servlet25/flash/basic/src/main/java/com/sun/faces/test/cluster/flash/issue2973/Bean.java
A       test/cluster/servlet25/flash/basic/src/main/resources
A       test/cluster/servlet25/flash/basic/pom.xml
A       test/cluster/servlet25/flash/basic/nbactions.xml

- New test.
  • Loading branch information
edburns committed May 7, 2014
1 parent f46ab11 commit 5b17d3b
Show file tree
Hide file tree
Showing 35 changed files with 2,105 additions and 96 deletions.
70 changes: 54 additions & 16 deletions jsf-ri/src/main/java/com/sun/faces/context/flash/ELFlash.java
Expand Up @@ -42,6 +42,7 @@

import com.sun.faces.config.WebConfiguration;
import com.sun.faces.config.WebConfiguration.WebContextInitParameter;
import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableDistributable;
import com.sun.faces.facelets.tag.ui.UIDebug;
import com.sun.faces.util.ByteArrayGuardAESCTR;
import com.sun.faces.util.FacesLogger;
Expand All @@ -62,7 +63,6 @@
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
Expand Down Expand Up @@ -140,14 +140,14 @@ public class ELFlash extends Flash {
private long numberOfFlashesBetweenFlashReapings = Long.
parseLong(WebContextInitParameter.NumberOfFlashesBetweenFlashReapings.getDefaultValue());

private Application application;

private final boolean distributable;
private ByteArrayGuardAESCTR guard;

// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="class vars">

private static final Logger LOGGER = FacesLogger.FLASH.getLogger();

/**
Expand All @@ -161,7 +161,7 @@ public class ELFlash extends Flash {
* stores the singleton ELFlash instance.</p>
*/
static final String FLASH_ATTRIBUTE_NAME = PREFIX + "f";

/**
* <p>This constant is used as the name of the cookie sent to the
* client. The cookie is used to allow the flash scope to
Expand Down Expand Up @@ -237,9 +237,9 @@ private enum CONSTANTS {
// <editor-fold defaultstate="collapsed" desc="Constructors and instance accessors">

/** Creates a new instance of ELFlash */
private ELFlash() {
private ELFlash(ExternalContext extContext) {
flashInnerMap = new ConcurrentHashMap<String,Map<String, Object>>();
WebConfiguration config = WebConfiguration.getInstance();
WebConfiguration config = WebConfiguration.getInstance(extContext);
String value;
try {
value = config.getOptionValue(WebContextInitParameter.NumberOfConcurrentFlashUsers);
Expand All @@ -261,7 +261,8 @@ private ELFlash() {

}

application = FacesContext.getCurrentInstance().getApplication();
distributable = config.isOptionEnabled(EnableDistributable);

guard = new ByteArrayGuardAESCTR();

}
Expand Down Expand Up @@ -299,10 +300,24 @@ static ELFlash getFlash(ExternalContext extContext, boolean create) {
if (null == flash && create) {
synchronized (extContext.getContext()) {
if (null == (flash = (ELFlash)
appMap.get(FLASH_ATTRIBUTE_NAME))) {
flash = new ELFlash();
appMap.get(FLASH_ATTRIBUTE_NAME))) {
flash = new ELFlash(extContext);
appMap.put(FLASH_ATTRIBUTE_NAME, flash);
}
}
}

// If we are in a clustered environment, store a helper to ensure
// our innerMap gets successfully replicated
if (null != appMap.get(EnableDistributable.getQualifiedName())) {
synchronized (extContext.getContext()) {
Map<String, Object> sessionMap = extContext.getSessionMap();
SessionHelper sessionHelper =
SessionHelper.getInstance(extContext);
if (null == sessionHelper) {
sessionHelper = new SessionHelper();
}
sessionHelper.update(extContext, flash);
}
}
return flash;
Expand Down Expand Up @@ -363,13 +378,13 @@ public void setRedirect(boolean newValue) {
public Object get(Object key) {
Object result = null;

FacesContext context = FacesContext.getCurrentInstance();
if (null != key) {
if (key.equals("keepMessages")) {
result = this.isKeepMessages();
} else if (key.equals("redirect")) {
result = this.isRedirect();
} else {
FacesContext context = FacesContext.getCurrentInstance();
if (isKeepFlagSet(context)) {
result = getPhaseMapForReading().get(key);
keep(key.toString());
Expand All @@ -384,6 +399,12 @@ public Object get(Object key) {
if (null == result) {
result = getPhaseMapForReading().get(key);
}
if (distributable) {
SessionHelper sessionHelper =
SessionHelper.getInstance(context.getExternalContext());
assert(null != sessionHelper);
sessionHelper.update(context.getExternalContext(), this);
}

if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.log(Level.FINEST, "get({0}) = {1}", new Object [] { key, result});
Expand All @@ -408,21 +429,30 @@ public Object put(String key, Object value) {
wasSpecialPut = true;
}
}
FacesContext context = FacesContext.getCurrentInstance();
if (!wasSpecialPut) {
result = (null == b) ? getPhaseMapForWriting().put(key, value) : b;
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.log(Level.FINEST, "put({0},{1})", new Object [] { key, value});
}
application.publishEvent(FacesContext.getCurrentInstance(), PostPutFlashValueEvent.class, key);
context.getApplication().publishEvent(context, PostPutFlashValueEvent.class, key);
}
if (distributable) {
SessionHelper sessionHelper =
SessionHelper.getInstance(context.getExternalContext());
assert(null != sessionHelper);
sessionHelper.update(context.getExternalContext(), this);
}

return result;
}

@SuppressWarnings("element-type-mismatch")
public Object remove(Object key) {
Object result = null;

application.publishEvent(FacesContext.getCurrentInstance(), PreRemoveFlashValueEvent.class, key);
FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().publishEvent(context, PreRemoveFlashValueEvent.class, key);
result = getPhaseMapForWriting().remove(key);

return result;
Expand Down Expand Up @@ -548,7 +578,7 @@ public void keep(String key) {

if (null != toKeep) {
getPhaseMapForWriting().put(key, toKeep);
application.publishEvent(FacesContext.getCurrentInstance(), PostKeepFlashValueEvent.class, key);
context.getApplication().publishEvent(context, PostKeepFlashValueEvent.class, key);

}
}
Expand Down Expand Up @@ -673,9 +703,17 @@ public void doLastPhaseActions(FacesContext context, boolean outgoingResponseIsR
}

// </editor-fold>

// <editor-fold defaultstate="collapsed" desc="Helpers">

void setFlashInnerMap(Map<String,Map<String, Object>> flashInnerMap) {
this.flashInnerMap = flashInnerMap;
}

Map<String, Map<String,Object>> getFlashInnerMap() {
return flashInnerMap;
}

public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("[\n");
Expand Down
Expand Up @@ -175,9 +175,8 @@ public FlashELResolver() {
* <p>Hook into the EL resolution process to introduce the
* <code>flash</code> implicit object. If
* <code>property</code> is <code>null</code>, take no action
* and return <code>null</code>. If <code>base</code> is
* <code>null</code> and value is the literal string "flash", return
* the {@link ELFlash} instance, which is a Map. If
* and return <code>null</code>. if <code>base</code> is null, return null.
* If
* <code>base</code> is an instance of <code>ELFlash</code> and
* property is the literal string "keep", set a ThreadLocal property
* that will be inspected by the flash on the next link in the
Expand All @@ -203,77 +202,48 @@ public Object getValue(ELContext elContext, Object base, Object property)

Object result = null;

// Deal with getValue(null, "flash").
if (null == base)
{
// If the property is the implicit object "flash"...
if (property.toString().equals(FLASH_VARIABLE_NAME))
{
FacesContext facesContext =
(FacesContext) elContext.getContext(FacesContext.class);
ExternalContext extCtx = facesContext.getExternalContext();

// try to get the flash from the session.
FlashFactory ff = (FlashFactory)
FactoryFinder.getFactory(FactoryFinder.FLASH_FACTORY);
Map<String, Object> flash = ff.getFlash(false);

elContext.setPropertyResolved(true);

if (null == flash)
{
// create a new one and store it in the session.
flash = ff.getFlash(true);
extCtx.getSessionMap().put(ELFlash.FLASH_ATTRIBUTE_NAME, flash);
}

result = flash;
}
return null;
}
// If the base argument is the flash itself...
else if (base instanceof Flash)
{
FacesContext facesContext =
(FacesContext) elContext.getContext(FacesContext.class);
ExternalContext extCtx = facesContext.getExternalContext();

// try to get the flash from the session.
FlashFactory ff = (FlashFactory)
FactoryFinder.getFactory(FactoryFinder.FLASH_FACTORY);
Map<String, Object> flash = ff.getFlash(false);

if (base == flash)
{
FacesContext facesContext =
(FacesContext) elContext.getContext(FacesContext.class);
ExternalContext extCtx = facesContext.getExternalContext();

// and the property argument is "keep"...
if (property.toString().equals(FLASH_KEEP_VARIABLE_NAME))
{
elContext.setPropertyResolved(true);
elContext.setPropertyResolved(true);

// then this is a request to promote the value
// "property", which is assumed to have been previously
// stored in request scope via the "flash.now"
// expression, to flash scope.
result = base;
// Set a flag so the flash itself can look in the request
// and promote the value to the next request
ff.getFlash(true);
ELFlash.setKeepFlag(facesContext);
// then this is a request to promote the value
// "property", which is assumed to have been previously
// stored in request scope via the "flash.now"
// expression, to flash scope.
result = base;
// Set a flag so the flash itself can look in the request
// and promote the value to the next request
FlashFactory ff = (FlashFactory)
FactoryFinder.getFactory(FactoryFinder.FLASH_FACTORY);
ff.getFlash(true);
ELFlash.setKeepFlag(facesContext);
}
// Otherwise, if base is the flash, and property is "now"...
else if (property.toString().equals(FLASH_NOW_VARIABLE_NAME))
{
// PENDING(edburns): use FacesContext.getAttributes() instead of
// request scope.
// PENDING(edburns): use FacesContext.getAttributes() instead of
// request scope.
Map<String, Object> requestMap = extCtx.getRequestMap();
requestMap.put(ELFlash.FLASH_NOW_REQUEST_KEY, property);
elContext.setPropertyResolved(true);
result = requestMap;
}
else
{
result = null;
result = null;
}
}
}

return result;
Expand Down Expand Up @@ -388,8 +358,7 @@ public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext elContext,
ExternalContext extCtx = facesContext.getExternalContext();

//noinspection unchecked
if (null != (flash = (Map<String, Object>)
extCtx.getSessionMap().get(ELFlash.FLASH_ATTRIBUTE_NAME))) {
if (null != (flash = extCtx.getFlash())) {
Iterator<Map.Entry<String, Object>> iter = flash.entrySet().iterator();
Map.Entry<String, Object> cur;
ArrayList<FeatureDescriptor> fds;
Expand Down

0 comments on commit 5b17d3b

Please sign in to comment.