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