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