Source code: com/sun/facelets/StateWriter.java
1 /**
2 * Licensed under the Common Development and Distribution License,
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://www.sun.com/cddl/
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
11 * implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
15 package com.sun.facelets;
16
17 import java.io.IOException;
18 import java.io.Writer;
19
20 import com.sun.facelets.util.FastWriter;
21
22 /**
23 * A class for handling state insertion. Content is written
24 * directly to "out" until an attempt to write state; at that
25 * point, it's redirected into a buffer that can be picked through
26 * in theory, this buffer should be very small, since it only
27 * needs to be enough to contain all the content after the close
28 * of the first (and, hopefully, only) form.
29 * <p>
30 * Potential optimizations:
31 * <ul>
32 * <li>If we created a new FastWriter at each call to writingState(),
33 * and stored a List of them, then we'd know that state tokens could
34 * only possibly be near the start of each buffer (and might not be there
35 * at all). (There might be a close-element before the state token). Then,
36 * we'd only need to check the start of the buffer for the state token;
37 * if it's there, write out the real state, then blast the rest of the
38 * buffer out. This wouldn't even require toString(), which for
39 * large buffers is expensive. However, this optimization is only
40 * going to be especially meaningful for the multi-form case.
41 * </li>
42 * <li>More of a FastWriter optimization than a StateWriter, but:
43 * it is far faster to create a set of small 1K buffers than constantly
44 * reallocating one big buffer.</li>
45 * </ul>
46 *
47 * @author Adam Winer
48 * @version $Id: StateWriter.java,v 1.1 2006/04/12 05:50:45 adamwiner Exp $
49 */
50 final class StateWriter extends Writer {
51
52 private int initialSize;
53 private Writer out;
54 private FastWriter fast;
55 private boolean writtenState;
56
57 static public StateWriter getCurrentInstance() {
58 return (StateWriter) CURRENT_WRITER.get();
59 }
60
61 public StateWriter(Writer initialOut, int initialSize) {
62 if (initialSize < 0) {
63 throw new IllegalArgumentException("Initial Size cannot be less than 0");
64 }
65
66 this.initialSize = initialSize;
67 this.out = initialOut;
68
69 CURRENT_WRITER.set(this);
70 }
71
72 /**
73 * Mark that state is about to be written. Contrary to what you'd expect,
74 * we cannot and should not assume that this location is really going
75 * to have state; it is perfectly legit to have a ResponseWriter that
76 * filters out content, and ignores an attempt to write out state
77 * at this point. So, we have to check after the fact to see
78 * if there really are state markers.
79 */
80 public void writingState() {
81 if (!this.writtenState) {
82 this.writtenState = true;
83 this.out = this.fast = new FastWriter(this.initialSize);
84 }
85 }
86
87 public boolean isStateWritten() {
88 return this.writtenState;
89 }
90
91 public void close() throws IOException {
92 // do nothing
93 }
94
95 public void flush() throws IOException {
96 // do nothing
97 }
98
99 public void write(char[] cbuf, int off, int len) throws IOException {
100 this.out.write(cbuf, off, len);
101 }
102
103 public void write(char[] cbuf) throws IOException {
104 this.out.write(cbuf);
105 }
106
107 public void write(int c) throws IOException {
108 this.out.write(c);
109 }
110
111 public void write(String str, int off, int len) throws IOException {
112 this.out.write(str, off, len);
113 }
114
115 public void write(String str) throws IOException {
116 this.out.write(str);
117 }
118
119 public String getAndResetBuffer() {
120 if (!this.writtenState) {
121 throw new IllegalStateException(
122 "Did not write state; no buffer is available");
123 }
124
125 String result = this.fast.toString();
126 this.fast.reset();
127 return result;
128 }
129
130 public void release() {
131 CURRENT_WRITER.set(null);
132 }
133
134 static private final ThreadLocal CURRENT_WRITER = new ThreadLocal();
135 }