Revision: 1469
          http://stripes.svn.sourceforge.net/stripes/?rev=1469&view=rev
Author:   bengunter
Date:     2012-02-09 19:44:15 +0000 (Thu, 09 Feb 2012)
Log Message:
-----------
Fixed STS-823, STS-834 and similar issues reported in the comments of STS-788. 
Thorough testing revealed that WebLogic completely breaks 
PageContext.include(String, boolean) if it is preceded by a call to 
PageContext.pushBody(Writer). This is central to the streaming layout tags' 
functionality. As a workaround, if the app is running on WegLogic, the 
LayoutContext will use an alternative to the standard 
PageContext.include(String, boolean) to execute the include, capture its 
output, and pass it through to the underlying JspWriter. Streaming layout tags 
now work on WebLogic.

Modified Paths:
--------------
    
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java

Modified: 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java
===================================================================
--- 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java
    2012-02-09 19:17:37 UTC (rev 1468)
+++ 
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java
    2012-02-09 19:44:15 UTC (rev 1469)
@@ -15,6 +15,8 @@
 package net.sourceforge.stripes.tag.layout;
 
 import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -23,6 +25,9 @@
 import java.util.Map.Entry;
 
 import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
 import javax.servlet.jsp.PageContext;
 
 import net.sourceforge.stripes.exception.StripesRuntimeException;
@@ -43,6 +48,13 @@
     public static final String LAYOUT_CONTEXT_KEY = 
LayoutContext.class.getName() + "#Context";
 
     /**
+     * The attribute name by which the indicator of broken include 
functionality in the application
+     * server can be found in the application scope.
+     */
+    public static final String BROKEN_INCLUDE_KEY = 
LayoutContext.class.getName()
+            + "#BROKEN_INCLUDE";
+
+    /**
      * Create a new layout context for the given render tag and push it onto 
the stack of layout
      * contexts in a JSP page context.
      */
@@ -211,13 +223,115 @@
             IOException {
         try {
             pageContext.getRequest().setAttribute(LAYOUT_CONTEXT_KEY, this);
-            pageContext.include(relativeUrlPath, false);
+            if (isIncludeBroken(pageContext))
+                doIncludeHack(pageContext, relativeUrlPath);
+            else
+                pageContext.include(relativeUrlPath, false);
         }
         finally {
             pageContext.getRequest().removeAttribute(LAYOUT_CONTEXT_KEY);
         }
     }
 
+    /**
+     * Returns true if the current thread is executing in an application 
server that is known to
+     * have issues with doing normal includes using {@link 
PageContext#include(String, boolean)}.
+     */
+    protected boolean isIncludeBroken(PageContext pageContext) {
+        Boolean b = (Boolean) 
pageContext.getServletContext().getAttribute(BROKEN_INCLUDE_KEY);
+        if (b == null) {
+            b = pageContext.getClass().getName().startsWith("weblogic.");
+            pageContext.getServletContext().setAttribute(BROKEN_INCLUDE_KEY, 
b);
+            if (b) {
+                log.info("This application server's include is broken so a 
workaround will be used.");
+            }
+        }
+
+        return b;
+    }
+
+    /**
+     * An alternative to {@link PageContext#include(String, boolean)} that 
works around broken
+     * include functionality in certain application servers, including several 
current and recent
+     * releases of WebLogic.
+     */
+    protected void doIncludeHack(PageContext pageContext, String 
relativeUrlPath)
+            throws ServletException, IOException {
+        class MyServletOutputStream extends ServletOutputStream {
+            static final String DEFAULT_CHARSET = "UTF-8";
+
+            Writer out;
+            String charset = DEFAULT_CHARSET;
+
+            MyServletOutputStream(Writer out) {
+                this.out = out;
+            }
+
+            String getCharset() {
+                return charset;
+            }
+
+            void setCharset(String charset) {
+                this.charset = charset == null ? DEFAULT_CHARSET : charset;
+            }
+
+            @Override
+            public void write(int b) throws IOException {
+                throw new IOException("Unexpected call to write(byte)");
+            }
+
+            @Override
+            public void print(char c) throws IOException {
+                out.write(c);
+            }
+
+            @Override
+            public void print(String s) throws IOException {
+                out.write(s);
+            }
+
+            @Override
+            public void write(byte[] buf, int off, int len) throws IOException 
{
+                String s = new String(buf, off, len, charset);
+                out.write(s);
+            }
+
+            @Override
+            public void write(byte[] buf) throws IOException {
+                String s = new String(buf, charset);
+                out.write(s);
+            }
+        }
+
+        final MyServletOutputStream os = new 
MyServletOutputStream(pageContext.getOut());
+        final PrintWriter writer = new PrintWriter(pageContext.getOut());
+        final HttpServletResponse response = new HttpServletResponseWrapper(
+                (HttpServletResponse) pageContext.getResponse()) {
+            @Override
+            public String getCharacterEncoding() {
+                return os.getCharset();
+            }
+
+            @Override
+            public void setCharacterEncoding(String charset) {
+                os.setCharset(charset);
+            }
+
+            @Override
+            public ServletOutputStream getOutputStream() throws IOException {
+                return os;
+            }
+
+            @Override
+            public PrintWriter getWriter() throws IOException {
+                return writer;
+            }
+        };
+
+        pageContext.getRequest().getRequestDispatcher(relativeUrlPath)
+                .include(pageContext.getRequest(), response);
+    }
+
     /** Get the render tag that created this context. */
     public LayoutRenderTag getRenderTag() { return renderTag; }
 

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Virtualization & Cloud Management Using Capacity Planning
Cloud computing makes use of virtualization - but cloud computing 
also focuses on allowing computing to be delivered as a service.
http://www.accelacomm.com/jaw/sfnl/114/51521223/
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development

Reply via email to