1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.context;
21
22 import java.io.IOException;
23 import java.io.Writer;
24 import java.util.ArrayList;
25 import java.util.List;
26
27 import javax.faces.component.UIComponent;
28 import javax.faces.context.PartialResponseWriter;
29 import javax.faces.context.ResponseWriter;
30
31 import org.apache.myfaces.util.CDataEndEscapeFilterWriter;
32 import org.apache.myfaces.util.IllegalXmlCharacterFilterWriter;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 public class PartialResponseWriterImpl extends PartialResponseWriter
74 {
75
76 class StackEntry
77 {
78 ResponseWriter writer;
79 Writer _doubleBuffer;
80
81 StackEntry(ResponseWriter writer, Writer doubleBuffer)
82 {
83 this.writer = writer;
84 _doubleBuffer = doubleBuffer;
85 }
86
87 public ResponseWriter getWriter()
88 {
89 return writer;
90 }
91
92 public void setWriter(ResponseWriter writer)
93 {
94 this.writer = writer;
95 }
96
97 public Writer getDoubleBuffer()
98 {
99 return _doubleBuffer;
100 }
101
102 public void setDoubleBuffer(Writer doubleBuffer)
103 {
104 _doubleBuffer = doubleBuffer;
105 }
106 }
107
108 ResponseWriter _cdataDoubleBufferWriter = null;
109 Writer _doubleBuffer = null;
110 List<StackEntry> _nestingStack = new ArrayList<StackEntry>(4);
111
112 public PartialResponseWriterImpl(ResponseWriter writer)
113 {
114 super(writer.cloneWithWriter(new IllegalXmlCharacterFilterWriter(writer)));
115 }
116
117 @Override
118 public void startCDATA() throws IOException
119 {
120 if (!isDoubleBufferEnabled())
121 {
122 super.startCDATA();
123 }
124 else
125 {
126 _cdataDoubleBufferWriter.write("<![CDATA[");
127 }
128 openDoubleBuffer();
129 }
130
131 private void openDoubleBuffer()
132 {
133 _doubleBuffer = new CDataEndEscapeFilterWriter(_cdataDoubleBufferWriter == null ?
134 this.getWrapped() : _cdataDoubleBufferWriter );
135 _cdataDoubleBufferWriter = getWrapped().cloneWithWriter(_doubleBuffer);
136
137 StackEntry entry = new StackEntry(_cdataDoubleBufferWriter, _doubleBuffer);
138
139 _nestingStack.add(0, entry);
140 }
141
142 @Override
143 public void endCDATA() throws IOException
144 {
145 closeDoubleBuffer(false);
146 if (isDoubleBufferEnabled())
147 {
148 _cdataDoubleBufferWriter.write("]]>");
149 }
150 else
151 {
152 super.endCDATA();
153 }
154 }
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169 private void closeDoubleBuffer(boolean force) throws IOException
170 {
171 if (!isDoubleBufferEnabled())
172 {
173 return;
174 }
175
176
177
178
179
180 if (force)
181 {
182 while (!_nestingStack.isEmpty())
183 {
184 popAndEncodeCurrentStackEntry();
185
186 }
187 }
188 else
189 {
190 popAndEncodeCurrentStackEntry();
191 }
192 }
193
194 private void popAndEncodeCurrentStackEntry() throws IOException
195 {
196 _nestingStack.remove(0);
197 StackEntry parent = (_nestingStack.isEmpty()) ? null : _nestingStack.get(0);
198 if (parent != null)
199 {
200 _cdataDoubleBufferWriter = parent.getWriter();
201 _doubleBuffer = parent.getDoubleBuffer();
202 }
203 else
204 {
205 _cdataDoubleBufferWriter = null;
206 _doubleBuffer = null;
207 }
208 }
209
210
211
212 @Override
213 public void endInsert() throws IOException
214 {
215
216
217
218
219 closeDoubleBuffer(true);
220 super.endInsert();
221 }
222
223 @Override
224 public void endUpdate() throws IOException
225 {
226
227
228
229
230 closeDoubleBuffer(true);
231 super.endUpdate();
232 }
233
234 @Override
235 public void endExtension() throws IOException
236 {
237
238
239
240
241 closeDoubleBuffer(true);
242 super.endExtension();
243 }
244
245 @Override
246 public void endEval() throws IOException
247 {
248
249
250
251
252 closeDoubleBuffer(true);
253 super.endEval();
254 }
255
256 @Override
257 public void endError() throws IOException
258 {
259
260
261
262
263 closeDoubleBuffer(true);
264 super.endError();
265 }
266
267
268
269 @Override
270 public void endElement(String name) throws IOException
271 {
272 if (isDoubleBufferEnabled())
273 {
274 _cdataDoubleBufferWriter.endElement(name);
275 }
276 else
277 {
278 super.endElement(name);
279 }
280 }
281
282 @Override
283 public void writeComment(Object comment) throws IOException
284 {
285 if (isDoubleBufferEnabled())
286 {
287 _cdataDoubleBufferWriter.writeComment(comment);
288 }
289 else
290 {
291 super.writeComment(comment);
292 }
293 }
294
295 private boolean isDoubleBufferEnabled()
296 {
297 return !_nestingStack.isEmpty();
298 }
299
300 @Override
301 public void startElement(String name, UIComponent component) throws IOException
302 {
303 if (isDoubleBufferEnabled())
304 {
305 _cdataDoubleBufferWriter.startElement(name, component);
306 }
307 else
308 {
309 super.startElement(name, component);
310 }
311 }
312
313 @Override
314 public void writeText(Object text, String property) throws IOException
315 {
316 if (isDoubleBufferEnabled())
317 {
318 _cdataDoubleBufferWriter.writeText(text, property);
319 }
320 else
321 {
322 super.writeText(text, property);
323 }
324 }
325
326 @Override
327 public void writeText(char[] text, int off, int len) throws IOException
328 {
329 if (isDoubleBufferEnabled())
330 {
331 _cdataDoubleBufferWriter.writeText(text, off, len);
332 }
333 else
334 {
335 super.writeText(text, off, len);
336 }
337 }
338
339 @Override
340 public void write(char[] cbuf, int off, int len) throws IOException
341 {
342 if (isDoubleBufferEnabled())
343 {
344 _cdataDoubleBufferWriter.write(cbuf, off, len);
345 }
346 else
347 {
348 super.write(cbuf, off, len);
349 }
350 }
351
352 @Override
353 public ResponseWriter cloneWithWriter(Writer writer)
354 {
355 return super.cloneWithWriter(writer);
356 }
357
358 @Override
359 public void writeURIAttribute(String name, Object value, String property) throws IOException
360 {
361 if (isDoubleBufferEnabled())
362 {
363 _cdataDoubleBufferWriter.writeURIAttribute(name, value, property);
364 }
365 else
366 {
367 super.writeURIAttribute(name, value, property);
368 }
369 }
370
371 @Override
372 public void close() throws IOException
373 {
374
375
376
377
378
379 if (isDoubleBufferEnabled())
380 {
381
382
383 closeDoubleBuffer(true);
384
385 super.endCDATA();
386 }
387 super.close();
388 }
389
390 @Override
391 public void flush() throws IOException
392 {
393 if (isDoubleBufferEnabled())
394 {
395 _cdataDoubleBufferWriter.flush();
396 }
397 super.flush();
398 }
399
400 @Override
401 public void writeAttribute(String name, Object value, String property) throws IOException
402 {
403 if (isDoubleBufferEnabled())
404 {
405 _cdataDoubleBufferWriter.writeAttribute(name, value, property);
406 }
407 else
408 {
409 super.writeAttribute(name, value, property);
410 }
411 }
412
413 @Override
414 public void writeText(Object object, UIComponent component, String string) throws IOException
415 {
416 if (isDoubleBufferEnabled())
417 {
418 _cdataDoubleBufferWriter.writeText(object, component, string);
419 }
420 else
421 {
422 super.writeText(object, component, string);
423 }
424 }
425
426 @Override
427 public Writer append(char c) throws IOException
428 {
429 if (isDoubleBufferEnabled())
430 {
431 _cdataDoubleBufferWriter.append(c);
432 return this;
433 }
434 else
435 {
436 return super.append(c);
437 }
438 }
439
440 @Override
441 public Writer append(CharSequence csq, int start, int end) throws IOException
442 {
443 if (isDoubleBufferEnabled())
444 {
445 _cdataDoubleBufferWriter.append(csq, start, end);
446 return this;
447 }
448 else
449 {
450 return super.append(csq, start, end);
451 }
452 }
453
454 @Override
455 public Writer append(CharSequence csq) throws IOException
456 {
457 if (isDoubleBufferEnabled())
458 {
459 _cdataDoubleBufferWriter.append(csq);
460 return this;
461 }
462 else
463 {
464 return super.append(csq);
465 }
466 }
467
468 @Override
469 public void write(char[] cbuf) throws IOException
470 {
471 if (isDoubleBufferEnabled())
472 {
473 _cdataDoubleBufferWriter.write(cbuf);
474 }
475 else
476 {
477 super.write(cbuf);
478 }
479 }
480
481 @Override
482 public void write(int c) throws IOException
483 {
484 if (isDoubleBufferEnabled())
485 {
486 _cdataDoubleBufferWriter.write(c);
487 }
488 else
489 {
490 super.write(c);
491 }
492 }
493
494 @Override
495 public void write(String str, int off, int len) throws IOException
496 {
497 if (isDoubleBufferEnabled())
498 {
499 _cdataDoubleBufferWriter.write(str, off, len);
500 }
501 else
502 {
503 super.write(str, off, len);
504 }
505 }
506
507 @Override
508 public void write(String str) throws IOException
509 {
510 if (isDoubleBufferEnabled())
511 {
512 _cdataDoubleBufferWriter.write(str);
513 }
514 else
515 {
516 super.write(str);
517 }
518 }
519 }