1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.shared.renderkit.html;
20
21 import java.io.IOException;
22 import java.io.Writer;
23 import java.nio.charset.Charset;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29 import javax.el.ValueExpression;
30
31 import javax.faces.FacesException;
32 import javax.faces.component.UIComponent;
33 import javax.faces.context.FacesContext;
34 import javax.faces.context.ResponseWriter;
35 import javax.faces.render.Renderer;
36
37 import org.apache.myfaces.shared.config.MyfacesConfig;
38 import org.apache.myfaces.shared.renderkit.ContentTypeUtils;
39 import org.apache.myfaces.shared.renderkit.RendererUtils;
40 import org.apache.myfaces.shared.renderkit.html.util.UnicodeEncoder;
41 import org.apache.myfaces.shared.util.CommentUtils;
42 import org.apache.myfaces.shared.util.StreamCharBuffer;
43
44 public class HtmlResponseWriterImpl
45 extends ResponseWriter
46 {
47 private static final Logger log = Logger.getLogger(HtmlResponseWriterImpl.class.getName());
48
49 private static final String DEFAULT_CONTENT_TYPE = "text/html";
50 private static final String DEFAULT_CHARACTER_ENCODING = "ISO-8859-1";
51 private static final String UTF8 = "UTF-8";
52
53 private static final String APPLICATION_XML_CONTENT_TYPE = "application/xml";
54 private static final String TEXT_XML_CONTENT_TYPE = "text/xml";
55
56
57
58
59
60
61
62 private Writer _outputWriter;
63
64
65
66
67 private Writer _currentWriter;
68
69
70
71
72 private StreamCharBuffer _buffer;
73
74 private String _contentType;
75
76 private String _writerContentTypeMode;
77
78
79
80
81 private boolean _isXhtmlContentType;
82
83
84
85
86
87 private boolean _useStraightXml;
88
89 private String _characterEncoding;
90 private boolean _wrapScriptContentWithXmlCommentTag;
91 private boolean _isUTF8;
92
93 private String _startElementName;
94 private boolean _isInsideScript = false;
95 private boolean _isStyle = false;
96 private Boolean _isTextArea;
97 private UIComponent _startElementUIComponent;
98 private boolean _startTagOpen;
99 private Map<String, Object> _passThroughAttributesMap;
100 private FacesContext _facesContext;
101
102 private boolean _cdataOpen;
103
104 private List<String> _startedChangedElements;
105 private List<Integer> _startedElementsCount;
106
107 private static final String CDATA_START = "<![CDATA[ \n";
108 private static final String CDATA_START_NO_LINE_RETURN = "<![CDATA[";
109 private static final String COMMENT_START = "<!--\n";
110 private static final String CDATA_COMMENT_START = "//<![CDATA[ \n";
111 private static final String CDATA_COMMENT_END = "\n//]]>";
112 private static final String CDATA_END = "\n]]>";
113 private static final String CDATA_END_NO_LINE_RETURN = "]]>";
114 private static final String COMMENT_COMMENT_END = "\n//-->";
115 private static final String COMMENT_END = "\n-->";
116
117 static private final String[][] EMPTY_ELEMENT_ARR = new String[256][];
118
119 static private final String[] A_NAMES = new String[]
120 {
121 "area",
122 };
123
124 static private final String[] B_NAMES = new String[]
125 {
126 "br",
127 "base",
128 "basefont",
129 };
130
131 static private final String[] C_NAMES = new String[]
132 {
133 "col",
134 };
135
136 static private final String[] E_NAMES = new String[]
137 {
138 "embed",
139 };
140
141 static private final String[] F_NAMES = new String[]
142 {
143 "frame",
144 };
145
146 static private final String[] H_NAMES = new String[]
147 {
148 "hr",
149 };
150
151 static private final String[] I_NAMES = new String[]
152 {
153 "img",
154 "input",
155 "isindex",
156 };
157
158 static private final String[] L_NAMES = new String[]
159 {
160 "link",
161 };
162
163 static private final String[] M_NAMES = new String[]
164 {
165 "meta",
166 };
167
168 static private final String[] P_NAMES = new String[]
169 {
170 "param",
171 };
172
173 static
174 {
175 EMPTY_ELEMENT_ARR['a'] = A_NAMES;
176 EMPTY_ELEMENT_ARR['A'] = A_NAMES;
177 EMPTY_ELEMENT_ARR['b'] = B_NAMES;
178 EMPTY_ELEMENT_ARR['B'] = B_NAMES;
179 EMPTY_ELEMENT_ARR['c'] = C_NAMES;
180 EMPTY_ELEMENT_ARR['C'] = C_NAMES;
181 EMPTY_ELEMENT_ARR['e'] = E_NAMES;
182 EMPTY_ELEMENT_ARR['E'] = E_NAMES;
183 EMPTY_ELEMENT_ARR['f'] = F_NAMES;
184 EMPTY_ELEMENT_ARR['F'] = F_NAMES;
185 EMPTY_ELEMENT_ARR['h'] = H_NAMES;
186 EMPTY_ELEMENT_ARR['H'] = H_NAMES;
187 EMPTY_ELEMENT_ARR['i'] = I_NAMES;
188 EMPTY_ELEMENT_ARR['I'] = I_NAMES;
189 EMPTY_ELEMENT_ARR['l'] = L_NAMES;
190 EMPTY_ELEMENT_ARR['L'] = L_NAMES;
191 EMPTY_ELEMENT_ARR['m'] = M_NAMES;
192 EMPTY_ELEMENT_ARR['M'] = M_NAMES;
193 EMPTY_ELEMENT_ARR['p'] = P_NAMES;
194 EMPTY_ELEMENT_ARR['P'] = P_NAMES;
195 }
196
197 public HtmlResponseWriterImpl(Writer writer, String contentType, String characterEncoding)
198 {
199 this(writer,contentType,characterEncoding,true);
200 }
201
202 public HtmlResponseWriterImpl(Writer writer, String contentType, String characterEncoding,
203 boolean wrapScriptContentWithXmlCommentTag)
204 {
205 this(writer,contentType, characterEncoding, wrapScriptContentWithXmlCommentTag,
206 contentType != null && HtmlRendererUtils.isXHTMLContentType(contentType) ?
207 ContentTypeUtils.XHTML_CONTENT_TYPE : ContentTypeUtils.HTML_CONTENT_TYPE);
208 }
209
210 public HtmlResponseWriterImpl(Writer writer, String contentType, String characterEncoding,
211 boolean wrapScriptContentWithXmlCommentTag, String writerContentTypeMode)
212 throws FacesException
213 {
214 _outputWriter = writer;
215
216 _currentWriter = _outputWriter;
217 _wrapScriptContentWithXmlCommentTag = wrapScriptContentWithXmlCommentTag;
218
219 _contentType = contentType;
220 if (_contentType == null)
221 {
222 if (log.isLoggable(Level.FINE))
223 {
224 log.fine("No content type given, using default content type " + DEFAULT_CONTENT_TYPE);
225 }
226 _contentType = DEFAULT_CONTENT_TYPE;
227 }
228 _writerContentTypeMode = writerContentTypeMode;
229 _isXhtmlContentType = writerContentTypeMode.indexOf(ContentTypeUtils.XHTML_CONTENT_TYPE) != -1;
230
231 _useStraightXml = _isXhtmlContentType && (_contentType.indexOf(APPLICATION_XML_CONTENT_TYPE) != -1 ||
232 _contentType.indexOf(TEXT_XML_CONTENT_TYPE) != -1);
233
234 if (characterEncoding == null)
235 {
236 if (log.isLoggable(Level.FINE))
237 {
238 log.fine("No character encoding given, using default character encoding " +
239 DEFAULT_CHARACTER_ENCODING);
240 }
241 _characterEncoding = DEFAULT_CHARACTER_ENCODING;
242 }
243 else
244 {
245
246 _characterEncoding = characterEncoding.toUpperCase();
247
248
249 if (!Charset.isSupported(_characterEncoding))
250 {
251 throw new IllegalArgumentException("Encoding "+_characterEncoding
252 +" not supported by HtmlResponseWriterImpl");
253 }
254 }
255 _isUTF8 = UTF8.equals(_characterEncoding);
256 _startedChangedElements = new ArrayList<String>();
257 _startedElementsCount = new ArrayList<Integer>();
258 }
259
260 public static boolean supportsContentType(String contentType)
261 {
262 String[] supportedContentTypes = HtmlRendererUtils.getSupportedContentTypes();
263
264 for (int i = 0; i < supportedContentTypes.length; i++)
265 {
266 String supportedContentType = supportedContentTypes[i];
267
268 if(supportedContentType.indexOf(contentType)!=-1)
269 {
270 return true;
271 }
272 }
273 return false;
274 }
275
276 public String getContentType()
277 {
278 return _contentType;
279 }
280
281 public String getWriterContentTypeMode()
282 {
283 return _writerContentTypeMode;
284 }
285
286 public String getCharacterEncoding()
287 {
288 return _characterEncoding;
289 }
290
291 public void flush() throws IOException
292 {
293
294
295
296 closeStartTagIfNecessary();
297 }
298
299 public void startDocument()
300 {
301
302 }
303
304 public void endDocument() throws IOException
305 {
306 MyfacesConfig myfacesConfig = MyfacesConfig.getCurrentInstance(
307 FacesContext.getCurrentInstance().getExternalContext());
308 if (myfacesConfig.isEarlyFlushEnabled())
309 {
310 _currentWriter.flush();
311 }
312 _facesContext = null;
313 }
314
315 public void startElement(String name, UIComponent uiComponent) throws IOException
316 {
317 if (name == null)
318 {
319 throw new NullPointerException("elementName name must not be null");
320 }
321
322 closeStartTagIfNecessary();
323 _currentWriter.write('<');
324
325 resetStartedElement();
326
327 _startElementName = name;
328 _startElementUIComponent = uiComponent;
329 _startTagOpen = true;
330 _passThroughAttributesMap = (_startElementUIComponent != null) ?
331 _startElementUIComponent.getPassThroughAttributes(false) : null;
332
333 if (_passThroughAttributesMap != null)
334 {
335 Object value = _passThroughAttributesMap.get(
336 Renderer.PASSTHROUGH_RENDERER_LOCALNAME_KEY);
337 if (value != null)
338 {
339 if (value instanceof ValueExpression)
340 {
341 value = ((ValueExpression)value).getValue(
342 getFacesContext().getELContext());
343 }
344 String elementName = value.toString().trim();
345
346 if (!name.equals(elementName))
347 {
348 _startElementName = elementName;
349 _startedChangedElements.add(elementName);
350 _startedElementsCount.add(0);
351 }
352 _currentWriter.write((String) elementName);
353 }
354 else
355 {
356 _currentWriter.write(name);
357 }
358 }
359 else
360 {
361 _currentWriter.write(name);
362 }
363
364 if (!_startedElementsCount.isEmpty())
365 {
366 int i = _startedElementsCount.size()-1;
367 _startedElementsCount.set(i, _startedElementsCount.get(i)+1);
368 }
369
370
371
372
373 if(isScript(_startElementName))
374 {
375
376 _isInsideScript = true;
377 _isStyle = false;
378 _isTextArea = Boolean.FALSE;
379 }
380 else if (isStyle(_startElementName))
381 {
382 _isInsideScript = false;
383 _isStyle = true;
384 _isTextArea = Boolean.FALSE;
385 }
386 }
387
388 @Override
389 public void startCDATA() throws IOException
390 {
391 if (!_cdataOpen)
392 {
393 write(CDATA_START_NO_LINE_RETURN);
394 _cdataOpen = true;
395 }
396 }
397
398 @Override
399 public void endCDATA() throws IOException
400 {
401 if (_cdataOpen)
402 {
403 write(CDATA_END_NO_LINE_RETURN);
404 _cdataOpen = false;
405 }
406 }
407
408 private void closeStartTagIfNecessary() throws IOException
409 {
410 if (_startTagOpen)
411 {
412 if (_passThroughAttributesMap != null)
413 {
414 for (Map.Entry<String, Object> entry : _passThroughAttributesMap.entrySet())
415 {
416 String key = entry.getKey();
417 Object value = entry.getValue();
418 if (Renderer.PASSTHROUGH_RENDERER_LOCALNAME_KEY.equals(key))
419 {
420
421
422 continue;
423 }
424 if (value instanceof ValueExpression)
425 {
426 value = ((ValueExpression)value).getValue(getFacesContext().getELContext());
427 }
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443 encodeAndWriteAttribute(key, value);
444 }
445 }
446
447 if (!_useStraightXml && isEmptyElement(_startElementName))
448 {
449 _currentWriter.write(" />");
450
451
452 resetStartedElement();
453 }
454 else
455 {
456 _currentWriter.write('>');
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472 if (isScript(_startElementName) && (_isXhtmlContentType || _wrapScriptContentWithXmlCommentTag))
473 {
474
475
476 getInternalBuffer(true);
477 _currentWriter = getInternalBuffer().getWriter();
478 }
479 if (isStyle(_startElementName) && _isXhtmlContentType)
480 {
481
482
483 getInternalBuffer(true);
484 _currentWriter = getInternalBuffer().getWriter();
485 }
486 }
487 _startTagOpen = false;
488 }
489 }
490
491 private boolean isEmptyElement(String elem)
492 {
493
494
495
496
497
498
499
500 String[] array = EMPTY_ELEMENT_ARR[elem.charAt(0)];
501 if (array != null)
502 {
503 for (int i = array.length - 1; i >= 0; i--)
504 {
505 if (elem.equalsIgnoreCase(array[i]))
506 {
507 return true;
508 }
509 }
510 }
511 return false;
512 }
513
514 private void resetStartedElement()
515 {
516 _startElementName = null;
517 _startElementUIComponent = null;
518 _passThroughAttributesMap = null;
519 _isStyle = false;
520 _isTextArea = null;
521 }
522
523 public void endElement(String name) throws IOException
524 {
525 if (name == null)
526 {
527 throw new NullPointerException("elementName name must not be null");
528 }
529
530 String elementName = name;
531
532 if (!_startedElementsCount.isEmpty())
533 {
534 int i = _startedElementsCount.size()-1;
535 _startedElementsCount.set(i, _startedElementsCount.get(i)-1);
536 if (_startedElementsCount.get(i) == 0)
537 {
538 elementName = _startedChangedElements.get(i);
539 _startedChangedElements.remove(i);
540 _startedElementsCount.remove(i);
541 }
542 }
543
544 if (log.isLoggable(Level.WARNING))
545 {
546 if (_startElementName != null &&
547 !elementName.equals(_startElementName))
548 {
549 log.warning("HTML nesting warning on closing " + elementName + ": element " + _startElementName +
550 (_startElementUIComponent==null?"":(" rendered by component : "+
551 RendererUtils.getPathToComponent(_startElementUIComponent)))+" not explicitly closed");
552 }
553 }
554
555 if(_startTagOpen)
556 {
557
558
559
560 closeStartTagIfNecessary();
561
562
563 if(_startElementName!=null)
564 {
565 if (isScript() && (_isXhtmlContentType || _wrapScriptContentWithXmlCommentTag))
566 {
567 writeScriptContent();
568 _currentWriter = _outputWriter;
569 }
570 else if (isStyle() && _isXhtmlContentType)
571 {
572 writeStyleContent();
573 _currentWriter = _outputWriter;
574 }
575
576
577 writeEndTag(elementName);
578 }
579 }
580 else
581 {
582 if (!_useStraightXml && isEmptyElement(elementName))
583 {
584
585
586
587
588
589
590
591 }
592 else
593 {
594 if (isScript() && (_isXhtmlContentType || _wrapScriptContentWithXmlCommentTag))
595 {
596 writeScriptContent();
597 _currentWriter = _outputWriter;
598 }
599 else if (isStyle() && _isXhtmlContentType)
600 {
601 writeStyleContent();
602 _currentWriter = _outputWriter;
603 }
604 writeEndTag(elementName);
605 }
606 }
607
608 resetStartedElement();
609 }
610
611
612
613 private void writeStyleContent() throws IOException
614 {
615 String content = getInternalBuffer().toString();
616
617 if(_isXhtmlContentType)
618 {
619
620
621
622
623
624
625
626 String trimmedContent = content.trim();
627 if (trimmedContent.startsWith(CommentUtils.CDATA_SIMPLE_START) && trimmedContent.endsWith(
628 CommentUtils.CDATA_SIMPLE_END))
629 {
630 _outputWriter.write(content);
631 return;
632 }
633 else if (CommentUtils.isStartMatchWithCommentedCDATA(trimmedContent) &&
634 CommentUtils.isEndMatchWithCommentedCDATA(trimmedContent))
635 {
636 _outputWriter.write(content);
637 return;
638 }
639 else if (trimmedContent.startsWith(CommentUtils.COMMENT_SIMPLE_START) &&
640 trimmedContent.endsWith(CommentUtils.COMMENT_SIMPLE_END))
641 {
642
643 _outputWriter.write(CDATA_START);
644 _outputWriter.write(trimmedContent.substring(4,trimmedContent.length()-3));
645 _outputWriter.write(CDATA_END);
646 return;
647 }
648 else
649 {
650 _outputWriter.write(CDATA_START);
651 _outputWriter.write(content);
652 _outputWriter.write(CDATA_END);
653 return;
654 }
655 }
656
657
658
659 _outputWriter.write(content);
660 }
661
662 private void writeScriptContent() throws IOException
663 {
664 String content = getInternalBuffer().toString();
665 String trimmedContent = null;
666
667 if(_isXhtmlContentType)
668 {
669 trimmedContent = content.trim();
670
671 if ( trimmedContent.startsWith(CommentUtils.COMMENT_SIMPLE_START) &&
672 CommentUtils.isEndMatchtWithInlineCommentedXmlCommentTag(trimmedContent))
673 {
674
675
676 if (_cdataOpen)
677 {
678 _outputWriter.write("//\n");
679 }
680 else
681 {
682 _outputWriter.write(CDATA_COMMENT_START);
683 }
684
685 _outputWriter.write(trimmedContent.substring(4));
686
687 if (_cdataOpen)
688 {
689 _outputWriter.write("\n");
690 }
691 else
692 {
693 _outputWriter.write(CDATA_COMMENT_END);
694 }
695
696 return;
697 }
698 else if (CommentUtils.isStartMatchWithCommentedCDATA(trimmedContent) &&
699 CommentUtils.isEndMatchWithCommentedCDATA(trimmedContent))
700 {
701 _outputWriter.write(content);
702 return;
703 }
704 else if (CommentUtils.isStartMatchWithInlineCommentedCDATA(trimmedContent) &&
705 CommentUtils.isEndMatchWithInlineCommentedCDATA(trimmedContent))
706 {
707 _outputWriter.write(content);
708 return;
709 }
710 else
711 {
712
713
714 if (_cdataOpen)
715 {
716 _outputWriter.write("//\n");
717 }
718 else
719 {
720 _outputWriter.write(CDATA_COMMENT_START);
721 }
722
723 _outputWriter.write(content);
724
725 if (_cdataOpen)
726 {
727 _outputWriter.write("\n");
728 }
729 else
730 {
731 _outputWriter.write(CDATA_COMMENT_END);
732 }
733
734 return;
735 }
736 }
737 else
738 {
739 if (_wrapScriptContentWithXmlCommentTag)
740 {
741 trimmedContent = content.trim();
742
743 if ( trimmedContent.startsWith(CommentUtils.COMMENT_SIMPLE_START) &&
744 CommentUtils.isEndMatchtWithInlineCommentedXmlCommentTag(trimmedContent))
745 {
746 _outputWriter.write(content);
747 return;
748 }
749 else if (CommentUtils.isStartMatchWithCommentedCDATA(trimmedContent) &&
750 CommentUtils.isEndMatchWithCommentedCDATA(trimmedContent))
751 {
752 _outputWriter.write(content);
753 return;
754 }
755 else if (CommentUtils.isStartMatchWithInlineCommentedCDATA(trimmedContent) &&
756 CommentUtils.isEndMatchWithInlineCommentedCDATA(trimmedContent))
757 {
758 _outputWriter.write(content);
759 return;
760 }
761 else
762 {
763 _outputWriter.write(COMMENT_START);
764 _outputWriter.write(content);
765 _outputWriter.write(COMMENT_COMMENT_END);
766 return;
767 }
768 }
769 }
770
771
772 _outputWriter.write(content);
773 }
774
775
776 private void writeEndTag(String name)
777 throws IOException
778 {
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798 if (isScript(name))
799 {
800
801 _isInsideScript = false;
802 }
803 else if (isStyle(name))
804 {
805 _isStyle = false;
806 }
807
808 _currentWriter.write("</");
809 _currentWriter.write(name);
810 _currentWriter.write('>');
811 }
812
813 public void writeAttribute(String name, Object value, String componentPropertyName) throws IOException
814 {
815 if (name == null)
816 {
817 throw new NullPointerException("attributeName name must not be null");
818 }
819 if (!_startTagOpen)
820 {
821 throw new IllegalStateException("Must be called before the start element is closed (attribute '"
822 + name + "')");
823 }
824
825
826 if (_passThroughAttributesMap != null && _passThroughAttributesMap.containsKey(name))
827 {
828 return;
829 }
830
831 if (value instanceof Boolean)
832 {
833 if (((Boolean)value).booleanValue())
834 {
835
836 _currentWriter.write(' ');
837 _currentWriter.write(name);
838 _currentWriter.write("=\"");
839 _currentWriter.write(name);
840 _currentWriter.write('"');
841 }
842 }
843 else
844 {
845 String strValue = (value==null)?"":value.toString();
846 _currentWriter.write(' ');
847 _currentWriter.write(name);
848 _currentWriter.write("=\"");
849 org.apache.myfaces.shared.renderkit.html.util.HTMLEncoder.encode(_currentWriter,
850 strValue, false, false, !_isUTF8);
851 _currentWriter.write('"');
852 }
853 }
854
855 private void encodeAndWriteAttribute(String name, Object value) throws IOException
856 {
857 String strValue = (value==null)?"":value.toString();
858 _currentWriter.write(' ');
859 _currentWriter.write(name);
860 _currentWriter.write("=\"");
861 org.apache.myfaces.shared.renderkit.html.util.HTMLEncoder.encode(_currentWriter,
862 strValue, false, false, !_isUTF8);
863 _currentWriter.write('"');
864 }
865
866 public void writeURIAttribute(String name, Object value, String componentPropertyName) throws IOException
867 {
868 if (name == null)
869 {
870 throw new NullPointerException("attributeName name must not be null");
871 }
872 if (!_startTagOpen)
873 {
874 throw new IllegalStateException("Must be called before the start element is closed (attribute '"
875 + name + "')");
876 }
877
878
879 if (_passThroughAttributesMap != null && _passThroughAttributesMap.containsKey(name))
880 {
881 return;
882 }
883
884 encodeAndWriteURIAttribute(name, value);
885 }
886
887 private void encodeAndWriteURIAttribute(String name, Object value) throws IOException
888 {
889 String strValue = value.toString();
890 _currentWriter.write(' ');
891 _currentWriter.write(name);
892 _currentWriter.write("=\"");
893 if (strValue.toLowerCase().startsWith("javascript:"))
894 {
895 org.apache.myfaces.shared.renderkit.html.util.HTMLEncoder.encode(_currentWriter,
896 strValue, false, false, !_isUTF8);
897 }
898 else
899 {
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928 org.apache.myfaces.shared.renderkit.html.util.HTMLEncoder.encodeURIAttribute(_currentWriter,
929 strValue, _characterEncoding);
930 }
931 _currentWriter.write('"');
932 }
933
934 public void writeComment(Object value) throws IOException
935 {
936 if (value == null)
937 {
938 throw new NullPointerException("comment name must not be null");
939 }
940
941 closeStartTagIfNecessary();
942 _currentWriter.write("<!--");
943 _currentWriter.write(value.toString());
944 _currentWriter.write("-->");
945 }
946
947 public void writeText(Object value, String componentPropertyName) throws IOException
948 {
949 if (value == null)
950 {
951 throw new NullPointerException("Text must not be null.");
952 }
953
954 closeStartTagIfNecessary();
955
956 String strValue = value.toString();
957
958 if (isScriptOrStyle())
959 {
960
961 if (_isUTF8)
962 {
963 _currentWriter.write(strValue);
964 }
965 else
966 {
967 UnicodeEncoder.encode(_currentWriter, strValue);
968 }
969 }
970 else
971 {
972 org.apache.myfaces.shared.renderkit.html.util.HTMLEncoder.encode(_currentWriter,
973 strValue, false, false, !_isUTF8);
974 }
975 }
976
977 public void writeText(char cbuf[], int off, int len) throws IOException
978 {
979 if (cbuf == null)
980 {
981 throw new NullPointerException("cbuf name must not be null");
982 }
983 if (cbuf.length < off + len)
984 {
985 throw new IndexOutOfBoundsException((off + len) + " > " + cbuf.length);
986 }
987
988 closeStartTagIfNecessary();
989
990 if (isScriptOrStyle())
991 {
992 String strValue = new String(cbuf, off, len);
993
994 if (_isUTF8)
995 {
996 _currentWriter.write(strValue);
997 }
998 else
999 {
1000 UnicodeEncoder.encode(_currentWriter, strValue);
1001 }
1002 }
1003 else if (isTextarea())
1004 {
1005
1006 org.apache.myfaces.shared.renderkit.html.util.HTMLEncoder.encode(
1007 cbuf, off, len, false, false, !_isUTF8, _currentWriter);
1008 }
1009 else
1010 {
1011
1012 org.apache.myfaces.shared.renderkit.html.util.HTMLEncoder.encode(
1013 cbuf, off, len, true, true, !_isUTF8, _currentWriter);
1014 }
1015 }
1016
1017 private boolean isScriptOrStyle()
1018 {
1019
1020
1021 return _isStyle || _isInsideScript;
1022 }
1023
1024
1025
1026
1027
1028
1029 private boolean isScript(String element)
1030 {
1031 return (HTML.SCRIPT_ELEM.equalsIgnoreCase(element));
1032 }
1033
1034 private boolean isScript()
1035 {
1036 return _isInsideScript;
1037 }
1038
1039 private boolean isStyle(String element)
1040 {
1041 return (HTML.STYLE_ELEM.equalsIgnoreCase(element));
1042 }
1043
1044 private boolean isStyle()
1045 {
1046 return _isStyle;
1047 }
1048
1049 private boolean isTextarea()
1050 {
1051 initializeStartedTagInfo();
1052
1053 return _isTextArea != null && _isTextArea.booleanValue();
1054 }
1055
1056 private void initializeStartedTagInfo()
1057 {
1058 if(_startElementName != null)
1059 {
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074 if(_isTextArea == null)
1075 {
1076 if(_startElementName.equalsIgnoreCase(HTML.TEXTAREA_ELEM))
1077 {
1078 _isTextArea = Boolean.TRUE;
1079 }
1080 else
1081 {
1082 _isTextArea = Boolean.FALSE;
1083 }
1084 }
1085 }
1086 }
1087
1088 public ResponseWriter cloneWithWriter(Writer writer)
1089 {
1090 HtmlResponseWriterImpl newWriter
1091 = new HtmlResponseWriterImpl(writer, getContentType(), getCharacterEncoding(),
1092 _wrapScriptContentWithXmlCommentTag, _writerContentTypeMode);
1093
1094
1095 return newWriter;
1096 }
1097
1098
1099
1100
1101 public void close() throws IOException
1102 {
1103 closeStartTagIfNecessary();
1104 _currentWriter.close();
1105 _facesContext = null;
1106 }
1107
1108 public void write(char cbuf[], int off, int len) throws IOException
1109 {
1110 closeStartTagIfNecessary();
1111
1112 if (_isUTF8)
1113 {
1114 _currentWriter.write(cbuf, off, len);
1115 }
1116 else
1117 {
1118 UnicodeEncoder.encode(_currentWriter, cbuf, off, len);
1119 }
1120 }
1121
1122 public void write(int c) throws IOException
1123 {
1124 closeStartTagIfNecessary();
1125 _currentWriter.write(c);
1126 }
1127
1128 public void write(char cbuf[]) throws IOException
1129 {
1130 closeStartTagIfNecessary();
1131
1132 if (_isUTF8)
1133 {
1134 _currentWriter.write(cbuf);
1135 }
1136 else
1137 {
1138 UnicodeEncoder.encode(_currentWriter, cbuf, 0, cbuf.length);
1139 }
1140 }
1141
1142 public void write(String str) throws IOException
1143 {
1144 closeStartTagIfNecessary();
1145
1146
1147 if (str != null && str.length() > 0)
1148 {
1149
1150 if (_isUTF8)
1151 {
1152 _currentWriter.write(str);
1153 }
1154 else
1155 {
1156 UnicodeEncoder.encode(_currentWriter, str);
1157 }
1158 }
1159 }
1160
1161 public void write(String str, int off, int len) throws IOException
1162 {
1163 closeStartTagIfNecessary();
1164
1165 if (_isUTF8)
1166 {
1167 _currentWriter.write(str, off, len);
1168 }
1169 else
1170 {
1171 UnicodeEncoder.encode(_currentWriter, str, off, len);
1172 }
1173 }
1174
1175
1176
1177
1178
1179
1180 public void writeText(Object object, UIComponent component, String string) throws IOException
1181 {
1182 writeText(object,string);
1183 }
1184
1185 protected StreamCharBuffer getInternalBuffer()
1186 {
1187 return getInternalBuffer(false);
1188 }
1189
1190 protected StreamCharBuffer getInternalBuffer(boolean reset)
1191 {
1192 if (_buffer == null)
1193 {
1194 _buffer = new StreamCharBuffer(256, 100);
1195 }
1196 else if (reset)
1197 {
1198 _buffer.reset();
1199 }
1200 return _buffer;
1201 }
1202
1203 protected FacesContext getFacesContext()
1204 {
1205 if (_facesContext == null)
1206 {
1207 _facesContext = FacesContext.getCurrentInstance();
1208 }
1209 return _facesContext;
1210 }
1211
1212 protected boolean getWrapScriptContentWithXmlCommentTag()
1213 {
1214 return _wrapScriptContentWithXmlCommentTag;
1215 }
1216
1217 protected void forceFlush() throws IOException
1218 {
1219 _currentWriter.flush();
1220 }
1221 }