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