Revision: 1470
          http://stripes.svn.sourceforge.net/stripes/?rev=1470&view=rev
Author:   bengunter
Date:     2012-02-09 19:57:28 +0000 (Thu, 09 Feb 2012)
Log Message:
-----------
Applied fix for STS-823, STS-834 and similar issues reported in the comments of 
STS-788 from 1.5.x branch.

Modified Paths:
--------------
    trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java
    trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutWriter.java

Property Changed:
----------------
    trunk/


Property changes on: trunk
___________________________________________________________________
Modified: svn:mergeinfo
   - /branches/1.5.x:1463-1464,1466
   + /branches/1.5.x:1463-1464,1466,1468-1469

Modified: 
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java
===================================================================
--- trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java     
2012-02-09 19:44:15 UTC (rev 1469)
+++ trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java     
2012-02-09 19:57:28 UTC (rev 1470)
@@ -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; }
 

Modified: trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutWriter.java
===================================================================
--- trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutWriter.java      
2012-02-09 19:44:15 UTC (rev 1469)
+++ trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutWriter.java      
2012-02-09 19:57:28 UTC (rev 1470)
@@ -164,7 +164,7 @@
             default:
                 if (this.silentState)
                     ++mark;
-                else if (i > mark && i == n - 1)
+                else if (i >= mark && i == n - 1)
                     getOut().write(cbuf, mark, i - mark + 1);
             }
         }

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