You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by st...@apache.org on 2013/04/21 21:46:16 UTC

[2/3] git commit: DELTASPIKE-289 add postback handling for windowId

DELTASPIKE-289 add postback handling for windowId


Project: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/commit/30661b05
Tree: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/tree/30661b05
Diff: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/diff/30661b05

Branch: refs/heads/master
Commit: 30661b0551940cf7e40b3db2dd3263b3d8b23c2a
Parents: ff5df7d
Author: Mark Struberg <st...@apache.org>
Authored: Sun Apr 21 19:48:47 2013 +0200
Committer: Mark Struberg <st...@apache.org>
Committed: Sun Apr 21 19:48:47 2013 +0200

----------------------------------------------------------------------
 .../META-INF/apache-deltaspike.properties          |   26 +-
 .../jsf/spi/scope/window/ClientWindow.java         |   51 ++++
 .../jsf/spi/scope/window/ClientWindowConfig.java   |   84 ++++++
 .../scope/window/DefaultClientWindowConfig.java    |  218 +++++++++++++++
 .../jsf/spi/window/ClientWindowConfig.java         |   79 ------
 .../jsf/spi/window/DefaultClientWindowConfig.java  |  215 --------------
 .../request/DeltaSpikeLifecycleWrapper.java        |    3 +
 .../jsf/impl/scope/window/DefaultClientWindow.java |   96 +++++++
 .../impl/scope/window/WindowIdHolderComponent.java |  154 ++++++++++
 .../scope/window/WindowIdRenderKitFactory.java     |  101 +++++++
 .../scope/window/WindowIdRenderKitWrapper.java     |   92 ++++++
 .../src/main/resources/META-INF/faces-config.xml   |    3 +-
 12 files changed, 814 insertions(+), 308 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/30661b05/deltaspike/core/impl/src/test/resources/META-INF/apache-deltaspike.properties
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/resources/META-INF/apache-deltaspike.properties b/deltaspike/core/impl/src/test/resources/META-INF/apache-deltaspike.properties
index c20b420..b935ffc 100644
--- a/deltaspike/core/impl/src/test/resources/META-INF/apache-deltaspike.properties
+++ b/deltaspike/core/impl/src/test/resources/META-INF/apache-deltaspike.properties
@@ -1,19 +1,19 @@
-#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
+# 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.
+# 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.
 
 testProperty03=test_value_03
 org.apache.deltaspike.core.spi.activation.ClassDeactivator=org.apache.deltaspike.test.core.impl.activation.TestClassDeactivator

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/30661b05/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/ClientWindow.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/ClientWindow.java b/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/ClientWindow.java
new file mode 100644
index 0000000..d272f33
--- /dev/null
+++ b/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/ClientWindow.java
@@ -0,0 +1,51 @@
+/*
+ * 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.spi.scope.window;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * <p>API to interact with the window/browser tab handling.
+ * This originally got implemented in Apache MyFaces CODI
+ * which was the basis for the respective feature in JSF-2.2.
+ * We now orientate us a bit on the JSF-2.2 API for making it
+ * easier to provide this feature for JSF-2.0, JSF-2.1 and also
+ * JSF-2.2 JSF implementations.</p>
+ *
+ * <p>Please not that in JSF-2.2 a <code>javax.faces.lifecycle.ClientWindow</code>
+ * instance gets created for each and every request, but in DeltaSpike our
+ * ClientWindow instances are most likely &#064;ApplicationScoped.
+ * </p>
+ */
+public interface ClientWindow
+{
+
+    /**
+     * Extract the windowId for the current request.
+     * This method is intended to get executed at the start of the JSF lifecycle.
+     * We also need to take care about JSF-2.2 ClientWindow in the future.
+     * Depending on the {@link ClientWindowConfig.ClientWindowRenderMode} and
+     * after consulting {@link ClientWindowConfig} we will first send an
+     * intermediate page if the request is an initial GET request.
+     *
+     * @param facesContext for the request
+     * @return the extracted WindowId of the Request, or <code>null</code> if there is no window assigned.
+     */
+    String getWindowId(FacesContext facesContext);
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/30661b05/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/ClientWindowConfig.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/ClientWindowConfig.java b/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/ClientWindowConfig.java
new file mode 100644
index 0000000..dd3c5db
--- /dev/null
+++ b/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/ClientWindowConfig.java
@@ -0,0 +1,84 @@
+/*
+ * 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.spi.scope.window;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * Configuration for ClientWindow handler which is used
+ * to determine the correct windowId for &#063;WindowScoped beans.
+ */
+public interface ClientWindowConfig
+{
+    public enum ClientWindowRenderMode
+    {
+        /**
+         * Any window or browser tab detection is disabled for this request
+         */
+        NONE,
+
+        /**
+         * <p>The GET request results in an intermediate small html page which
+         * checks if the browser tab fits the selected windowId</p>
+         * <p>The ClientWindow html extracts the windowId from the window.name and
+         * enforces a 2nd GET which will contain the windowId and will get routed
+         * through to the target JSF page.</p>
+         */
+        CLIENTWINDOW,
+
+        /**
+         * Render each GET request with the windowId you get during the request
+         * and perform a lazy check on the client side via JavaScript or similar.
+         */
+        LAZY,
+
+        /**
+         * If you set this mode, you also need to provide an own {@link ClientWindow} implementation.
+         */
+        CUSTOM
+
+    }
+
+    /**
+     * @return whether JavaScript is enabled
+     */
+    boolean isJavaScriptEnabled();
+
+    /**
+     * @param javaScriptEnabled whether JavaScript is enabled
+     */
+    void setJavaScriptEnabled(boolean javaScriptEnabled);
+
+    /**
+     * Determine whether this request should take care of clientWindow detection.
+     * This can e.g. get disabled for download pages or if a useragent doesn't
+     * support html5 or any other required technique.
+     * This only gets checked for GET requests!
+     *
+     * @param facesContext
+     * @return the selected ClientWindowRenderMode
+     */
+    ClientWindowRenderMode getClientWindowRenderMode(FacesContext facesContext);
+
+    /**
+     * @return the prepared html which gets sent out to the client as intermediate client window.
+     */
+    String getClientWindowHtml();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/30661b05/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/DefaultClientWindowConfig.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/DefaultClientWindowConfig.java b/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/DefaultClientWindowConfig.java
new file mode 100644
index 0000000..a3bcf22
--- /dev/null
+++ b/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/scope/window/DefaultClientWindowConfig.java
@@ -0,0 +1,218 @@
+/*
+ * 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.spi.scope.window;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.context.FacesContext;
+import javax.inject.Inject;
+import javax.servlet.http.Cookie;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.Map;
+
+import org.apache.deltaspike.core.api.projectstage.ProjectStage;
+import org.apache.deltaspike.core.util.ClassUtils;
+import org.apache.deltaspike.core.util.ExceptionUtils;
+
+/**
+ * <p>Default implementation of {@link ClientWindowConfig}.
+ * By default it will use the internal <code>windowhandler.html</code></p>
+ *
+ * <p>You can &#064;Specializes this class to tweak the configuration or
+ * provide a completely new implementation as &#064;Alternative.</p>
+ */
+@SessionScoped
+public class DefaultClientWindowConfig implements ClientWindowConfig, Serializable
+{
+    /**
+     * We will set a cookie with this very name if a noscript link got clicked by the user
+     */
+    public static final String COOKIE_NAME_NOSCRIPT_ENABLED = "deltaspikeNoScriptEnabled";
+
+    /**
+     * The location of the default windowhandler resource
+     */
+    private static final String DEFAULT_WINDOW_HANDLER_HTML_FILE = "static/windowhandler.html";
+
+
+    private volatile Boolean javaScriptEnabled = null;
+
+    /**
+     * lazily initiated via {@link #getUserAgent(javax.faces.context.FacesContext)}
+     */
+    private volatile String userAgent = null;
+
+    /**
+     * Contains the cached ClientWindow handler html for this session.
+     */
+    private String clientWindowtml;
+
+    @Inject
+    private ProjectStage projectStage;
+
+
+    @Override
+    public boolean isJavaScriptEnabled()
+    {
+        if (javaScriptEnabled == null)
+        {
+            synchronized (this)
+            {
+                // double lock checking idiom on volatile variable works since java5
+                if (javaScriptEnabled == null)
+                {
+                    // no info means that it is default -> true
+                    javaScriptEnabled = Boolean.TRUE;
+
+                    FacesContext facesContext = FacesContext.getCurrentInstance();
+                    if (facesContext != null)
+                    {
+                        Cookie cookie = (Cookie) facesContext.getExternalContext().
+                                getRequestCookieMap().get(COOKIE_NAME_NOSCRIPT_ENABLED);
+                        if (cookie != null)
+                        {
+                            javaScriptEnabled = Boolean.parseBoolean(cookie.getValue());
+                        }
+                    }
+                }
+            }
+        }
+        return javaScriptEnabled;
+    }
+
+
+    @Override
+    public void setJavaScriptEnabled(boolean javaScriptEnabled)
+    {
+        this.javaScriptEnabled = Boolean.valueOf(javaScriptEnabled);
+    }
+
+    /**
+     * By default we use {@link ClientWindowRenderMode#CLIENTWINDOW} unless
+     * we detect a bot.
+     * Override this method to exclude other requests from getting accessed.
+     *
+     * @param facesContext
+     * @return
+     */
+    @Override
+    public ClientWindowRenderMode getClientWindowRenderMode(FacesContext facesContext)
+    {
+        if (!isJavaScriptEnabled())
+        {
+            return ClientWindowRenderMode.NONE;
+        }
+
+        String userAgent = getUserAgent(facesContext);
+
+        if (userAgent != null &&
+            ( userAgent.indexOf("bot")     >= 0 || // Googlebot, etc
+              userAgent.indexOf("Bot")     >= 0 || // BingBot, etc
+              userAgent.indexOf("Slurp")   >= 0 || // Yahoo Slurp
+              userAgent.indexOf("Crawler") >= 0    // various other Crawlers
+            ) )
+        {
+            return ClientWindowRenderMode.NONE;
+        }
+
+        return ClientWindowRenderMode.CLIENTWINDOW;
+    }
+
+    @Override
+    public String getClientWindowHtml()
+    {
+        if (projectStage != ProjectStage.Development && clientWindowtml != null)
+        {
+            // use cached windowHandlerHtml except in Development
+            return clientWindowtml;
+        }
+
+        InputStream is = ClassUtils.getClassLoader(null).getResourceAsStream(getClientWindowResourceLocation());
+        StringBuffer sb = new StringBuffer();
+        try
+        {
+            byte[] buf = new byte[16 * 1024];
+            int bytesRead;
+            while ((bytesRead = is.read(buf)) != -1)
+            {
+                String sbuf = new String(buf, 0, bytesRead);
+                sb.append(sbuf);
+            }
+        }
+        catch (IOException e)
+        {
+            ExceptionUtils.throwAsRuntimeException(e);
+        }
+        finally
+        {
+            try
+            {
+                is.close();
+            }
+            catch (IOException e)
+            {
+                // do nothing, all fine so far
+            }
+        }
+
+        clientWindowtml = sb.toString();
+
+        return clientWindowtml;
+    }
+
+    /**
+     * This information will get stored as it cannot
+     * change during the session anyway.
+     * @return the UserAgent of the request.
+     */
+    public String getUserAgent(FacesContext facesContext)
+    {
+        if (userAgent == null)
+        {
+            synchronized (this)
+            {
+                if (userAgent == null)
+                {
+                    Map<String, String[]> requestHeaders =
+                            facesContext.getExternalContext().getRequestHeaderValuesMap();
+
+                    if (requestHeaders != null &&
+                            requestHeaders.containsKey("User-Agent"))
+                    {
+                        String[] userAgents = requestHeaders.get("User-Agent");
+                        userAgent = userAgents.length > 0 ? userAgents[0] : null;
+                    }
+                }
+            }
+        }
+
+        return userAgent;
+    }
+
+
+    /**
+     * Overwrite this to define your own ClientWindow handler html location.
+     * This will get picked up as resource from the classpath.
+     */
+    public String getClientWindowResourceLocation()
+    {
+        return DEFAULT_WINDOW_HANDLER_HTML_FILE;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/30661b05/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/window/ClientWindowConfig.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/window/ClientWindowConfig.java b/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/window/ClientWindowConfig.java
deleted file mode 100644
index 94690ec..0000000
--- a/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/window/ClientWindowConfig.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.spi.window;
-
-import javax.faces.context.FacesContext;
-
-/**
- * Configuration for ClientWindow handler which is used
- * to determine the correct windowId for &#063;WindowScoped beans.
- */
-public interface ClientWindowConfig
-{
-    public enum ClientWindowRenderMode
-    {
-        /**
-         * Any window or browser tab detection is disabled for this request
-         */
-        NONE,
-
-        /**
-         * <p>The GET request results in an intermediate small html page which
-         * checks if the browser tab fits the selected windowId</p>
-         * <p>The ClientWindow html extracts the windowId from the window.name and
-         * enforces a 2nd GET which will contain the windowId and will get routed
-         * through to the target JSF page.</p>
-         */
-        CLIENTWINDOW,
-
-        /**
-         * Render each GET request with the windowId you get during the request
-         * and perform a lazy check on the client side via JavaScript or similar.
-         */
-        LAZY
-
-    }
-
-    /**
-     * @return whether JavaScript is enabled
-     */
-    boolean isJavaScriptEnabled();
-
-    /**
-     * @param javaScriptEnabled whether JavaScript is enabled
-     */
-    void setJavaScriptEnabled(boolean javaScriptEnabled);
-
-    /**
-     * Determine whether this request should take care of clientWindow detection.
-     * This can e.g. get disabled for download pages or if a useragent doesn't
-     * support html5 or any other required technique.
-     * This only gets checked for GET requests!
-     *
-     * @param facesContext
-     * @return the selected ClientWindowRenderMode
-     */
-    ClientWindowRenderMode getClientWindowRenderMode(FacesContext facesContext);
-
-    /**
-     * @return the prepared html which gets sent out to the client as intermediate client window.
-     */
-    String getClientWindowHtml();
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/30661b05/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/window/DefaultClientWindowConfig.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/window/DefaultClientWindowConfig.java b/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/window/DefaultClientWindowConfig.java
deleted file mode 100644
index dbec591..0000000
--- a/deltaspike/modules/jsf/api/src/main/java/org/apache/deltaspike/jsf/spi/window/DefaultClientWindowConfig.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 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.spi.window;
-
-import javax.enterprise.context.SessionScoped;
-import javax.faces.context.FacesContext;
-import javax.inject.Inject;
-import javax.servlet.http.Cookie;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Serializable;
-import java.util.Map;
-
-import org.apache.deltaspike.core.api.projectstage.ProjectStage;
-import org.apache.deltaspike.core.util.ClassUtils;
-import org.apache.deltaspike.core.util.ExceptionUtils;
-
-/**
- * Default implementation of {@link ClientWindowConfig}.
- * It will use the internal <code>windowhandler.html</code>
- */
-@SessionScoped
-public class DefaultClientWindowConfig implements ClientWindowConfig, Serializable
-{
-    /**
-     * We will set a cookie with this very name if a noscript link got clicked by the user
-     */
-    public static final String COOKIE_NAME_NOSCRIPT_ENABLED = "deltaspikeNoScriptEnabled";
-
-    /**
-     * The location of the default windowhandler resource
-     */
-    private static final String DEFAULT_WINDOW_HANDLER_HTML_FILE = "static/windowhandler.html";
-
-
-    private volatile Boolean javaScriptEnabled = null;
-
-    /**
-     * lazily initiated via {@link #getUserAgent(javax.faces.context.FacesContext)}
-     */
-    private volatile String userAgent = null;
-
-    /**
-     * Contains the cached ClientWindow handler html for this session.
-     */
-    private String clientWindowtml;
-
-    @Inject
-    private ProjectStage projectStage;
-
-
-    @Override
-    public boolean isJavaScriptEnabled()
-    {
-        if (javaScriptEnabled == null)
-        {
-            synchronized (this)
-            {
-                // double lock checking idiom on volatile variable works since java5
-                if (javaScriptEnabled == null)
-                {
-                    // no info means that it is default -> true
-                    javaScriptEnabled = Boolean.TRUE;
-
-                    FacesContext facesContext = FacesContext.getCurrentInstance();
-                    if (facesContext != null)
-                    {
-                        Cookie cookie = (Cookie) facesContext.getExternalContext().
-                                getRequestCookieMap().get(COOKIE_NAME_NOSCRIPT_ENABLED);
-                        if (cookie != null)
-                        {
-                            javaScriptEnabled = Boolean.parseBoolean(cookie.getValue());
-                        }
-                    }
-                }
-            }
-        }
-        return javaScriptEnabled;
-    }
-
-
-    @Override
-    public void setJavaScriptEnabled(boolean javaScriptEnabled)
-    {
-        this.javaScriptEnabled = Boolean.valueOf(javaScriptEnabled);
-    }
-
-    /**
-     * By default we use {@link ClientWindowRenderMode#CLIENTWINDOW} unless
-     * we detect a bot.
-     * Override this method to exclude other requests from getting accessed.
-     *
-     * @param facesContext
-     * @return
-     */
-    @Override
-    public ClientWindowRenderMode getClientWindowRenderMode(FacesContext facesContext)
-    {
-        if (!isJavaScriptEnabled())
-        {
-            return ClientWindowRenderMode.NONE;
-        }
-
-        String userAgent = getUserAgent(facesContext);
-
-        if (userAgent != null &&
-            ( userAgent.indexOf("bot")     >= 0 || // Googlebot, etc
-              userAgent.indexOf("Bot")     >= 0 || // BingBot, etc
-              userAgent.indexOf("Slurp")   >= 0 || // Yahoo Slurp
-              userAgent.indexOf("Crawler") >= 0    // various other Crawlers
-            ) )
-        {
-            return ClientWindowRenderMode.NONE;
-        }
-
-        return ClientWindowRenderMode.CLIENTWINDOW;
-    }
-
-    @Override
-    public String getClientWindowHtml()
-    {
-        if (projectStage != ProjectStage.Development && clientWindowtml != null)
-        {
-            // use cached windowHandlerHtml except in Development
-            return clientWindowtml;
-        }
-
-        InputStream is = ClassUtils.getClassLoader(null).getResourceAsStream(getClientWindowResourceLocation());
-        StringBuffer sb = new StringBuffer();
-        try
-        {
-            byte[] buf = new byte[16 * 1024];
-            int bytesRead;
-            while ((bytesRead = is.read(buf)) != -1)
-            {
-                String sbuf = new String(buf, 0, bytesRead);
-                sb.append(sbuf);
-            }
-        }
-        catch (IOException e)
-        {
-            ExceptionUtils.throwAsRuntimeException(e);
-        }
-        finally
-        {
-            try
-            {
-                is.close();
-            }
-            catch (IOException e)
-            {
-                // do nothing, all fine so far
-            }
-        }
-
-        clientWindowtml = sb.toString();
-
-        return clientWindowtml;
-    }
-
-    /**
-     * This information will get stored as it cannot
-     * change during the session anyway.
-     * @return the UserAgent of the request.
-     */
-    public String getUserAgent(FacesContext facesContext)
-    {
-        if (userAgent == null)
-        {
-            synchronized (this)
-            {
-                if (userAgent == null)
-                {
-                    Map<String, String[]> requestHeaders =
-                            facesContext.getExternalContext().getRequestHeaderValuesMap();
-
-                    if (requestHeaders != null &&
-                            requestHeaders.containsKey("User-Agent"))
-                    {
-                        String[] userAgents = requestHeaders.get("User-Agent");
-                        userAgent = userAgents.length > 0 ? userAgents[0] : null;
-                    }
-                }
-            }
-        }
-
-        return userAgent;
-    }
-
-
-    /**
-     * Overwrite this to define your own ClientWindow handler html location.
-     * This will get picked up as resource from the classpath.
-     */
-    public String getClientWindowResourceLocation()
-    {
-        return DEFAULT_WINDOW_HANDLER_HTML_FILE;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/30661b05/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeLifecycleWrapper.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeLifecycleWrapper.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeLifecycleWrapper.java
index 28ad66d..9d4808d 100644
--- a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeLifecycleWrapper.java
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/listener/request/DeltaSpikeLifecycleWrapper.java
@@ -56,7 +56,10 @@ class DeltaSpikeLifecycleWrapper extends Lifecycle
         //TODO broadcastApplicationStartupBroadcaster();
         broadcastBeforeFacesRequestEvent(facesContext);
 
+        //X TODO add ClientWindow handling
         this.wrapped.execute(facesContext);
+
+
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/30661b05/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
new file mode 100644
index 0000000..4ab6d37
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/DefaultClientWindow.java
@@ -0,0 +1,96 @@
+/*
+ * 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;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.inject.Inject;
+
+import java.util.logging.Logger;
+
+import org.apache.deltaspike.core.spi.scope.window.WindowContext;
+import org.apache.deltaspike.jsf.spi.scope.window.ClientWindow;
+import org.apache.deltaspike.jsf.spi.scope.window.ClientWindowConfig;
+
+import static org.apache.deltaspike.jsf.spi.scope.window.ClientWindowConfig.ClientWindowRenderMode;
+
+/**
+ * This is the default implementation of the window/browser tab
+ * detection handling for JSF applications.
+ * This is to big degrees a port of Apache MyFaces CODI
+ * ClientSideWindowHandler.
+ *
+ * It will act according to the configured {@link ClientWindowRenderMode}.
+ *
+ *
+ */
+@ApplicationScoped
+public class DefaultClientWindow implements ClientWindow
+{
+    private static final Logger logger = Logger.getLogger(DefaultClientWindow.class.getName());
+
+
+    @Inject
+    private ClientWindowConfig clientWindowConfig;
+
+    @Inject
+    private WindowContext windowContext;
+
+
+    @Override
+    public String getWindowId(FacesContext facesContext)
+    {
+        if (ClientWindowRenderMode.NONE.equals(clientWindowConfig.getClientWindowRenderMode(facesContext)))
+        {
+            return null;
+        }
+
+        String windowId = null;
+
+        if (facesContext.isPostback())
+        {
+            return getPostBackWindowId(facesContext);
+        }
+
+        return windowId;
+    }
+
+    /**
+     * Extract the windowId for http POST
+     */
+    private String getPostBackWindowId(FacesContext facesContext)
+    {
+        UIViewRoot uiViewRoot = facesContext.getViewRoot();
+
+        if (uiViewRoot != null)
+        {
+            WindowIdHolderComponent existingWindowIdHolder
+                = WindowIdHolderComponent.getWindowIdHolderComponent(uiViewRoot);
+            if (existingWindowIdHolder != null)
+            {
+                return existingWindowIdHolder.getWindowId();
+            }
+        }
+
+        return null;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/30661b05/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdHolderComponent.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdHolderComponent.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdHolderComponent.java
new file mode 100644
index 0000000..e4f7326
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdHolderComponent.java
@@ -0,0 +1,154 @@
+/*
+ * 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;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIOutput;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+/**
+ * UI Component holder for the windowId in case of post-backs.
+ * We store this component as direct child in the ViewRoot
+ * and evaluate it's value on postbacks.
+ */
+public class WindowIdHolderComponent extends UIOutput
+{
+    private static final Logger logger = Logger.getLogger(WindowIdHolderComponent.class.getName());
+
+    private String windowId;
+
+    /**
+     * Default constructor might be invoked by the jsf implementation
+     */
+    @SuppressWarnings("UnusedDeclaration")
+    public WindowIdHolderComponent()
+    {
+    }
+
+    /**
+     * Constructor which creates the holder for the given window-id
+     * @param windowId current window-id
+     */
+    public WindowIdHolderComponent(String windowId)
+    {
+        this.windowId = windowId;
+    }
+
+    /**
+     * Needed for server-side window-handler and client-side window handler for supporting postbacks
+     */
+    public static void addWindowIdHolderComponent(FacesContext facesContext, String windowId)
+    {
+        if (windowId == null || windowId.length() == 0)
+        {
+            return;
+        }
+
+        UIViewRoot uiViewRoot = facesContext.getViewRoot();
+
+        if (uiViewRoot == null)
+        {
+            return;
+        }
+
+        WindowIdHolderComponent existingWindowIdHolder = getWindowIdHolderComponent(uiViewRoot);
+        if (existingWindowIdHolder != null)
+        {
+            if (!windowId.equals(existingWindowIdHolder.getWindowId()))
+            {
+                logger.log(Level.FINE, "updating WindowIdHolderComponent from %1 to %2",
+                        new Object[]{existingWindowIdHolder.getId(), windowId});
+
+                existingWindowIdHolder.changeWindowId(windowId);
+            }
+            return;
+        }
+        else
+        {
+            // add as first child
+            uiViewRoot.getChildren().add(0, new WindowIdHolderComponent(windowId));
+        }
+    }
+
+    public static WindowIdHolderComponent getWindowIdHolderComponent(UIViewRoot uiViewRoot)
+    {
+        List<UIComponent> uiComponents = uiViewRoot.getChildren();
+
+        // performance improvement - don't change - see EXTCDI-256 :
+        for (int i = 0, size = uiComponents.size(); i < size; i++)
+        {
+            UIComponent uiComponent = uiComponents.get(i);
+            if (uiComponent instanceof WindowIdHolderComponent)
+            {
+                //in this case we have the same view-root
+                return (WindowIdHolderComponent) uiComponent;
+            }
+        }
+
+        return null;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Object saveState(FacesContext facesContext)
+    {
+        Object[] values = new Object[2];
+        values[0] = super.saveState(facesContext);
+        values[1] = windowId;
+        return values;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void restoreState(FacesContext facesContext, Object state)
+    {
+        if (state == null)
+        {
+            return;
+        }
+
+        Object[] values = (Object[]) state;
+        super.restoreState(facesContext, values[0]);
+
+        windowId = (String) values[1];
+    }
+
+    /**
+     * @return the current windowId
+     */
+    public String getWindowId()
+    {
+        return windowId;
+    }
+
+    void changeWindowId(String windowId)
+    {
+        this.windowId = windowId;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/30661b05/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitFactory.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitFactory.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitFactory.java
new file mode 100644
index 0000000..883ddb0
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitFactory.java
@@ -0,0 +1,101 @@
+/*
+ * 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;
+
+import javax.faces.context.FacesContext;
+import javax.faces.render.RenderKit;
+import javax.faces.render.RenderKitFactory;
+import java.util.Iterator;
+
+import org.apache.deltaspike.core.spi.activation.Deactivatable;
+import org.apache.deltaspike.core.util.ClassDeactivationUtils;
+
+
+/**
+ * Registers the @{link WindowIdRenderKit}
+ */
+public class WindowIdRenderKitFactory extends RenderKitFactory implements Deactivatable
+{
+    private final RenderKitFactory wrapped;
+
+    private final boolean deactivated;
+
+    /**
+     * Constructor for wrapping the given {@link javax.faces.render.RenderKitFactory}
+     * @param wrapped render-kit-factory which will be wrapped
+     */
+    public WindowIdRenderKitFactory(RenderKitFactory wrapped)
+    {
+        this.wrapped = wrapped;
+        this.deactivated = !isActivated();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void addRenderKit(String s, RenderKit renderKit)
+    {
+        wrapped.addRenderKit(s, renderKit);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public RenderKit getRenderKit(FacesContext facesContext, String s)
+    {
+        RenderKit renderKit = wrapped.getRenderKit(facesContext, s);
+
+        if (renderKit == null)
+        {
+            return null;
+        }
+
+        if (deactivated)
+        {
+            return renderKit;
+        }
+
+        return new WindowIdRenderKitWrapper(renderKit);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Iterator<String> getRenderKitIds()
+    {
+        return wrapped.getRenderKitIds();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public RenderKitFactory getWrapped()
+    {
+        return wrapped;
+    }
+
+    public boolean isActivated()
+    {
+        return ClassDeactivationUtils.isActivated(getClass());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/30661b05/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitWrapper.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitWrapper.java b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitWrapper.java
new file mode 100644
index 0000000..bb939d5
--- /dev/null
+++ b/deltaspike/modules/jsf/impl/src/main/java/org/apache/deltaspike/jsf/impl/scope/window/WindowIdRenderKitWrapper.java
@@ -0,0 +1,92 @@
+/*
+ * 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;
+
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.render.RenderKit;
+import javax.faces.render.RenderKitWrapper;
+import java.io.Writer;
+
+import org.apache.deltaspike.core.api.provider.BeanProvider;
+import org.apache.deltaspike.core.spi.scope.window.WindowContext;
+
+/**
+ * Wraps the RenderKit and adds the
+ * {@link WindowIdHolderComponent} to the view tree
+ */
+public class WindowIdRenderKitWrapper extends RenderKitWrapper
+{
+    private final RenderKit wrapped;
+
+    /**
+     * This will get initialized lazily to prevent boot order issues
+     * with the JSF and CDI containers.
+     */
+    private volatile WindowContext windowContext;
+
+
+    //needed if the renderkit gets proxied - see EXTCDI-215
+    protected WindowIdRenderKitWrapper()
+    {
+        this.wrapped = null;
+    }
+
+    public WindowIdRenderKitWrapper(RenderKit wrapped)
+    {
+        this.wrapped = wrapped;
+    }
+
+    @Override
+    public RenderKit getWrapped()
+    {
+        return wrapped;
+    }
+
+    /**
+     * Adds a {@link WindowIdHolderComponent} with the
+     * current windowId to the component tree.
+     */
+    public ResponseWriter createResponseWriter(Writer writer, String s, String s1)
+    {
+        FacesContext facesContext = FacesContext.getCurrentInstance();
+        String windowId = getWindowContext().getCurrentWindowId();
+
+        WindowIdHolderComponent.addWindowIdHolderComponent(facesContext, windowId);
+
+        return wrapped.createResponseWriter(writer, s, s1);
+    }
+
+
+    private WindowContext getWindowContext()
+    {
+        if (windowContext == null)
+        {
+            synchronized (this)
+            {
+                if (windowContext == null)
+                {
+                    windowContext = BeanProvider.getContextualReference(WindowContext.class);
+                }
+            }
+        }
+
+        return windowContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/30661b05/deltaspike/modules/jsf/impl/src/main/resources/META-INF/faces-config.xml
----------------------------------------------------------------------
diff --git a/deltaspike/modules/jsf/impl/src/main/resources/META-INF/faces-config.xml b/deltaspike/modules/jsf/impl/src/main/resources/META-INF/faces-config.xml
index 50ed167..6d951da 100644
--- a/deltaspike/modules/jsf/impl/src/main/resources/META-INF/faces-config.xml
+++ b/deltaspike/modules/jsf/impl/src/main/resources/META-INF/faces-config.xml
@@ -36,5 +36,6 @@
     <factory>
         <lifecycle-factory>org.apache.deltaspike.jsf.impl.listener.request.DeltaSpikeLifecycleFactoryWrapper</lifecycle-factory>
         <faces-context-factory>org.apache.deltaspike.jsf.impl.listener.request.DeltaSpikeFacesContextFactory</faces-context-factory>
+        <render-kit-factory>org.apache.deltaspike.jsf.impl.scope.window.WindowIdRenderKitFactory</render-kit-factory>
     </factory>
-</faces-config>
\ No newline at end of file
+</faces-config>