001: /**
002: * Licensed under the Common Development and Distribution License,
003: * you may not use this file except in compliance with the License.
004: * You may obtain a copy of the License at
005: *
006: * http://www.sun.com/cddl/
007: *
008: * Unless required by applicable law or agreed to in writing, software
009: * distributed under the License is distributed on an "AS IS" BASIS,
010: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
011: * implied. See the License for the specific language governing
012: * permissions and limitations under the License.
013: */package com.sun.facelets;
014:
015: import java.io.IOException;
016: import java.io.Writer;
017:
018: import com.sun.facelets.util.FastWriter;
019:
020: /**
021: * A class for handling state insertion. Content is written
022: * directly to "out" until an attempt to write state; at that
023: * point, it's redirected into a buffer that can be picked through
024: * in theory, this buffer should be very small, since it only
025: * needs to be enough to contain all the content after the close
026: * of the first (and, hopefully, only) form.
027: * <p>
028: * Potential optimizations:
029: * <ul>
030: * <li>If we created a new FastWriter at each call to writingState(),
031: * and stored a List of them, then we'd know that state tokens could
032: * only possibly be near the start of each buffer (and might not be there
033: * at all). (There might be a close-element before the state token). Then,
034: * we'd only need to check the start of the buffer for the state token;
035: * if it's there, write out the real state, then blast the rest of the
036: * buffer out. This wouldn't even require toString(), which for
037: * large buffers is expensive. However, this optimization is only
038: * going to be especially meaningful for the multi-form case.
039: * </li>
040: * <li>More of a FastWriter optimization than a StateWriter, but:
041: * it is far faster to create a set of small 1K buffers than constantly
042: * reallocating one big buffer.</li>
043: * </ul>
044: *
045: * @author Adam Winer
046: * @version $Id: StateWriter.java,v 1.1 2006/04/12 05:50:45 adamwiner Exp $
047: */
048: final class StateWriter extends Writer {
049:
050: private int initialSize;
051: private Writer out;
052: private FastWriter fast;
053: private boolean writtenState;
054:
055: static public StateWriter getCurrentInstance() {
056: return (StateWriter) CURRENT_WRITER.get();
057: }
058:
059: public StateWriter(Writer initialOut, int initialSize) {
060: if (initialSize < 0) {
061: throw new IllegalArgumentException(
062: "Initial Size cannot be less than 0");
063: }
064:
065: this .initialSize = initialSize;
066: this .out = initialOut;
067:
068: CURRENT_WRITER.set(this );
069: }
070:
071: /**
072: * Mark that state is about to be written. Contrary to what you'd expect,
073: * we cannot and should not assume that this location is really going
074: * to have state; it is perfectly legit to have a ResponseWriter that
075: * filters out content, and ignores an attempt to write out state
076: * at this point. So, we have to check after the fact to see
077: * if there really are state markers.
078: */
079: public void writingState() {
080: if (!this .writtenState) {
081: this .writtenState = true;
082: this .out = this .fast = new FastWriter(this .initialSize);
083: }
084: }
085:
086: public boolean isStateWritten() {
087: return this .writtenState;
088: }
089:
090: public void close() throws IOException {
091: // do nothing
092: }
093:
094: public void flush() throws IOException {
095: // do nothing
096: }
097:
098: public void write(char[] cbuf, int off, int len) throws IOException {
099: this .out.write(cbuf, off, len);
100: }
101:
102: public void write(char[] cbuf) throws IOException {
103: this .out.write(cbuf);
104: }
105:
106: public void write(int c) throws IOException {
107: this .out.write(c);
108: }
109:
110: public void write(String str, int off, int len) throws IOException {
111: this .out.write(str, off, len);
112: }
113:
114: public void write(String str) throws IOException {
115: this .out.write(str);
116: }
117:
118: public String getAndResetBuffer() {
119: if (!this .writtenState) {
120: throw new IllegalStateException(
121: "Did not write state; no buffer is available");
122: }
123:
124: String result = this .fast.toString();
125: this .fast.reset();
126: return result;
127: }
128:
129: public void release() {
130: CURRENT_WRITER.set(null);
131: }
132:
133: static private final ThreadLocal CURRENT_WRITER = new ThreadLocal();
134: }
|