You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by ta...@apache.org on 2015/06/29 20:57:14 UTC
[2/2] deltaspike git commit: DELTASPIKE-932 moved modes to own classes
DELTASPIKE-932 moved modes to own classes
Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/ff4c502f
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/ff4c502f
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/ff4c502f
Branch: refs/heads/master
Commit: ff4c502f23ae36143923e00cea7c6e57da8a97f5
Parents: 99a8804
Author: Thomas Andraschko <ta...@apache.org>
Authored: Mon Jun 29 20:57:04 2015 +0200
Committer: Thomas Andraschko <ta...@apache.org>
Committed: Mon Jun 29 20:57:04 2015 +0200
----------------------------------------------------------------------
.../impl/scope/window/DefaultClientWindow.java | 403 ++-----------------
.../strategy/AbstractClientWindowStrategy.java | 195 +++++++++
.../strategy/ClientSideWindowStrategy.java | 198 +++++++++
.../strategy/DelegatedWindowStrategy.java | 47 +++
.../window/strategy/LazyWindowStrategy.java | 89 ++++
.../window/strategy/NoneWindowStrategy.java | 35 ++
.../jsf/impl/util/ClientWindowHelper.java | 377 ++++++++---------
7 files changed, 793 insertions(+), 551 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ff4c502f/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/DefaultClientWindow.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/DefaultClientWindow.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/DefaultClientWindow.java
index c6f4932..2db4b7e 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/DefaultClientWindow.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/DefaultClientWindow.java
@@ -18,28 +18,17 @@
*/
package org.apache.deltaspike.jsf.impl.scope.window;
-import org.apache.deltaspike.core.spi.scope.window.WindowContext;
-import org.apache.deltaspike.jsf.api.config.JsfModuleConfig;
-import org.apache.deltaspike.jsf.impl.util.ClientWindowHelper;
-import org.apache.deltaspike.jsf.impl.util.JsfUtils;
import org.apache.deltaspike.jsf.spi.scope.window.ClientWindow;
import org.apache.deltaspike.jsf.spi.scope.window.ClientWindowConfig;
-import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
-import javax.faces.FacesException;
-import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.HashMap;
import java.util.Map;
-import java.util.Random;
-import javax.servlet.http.HttpServletRequest;
-import org.apache.deltaspike.core.util.StringUtils;
+import org.apache.deltaspike.jsf.impl.scope.window.strategy.ClientSideWindowStrategy;
+import org.apache.deltaspike.jsf.impl.scope.window.strategy.DelegatedWindowStrategy;
+import org.apache.deltaspike.jsf.impl.scope.window.strategy.LazyWindowStrategy;
+import org.apache.deltaspike.jsf.impl.scope.window.strategy.NoneWindowStrategy;
import static org.apache.deltaspike.jsf.spi.scope.window.ClientWindowConfig.ClientWindowRenderMode;
@@ -54,395 +43,69 @@ import static org.apache.deltaspike.jsf.spi.scope.window.ClientWindowConfig.Clie
@ApplicationScoped
public class DefaultClientWindow implements ClientWindow
{
- /**
- * Value which can be used as "window-id" by external clients which aren't aware of windows.
- * It deactivates e.g. the redirect for the initial request.
- */
- public static final String AUTOMATED_ENTRY_POINT_PARAMETER_KEY = "automatedEntryPoint";
-
- /**
- * The parameter for the windowId for POST requests
- */
- public static final String DELTASPIKE_WINDOW_ID_POST_PARAM = "dspwid";
- public static final String JSF_WINDOW_ID_POST_PARAM = "javax.faces.ClientWindow";
-
- /**
- * GET request parameter
- */
- public static final String DELTASPIKE_WINDOW_ID_URL_PARAM = "dswid";
-
- private static final String PER_USE_CLIENT_WINDOW_URL_QUERY_PARAMETER_DISABLED_KEY =
- ClientWindow.class.getName() + ".ClientWindowRenderModeEnablement";
-
- private static final String WINDOW_ID_COOKIE_PREFIX = "dsWindowId-";
- private static final String DELTASPIKE_REQUEST_TOKEN = "dsrid";
-
- private static final String UNINITIALIZED_WINDOW_ID_VALUE = "uninitializedWindowId";
- private static final String WINDOW_ID_REPLACE_PATTERN = "$$windowIdValue$$";
- private static final String NOSCRIPT_URL_REPLACE_PATTERN = "$$noscriptUrl$$";
-
- /**
- * Use this parameter to force a 'direct' request from the clients without any windowId detection
- * We keep this name for backward compat with CODI.
- */
- private static final String NOSCRIPT_PARAMETER = "mfDirect";
-
- /**
- * This windowId will be used for all requests with disabled windowId feature
- */
- private static final String DEFAULT_WINDOW_ID = "default";
-
- private static final String WINDOW_ID_REQUEST_MAP_KEY =
- ClientWindow.class.getName() + ".WindowId";
-
- private static final String CACHE_QUERY_URL_PARAMETERS =
- "CACHE:" + DefaultClientWindow.class + "#getQueryURLParameters";
-
@Inject
private ClientWindowConfig clientWindowConfig;
@Inject
- private JsfModuleConfig jsfModuleConfig;
+ private ClientSideWindowStrategy clientSideWindowStrategy;
@Inject
- private WindowContext windowContext;
-
- private int maxWindowIdCount = 10;
+ private DelegatedWindowStrategy delegatedWindowStrategy;
+ @Inject
+ private LazyWindowStrategy lazyWindowStrategy;
- @PostConstruct
- protected void init()
- {
- this.maxWindowIdCount = ClientWindowHelper.getMaxWindowIdLength();
- }
+ @Inject
+ private NoneWindowStrategy noneWindowStrategy;
@Override
public String getWindowId(FacesContext facesContext)
{
- String windowId = getOrCreateWindowId(facesContext);
-
- if (windowId != null && windowId.length() > this.maxWindowIdCount)
- {
- windowId = windowId.substring(0, this.maxWindowIdCount);
- }
- return windowId;
- }
-
- protected String getOrCreateWindowId(FacesContext facesContext)
- {
- ExternalContext externalContext = facesContext.getExternalContext();
- Map<String, Object> requestMap = externalContext.getRequestMap();
-
- // try to lookup from cache
- String windowId = (String) requestMap.get(WINDOW_ID_REQUEST_MAP_KEY);
- if (windowId != null)
- {
- return windowId;
- }
-
- ClientWindowRenderMode clientWindowRenderMode = clientWindowConfig.getClientWindowRenderMode(facesContext);
- if (ClientWindowRenderMode.NONE.equals(clientWindowRenderMode))
- {
- // if this request should not get any window detection then we are done
- windowId = DEFAULT_WINDOW_ID;
- }
- else if (ClientWindowRenderMode.DELEGATED.equals(clientWindowRenderMode))
- {
- windowId = ClientWindowAdapter.getWindowIdFromJsf(facesContext);
- }
- else if (ClientWindowRenderMode.LAZY.equals(clientWindowRenderMode))
- {
- windowId = ClientWindowHelper.getInitialRedirectWindowId(facesContext);
-
- if (StringUtils.isEmpty(windowId))
- {
- windowId = externalContext.getRequestParameterMap().get(DELTASPIKE_WINDOW_ID_URL_PARAM);
- }
-
- boolean post = isPost(facesContext);
-
- if (StringUtils.isEmpty(windowId) && post)
- {
- windowId = getPostBackWindowId(facesContext);
- }
-
- if (StringUtils.isEmpty(windowId))
- {
- if (this.jsfModuleConfig.isInitialRedirectEnabled() && !post)
- {
- ClientWindowHelper.handleInitialRedirect(facesContext, generateNewWindowId());
- facesContext.responseComplete();
- windowId = null;
- }
- else
- {
- windowId = generateNewWindowId();
- }
- }
- }
- else if (ClientWindowRenderMode.CLIENTWINDOW.equals(clientWindowRenderMode))
- {
- boolean post = isPost(facesContext);
-
- if (post)
- {
- windowId = getPostBackWindowId(facesContext);
- }
- else if (isNoscriptRequest(externalContext))
- {
- // the client has JavaScript disabled
- clientWindowConfig.setJavaScriptEnabled(false);
-
- windowId = DEFAULT_WINDOW_ID;
- }
- else
- {
- windowId = getVerifiedWindowIdFromCookie(externalContext);
-
- boolean newWindowIdRequested = false;
- if (AUTOMATED_ENTRY_POINT_PARAMETER_KEY.equals(windowId))
- {
- // this is a marker for generating a new windowId
- windowId = generateNewWindowId();
- newWindowIdRequested = true;
- }
-
- if (windowId == null || newWindowIdRequested)
- {
- // GET request without windowId - send windowhandlerfilter.html to get the windowId
- sendWindowHandlerHtml(externalContext, windowId);
- facesContext.responseComplete();
- }
- }
- }
-
- // we have a valid windowId - set it and continue with the request
- if (windowId != null)
- {
- requestMap.put(WINDOW_ID_REQUEST_MAP_KEY, windowId);
- }
-
- return windowId;
- }
-
- /**
- * Create a unique windowId
- * @return
- */
- private String generateNewWindowId()
- {
- //X TODO proper mechanism
- return "" + (new Random()).nextInt() % 10000;
- }
-
- private boolean isPost(FacesContext context)
- {
- if (context.isPostback())
- {
- return true;
- }
-
- Object request = context.getExternalContext().getRequest();
- if (request instanceof HttpServletRequest)
- {
- if ("POST".equals(((HttpServletRequest) request).getMethod()))
- {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Extract the windowId for http POST
- */
- private String getPostBackWindowId(FacesContext facesContext)
- {
- Map<String, String> requestParams = facesContext.getExternalContext().getRequestParameterMap();
- String windowId = requestParams.get(DELTASPIKE_WINDOW_ID_POST_PARAM);
-
- if (windowId == null)
- {
- windowId = requestParams.get(JSF_WINDOW_ID_POST_PARAM);
- }
- return windowId;
- }
-
- private boolean isNoscriptRequest(ExternalContext externalContext)
- {
- String noscript = externalContext.getRequestParameterMap().get(NOSCRIPT_PARAMETER);
-
- return (noscript != null && "true".equals(noscript));
- }
-
- private void sendWindowHandlerHtml(ExternalContext externalContext, String windowId)
- {
- HttpServletResponse httpResponse = (HttpServletResponse) externalContext.getResponse();
-
- try
- {
- httpResponse.setStatus(HttpServletResponse.SC_OK);
- httpResponse.setContentType("text/html");
-
- String windowHandlerHtml = clientWindowConfig.getClientWindowHtml();
-
- if (windowId == null)
- {
- windowId = UNINITIALIZED_WINDOW_ID_VALUE;
- }
-
- // set the windowId value in the javascript code
- windowHandlerHtml = windowHandlerHtml.replace(WINDOW_ID_REPLACE_PATTERN, windowId);
-
- // set the noscript-URL for users with no JavaScript
- windowHandlerHtml =
- windowHandlerHtml.replace(NOSCRIPT_URL_REPLACE_PATTERN, getNoscriptUrl(externalContext));
-
- OutputStream os = httpResponse.getOutputStream();
- try
- {
- os.write(windowHandlerHtml.getBytes());
- }
- finally
- {
- os.close();
- }
- }
- catch (IOException ioe)
- {
- throw new FacesException(ioe);
- }
- }
-
- private String getNoscriptUrl(ExternalContext externalContext)
- {
- String url = externalContext.getRequestPathInfo();
- if (url == null)
- {
- url = "";
- }
-
- // only use the very last part of the url
- int lastSlash = url.lastIndexOf('/');
- if (lastSlash != -1)
- {
- url = url.substring(lastSlash + 1);
- }
-
- // add request parameter
- url = JsfUtils.addPageParameters(externalContext, url, true);
- url = JsfUtils.addParameter(externalContext, url, false, NOSCRIPT_PARAMETER, "true");
-
- // NOTE that the url could contain data for an XSS attack
- // like e.g. ?"></a><a href%3D"http://hacker.org/attack.html?a
- // DO NOT REMOVE THE FOLLOWING LINES!
- url = url.replace("\"", "");
- url = url.replace("\'", "");
-
- return url;
- }
-
- private String getVerifiedWindowIdFromCookie(ExternalContext externalContext)
- {
- String cookieName = WINDOW_ID_COOKIE_PREFIX + getRequestToken(externalContext);
- Cookie cookie = (Cookie) externalContext.getRequestCookieMap().get(cookieName);
-
- if (cookie != null)
- {
- // manually blast the cookie away, otherwise it pollutes the
- // cookie storage in some browsers. E.g. Firefox doesn't
- // cleanup properly, even if the max-age is reached.
- cookie.setMaxAge(0);
-
- return cookie.getValue();
- }
-
- return null;
- }
-
- private String getRequestToken(ExternalContext externalContext)
- {
- String requestToken = externalContext.getRequestParameterMap().get(DELTASPIKE_REQUEST_TOKEN);
- if (requestToken != null)
- {
- return requestToken;
- }
-
- return "";
+ return getClientWindow(facesContext).getWindowId(facesContext);
}
@Override
public void disableClientWindowRenderMode(FacesContext facesContext)
{
- ClientWindowRenderMode clientWindowRenderMode = clientWindowConfig.getClientWindowRenderMode(facesContext);
-
- if (ClientWindowRenderMode.DELEGATED.equals(clientWindowRenderMode))
- {
- facesContext.getExternalContext().getClientWindow().disableClientWindowRenderMode(facesContext);
- }
- else if (ClientWindowRenderMode.LAZY.equals(clientWindowRenderMode))
- {
- Map<Object, Object> attrMap = facesContext.getAttributes();
- attrMap.put(PER_USE_CLIENT_WINDOW_URL_QUERY_PARAMETER_DISABLED_KEY, Boolean.TRUE);
- }
+ getClientWindow(facesContext).disableClientWindowRenderMode(facesContext);
}
@Override
public void enableClientWindowRenderMode(FacesContext facesContext)
{
- ClientWindowRenderMode clientWindowRenderMode = clientWindowConfig.getClientWindowRenderMode(facesContext);
-
- if (ClientWindowRenderMode.DELEGATED.equals(clientWindowRenderMode))
- {
- facesContext.getExternalContext().getClientWindow().enableClientWindowRenderMode(facesContext);
- }
- else if (ClientWindowRenderMode.LAZY.equals(clientWindowRenderMode))
- {
- Map<Object, Object> attrMap = facesContext.getAttributes();
- attrMap.remove(PER_USE_CLIENT_WINDOW_URL_QUERY_PARAMETER_DISABLED_KEY);
- }
+ getClientWindow(facesContext).enableClientWindowRenderMode(facesContext);
}
@Override
public boolean isClientWindowRenderModeEnabled(FacesContext facesContext)
{
- ClientWindowRenderMode clientWindowRenderMode = clientWindowConfig.getClientWindowRenderMode(facesContext);
-
- if (ClientWindowRenderMode.LAZY.equals(clientWindowRenderMode))
- {
- Map<Object, Object> attrMap = facesContext.getAttributes();
- return !attrMap.containsKey(PER_USE_CLIENT_WINDOW_URL_QUERY_PARAMETER_DISABLED_KEY);
- }
-
- return false;
+ return getClientWindow(facesContext).isClientWindowRenderModeEnabled(facesContext);
}
@Override
public Map<String, String> getQueryURLParameters(FacesContext facesContext)
{
- ClientWindowRenderMode clientWindowRenderMode = clientWindowConfig.getClientWindowRenderMode(facesContext);
-
- if (ClientWindowRenderMode.LAZY.equals(clientWindowRenderMode))
- {
- if (!facesContext.getAttributes().containsKey(CACHE_QUERY_URL_PARAMETERS))
- {
- String windowId = getWindowId(facesContext);
-
- if (windowId == null)
- {
- return null;
- }
-
- Map<String, String> params = new HashMap<String, String>();
- params.put(DELTASPIKE_WINDOW_ID_URL_PARAM, windowId);
+ return getClientWindow(facesContext).getQueryURLParameters(facesContext);
+ }
- facesContext.getAttributes().put(CACHE_QUERY_URL_PARAMETERS, params);
- }
+ protected ClientWindow getClientWindow(FacesContext facesContext)
+ {
+ ClientWindowRenderMode clientWindowRenderMode = clientWindowConfig.getClientWindowRenderMode(facesContext);
- return (Map<String, String>) facesContext.getAttributes().get(CACHE_QUERY_URL_PARAMETERS);
+ switch (clientWindowRenderMode)
+ {
+ case CLIENTWINDOW:
+ return clientSideWindowStrategy;
+ case CUSTOM:
+ return null;
+ case DELEGATED:
+ return delegatedWindowStrategy;
+ case LAZY:
+ return lazyWindowStrategy;
+ case NONE:
+ return noneWindowStrategy;
+ default:
+ return null;
}
-
- return null;
}
}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ff4c502f/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/AbstractClientWindowStrategy.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/AbstractClientWindowStrategy.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/AbstractClientWindowStrategy.java
new file mode 100644
index 0000000..a985630
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/AbstractClientWindowStrategy.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.jsf.impl.scope.window.strategy;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Random;
+import javax.annotation.PostConstruct;
+import javax.faces.context.FacesContext;
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+import org.apache.deltaspike.core.spi.scope.window.WindowContext;
+import org.apache.deltaspike.jsf.api.config.JsfModuleConfig;
+import org.apache.deltaspike.jsf.impl.util.ClientWindowHelper;
+import org.apache.deltaspike.jsf.spi.scope.window.ClientWindow;
+import org.apache.deltaspike.jsf.spi.scope.window.ClientWindowConfig;
+
+public abstract class AbstractClientWindowStrategy implements ClientWindow
+{
+ /**
+ * This windowId will be used for all requests with disabled windowId feature
+ */
+ public static final String DEFAULT_WINDOW_ID = "default";
+
+ private static final String CACHE_QUERY_URL_PARAMETERS =
+ "CACHE:" + AbstractClientWindowStrategy.class.getName() + "#getQueryURLParameters";
+ private static final String CACHE_WINDOW_ID =
+ "CACHE:" + AbstractClientWindowStrategy.class.getName() + ".WindowId";
+
+ private static final String PER_USE_CLIENT_WINDOW_URL_QUERY_PARAMETER_DISABLED_KEY =
+ LazyWindowStrategy.class.getName() + ".ClientWindowRenderModeEnablement";
+
+ @Inject
+ protected ClientWindowConfig clientWindowConfig;
+
+ @Inject
+ protected JsfModuleConfig jsfModuleConfig;
+
+ @Inject
+ protected WindowContext windowContext;
+
+ private int maxWindowIdCount = 10;
+
+ @PostConstruct
+ protected void init()
+ {
+ this.maxWindowIdCount = ClientWindowHelper.getMaxWindowIdLength();
+ }
+
+
+ @Override
+ public String getWindowId(FacesContext facesContext)
+ {
+ Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
+
+ // try to lookup from cache
+ String windowId = (String) requestMap.get(CACHE_WINDOW_ID);
+ if (windowId != null)
+ {
+ return windowId;
+ }
+
+ windowId = getOrCreateWindowId(facesContext);
+
+ if (windowId != null && windowId.length() > this.maxWindowIdCount)
+ {
+ windowId = windowId.substring(0, this.maxWindowIdCount);
+
+ requestMap.put(CACHE_WINDOW_ID, windowId);
+ }
+
+ return windowId;
+ }
+
+ protected abstract String getOrCreateWindowId(FacesContext facesContext);
+
+ protected String generateNewWindowId()
+ {
+ //X TODO proper mechanism
+ return "" + (new Random()).nextInt() % 10000;
+ }
+
+ protected boolean isPost(FacesContext facesContext)
+ {
+ if (facesContext.isPostback())
+ {
+ return true;
+ }
+
+ Object request = facesContext.getExternalContext().getRequest();
+ if (request instanceof HttpServletRequest)
+ {
+ if ("POST".equals(((HttpServletRequest) request).getMethod()))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Extract the windowId for http POST
+ */
+ protected String getPostBackWindowId(FacesContext facesContext)
+ {
+ Map<String, String> requestParams = facesContext.getExternalContext().getRequestParameterMap();
+ String windowId = requestParams.get(ClientWindowHelper.RequestParameters.POST_WINDOW_ID);
+
+ if (windowId == null)
+ {
+ windowId = requestParams.get(ClientWindowHelper.RequestParameters.JSF_POST_WINDOW_ID);
+ }
+ return windowId;
+ }
+
+ @Override
+ public void disableClientWindowRenderMode(FacesContext facesContext)
+ {
+ if (isSupportClientWindowRenderingMode())
+ {
+ Map<Object, Object> attrMap = facesContext.getAttributes();
+ attrMap.put(PER_USE_CLIENT_WINDOW_URL_QUERY_PARAMETER_DISABLED_KEY, Boolean.TRUE);
+ }
+ }
+
+ @Override
+ public void enableClientWindowRenderMode(FacesContext facesContext)
+ {
+ if (isSupportClientWindowRenderingMode())
+ {
+ Map<Object, Object> attrMap = facesContext.getAttributes();
+ attrMap.remove(PER_USE_CLIENT_WINDOW_URL_QUERY_PARAMETER_DISABLED_KEY);
+ }
+ }
+
+ @Override
+ public boolean isClientWindowRenderModeEnabled(FacesContext facesContext)
+ {
+ if (isSupportClientWindowRenderingMode())
+ {
+ Map<Object, Object> attrMap = facesContext.getAttributes();
+ return !attrMap.containsKey(PER_USE_CLIENT_WINDOW_URL_QUERY_PARAMETER_DISABLED_KEY);
+ }
+
+ return false;
+ }
+
+ protected boolean isSupportClientWindowRenderingMode()
+ {
+ return false;
+ }
+
+ @Override
+ public Map<String, String> getQueryURLParameters(FacesContext facesContext)
+ {
+ Map<String, String> cachedParameters =
+ (Map<String, String>) facesContext.getAttributes().get(CACHE_QUERY_URL_PARAMETERS);
+
+ // cache paramters per request - will be called many times
+ if (cachedParameters == null)
+ {
+ cachedParameters = createQueryURLParameters(facesContext);
+ if (cachedParameters == null)
+ {
+ cachedParameters = Collections.EMPTY_MAP;
+ }
+
+ facesContext.getAttributes().put(CACHE_QUERY_URL_PARAMETERS, cachedParameters);
+ }
+
+ return cachedParameters;
+ }
+
+ protected Map<String, String> createQueryURLParameters(FacesContext facesContext)
+ {
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ff4c502f/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/ClientSideWindowStrategy.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/ClientSideWindowStrategy.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/ClientSideWindowStrategy.java
new file mode 100644
index 0000000..fdf2ee9
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/ClientSideWindowStrategy.java
@@ -0,0 +1,198 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.jsf.impl.scope.window.strategy;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Typed;
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.deltaspike.jsf.impl.util.ClientWindowHelper;
+import org.apache.deltaspike.jsf.impl.util.JsfUtils;
+
+@Dependent
+@Typed(ClientSideWindowStrategy.class)
+public class ClientSideWindowStrategy extends AbstractClientWindowStrategy
+{
+ /**
+ * Value which can be used as "window-id" by external clients which aren't aware of windows.
+ * It deactivates e.g. the redirect for the initial request.
+ */
+ private static final String AUTOMATED_ENTRY_POINT_PARAMETER_KEY = "automatedEntryPoint";
+
+ private static final String UNINITIALIZED_WINDOW_ID_VALUE = "uninitializedWindowId";
+ private static final String WINDOW_ID_REPLACE_PATTERN = "$$windowIdValue$$";
+ private static final String NOSCRIPT_URL_REPLACE_PATTERN = "$$noscriptUrl$$";
+
+ /**
+ * Use this parameter to force a 'direct' request from the clients without any windowId detection
+ * We keep this name for backward compat with CODI.
+ */
+ private static final String NOSCRIPT_PARAMETER = "mfDirect";
+
+
+ @Override
+ protected String getOrCreateWindowId(FacesContext facesContext)
+ {
+ String windowId = null;
+
+ boolean post = isPost(facesContext);
+
+ if (post)
+ {
+ windowId = getPostBackWindowId(facesContext);
+ }
+ else if (isNoscriptRequest(facesContext.getExternalContext()))
+ {
+ // the client has JavaScript disabled
+ clientWindowConfig.setJavaScriptEnabled(false);
+
+ windowId = DEFAULT_WINDOW_ID;
+ }
+ else
+ {
+ windowId = getVerifiedWindowIdFromCookie(facesContext.getExternalContext());
+
+ boolean newWindowIdRequested = false;
+ if (AUTOMATED_ENTRY_POINT_PARAMETER_KEY.equals(windowId))
+ {
+ // this is a marker for generating a new windowId
+ windowId = generateNewWindowId();
+ newWindowIdRequested = true;
+ }
+
+ if (windowId == null || newWindowIdRequested)
+ {
+ // GET request without windowId - send windowhandlerfilter.html to get the windowId
+ sendWindowHandlerHtml(facesContext.getExternalContext(), windowId);
+ facesContext.responseComplete();
+ }
+ }
+
+ return windowId;
+ }
+
+ protected boolean isNoscriptRequest(ExternalContext externalContext)
+ {
+ String noscript = externalContext.getRequestParameterMap().get(NOSCRIPT_PARAMETER);
+
+ return (noscript != null && "true".equals(noscript));
+ }
+
+ protected void sendWindowHandlerHtml(ExternalContext externalContext, String windowId)
+ {
+ HttpServletResponse httpResponse = (HttpServletResponse) externalContext.getResponse();
+
+ try
+ {
+ httpResponse.setStatus(HttpServletResponse.SC_OK);
+ httpResponse.setContentType("text/html");
+
+ String windowHandlerHtml = clientWindowConfig.getClientWindowHtml();
+
+ if (windowId == null)
+ {
+ windowId = UNINITIALIZED_WINDOW_ID_VALUE;
+ }
+
+ // set the windowId value in the javascript code
+ windowHandlerHtml = windowHandlerHtml.replace(WINDOW_ID_REPLACE_PATTERN, windowId);
+
+ // set the noscript-URL for users with no JavaScript
+ windowHandlerHtml =
+ windowHandlerHtml.replace(NOSCRIPT_URL_REPLACE_PATTERN, getNoscriptUrl(externalContext));
+
+ OutputStream os = httpResponse.getOutputStream();
+ try
+ {
+ os.write(windowHandlerHtml.getBytes());
+ }
+ finally
+ {
+ os.close();
+ }
+ }
+ catch (IOException ioe)
+ {
+ throw new FacesException(ioe);
+ }
+ }
+
+ protected String getNoscriptUrl(ExternalContext externalContext)
+ {
+ String url = externalContext.getRequestPathInfo();
+ if (url == null)
+ {
+ url = "";
+ }
+
+ // only use the very last part of the url
+ int lastSlash = url.lastIndexOf('/');
+ if (lastSlash != -1)
+ {
+ url = url.substring(lastSlash + 1);
+ }
+
+ // add request parameter
+ url = JsfUtils.addPageParameters(externalContext, url, true);
+ url = JsfUtils.addParameter(externalContext, url, false, NOSCRIPT_PARAMETER, "true");
+
+ // NOTE that the url could contain data for an XSS attack
+ // like e.g. ?"></a><a href%3D"http://hacker.org/attack.html?a
+ // DO NOT REMOVE THE FOLLOWING LINES!
+ url = url.replace("\"", "");
+ url = url.replace("\'", "");
+
+ return url;
+ }
+
+ protected String getVerifiedWindowIdFromCookie(ExternalContext externalContext)
+ {
+ String cookieName = ClientWindowHelper.Cookies.WINDOW_ID_PREFIX + getRequestToken(externalContext);
+ Cookie cookie = (Cookie) externalContext.getRequestCookieMap().get(cookieName);
+
+ if (cookie != null)
+ {
+ // manually blast the cookie away, otherwise it pollutes the
+ // cookie storage in some browsers. E.g. Firefox doesn't
+ // cleanup properly, even if the max-age is reached.
+ cookie.setMaxAge(0);
+
+ return cookie.getValue();
+ }
+
+ return null;
+ }
+
+ protected String getRequestToken(ExternalContext externalContext)
+ {
+ String requestToken =
+ externalContext.getRequestParameterMap().get(ClientWindowHelper.RequestParameters.REQUEST_TOKEN);
+ if (requestToken != null)
+ {
+ return requestToken;
+ }
+
+ return "";
+ }
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ff4c502f/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/DelegatedWindowStrategy.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/DelegatedWindowStrategy.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/DelegatedWindowStrategy.java
new file mode 100644
index 0000000..fd12e49
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/DelegatedWindowStrategy.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.jsf.impl.scope.window.strategy;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Typed;
+import javax.faces.context.FacesContext;
+import org.apache.deltaspike.jsf.impl.scope.window.ClientWindowAdapter;
+
+@Dependent
+@Typed(DelegatedWindowStrategy.class)
+public class DelegatedWindowStrategy extends AbstractClientWindowStrategy
+{
+ @Override
+ protected String getOrCreateWindowId(FacesContext facesContext)
+ {
+ return ClientWindowAdapter.getWindowIdFromJsf(facesContext);
+ }
+
+ @Override
+ public void disableClientWindowRenderMode(FacesContext facesContext)
+ {
+ facesContext.getExternalContext().getClientWindow().disableClientWindowRenderMode(facesContext);
+ }
+
+ @Override
+ public void enableClientWindowRenderMode(FacesContext facesContext)
+ {
+ facesContext.getExternalContext().getClientWindow().enableClientWindowRenderMode(facesContext);
+ }
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ff4c502f/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/LazyWindowStrategy.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/LazyWindowStrategy.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/LazyWindowStrategy.java
new file mode 100644
index 0000000..c1ae6ca
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/LazyWindowStrategy.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.jsf.impl.scope.window.strategy;
+
+import org.apache.deltaspike.jsf.impl.util.ClientWindowHelper;
+
+import javax.faces.context.FacesContext;
+import java.util.HashMap;
+import java.util.Map;
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Typed;
+import org.apache.deltaspike.core.util.StringUtils;
+
+@Dependent
+@Typed(LazyWindowStrategy.class)
+public class LazyWindowStrategy extends AbstractClientWindowStrategy
+{
+ @Override
+ protected String getOrCreateWindowId(FacesContext facesContext)
+ {
+ String windowId = ClientWindowHelper.getInitialRedirectWindowId(facesContext);
+
+ if (StringUtils.isEmpty(windowId))
+ {
+ Map<String, String> requestParameters = facesContext.getExternalContext().getRequestParameterMap();
+ windowId = requestParameters.get(ClientWindowHelper.RequestParameters.GET_WINDOW_ID);
+ }
+
+ boolean post = isPost(facesContext);
+
+ if (StringUtils.isEmpty(windowId) && post)
+ {
+ windowId = getPostBackWindowId(facesContext);
+ }
+
+ if (StringUtils.isEmpty(windowId))
+ {
+ if (jsfModuleConfig.isInitialRedirectEnabled() && !post)
+ {
+ ClientWindowHelper.handleInitialRedirect(facesContext, generateNewWindowId());
+ facesContext.responseComplete();
+ windowId = null;
+ }
+ else
+ {
+ windowId = generateNewWindowId();
+ }
+ }
+
+ return windowId;
+ }
+
+ @Override
+ protected boolean isSupportClientWindowRenderingMode()
+ {
+ return true;
+ }
+
+ @Override
+ protected Map<String, String> createQueryURLParameters(FacesContext facesContext)
+ {
+ String windowId = getWindowId(facesContext);
+
+ if (windowId == null)
+ {
+ return null;
+ }
+
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put(ClientWindowHelper.RequestParameters.GET_WINDOW_ID, windowId);
+ return parameters;
+ }
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ff4c502f/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/NoneWindowStrategy.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/NoneWindowStrategy.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/NoneWindowStrategy.java
new file mode 100644
index 0000000..225c927
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/strategy/NoneWindowStrategy.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.jsf.impl.scope.window.strategy;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Typed;
+import javax.faces.context.FacesContext;
+
+@Dependent
+@Typed(NoneWindowStrategy.class)
+public class NoneWindowStrategy extends AbstractClientWindowStrategy
+{
+ @Override
+ protected String getOrCreateWindowId(FacesContext facesContext)
+ {
+ return DEFAULT_WINDOW_ID;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/deltaspike/blob/ff4c502f/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/ClientWindowHelper.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/ClientWindowHelper.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/ClientWindowHelper.java
index 30cf6f0..c86a9b3 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/ClientWindowHelper.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/util/ClientWindowHelper.java
@@ -1,181 +1,196 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.deltaspike.jsf.impl.util;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.enterprise.inject.Typed;
-import javax.faces.FacesException;
-import javax.faces.context.ExternalContext;
-import javax.faces.context.FacesContext;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.deltaspike.jsf.api.config.base.JsfBaseConfig;
-import org.apache.deltaspike.jsf.spi.scope.window.ClientWindow;
-
-@Typed()
-public abstract class ClientWindowHelper
-{
- public static final String INITIAL_REDIRECT_WINDOW_ID = ClientWindowHelper.class.getName()
- + ".INITIAL_REDIRECT_WINDOW_ID";
- public static final String REQUEST_WINDOW_ID_COOKIE_PREFIX = "dsrwid-";
-
- private static final Logger LOG = Logger.getLogger(ClientWindowHelper.class.getName());
-
- /**
- * Handles the initial redirect for the URL modus, if no windowId is available in the current request URL.
- *
- * @param facesContext the {@link FacesContext}
- * @param newWindowId the new windowId
- */
- public static void handleInitialRedirect(FacesContext facesContext, String newWindowId)
- {
- // store the new windowId as context attribute to prevent infinite loops
- // #sendRedirect will append the windowId (from ClientWindow#getWindowId again) to the redirectUrl
- facesContext.getAttributes().put(INITIAL_REDIRECT_WINDOW_ID, newWindowId);
-
- ExternalContext externalContext = facesContext.getExternalContext();
-
- String url = externalContext.getRequestContextPath()
- + externalContext.getRequestServletPath();
-
- if (externalContext.getRequestPathInfo() != null)
- {
- url += externalContext.getRequestPathInfo();
- }
-
- url = JsfUtils.addRequestParameters(externalContext, url, true);
- //TODO check if it isn't better to fix addRequestParameters itself
- //only #encodeResourceURL is portable currently
- url = facesContext.getExternalContext().encodeResourceURL(url);
-
- // see #729
- addRequestWindowIdCookie(facesContext, newWindowId);
-
- try
- {
- externalContext.redirect(url);
- }
- catch (IOException e)
- {
- throw new FacesException("Could not send initial redirect!", e);
- }
- }
-
- public static boolean isInitialRedirect(FacesContext facesContext)
- {
- return facesContext.getAttributes().containsKey(INITIAL_REDIRECT_WINDOW_ID);
- }
-
- public static String getInitialRedirectWindowId(FacesContext facesContext)
- {
- return (String) facesContext.getAttributes().get(INITIAL_REDIRECT_WINDOW_ID);
- }
-
- /**
- * Appends the current windowId to the given url, if enabled via
- * {@link ClientWindow#isClientWindowRenderModeEnabled(javax.faces.context.FacesContext)}
- *
- * @param facesContext the {@link FacesContext}
- * @param url the url
- * @param clientWindow the {@link ClientWindow} to use
- * @return if enabled, the url with windowId, otherwise the umodified url
- */
- public static String appendWindowId(FacesContext facesContext, String url, ClientWindow clientWindow)
- {
- if (clientWindow != null && clientWindow.isClientWindowRenderModeEnabled(facesContext))
- {
- Map<String, String> parameters = clientWindow.getQueryURLParameters(facesContext);
-
- if (parameters != null && !parameters.isEmpty())
- {
- String targetUrl = url;
-
- for (Entry<String, String> entry : parameters.entrySet())
- {
- targetUrl = JsfUtils.addParameter(facesContext.getExternalContext(),
- targetUrl,
- true,
- entry.getKey(),
- entry.getValue());
- }
-
- if (targetUrl.contains("dswid=&"))
- {
- //remove empty dswid parameter
- targetUrl = targetUrl.replace("dswid=&", "");
- }
- return targetUrl;
- }
- }
-
- return url;
- }
-
- public static void addRequestWindowIdCookie(FacesContext context, String windowId)
- {
- Map<String, Object> properties = new HashMap();
- properties.put("path", "/");
- properties.put("maxAge", 30);
-
- context.getExternalContext().addResponseCookie(
- REQUEST_WINDOW_ID_COOKIE_PREFIX + windowId, windowId, properties);
- }
-
- public static Object getRequestWindowIdCookie(FacesContext context, String windowId)
- {
- Map<String, Object> cookieMap = context.getExternalContext().getRequestCookieMap();
-
- if (cookieMap.containsKey(REQUEST_WINDOW_ID_COOKIE_PREFIX + windowId))
- {
- return cookieMap.get(REQUEST_WINDOW_ID_COOKIE_PREFIX + windowId);
- }
-
- return null;
- }
-
- public static void removeRequestWindowIdCookie(FacesContext context, Cookie cookie)
- {
- cookie.setMaxAge(0);
- ((HttpServletResponse) context.getExternalContext().getResponse()).addCookie(cookie);
- }
-
- public static int getMaxWindowIdLength()
- {
- int result = JsfBaseConfig.ScopeCustomization.WindowRestriction.ID_MAX_LENGTH;
-
- if (result > JsfBaseConfig.ScopeCustomization.WindowRestriction.ID_MAX_LENGTH_DEFAULT)
- {
- if (LOG.isLoggable(Level.WARNING))
- {
- LOG.warning("ATTENTION: if you change this value to be significant longer than 10, " +
- "you can introduce a security issue in WindowIdHtmlRenderer. " +
- "If you increase it because window.name contains a value already, " +
- "please revisit that usage or " +
- "create shorter unique ids since they just need to be unique within the user-session.");
- }
- }
- return result;
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.deltaspike.jsf.impl.util;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.enterprise.inject.Typed;
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.deltaspike.jsf.api.config.base.JsfBaseConfig;
+import org.apache.deltaspike.jsf.spi.scope.window.ClientWindow;
+
+@Typed()
+public abstract class ClientWindowHelper
+{
+ private static final Logger LOG = Logger.getLogger(ClientWindowHelper.class.getName());
+
+ private static final String INITIAL_REDIRECT_WINDOW_ID = ClientWindowHelper.class.getName()
+ + ".INITIAL_REDIRECT_WINDOW_ID";
+
+ public abstract class RequestParameters
+ {
+ public static final String POST_WINDOW_ID = "dspwid";
+ public static final String JSF_POST_WINDOW_ID = "javax.faces.ClientWindow";
+ public static final String GET_WINDOW_ID = "dswid";
+ public static final String REQUEST_TOKEN = "dsrid";
+ }
+
+ public abstract class Cookies
+ {
+ public static final String REQUEST_WINDOW_ID_PREFIX = "dsrwid-";
+ public static final String WINDOW_ID_PREFIX = "dsWindowId-";
+ }
+
+
+ /**
+ * Handles the initial redirect for the LAZY mode, if no windowId is available in the current request URL.
+ *
+ * @param facesContext the {@link FacesContext}
+ * @param newWindowId the new windowId
+ */
+ public static void handleInitialRedirect(FacesContext facesContext, String newWindowId)
+ {
+ // store the new windowId as context attribute to prevent infinite loops
+ // #sendRedirect will append the windowId (from ClientWindow#getWindowId again) to the redirectUrl
+ facesContext.getAttributes().put(INITIAL_REDIRECT_WINDOW_ID, newWindowId);
+
+ ExternalContext externalContext = facesContext.getExternalContext();
+
+ String url = externalContext.getRequestContextPath()
+ + externalContext.getRequestServletPath();
+
+ if (externalContext.getRequestPathInfo() != null)
+ {
+ url += externalContext.getRequestPathInfo();
+ }
+
+ url = JsfUtils.addRequestParameters(externalContext, url, true);
+ //TODO check if it isn't better to fix addRequestParameters itself
+ //only #encodeResourceURL is portable currently
+ url = facesContext.getExternalContext().encodeResourceURL(url);
+
+ // see #729
+ addRequestWindowIdCookie(facesContext, newWindowId);
+
+ try
+ {
+ externalContext.redirect(url);
+ }
+ catch (IOException e)
+ {
+ throw new FacesException("Could not send initial redirect!", e);
+ }
+ }
+
+ public static boolean isInitialRedirect(FacesContext facesContext)
+ {
+ return facesContext.getAttributes().containsKey(INITIAL_REDIRECT_WINDOW_ID);
+ }
+
+ public static String getInitialRedirectWindowId(FacesContext facesContext)
+ {
+ return (String) facesContext.getAttributes().get(INITIAL_REDIRECT_WINDOW_ID);
+ }
+
+ /**
+ * Appends the current windowId to the given url, if enabled via
+ * {@link ClientWindow#isClientWindowRenderModeEnabled(javax.faces.context.FacesContext)}
+ *
+ * @param facesContext the {@link FacesContext}
+ * @param url the url
+ * @param clientWindow the {@link ClientWindow} to use
+ * @return if enabled, the url with windowId, otherwise the umodified url
+ */
+ public static String appendWindowId(FacesContext facesContext, String url, ClientWindow clientWindow)
+ {
+ if (clientWindow != null && clientWindow.isClientWindowRenderModeEnabled(facesContext))
+ {
+ Map<String, String> parameters = clientWindow.getQueryURLParameters(facesContext);
+
+ if (parameters != null && !parameters.isEmpty())
+ {
+ String targetUrl = url;
+
+ for (Entry<String, String> entry : parameters.entrySet())
+ {
+ targetUrl = JsfUtils.addParameter(facesContext.getExternalContext(),
+ targetUrl,
+ true,
+ entry.getKey(),
+ entry.getValue());
+
+ //remove empty parameter (e.g. dswid)
+ String emptyParameter = entry.getKey() + "=&";
+ if (targetUrl.contains(emptyParameter))
+ {
+ targetUrl = targetUrl.replace(emptyParameter, "");
+ }
+ }
+ return targetUrl;
+ }
+ }
+
+ return url;
+ }
+
+ public static void addRequestWindowIdCookie(FacesContext context, String windowId)
+ {
+ Map<String, Object> properties = new HashMap();
+ properties.put("path", "/");
+ properties.put("maxAge", 30);
+
+ context.getExternalContext().addResponseCookie(
+ Cookies.REQUEST_WINDOW_ID_PREFIX + windowId, windowId, properties);
+ }
+
+ public static Object getRequestWindowIdCookie(FacesContext context, String windowId)
+ {
+ Map<String, Object> cookieMap = context.getExternalContext().getRequestCookieMap();
+
+ if (cookieMap.containsKey(Cookies.REQUEST_WINDOW_ID_PREFIX + windowId))
+ {
+ return cookieMap.get(Cookies.REQUEST_WINDOW_ID_PREFIX + windowId);
+ }
+
+ return null;
+ }
+
+ public static void removeRequestWindowIdCookie(FacesContext context, Cookie cookie)
+ {
+ cookie.setMaxAge(0);
+ ((HttpServletResponse) context.getExternalContext().getResponse()).addCookie(cookie);
+ }
+
+ public static int getMaxWindowIdLength()
+ {
+ int result = JsfBaseConfig.ScopeCustomization.WindowRestriction.ID_MAX_LENGTH;
+
+ if (result > JsfBaseConfig.ScopeCustomization.WindowRestriction.ID_MAX_LENGTH_DEFAULT)
+ {
+ if (LOG.isLoggable(Level.WARNING))
+ {
+ LOG.warning("ATTENTION: if you change this value to be significant longer than 10, " +
+ "you can introduce a security issue in WindowIdHtmlRenderer. " +
+ "If you increase it because window.name contains a value already, " +
+ "please revisit that usage or " +
+ "create shorter unique ids since they just need to be unique within the user-session.");
+ }
+ }
+ return result;
+ }
+}