View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.shared.renderkit.html;
20  
21  import java.io.IOException;
22  import java.io.StringWriter;
23  import java.lang.reflect.Field;
24  
25  import org.apache.myfaces.shared.util.CommentUtils;
26  import org.apache.myfaces.test.base.AbstractJsfTestCase;
27  
28  /**
29   * Test class for HtmlResponseWriterImpl.
30   */
31  public class HtmlResponseWriterImplTest extends AbstractJsfTestCase
32  {
33      
34      private static final String COMMENT_START = "<!--";
35      private static final String COMMENT_END = "//-->";
36  
37      private StringWriter _stringWriter;
38      private HtmlResponseWriterImpl _writer;
39      
40      public HtmlResponseWriterImplTest(String name)
41      {
42          super(name);
43      }
44  
45      @Override
46      protected void setUp() throws Exception
47      {
48          super.setUp();
49          
50          _stringWriter = new StringWriter();
51          _writer = new HtmlResponseWriterImpl(_stringWriter, "text/html", "ISO-8859-1");
52      }
53  
54      @Override
55      protected void tearDown() throws Exception
56      {
57          _writer = null;
58          _stringWriter = null;
59          
60          super.tearDown();
61      }
62      
63      /**
64       * This test tests if it is possible to render HTML elements inside
65       * a script section without confusing the HtmlResponseWriterImpl.
66       * The related issue to this test is MYFACES-2668.
67       * 
68       * @throws IOException
69       * @throws NoSuchFieldException 
70       * @throws SecurityException 
71       * @throws IllegalAccessException 
72       * @throws IllegalArgumentException 
73       */
74      public void testHtmlElementsInsideScript() throws IOException, SecurityException, 
75              NoSuchFieldException, IllegalArgumentException, IllegalAccessException
76      {
77          // use reflection to get the field _isInsideScript to verify
78          // the internal behavior of HtmlResponseWriterImpl
79          Field insideScriptField = _writer.getClass().getDeclaredField("_isInsideScript");
80          insideScriptField.setAccessible(true);
81          
82          _writer.startDocument();
83          _writer.startElement("head", null);
84          
85          assertFalse("We have not entered a script element yet, so _isInsideScript should be " +
86                  "false (or null).", getFieldBooleanValue(insideScriptField, _writer, false));
87          
88          _writer.startElement("script", null);
89          
90          assertTrue("We have now entered a script element, so _isInsideScript should be " +
91                  "true.", getFieldBooleanValue(insideScriptField, _writer, false));
92          
93          _writer.startElement("table", null);
94          _writer.startElement("tr", null);
95          _writer.startElement("td", null);
96          
97          assertTrue("We have now opened various elements inside a script element, "+
98                  "but _isInsideScript should still be true.",
99                  getFieldBooleanValue(insideScriptField, _writer, false));
100         
101         _writer.write("column value");
102         
103         assertTrue("We have now written some text inside a script element, "+
104                 "but _isInsideScript should still be true.",
105                 getFieldBooleanValue(insideScriptField, _writer, false));
106         
107         _writer.endElement("td");
108         _writer.endElement("tr");
109         _writer.endElement("table");
110         _writer.endElement("script");
111         
112         assertFalse("We have now closed the script element, so _isInsideScript should be " +
113                 "false (or null).", getFieldBooleanValue(insideScriptField, _writer, false));
114         
115         _writer.endElement("head");
116         _writer.endDocument();
117         
118         String output = _stringWriter.toString();
119         assertTrue("A script start was rendered, so the output has to " +
120                 "contain " + COMMENT_START, output.contains(COMMENT_START));
121         assertTrue("A script end was rendered so the output has to " + 
122                 "contain " + COMMENT_END, output.contains(COMMENT_END));
123     }
124     
125     /**
126      * Utility method to get the value of the given Field, which is of
127      * type java.lang.Boolean. If it is null, the given defaulValue will
128      * be returned.
129      * 
130      * @param field
131      * @param instance
132      * @param defaultValue
133      * @return
134      * @throws IllegalArgumentException
135      * @throws IllegalAccessException
136      */
137     private boolean getFieldBooleanValue(Field field, Object instance, boolean defaultValue) 
138             throws IllegalArgumentException, IllegalAccessException
139     {
140         Boolean b = (Boolean) field.get(instance);
141         return b == null ? defaultValue : b;
142     }
143 
144     public void testScriptOnHtmlIsoEncodingAndScriptXhmlComments() throws IOException
145     {
146         _writer = new HtmlResponseWriterImpl(_stringWriter, "text/html", "ISO-8859-1", true);
147         String innerScript = "document.write('HELLO');"; 
148         _writer.startDocument();
149         _writer.startElement(HTML.SCRIPT_ELEM, null);
150         _writer.write(innerScript);
151         _writer.endElement(HTML.SCRIPT_ELEM);
152         _writer.endDocument();
153         
154         String output = _stringWriter.toString();
155         assertNotNull(output);
156         assertTrue("script does not contain body:" + innerScript, output.contains(innerScript));
157         assertTrue("script does not have start comment <!-- ", output.contains(CommentUtils.COMMENT_SIMPLE_START));
158         assertTrue("script does not have end comment --> ", output.contains("//"+CommentUtils.COMMENT_SIMPLE_END));
159     }
160     
161     public void testScriptOnHtmlIsoEncodingAndNoScriptXhmlComments() throws IOException
162     {
163         _writer = new HtmlResponseWriterImpl(_stringWriter, "text/html", "ISO-8859-1", false);
164         String innerScript = "document.write('HELLO');"; 
165         _writer.startDocument();
166         _writer.startElement(HTML.SCRIPT_ELEM, null);
167         _writer.write(innerScript);
168         _writer.endElement(HTML.SCRIPT_ELEM);
169         _writer.endDocument();
170         
171         String output = _stringWriter.toString();
172         assertNotNull(output);
173         assertTrue("script does not contain body:" + innerScript, output.contains(innerScript));
174         assertFalse("script have start comment <!-- ", output.contains(CommentUtils.COMMENT_SIMPLE_START));
175         assertFalse("script have end comment --> ", output.contains("//"+CommentUtils.COMMENT_SIMPLE_END));
176     }
177 
178     public void testScriptOnHtmlUTF8AndScriptXhmlComments() throws IOException
179     {
180         _writer = new HtmlResponseWriterImpl(_stringWriter, "text/html", "UTF-8", true);
181         String innerScript = "document.write('HELLO');"; 
182         _writer.startDocument();
183         _writer.startElement(HTML.SCRIPT_ELEM, null);
184         _writer.write(innerScript);
185         _writer.endElement(HTML.SCRIPT_ELEM);
186         _writer.endDocument();
187         
188         String output = _stringWriter.toString();
189         assertNotNull(output);
190         assertTrue("script does not contain body:" + innerScript, output.contains(innerScript));
191         assertTrue("script does not have start comment <!-- ", output.contains(CommentUtils.COMMENT_SIMPLE_START));
192         assertTrue("script does not have end comment --> ", output.contains("//"+CommentUtils.COMMENT_SIMPLE_END));
193     }
194     
195     public void testScriptOnHtmlUTF8AndNoScriptXhmlComments() throws IOException
196     {
197         _writer = new HtmlResponseWriterImpl(_stringWriter, "text/html", "UTF-8", false);
198         String innerScript = "document.write('HELLO');"; 
199         _writer.startDocument();
200         _writer.startElement(HTML.SCRIPT_ELEM, null);
201         _writer.write(innerScript);
202         _writer.endElement(HTML.SCRIPT_ELEM);
203         _writer.endDocument();
204         
205         String output = _stringWriter.toString();
206         assertNotNull(output);
207         assertTrue("script does not contain body:" + innerScript, output.contains(innerScript));
208         assertFalse("script have start comment <!-- ", output.contains(CommentUtils.COMMENT_SIMPLE_START));
209         assertFalse("script have end comment --> ", output.contains("//"+CommentUtils.COMMENT_SIMPLE_END));
210     }
211 
212     public void testScriptOnXhtmlIsoEncoding() throws IOException
213     {
214         _writer = new HtmlResponseWriterImpl(_stringWriter, "application/xhtml+xml", "ISO-8859-1", true);
215         String innerScript = "document.write('HELLO');"; 
216         _writer.startDocument();
217         _writer.startElement(HTML.SCRIPT_ELEM, null);
218         _writer.write(innerScript);
219         _writer.endElement(HTML.SCRIPT_ELEM);
220         _writer.endDocument();
221         
222         String output = _stringWriter.toString();
223         assertNotNull(output);
224         assertTrue("script does not contain body:" + innerScript, output.contains(innerScript));
225         assertTrue("script does not have start <![CDATA[ ", output.contains(CommentUtils.INLINE_SCRIPT_COMMENT+CommentUtils.CDATA_SIMPLE_START));
226         assertTrue("script does not have end ]]> ", output.contains(CommentUtils.INLINE_SCRIPT_COMMENT+CommentUtils.CDATA_SIMPLE_END));
227     }
228 
229     public void testScriptOnXhtmlUTF8Encoding() throws IOException
230     {
231         _writer = new HtmlResponseWriterImpl(_stringWriter, "application/xhtml+xml", "UTF-8", false);
232         String innerScript = "document.write('HELLO');"; 
233         _writer.startDocument();
234         _writer.startElement(HTML.SCRIPT_ELEM, null);
235         _writer.write(innerScript);
236         _writer.endElement(HTML.SCRIPT_ELEM);
237         _writer.endDocument();
238         
239         String output = _stringWriter.toString();
240         assertNotNull(output);
241         assertTrue("script does not contain body:" + innerScript, output.contains(innerScript));
242         assertTrue("script does not have start <![CDATA[ ", output.contains(CommentUtils.INLINE_SCRIPT_COMMENT+CommentUtils.CDATA_SIMPLE_START));
243         assertTrue("script does not have end ]]> ", output.contains(CommentUtils.INLINE_SCRIPT_COMMENT+CommentUtils.CDATA_SIMPLE_END));
244     }
245     
246     public void testStyleOnXhtmlIsoEncoding() throws IOException
247     {
248         _writer = new HtmlResponseWriterImpl(_stringWriter, "application/xhtml+xml", "ISO-8859-1", true);
249         String innerScript = "document.write('HELLO');"; 
250         _writer.startDocument();
251         _writer.startElement(HTML.STYLE_ELEM, null);
252         _writer.write(innerScript);
253         _writer.endElement(HTML.STYLE_ELEM);
254         _writer.endDocument();
255         
256         String output = _stringWriter.toString();
257         assertNotNull(output);
258         assertTrue("script does not contain body:" + innerScript, output.contains(innerScript));
259         assertTrue("script does not have start <![CDATA[ ", output.contains(CommentUtils.CDATA_SIMPLE_START));
260         assertTrue("script does not have end ]]> ", output.contains(CommentUtils.CDATA_SIMPLE_END));
261     }
262 
263     public void testStyleOnXhtmlUTF8Encoding() throws IOException
264     {
265         _writer = new HtmlResponseWriterImpl(_stringWriter, "application/xhtml+xml", "UTF-8", false);
266         String innerScript = "document.write('HELLO');"; 
267         _writer.startDocument();
268         _writer.startElement(HTML.STYLE_ELEM, null);
269         _writer.write(innerScript);
270         _writer.endElement(HTML.STYLE_ELEM);
271         _writer.endDocument();
272         
273         String output = _stringWriter.toString();
274         assertNotNull(output);
275         assertTrue("script does not contain body:" + innerScript, output.contains(innerScript));
276         assertTrue("script does not have start <![CDATA[ ", output.contains(CommentUtils.CDATA_SIMPLE_START));
277         assertTrue("script does not have end ]]> ", output.contains(CommentUtils.CDATA_SIMPLE_END));
278     }
279     
280     /**
281      * In html, it is not valid to have an empty tag with content
282      * 
283      * @throws IOException
284      */
285     public void testEmptyTagNotRenderEnd() throws IOException
286     {
287         _writer.startDocument();
288         _writer.startElement("body", null);
289         _writer.startElement("br", null);
290         _writer.writeText("hello", null);
291         _writer.endElement("br");
292         _writer.endElement("body");
293         _writer.endDocument();
294        
295         // the following should render <br />hello
296         String output = _stringWriter.toString();
297         assertNotNull(output);
298         assertTrue(output.contains("<br />"));
299         assertFalse(output.contains("</br>"));
300     }
301     
302     /**
303      * In xhtml, it is valid to have an html empty tag with content.
304      * 
305      * @throws IOException
306      */
307     public void testEmptyTagNotRenderEndOnXml() throws IOException
308     {
309         _writer = new HtmlResponseWriterImpl(_stringWriter, "application/xml", "UTF-8", false);
310         
311         _writer.startDocument();
312         _writer.startElement("body", null);
313         _writer.startElement("br", null);
314         _writer.writeText("hello", null);
315         _writer.endElement("br");
316         _writer.endElement("body");
317         _writer.endDocument();
318         
319      // the following should render <br>hello</br>
320         String output = _stringWriter.toString();
321         assertNotNull(output);
322         assertTrue(output.contains("<br>"));
323         assertTrue(output.contains("</br>"));
324     }
325     
326     /**
327      * In html, it is not valid to have an empty tag with content
328      * 
329      * @throws IOException
330      */
331     public void testEmptyTagNotRenderEndUppercase() throws IOException
332     {
333         _writer.startDocument();
334         _writer.startElement("body", null);
335         _writer.startElement("BR", null);
336         _writer.writeText("hello", null);
337         _writer.endElement("BR");
338         _writer.endElement("body");
339         _writer.endDocument();
340        
341         // the following should render <br />hello
342         String output = _stringWriter.toString();
343         assertNotNull(output);
344         assertTrue(output.contains("<BR />"));
345         assertFalse(output.contains("</BR>"));
346     }
347     
348     /**
349      * In xhtml, it is valid to have an html empty tag with content.
350      * 
351      * @throws IOException
352      */
353     public void testEmptyTagNotRenderEndOnXhtmlUppercase() throws IOException
354     {
355         _writer = new HtmlResponseWriterImpl(_stringWriter, "application/xml", "UTF-8", false);
356         
357         _writer.startDocument();
358         _writer.startElement("body", null);
359         _writer.startElement("BR", null);
360         _writer.writeText("hello", null);
361         _writer.endElement("BR");
362         _writer.endElement("body");
363         _writer.endDocument();
364         
365      // the following should render <br>hello</br>
366         String output = _stringWriter.toString();
367         assertNotNull(output);
368         assertTrue(output.contains("<BR>"));
369         assertTrue(output.contains("</BR>"));
370     }
371 }