You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by we...@apache.org on 2008/11/21 14:56:58 UTC

svn commit: r719581 - in /myfaces/core/branches/2_0_0: api/src/main/java/javax/faces/context/ impl/src/main/java/org/apache/myfaces/context/servlet/ impl/src/test/java/org/apache/myfaces/context/

Author: werpu
Date: Fri Nov 21 05:56:57 2008
New Revision: 719581

URL: http://svn.apache.org/viewvc?rev=719581&view=rev
Log:
blaTODO #48 Response suppression via a boolean switch in the faces context done

Added:
    myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/context/servlet/ResponseSwitch.java
    myfaces/core/branches/2_0_0/impl/src/test/java/org/apache/myfaces/context/
    myfaces/core/branches/2_0_0/impl/src/test/java/org/apache/myfaces/context/ResponseWrapperSwitchTest.java
Modified:
    myfaces/core/branches/2_0_0/api/src/main/java/javax/faces/context/FacesContext.java
    myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/context/servlet/FacesContextImpl.java

Modified: myfaces/core/branches/2_0_0/api/src/main/java/javax/faces/context/FacesContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2_0_0/api/src/main/java/javax/faces/context/FacesContext.java?rev=719581&r1=719580&r2=719581&view=diff
==============================================================================
--- myfaces/core/branches/2_0_0/api/src/main/java/javax/faces/context/FacesContext.java (original)
+++ myfaces/core/branches/2_0_0/api/src/main/java/javax/faces/context/FacesContext.java Fri Nov 21 05:56:57 2008
@@ -105,7 +105,7 @@
     
     public void enableResponseWriting(boolean enable)
     {
-        // TODO: JSF 2.0 #48
+        //do nothing per default we switch in the derived classes!
     }
     
     public abstract Application getApplication();

Modified: myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/context/servlet/FacesContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/context/servlet/FacesContextImpl.java?rev=719581&r1=719580&r2=719581&view=diff
==============================================================================
--- myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/context/servlet/FacesContextImpl.java (original)
+++ myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/context/servlet/FacesContextImpl.java Fri Nov 21 05:56:57 2008
@@ -18,6 +18,7 @@
  */
 package org.apache.myfaces.context.servlet;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -26,6 +27,8 @@
 import java.util.Map;
 import java.util.Set;
 
+import java.util.logging.Level;
+import java.util.logging.Logger;
 import javax.el.ELContext;
 import javax.el.ELContextEvent;
 import javax.el.ELContextListener;
@@ -45,6 +48,8 @@
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.context.ReleaseableExternalContext;
 import org.apache.myfaces.el.unified.FacesELContext;
 import org.apache.myfaces.shared_impl.util.NullIterator;
@@ -76,23 +81,30 @@
     private boolean _released = false;
     private ELContext _elContext;
     private Map<Object,Object> _attributes = null;
+    private ResponseSwitch _responseWrapper = null;
 
     // ~ Constructors -------------------------------------------------------------------------------
 
     public FacesContextImpl(final ServletContext servletContext, final ServletRequest servletRequest,
-                            final ServletResponse servletResponse)
-    {
-        this(new ServletExternalContextImpl(servletContext, servletRequest, servletResponse));
+                            final ServletResponse servletResponse) {
+        try {
+                //we wrap the servlet response to get our switching behavior!
+            _responseWrapper = new ResponseSwitch(servletResponse);
+            init(new ServletExternalContextImpl(servletContext, servletRequest, _responseWrapper));
+        } catch (IOException ex) {
+           Log log = LogFactory.getLog(this.getClass());
+           log.fatal("Could not obtain the response writers! Detail:"+ex.toString());
+        }
     }
 
-    private FacesContextImpl(final ReleaseableExternalContext externalContext)
-    {
+    private void init(final ReleaseableExternalContext externalContext) {
         _application = ((ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY)).getApplication();
         _renderKitFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
         _externalContext = externalContext;
         FacesContext.setCurrentInstance(this); // protected method, therefore must be called from here
     }
 
+
     // ~ Methods ------------------------------------------------------------------------------------
 
     @Override
@@ -444,4 +456,20 @@
         }
         return _attributes;
     }
