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 <[email protected]> Authored: Mon Jun 29 20:57:04 2015 +0200 Committer: Thomas Andraschko <[email protected]> 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; + } +}
