You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2012/01/16 23:03:23 UTC
svn commit: r1232188 - in
/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces:
context/PartialResponseWriterImpl.java util/CDataEndEscapeFilterWriter.java
Author: lu4242
Date: Mon Jan 16 22:03:23 2012
New Revision: 1232188
URL: http://svn.apache.org/viewvc?rev=1232188&view=rev
Log:
MYFACES-3449 [perf] replace buffer in PartialResponseWriter implementation with a fast filter
Added:
myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/util/CDataEndEscapeFilterWriter.java (with props)
Modified:
myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/PartialResponseWriterImpl.java
Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/PartialResponseWriterImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/PartialResponseWriterImpl.java?rev=1232188&r1=1232187&r2=1232188&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/PartialResponseWriterImpl.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/context/PartialResponseWriterImpl.java Mon Jan 16 22:03:23 2012
@@ -19,15 +19,16 @@
package org.apache.myfaces.context;
+import java.io.FilterWriter;
import java.io.IOException;
-import java.io.StringWriter;
import java.io.Writer;
-import java.util.LinkedList;
+import java.util.ArrayList;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.context.PartialResponseWriter;
import javax.faces.context.ResponseWriter;
+import org.apache.myfaces.util.CDataEndEscapeFilterWriter;
/**
* <p/>
@@ -67,55 +68,68 @@ import javax.faces.context.ResponseWrite
* @version $Revision$ $Date$
*/
-public class PartialResponseWriterImpl extends PartialResponseWriter {
+public class PartialResponseWriterImpl extends PartialResponseWriter
+{
- class StackEntry {
+ class StackEntry
+ {
ResponseWriter writer;
- StringWriter _doubleBuffer;
+ Writer _doubleBuffer;
- StackEntry(ResponseWriter writer, StringWriter doubleBuffer) {
+ StackEntry(ResponseWriter writer, Writer doubleBuffer)
+ {
this.writer = writer;
_doubleBuffer = doubleBuffer;
}
- public ResponseWriter getWriter() {
+ public ResponseWriter getWriter()
+ {
return writer;
}
- public void setWriter(ResponseWriter writer) {
+ public void setWriter(ResponseWriter writer)
+ {
this.writer = writer;
}
- public StringWriter getDoubleBuffer() {
+ public Writer getDoubleBuffer()
+ {
return _doubleBuffer;
}
- public void setDoubleBuffer(StringWriter doubleBuffer) {
+ public void setDoubleBuffer(Writer doubleBuffer)
+ {
_doubleBuffer = doubleBuffer;
}
}
ResponseWriter _cdataDoubleBufferWriter = null;
- StringWriter _doubleBuffer = null;
- List<StackEntry> _nestingStack = new LinkedList<StackEntry>();
+ Writer _doubleBuffer = null;
+ List<StackEntry> _nestingStack = new ArrayList<StackEntry>(4);
- public PartialResponseWriterImpl(ResponseWriter writer) {
+ public PartialResponseWriterImpl(ResponseWriter writer)
+ {
super(writer);
}
@Override
- public void startCDATA() throws IOException {
- if (!isDoubleBufferEnabled()) {
+ public void startCDATA() throws IOException
+ {
+ if (!isDoubleBufferEnabled())
+ {
super.startCDATA();
- } else {
+ }
+ else
+ {
_cdataDoubleBufferWriter.write("<![CDATA[");
}
openDoubleBuffer();
}
- private void openDoubleBuffer() {
- _doubleBuffer = new StringWriter();
- //_cdataDoubleBufferWriter = new HtmlResponseWriterImpl(_doubleBuffer, super.getContentType(), super.getCharacterEncoding());
+ private void openDoubleBuffer()
+ {
+ _doubleBuffer = new CDataEndEscapeFilterWriter(_cdataDoubleBufferWriter == null ?
+ this.getWrapped() : _cdataDoubleBufferWriter );
_cdataDoubleBufferWriter = getWrapped().cloneWithWriter(_doubleBuffer);
StackEntry entry = new StackEntry(_cdataDoubleBufferWriter, _doubleBuffer);
@@ -124,11 +138,15 @@ public class PartialResponseWriterImpl e
}
@Override
- public void endCDATA() throws IOException {
+ public void endCDATA() throws IOException
+ {
closeDoubleBuffer(false);
- if (isDoubleBufferEnabled()) {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.write("]]>");
- } else {
+ }
+ else
+ {
super.endCDATA();
}
}
@@ -146,97 +164,52 @@ public class PartialResponseWriterImpl e
* internal CDATA nesting counter is at the nesting depth 1
* @throws IOException
*/
- private void closeDoubleBuffer(boolean force) throws IOException {
- if (!isDoubleBufferEnabled()) return;
+ private void closeDoubleBuffer(boolean force) throws IOException
+ {
+ if (!isDoubleBufferEnabled())
+ {
+ return;
+ }
/*
* if a force close is issued we reset the condition
* to 1 to reach the underlying closing block
*/
- if (force) {
- while (!_nestingStack.isEmpty()) {
+ if (force)
+ {
+ while (!_nestingStack.isEmpty())
+ {
popAndEncodeCurrentStackEntry();
}
- } else {
+ }
+ else
+ {
popAndEncodeCurrentStackEntry();
}
}
- private void popAndEncodeCurrentStackEntry() throws IOException {
+ private void popAndEncodeCurrentStackEntry() throws IOException
+ {
StackEntry elem = _nestingStack.remove(0);
StackEntry parent = (_nestingStack.isEmpty()) ? null : _nestingStack.get(0);
- String result = postProcess(elem);
- if (parent != null) {
+ if (parent != null)
+ {
_cdataDoubleBufferWriter = parent.getWriter();
_doubleBuffer = parent.getDoubleBuffer();
-
- _cdataDoubleBufferWriter.write(result);
- } else {
- _cdataDoubleBufferWriter = null;
- _doubleBuffer = null;
-
- //todo write it in a blocks of strings which have
- //the inherent string length included
- super.write(result);
}
- elem.getDoubleBuffer().close();
- elem.getWriter().close();
- }
-
- /**
- * string post processing
- *
- * @param currentElement the current writer element
- * @return the post processed string
- * @throws IOException in case of an error
- */
- private String postProcess(StackEntry currentElement) throws IOException {
-
- currentElement.getWriter().flush();
- StringBuffer buffer = currentElement.getDoubleBuffer().getBuffer();
-
- int i = buffer.indexOf("]]>");
- if (i >= 0)
+ else
{
- do
- {
- buffer.replace(i, i+3, "]]><![CDATA[]]]]><![CDATA[>");
- i=i+27; //27 is "]]><![CDATA[]]]]><![CDATA[>".length();
- }
- while ( (i = buffer.indexOf("]]>",i)) >= 0 );
- }
- return buffer.toString();
- /*
- String resultString = buffer.toString();
- //section http://www.w3.org/TR/REC-xml/#sec-cdata-sect everything is parsed
- //until it hits a ]]> hence we need to do some mapping here
-
- //ok since our maximum string size is Integer.MAX_VALUE (most JVMs use char [] as
- //representations
- //we can work on strings directly, instead of having to go through streams
- //it is absolutely unlikely that we will ever have a buffered stream bigger than that
- //for our writer!
- if (resultString.contains("]]>")) {
-
- //we now first remove pending javascript CDATA blocks
- //the reason is if we leave them the ppr chokes on them
- //the syntax from the auto generated CDATA usually is //\s+<![CDATA[
- // -= Leonardo Uribe =- Do this cause a bug on the client side, because
- // scripts containing '&' will be considered invalid xml.
- //resultString = resultString.replaceAll("//\\s*((\\<\\!\\[CDATA\\[)|(\\]\\]\\>))", "");
-
- //now to fullfill the xml spec we have to replace all ]] with blocks of cdata
- resultString = resultString.replaceAll("\\]\\]\\>", "]]><![CDATA[]]]]><![CDATA[>");
+ _cdataDoubleBufferWriter = null;
+ _doubleBuffer = null;
}
- return resultString;
- */
}
//--- we need to override ppr specifics to cover the case
@Override
- public void endInsert() throws IOException {
+ public void endInsert() throws IOException
+ {
//we use a force close here to fix possible user CDATA corrections
//under normal conditions the force close just processes the same
//the underlying close cdata does, but nevertheless
@@ -246,7 +219,8 @@ public class PartialResponseWriterImpl e
}
@Override
- public void endUpdate() throws IOException {
+ public void endUpdate() throws IOException
+ {
//we use a force close here to fix possible user CDATA corrections
//under normal conditions the force close just processes the same
//the underlying close cdata does, but nevertheless
@@ -256,7 +230,8 @@ public class PartialResponseWriterImpl e
}
@Override
- public void endExtension() throws IOException {
+ public void endExtension() throws IOException
+ {
//we use a force close here to fix possible user CDATA corrections
//under normal conditions the force close just processes the same
//the underlying close cdata does, but nevertheless
@@ -266,7 +241,8 @@ public class PartialResponseWriterImpl e
}
@Override
- public void endEval() throws IOException {
+ public void endEval() throws IOException
+ {
//we use a force close here to fix possible user CDATA corrections
//under normal conditions the force close just processes the same
//the underlying close cdata does, but nevertheless
@@ -276,7 +252,8 @@ public class PartialResponseWriterImpl e
}
@Override
- public void endError() throws IOException {
+ public void endError() throws IOException
+ {
//we use a force close here to fix possible user CDATA corrections
//under normal conditions the force close just processes the same
//the underlying close cdata does, but nevertheless
@@ -288,85 +265,117 @@ public class PartialResponseWriterImpl e
//--- optional delegation method ---
@Override
- public void endElement(String name) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void endElement(String name) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.endElement(name);
- } else {
+ }
+ else
+ {
super.endElement(name);
}
}
@Override
- public void writeComment(Object comment) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void writeComment(Object comment) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.writeComment(comment);
- } else {
+ }
+ else
+ {
super.writeComment(comment);
}
}
- private boolean isDoubleBufferEnabled() {
+ private boolean isDoubleBufferEnabled()
+ {
return !_nestingStack.isEmpty();
}
@Override
- public void startElement(String name, UIComponent component) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void startElement(String name, UIComponent component) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.startElement(name, component);
- } else {
+ }
+ else
+ {
super.startElement(name, component);
}
}
@Override
- public void writeText(Object text, String property) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void writeText(Object text, String property) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.writeText(text, property);
- } else {
+ }
+ else
+ {
super.writeText(text, property);
}
}
@Override
- public void writeText(char[] text, int off, int len) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void writeText(char[] text, int off, int len) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.writeText(text, off, len);
- } else {
+ }
+ else
+ {
super.writeText(text, off, len);
}
}
@Override
- public void write(char[] cbuf, int off, int len) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void write(char[] cbuf, int off, int len) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.write(cbuf, off, len);
- } else {
+ }
+ else
+ {
super.write(cbuf, off, len);
}
}
@Override
- public ResponseWriter cloneWithWriter(Writer writer) {
+ public ResponseWriter cloneWithWriter(Writer writer)
+ {
return super.cloneWithWriter(writer);
}
@Override
- public void writeURIAttribute(String name, Object value, String property) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void writeURIAttribute(String name, Object value, String property) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.writeURIAttribute(name, value, property);
- } else {
+ }
+ else
+ {
super.writeURIAttribute(name, value, property);
}
}
@Override
- public void close() throws IOException {
+ public void close() throws IOException
+ {
//in case of a close
//we have a user error of a final CDATA block
//we do some error correction here
//since a close is issued we do not care about
//a proper closure of the cdata block here anymore
- if (isDoubleBufferEnabled()) {
+ if (isDoubleBufferEnabled())
+ {
//we have to properly close all nested cdata stacks
//end end our cdata block if open
closeDoubleBuffer(true);
@@ -377,93 +386,131 @@ public class PartialResponseWriterImpl e
}
@Override
- public void flush() throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void flush() throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.flush();
}
super.flush();
}
@Override
- public void writeAttribute(String name, Object value, String property) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void writeAttribute(String name, Object value, String property) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.writeAttribute(name, value, property);
- } else {
+ }
+ else
+ {
super.writeAttribute(name, value, property);
}
}
@Override
- public void writeText(Object object, UIComponent component, String string) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void writeText(Object object, UIComponent component, String string) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.writeText(object, component, string);
- } else {
+ }
+ else
+ {
super.writeText(object, component, string);
}
}
@Override
- public Writer append(char c) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public Writer append(char c) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.append(c);
return this;
- } else {
+ }
+ else
+ {
return super.append(c);
}
}
@Override
- public Writer append(CharSequence csq, int start, int end) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public Writer append(CharSequence csq, int start, int end) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.append(csq, start, end);
return this;
- } else {
+ }
+ else
+ {
return super.append(csq, start, end);
}
}
@Override
- public Writer append(CharSequence csq) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public Writer append(CharSequence csq) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.append(csq);
return this;
- } else {
+ }
+ else
+ {
return super.append(csq);
}
}
@Override
- public void write(char[] cbuf) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void write(char[] cbuf) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.write(cbuf);
- } else {
+ }
+ else
+ {
super.write(cbuf);
}
}
@Override
- public void write(int c) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void write(int c) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.write(c);
- } else {
+ }
+ else
+ {
super.write(c);
}
}
@Override
- public void write(String str, int off, int len) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void write(String str, int off, int len) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.write(str, off, len);
- } else {
+ }
+ else
+ {
super.write(str, off, len);
}
}
@Override
- public void write(String str) throws IOException {
- if (isDoubleBufferEnabled()) {
+ public void write(String str) throws IOException
+ {
+ if (isDoubleBufferEnabled())
+ {
_cdataDoubleBufferWriter.write(str);
- } else {
+ }
+ else
+ {
super.write(str);
}
}
Added: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/util/CDataEndEscapeFilterWriter.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/util/CDataEndEscapeFilterWriter.java?rev=1232188&view=auto
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/util/CDataEndEscapeFilterWriter.java (added)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/util/CDataEndEscapeFilterWriter.java Mon Jan 16 22:03:23 2012
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.util;
+
+import java.io.FilterWriter;
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ *
+ * @author Leonardo Uribe
+ */
+public class CDataEndEscapeFilterWriter extends FilterWriter
+{
+ private char c1;
+ private char c2;
+ private int pos;
+
+ public CDataEndEscapeFilterWriter(Writer out)
+ {
+ super(out);
+ pos = 0;
+ }
+
+ @Override
+ public void write(int c) throws IOException
+ {
+ super.write(c);
+ c1 = c2;
+ c2 = (char) c;
+ pos ++;
+ if (pos > 2)
+ {
+ if (c1 == ']' && c2 == ']' && c == '>')
+ {
+ //"]]><![CDATA[]]]]><![CDATA[>"
+ out.write("<![CDATA[]]]]><![CDATA[>");
+ }
+ }
+ }
+
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException
+ {
+ int index = off;
+ for (int i = 0; i < len; i++)
+ {
+ char c = cbuf[off+i];
+ if (c1 == ']' && c2 == ']' && c == '>')
+ {
+ super.write(cbuf, index, i+1);
+ index = i+1;
+ out.write("<![CDATA[]]]]><![CDATA[>");
+ }
+ c1 = c2;
+ c2 = (char) cbuf[off+i];
+ pos++;
+ }
+ if (index < off+len)
+ {
+ super.write(cbuf, index, off+len-index);
+ }
+ }
+
+ @Override
+ public void write(String str, int off, int len) throws IOException
+ {
+ int index = off;
+ for (int i = 0; i < len; i++)
+ {
+ char c = str.charAt(off+i);
+ if (c1 == ']' && c2 == ']' && c == '>')
+ {
+ super.write(str, index, i+1);
+ index = i+1;
+ out.write("<![CDATA[]]]]><![CDATA[>");
+ }
+ c1 = c2;
+ c2 = (char) str.charAt(off+i);
+ pos++;
+ }
+ if (index < off+len)
+ {
+ super.write(str, index, off+len-index);
+ }
+ }
+}
Propchange: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/util/CDataEndEscapeFilterWriter.java
------------------------------------------------------------------------------
svn:eol-style = native