+
+    /**
+     * if set to false the response writing is suppressed
+     * this construct has been added to deal with
+     * subview lifecycles in the ajax cycle
+     *
+     * @param enable if set to true the response is routed through if set to false
+     * the response is suppressed!
+     */
+    @Override
+    public void enableResponseWriting(boolean enable) {
+        _responseWrapper.setEnabled(enable);
+        super.enableResponseWriting(enable);
+    }
+
+
 }

Added: myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/context/servlet/ResponseSwitch.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/context/servlet/ResponseSwitch.java?rev=719581&view=auto
==============================================================================
--- myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/context/servlet/ResponseSwitch.java (added)
+++ myfaces/core/branches/2_0_0/impl/src/main/java/org/apache/myfaces/context/servlet/ResponseSwitch.java Fri Nov 21 05:56:57 2008
@@ -0,0 +1,219 @@
+/**
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.myfaces.context.servlet;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletResponse;
+import javax.servlet.ServletResponseWrapper;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+/**
+ * implementation of a switching response
+ * wrapper to turn output on and off according to
+ * the JSF spec 2.p.
+ * <p/>
+ * The Response has to be switchable between on and off according
+ * to the JSF spec 2.0!
+ * <p/>
+ * we use an internal delegate to enable the switchting
+ * between on and off states!
+ *
+ * @author Werner Punz(latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+class ResponseSwitch extends ServletResponseWrapper {
+
+    boolean _enabled = true;
+    /**
+     * one writer and
+     * one stream per response
+     */
+    Writer _switchableWriter;
+    OutputStream _switchableOutputStream;
+
+    public ResponseSwitch(ServletResponse response) throws IOException {
+        super(response);
+    }
+
+    public void setEnabled(boolean enabled) {
+        _enabled = enabled;
+    }
+
+    public boolean isEnabled() {
+        return _enabled;
+    }
+
+    @Override
+    public int getBufferSize() {
+        if (_enabled) {
+            return super.getBufferSize();
+        }
+        return 0;
+    }
+
+    @Override
+    public boolean isCommitted() {
+        if (_enabled) {
+            return super.isCommitted();
+        }
+        return false;
+    }
+
+    @Override
+    public void reset() {
+        if (_enabled) {
+            super.reset();
+        }
+    }
+
+    @Override
+    public void resetBuffer() {
+        if (_enabled) {
+            super.resetBuffer();
+        }
+    }
+
+    @Override
+    public ServletOutputStream getOutputStream() throws IOException {
+        if (_switchableOutputStream == null) {
+            _switchableOutputStream = new SwitchableOutputStream(super.getOutputStream());
+        }
+        return (SwitchableOutputStream) _switchableOutputStream;
+    }
+
+    @Override
+    public PrintWriter getWriter() throws IOException {
+        if (_switchableWriter == null) {
+            _switchableWriter = new PrintWriter(new SwitchableWriter(super.getWriter()));
+        }
+        return (PrintWriter) _switchableWriter;
+    }
+
+    class SwitchableOutputStream extends ServletOutputStream {
+
+        OutputStream _delegate = null;
+
+        public SwitchableOutputStream(ServletOutputStream delegate) {
+            _delegate = delegate;
+        }
+
+        public void write(int i) throws IOException {
+            if (_enabled) {
+                _delegate.write(i);
+            }
+        }
+
+        public void write(byte[] bytes) throws IOException {
+            if (_enabled) {
+                _delegate.write(bytes);
+            }
+        }
+
+        public void write(byte[] bytes, int i, int i1) throws IOException {
+            if (_enabled) {
+                _delegate.write(bytes, i, i1);
+            }
+        }
+
+        public void flush() throws IOException {
+            if (_enabled) {
+                _delegate.flush();
+            }
+        }
+
+        public void close() throws IOException {
+            if (_enabled) {
+                _delegate.close();
+            }
+        }
+    }
+
+    class SwitchableWriter extends Writer {
+
+        Writer _delegate = null;
+
+        public SwitchableWriter(Writer delegate) {
+            _delegate = delegate;
+        }
+
+        public void write(String arg0, int arg1, int arg2) throws IOException {
+            if (_enabled) {
+                _delegate.write(arg0, arg1, arg2);
+            }
+        }
+
+        public void write(String arg0) throws IOException {
+            if (_enabled) {
+                _delegate.write(arg0);
+            }
+        }
+
+        public void write(char[] arg0, int arg1, int arg2) throws IOException {
+            if (_enabled) {
+                _delegate.write(arg0, arg1, arg2);
+            }
+        }
+
+        public void write(char[] arg0) throws IOException {
+            if (_enabled) {
+                _delegate.write(arg0);
+
+            }
+        }
+
+        public void write(int arg0) throws IOException {
+            if (_enabled) {
+                _delegate.write(arg0);
+            }
+        }
+
+        public void flush() throws IOException {
+            if (_enabled) {
+                _delegate.flush();
+            }
+        }
+
+        public void close() throws IOException {
+            if (_enabled) {
+                _delegate.close();
+            }
+        }
+
+        public Writer append(char arg0) throws IOException {
+            if (_enabled) {
+                return _delegate.append(arg0);
+            }
+            return this;
+        }
+
+        public Writer append(CharSequence arg0, int arg1, int arg2) throws IOException {
+            if (_enabled) {
+                return _delegate.append(arg0, arg1, arg2);
+            }
+            return this;
+        }
+
+        public Writer append(CharSequence arg0) throws IOException {
+            if (_enabled) {
+                return _delegate.append(arg0);
+            }
+            return this;
+        }
+    }
+}

