You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by aw...@apache.org on 2007/06/19 20:22:02 UTC
svn commit: r548812 - in
/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal:
io/HtmlResponseWriter.java io/ResponseWriterDecorator.java
renderkit/core/ppr/PPRResponseWriter.java
Author: awiner
Date: Tue Jun 19 11:22:01 2007
New Revision: 548812
URL: http://svn.apache.org/viewvc?view=rev&rev=548812
Log:
TRINIDAD-46: PPR over XMLHttp
- Fix for Facelets, which does some very twisted things with its PPR stack.
- Add some better toString() implementations for the response writers which
helped diagnosing this.
Modified:
myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/io/HtmlResponseWriter.java
myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/io/ResponseWriterDecorator.java
myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PPRResponseWriter.java
Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/io/HtmlResponseWriter.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/io/HtmlResponseWriter.java?view=diff&rev=548812&r1=548811&r2=548812
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/io/HtmlResponseWriter.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/io/HtmlResponseWriter.java Tue Jun 19 11:22:01 2007
@@ -366,6 +366,11 @@
}
}
+ public String toString()
+ {
+ return "HtmlResponseWriter[" + _out + "]";
+ }
+
//
// Private methods
//
Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/io/ResponseWriterDecorator.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/io/ResponseWriterDecorator.java?view=diff&rev=548812&r1=548811&r2=548812
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/io/ResponseWriterDecorator.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/io/ResponseWriterDecorator.java Tue Jun 19 11:22:01 2007
@@ -179,5 +179,11 @@
return getResponseWriter().cloneWithWriter(writer);
}
+ public String toString()
+ {
+ return super.toString() + "[" + _decorated.toString() + "]";
+
+ }
+
private final ResponseWriter _decorated;
}
Modified: myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PPRResponseWriter.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PPRResponseWriter.java?view=diff&rev=548812&r1=548811&r2=548812
==============================================================================
--- myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PPRResponseWriter.java (original)
+++ myfaces/trinidad/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/ppr/PPRResponseWriter.java Tue Jun 19 11:22:01 2007
@@ -56,7 +56,7 @@
if (!(pprContext instanceof PartialPageContextImpl))
throw new IllegalArgumentException();
- _pprContext = (PartialPageContextImpl) pprContext;
+ _state = new State((PartialPageContextImpl) pprContext);
_xml = new XmlResponseWriter(out, out.getCharacterEncoding());
}
@@ -69,8 +69,8 @@
super(out, base);
// New XmlResponseWriter
_xml = new XmlResponseWriter(out, out.getCharacterEncoding());
- // But same ppr context
- _pprContext = base._pprContext;
+ // But the rest of the state is shared
+ _state = base._state;
}
@@ -80,19 +80,33 @@
getResponseWriter().cloneWithWriter(writer),
this);
- // BIG HACK: ViewTag is going to clone the ResponseWriter so that
+ // BIG HACK: The JSF 1.1
+ // ViewTag is going to clone the ResponseWriter so that
// it can write its BodyContent out. But that'll clone a
// PPRResponseWriter, which then will adamantly refuse to write
// out any content! To "fix" this, we make the lousy assumption
// that if we're being cloned, and our element depth is zero,
// then we're probably being used in this way, and we should just
// let everything through.
- ppr._forceInsideTarget = ppr._elementDepth == 0;
+ // HOWEVER, in Facelets, cloneWithWriter() is called eaaaaarly.
+ // Catch that by ignoring this unless we've at least had a call
+ // to startDocument()
+ _state.forceInsideTarget = (_state.documentStarted &&
+ (_state.elementDepth == 0));
return ppr;
}
public void startDocument() throws IOException
{
+ // Mark that we've started the document, so cloneWithWriter()
+ // can start activating "forceInsideTarget" correctly
+ _state.documentStarted = true;
+
+ // Mark that we're in the middle of starting the document,
+ // so that _disableIfNeeded() can do its thing - see that
+ // function for more info
+ _state.documentStarting = true;
+
// We force the encoding to be text/xml in XmlHttpServletResponse
// because setContentType is ignored when inside an included page (bug 5591124)
_xml.startDocument();
@@ -101,7 +115,7 @@
// Used for an Iframe based communication channel, since it cannot
// read response headers
super.write("<?Tr-XHR-Response-Type ?>\n");
-
+
_xml.startElement("content", null);
String viewId = _facesContext.getViewRoot().getViewId();
String actionURL = _facesContext.getApplication().
@@ -113,6 +127,8 @@
// TODO: Portlet support for PPR?
_xml.writeText(" ", null);
+
+ _state.documentStarting = false;
}
public void endDocument() throws IOException
@@ -125,8 +141,11 @@
_xml.endElement("content");
_xml.endDocument();
- }
+ // Force "inside target mode" - this is for Facelets,
+ // where the state is rendered after endDocument() is called
+ _state.forceInsideTarget = true;
+ }
public void writeComment(Object text) throws IOException
{
@@ -153,6 +172,7 @@
public void write(String text) throws IOException
{
+ _disableIfNeeded();
if (_isInsideTarget())
super.write(text);
}
@@ -162,6 +182,7 @@
int start,
int length) throws IOException
{
+ _disableIfNeeded();
if (_isInsideTarget())
super.write(text, start, length);
}
@@ -175,6 +196,7 @@
@Override
public void write(char[] c) throws IOException
{
+ _disableIfNeeded();
if (_isInsideTarget())
super.write(c);
}
@@ -182,6 +204,7 @@
@Override
public void write(String text, int off, int len) throws IOException
{
+ _disableIfNeeded();
if (_isInsideTarget())
super.write(text, off, len);
}
@@ -200,10 +223,10 @@
public void startElement(String name, UIComponent component)
throws IOException
{
- _elementDepth++;
- if (_pushPartialTarget(component, name))
+ _state.elementDepth++;
+ _pushPartialTarget(component, name);
{
- _enteringPPR = component;
+ _state.enteringPPR = component;
}
if (_isInsideTarget())
@@ -229,11 +252,12 @@
public void endElement(String name) throws IOException
{
- _elementDepth--;
+ _state.elementDepth--;
if (_isInsideTarget())
super.endElement(name);
_popPartialTarget(name);
+ super.flush();
}
public void writeAttribute(String name,
@@ -339,13 +363,11 @@
}
}
- private boolean _pushPartialTarget(
+ private void _pushPartialTarget(
UIComponent component,
String elementName)
throws IOException
{
- boolean enteringPPR = false;
-
PPRTag tag = null;
// If we're already inside a target, don't bother
@@ -354,10 +376,10 @@
if (component != null)
{
String clientId = component.getClientId(_facesContext);
- if (_pprContext.isPartialTarget(clientId))
+ if (_state.pprContext.isPartialTarget(clientId))
{
tag = new PPRTag(clientId);
- enteringPPR = true;
+ _state.enteringPPR = component;
}
}
}
@@ -365,22 +387,21 @@
if (tag != null)
{
super.flush();
- tag.start(_pprContext, elementName);
+ tag.start(_state.pprContext, elementName);
}
- _componentStack.add(tag);
-
- return enteringPPR;
+ _state.componentStack.add(tag);
}
private void _popPartialTarget(String elementName) throws IOException
{
- int pos = _componentStack.size() - 1;
- PPRTag tag = (PPRTag) _componentStack.get(pos);
- _componentStack.remove(pos);
+ List<PPRTag> componentStack = _state.componentStack;
+ int pos = componentStack.size() - 1;
+ PPRTag tag = (PPRTag) componentStack.get(pos);
+ componentStack.remove(pos);
if (tag != null)
- tag.finish(_pprContext, elementName);
+ tag.finish(_state.pprContext, elementName);
}
private boolean _isInsideTarget()
@@ -388,21 +409,58 @@
// Only use the real ResponseWriter when we are rendering
// a partial target subtree. Otherwise, we discard all
// output.
- return _pprContext.isInsidePartialTarget() || _forceInsideTarget;
+ return _state.forceInsideTarget ||
+ _state.pprContext.isInsidePartialTarget();
+
+ }
+
+
+ //
+ // Facelets - as of version 1.1.11 - does something
+ // very strange with its ResponseWriter stack.
+ // It starts with an ordinary stack (which will have
+ // a PPRResponseWriter around an HtmlResponseWriter).
+ // Then it treats that *as an ordinary Writer*, and
+ // wraps it in a "StateWriter" class, which merely
+ // is used to switch between passing output through
+ // and buffering it. Then it takes that StateWriter
+ // and uses it to cloneWithWriter() a new ResponseWriter
+ // stack! As a result, we have the following stack
+ // outermost to innermost:
+ // PPRResponseWriter
+ // HtmlResponseWriter
+ // StateWriter
+ // PPRResponseWriter
+ // HtmlResponseWriter
+ // ServletResponse's Writer
+ // In the end, we have to get that "inner" PPRResponseWriter
+ // to just cut it out and pass everything through. Hence,
+ // this hack! So If I get a "write" call while we're
+ // inside of startDocument(), assume that I must be an
+ // abused PPRResponseWriter, and just put myself in
+ // pass-everything-through mode
+ //
+ private void _disableIfNeeded()
+ {
+ if (_state.documentStarting)
+ {
+ _state = new State(_state.pprContext);
+ _state.forceInsideTarget = true;
+ }
}
private void _handleIdAttribute(String name, Object value)
{
- if ((_enteringPPR != null) && "id".equals(name))
+ if ((_state.enteringPPR != null) && "id".equals(name))
{
if (_LOG.isFine())
{
_LOG.fine("Using id {1} for element of {0}",
- new Object[]{_enteringPPR, value});
+ new Object[]{_state.enteringPPR, value});
}
- _pprContext.addRenderedPartialTarget(value.toString());
- _enteringPPR = null;
+ _state.pprContext.addRenderedPartialTarget(value.toString());
+ _state.enteringPPR = null;
}
}
@@ -445,10 +503,10 @@
{
if (_id != null)
{
- if (_enteringPPR != null)
+ if (_state.enteringPPR != null)
{
- _LOG.warning("NO_PPR_CAPABLE_ID", _enteringPPR);
- _enteringPPR = null;
+ _LOG.warning("NO_PPR_CAPABLE_ID", _state.enteringPPR);
+ _state.enteringPPR = null;
}
// Close up wrapper elements needed to ensure valid HTML
@@ -504,15 +562,27 @@
private String _id;
}
- private UIComponent _enteringPPR;
- private ResponseWriter _xml;
- private boolean _forceInsideTarget;
- private int _elementDepth;
- private final List<PPRTag> _componentStack = new ArrayList<PPRTag>(50);
- private final PartialPageContextImpl _pprContext;
+ private State _state;
+ private ResponseWriter _xml;
private final FacesContext _facesContext =
- FacesContext.getCurrentInstance();
+ FacesContext.getCurrentInstance();
+
+ static private class State
+ {
+ public State(PartialPageContextImpl pprContext)
+ {
+ this.pprContext = pprContext;
+ }
+
+ public UIComponent enteringPPR;
+ public boolean forceInsideTarget;
+ public int elementDepth;
+ public boolean documentStarted;
+ public boolean documentStarting;
+ public final List<PPRTag> componentStack = new ArrayList<PPRTag>(50);
+ public final PartialPageContextImpl pprContext;
+ }
static private final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(PPRResponseWriter.class);
}