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;
+    }
+}

Reply via email to