Added: myfaces/core/branches/2_0_0/impl/src/test/java/org/apache/myfaces/context/ResponseWrapperSwitchTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2_0_0/impl/src/test/java/org/apache/myfaces/context/ResponseWrapperSwitchTest.java?rev=719581&view=auto
==============================================================================
--- myfaces/core/branches/2_0_0/impl/src/test/java/org/apache/myfaces/context/ResponseWrapperSwitchTest.java (added)
+++ myfaces/core/branches/2_0_0/impl/src/test/java/org/apache/myfaces/context/ResponseWrapperSwitchTest.java Fri Nov 21 05:56:57 2008
@@ -0,0 +1,253 @@
+/*
+ *  Copyright 2008 werpu.
+ * 
+ *  Licensed 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.
+ *  under the License.
+ */
+package org.apache.myfaces.context;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletResponse;
+import javax.servlet.ServletResponseWrapper;
+
+import org.apache.myfaces.context.servlet.FacesContextImpl;
+import org.apache.shale.test.base.AbstractJsfTestCase;
+import org.apache.shale.test.mock.MockResponseWriter;
+
+/**
+ * Testcase for the response switching
+ *
+ * @author Werner Punz(latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+public class ResponseWrapperSwitchTest extends AbstractJsfTestCase {
+
+    public ResponseWrapperSwitchTest() {
+        super("ResponseWrapperSwitchTest");
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * we define our own response class to be able to test the output suppression!
+     */
+    class NewStreamingMockResponse extends ServletResponseWrapper {
+
+        PrintWriter _writer;
+        ServletOutputStream _strm;
+        ServletResponse _response;
+
+        public NewStreamingMockResponse(ServletResponse response, ServletOutputStream strm, PrintWriter writer) {
+            super(response);
+            _strm = strm;
+            _writer = writer;
+            _response = response;
+        }
+
+        @Override
+        public ServletResponse getResponse() {
+            return _response;
+        }
+
+        @Override
+        public ServletOutputStream getOutputStream() throws IOException {
+            return _strm;
+        }
+
+        @Override
+        public PrintWriter getWriter() throws IOException {
+            return _writer;
+        }
+    }
+
+    /**
+     * we need to define our own mockup for the output stream
+     * so that we can simulate a servlet one
+     */
+    class ServletOutputStreamMock extends ServletOutputStream {
+
+        private OutputStream _bos = null;
+
+        ServletOutputStreamMock(OutputStream ostr) {
+            _bos = ostr;
+        }
+
+        public void write(byte[] arg0) throws IOException {
+            _bos.write(arg0);
+        }
+
+        public void flush() throws IOException {
+            _bos.flush();
+        }
+
+        public String toString() {
+            return _bos.toString();
+        }
+
+        public void close() throws IOException {
+            _bos.close();
+        }
+
+        /**
+         * @return the _bos
+         */
+        public OutputStream getBos() {
+            return _bos;
+        }
+
+        /**
+         * @param bos the _bos to set
+         */
+        public void setBos(OutputStream bos) {
+            this._bos = bos;
+        }
+
+        @Override
+        public void write(int arg0) throws IOException {
+            _bos.write(arg0);
+        }
+    }
+
+    /**
+     * testing the off switch for the
+     * response
+     */
+    public void testSwitchOnWriter() {
+
+        ByteArrayOutputStream ostr = new ByteArrayOutputStream();
+        ByteArrayOutputStream ostrWriter = new ByteArrayOutputStream();
+        PrintWriter writer = new PrintWriter(ostrWriter);
+        ServletOutputStreamMock sOstr = new ServletOutputStreamMock(ostr);
+        NewStreamingMockResponse resp = new NewStreamingMockResponse(response, sOstr, writer);
+
+        FacesContext context = new FacesContextImpl(servletContext, request, resp);
+
+
+        ResponseWriter responseWriter = context.getResponseWriter();
+        if (responseWriter == null) {
+            try {
+                responseWriter = new MockResponseWriter(((ServletResponse) context.getExternalContext().getResponse()).getWriter(), null, null);
+            } catch (IOException ex) {
+                super.fail(ex.getMessage());
+            }
+            context.setResponseWriter(responseWriter);
+        }
+
+
+
+        assertTrue("responsewriter not null", responseWriter != null);
+
+        try {
+            responseWriter.append("hello world");
+            responseWriter.flush();
+            responseWriter.close();
+
+        } catch (IOException ex) {
+            super.fail(ex.getMessage());
+        }
+
+        assertTrue(ostrWriter.toString().trim().equals("hello world"));
+
+    }
+
+    /**
+     * Test switch off on the writer api
+     */
+    public void testSwitchOffWriter() {
+        ByteArrayOutputStream ostr = new ByteArrayOutputStream();
+        ByteArrayOutputStream ostrWriter = new ByteArrayOutputStream();
+        PrintWriter writer = new PrintWriter(ostrWriter);
+        ServletOutputStreamMock sOstr = new ServletOutputStreamMock(ostr);
+        NewStreamingMockResponse resp = new NewStreamingMockResponse(response, sOstr, writer);
+
+        FacesContext context = new FacesContextImpl(servletContext, request, resp);
+
+
+        ResponseWriter responseWriter = context.getResponseWriter();
+        if (responseWriter == null) {
+            try {
+                responseWriter = new MockResponseWriter(((ServletResponse) context.getExternalContext().getResponse()).getWriter(), null, null);
+            } catch (IOException ex) {
+                super.fail(ex.getMessage());
+            }
+            context.setResponseWriter(responseWriter);
+        }
+
+
+
+        assertTrue("responsewriter not null", responseWriter != null);
+        context.enableResponseWriting(false);
+
+        try {
+            responseWriter.append("hello world");
+            responseWriter.flush();
+            responseWriter.close();
+
+        } catch (IOException ex) {
+            super.fail(ex.getMessage());
+        }
+
+
+        assertTrue(ostrWriter.toString().trim().equals(""));
+
+
+    }
+
+    /**
+     * test switch off on the stream api
+     * if this works then the stream switch
+     * shoud work on the facesContext should work as well!
+     * @throws java.io.IOException
+     */
+    public void testSwitchOffOstr() {
+        ByteArrayOutputStream ostr = new ByteArrayOutputStream();
+        ByteArrayOutputStream ostrWriter = new ByteArrayOutputStream();
+        PrintWriter writer = new PrintWriter(ostrWriter);
+        ServletOutputStreamMock sOstr = new ServletOutputStreamMock(ostr);
+        NewStreamingMockResponse resp = new NewStreamingMockResponse(response, sOstr, writer);
+
+        FacesContext context = new FacesContextImpl(servletContext, request, resp);
+        context.enableResponseWriting(false);
+        try {
+            OutputStream finalOstr = (OutputStream) ((ServletResponse) context.getExternalContext().getResponse()).getOutputStream();
+            PrintWriter finalWriter = new PrintWriter(finalOstr);
+           
+            finalWriter.write("hello world");
+            finalOstr.write('a');
+            finalOstr.flush();
+            finalOstr.close();
+
+        } catch (IOException ex) {
+            super.fail(ex.getMessage());
+        }
+
+
+        assertTrue(ostr.toString().trim().equals(""));
+
+
+    }
+}