1   package org.apache.velocity.test;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.    
20   */
21  
22  import java.io.BufferedWriter;
23  import java.io.FileOutputStream;
24  import java.io.OutputStreamWriter;
25  import java.io.StringWriter;
26  import java.io.Writer;
27  import java.util.ArrayList;
28  import java.util.List;
29  
30  import junit.framework.Test;
31  import junit.framework.TestSuite;
32  
33  import org.apache.velocity.Template;
34  import org.apache.velocity.VelocityContext;
35  import org.apache.velocity.app.VelocityEngine;
36  import org.apache.velocity.app.event.EventCartridge;
37  import org.apache.velocity.app.event.implement.EscapeHtmlReference;
38  import org.apache.velocity.app.event.implement.EscapeJavaScriptReference;
39  import org.apache.velocity.app.event.implement.EscapeReference;
40  import org.apache.velocity.app.event.implement.EscapeSqlReference;
41  import org.apache.velocity.app.event.implement.EscapeXmlReference;
42  import org.apache.velocity.app.event.implement.InvalidReferenceInfo;
43  import org.apache.velocity.app.event.implement.ReportInvalidReferences;
44  import org.apache.velocity.context.Context;
45  import org.apache.velocity.runtime.RuntimeConstants;
46  
47  /**
48   * Tests the operation of the built in event handlers.
49   *
50   * @author <a href="mailto:wglass@forio.com">Will Glass-Husain</a>
51   * @version $Id: BuiltInEventHandlerTestCase.java 463298 2006-10-12 16:10:32Z henning $
52   */
53  public class BuiltInEventHandlerTestCase extends BaseTestCase {
54  
55  
56      /**
57      * VTL file extension.
58      */
59     private static final String TMPL_FILE_EXT = "vm";
60  
61     /**
62      * Comparison file extension.
63      */
64     private static final String CMP_FILE_EXT = "cmp";
65  
66     /**
67      * Comparison file extension.
68      */
69     private static final String RESULT_FILE_EXT = "res";
70  
71     /**
72      * Path for templates. This property will override the
73      * value in the default velocity properties file.
74      */
75     private final static String FILE_RESOURCE_LOADER_PATH = TEST_COMPARE_DIR + "/includeevent";
76  
77     /**
78      * Results relative to the build directory.
79      */
80     private static final String RESULTS_DIR = TEST_RESULT_DIR + "/includeevent";
81  
82     /**
83      * Results relative to the build directory.
84      */
85     private static final String COMPARE_DIR = TEST_COMPARE_DIR + "/includeevent/compare";
86  
87      /**
88       * Default constructor.
89       */
90      public BuiltInEventHandlerTestCase(String name)
91      {
92          super(name);
93      }
94  
95      public void setUp()
96      {
97          assureResultsDirectoryExists(RESULTS_DIR);
98      }
99  
100     public static Test suite()
101     {
102        return new TestSuite(BuiltInEventHandlerTestCase.class);
103     }
104 
105 
106 
107     /**
108      * Test reporting of invalid syntax
109      * @throws Exception
110      */
111     public void testReportInvalidReferences1() throws Exception
112     {
113         VelocityEngine ve = new VelocityEngine();
114         ReportInvalidReferences reporter = new ReportInvalidReferences();
115         ve.init();
116 
117         VelocityContext context = new VelocityContext();
118         EventCartridge ec = new EventCartridge();
119         ec.addEventHandler(reporter);
120         ec.attachToContext(context);
121 
122         context.put("a1","test");
123         context.put("b1","test");
124         Writer writer = new StringWriter();
125 
126         ve.evaluate(context,writer,"test","$a1 $c1 $a1.length() $a1.foobar()");
127 
128         List errors = reporter.getInvalidReferences();
129         assertEquals(2,errors.size());
130         assertEquals("$c1",((InvalidReferenceInfo) errors.get(0)).getInvalidReference());
131         assertEquals("$a1.foobar()",((InvalidReferenceInfo) errors.get(1)).getInvalidReference());
132     }
133 
134     public void testReportInvalidReferences2() throws Exception
135     {
136         VelocityEngine ve = new VelocityEngine();
137         ve.setProperty("eventhandler.invalidreference.exception","true");
138         ReportInvalidReferences reporter = new ReportInvalidReferences();
139         ve.init();
140 
141         VelocityContext context = new VelocityContext();
142         EventCartridge ec = new EventCartridge();
143         ec.addEventHandler(reporter);
144         ec.attachToContext(context);
145 
146         context.put("a1","test");
147         context.put("b1","test");
148         Writer writer = new StringWriter();
149 
150         ve.evaluate(context,writer,"test","$a1 no problem");
151 
152         try {
153             ve.evaluate(context,writer,"test","$a1 $c1 $a1.length() $a1.foobar()");
154             fail ("Expected exception.");
155         } catch (RuntimeException E) {}
156         
157     }
158 
159     /**
160      * Test escaping
161      * @throws Exception
162      */
163     public void testEscapeHtml() throws Exception
164     {
165         EscapeReference esc = new EscapeHtmlReference();
166         assertEquals("test string&amp;another&lt;b&gt;bold&lt;/b&gt;test",esc.referenceInsert("","test string&another<b>bold</b>test"));
167         assertEquals("&lt;&quot;&gt;",esc.referenceInsert("","<\">"));
168         assertEquals("test string",esc.referenceInsert("","test string"));
169     }
170 
171     /**
172      * Test escaping
173      * @throws Exception
174      */
175     public void testEscapeXml() throws Exception
176     {
177         EscapeReference esc = new EscapeXmlReference();
178         assertEquals("test string&amp;another&lt;b&gt;bold&lt;/b&gt;test",esc.referenceInsert("","test string&another<b>bold</b>test"));
179         assertEquals("&lt;&quot;&gt;",esc.referenceInsert("","<\">"));
180         assertEquals("&apos;",esc.referenceInsert("","'"));
181         assertEquals("test string",esc.referenceInsert("","test string"));
182     }
183 
184     /**
185      * Test escaping
186      * @throws Exception
187      */
188     public void testEscapeSql() throws Exception
189     {
190         EscapeReference esc = new EscapeSqlReference();
191         assertEquals("Jimmy''s Pizza",esc.referenceInsert("","Jimmy's Pizza"));
192         assertEquals("test string",esc.referenceInsert("","test string"));
193     }
194 
195     /**
196      * Test escaping
197      * @throws Exception
198      */
199     public void testEscapeJavaScript() throws Exception
200     {
201         EscapeReference esc = new EscapeJavaScriptReference();
202         assertEquals("Jimmy\\'s Pizza",esc.referenceInsert("","Jimmy's Pizza"));
203         assertEquals("test string",esc.referenceInsert("","test string"));
204     }
205 
206     /**
207      * test that escape reference handler works with no match restrictions
208      * @throws Exception
209      */
210     public void testEscapeReferenceMatchAll() throws Exception
211     {
212         VelocityEngine ve = new VelocityEngine();
213         ve.setProperty(RuntimeConstants.EVENTHANDLER_REFERENCEINSERTION, "org.apache.velocity.app.event.implement.EscapeHtmlReference");
214         ve.init();
215 
216         Context context;
217         Writer writer;
218 
219         // test normal reference
220         context = new VelocityContext();
221         writer = new StringWriter();
222         context.put("bold","<b>");
223         ve.evaluate(context,writer,"test","$bold test & test");
224         assertEquals("&lt;b&gt; test & test",writer.toString());
225 
226         // test method reference
227         context = new VelocityContext();
228         writer = new StringWriter();
229         context.put("bold","<b>");
230         ve.evaluate(context,writer,"test","$bold.substring(0,1)");
231         assertEquals("&lt;",writer.toString());
232     }
233 
234     /**
235      * test that escape reference handler works with match restrictions
236      * @throws Exception
237      */
238     public void testEscapeReferenceMatch() throws Exception
239     {
240         // set up HTML match on everything, JavaScript match on _js*
241         VelocityEngine ve = new VelocityEngine();
242         ve.setProperty(RuntimeConstants.EVENTHANDLER_REFERENCEINSERTION, "org.apache.velocity.app.event.implement.EscapeHtmlReference,org.apache.velocity.app.event.implement.EscapeJavaScriptReference");
243         ve.setProperty("eventhandler.escape.javascript.match", "/.*_js.*/");
244         ve.init();
245 
246         Writer writer;
247 
248         // Html no JavaScript
249         writer = new StringWriter();
250         ve.evaluate(newEscapeContext(),writer,"test","$test1");
251         assertEquals("Jimmy's &lt;b&gt;pizza&lt;/b&gt;",writer.toString());
252 
253         // JavaScript and HTML
254         writer = new StringWriter();
255         ve.evaluate(newEscapeContext(),writer,"test","$test1_js");
256         assertEquals("Jimmy\\'s &lt;b&gt;pizza&lt;/b&gt;",writer.toString());
257 
258         // JavaScript and HTML
259         writer = new StringWriter();
260         ve.evaluate(newEscapeContext(),writer,"test","$test1_js_test");
261         assertEquals("Jimmy\\'s &lt;b&gt;pizza&lt;/b&gt;",writer.toString());
262 
263         // JavaScript and HTML (method call)
264         writer = new StringWriter();
265         ve.evaluate(newEscapeContext(),writer,"test","$test1_js.substring(0,7)");
266         assertEquals("Jimmy\\'s",writer.toString());
267     }
268 
269     private Context newEscapeContext()
270     {
271         Context context = new VelocityContext();
272         context.put("test1","Jimmy's <b>pizza</b>");
273         context.put("test1_js","Jimmy's <b>pizza</b>");
274         context.put("test1_js_test","Jimmy's <b>pizza</b>");
275         return context;
276     }
277 
278     public void testPrintExceptionHandler() throws Exception
279     {
280         VelocityEngine ve1 = new VelocityEngine();
281         ve1.setProperty(RuntimeConstants.EVENTHANDLER_METHODEXCEPTION, "org.apache.velocity.app.event.implement.PrintExceptions");
282         ve1.init();
283 
284         VelocityEngine ve2 = new VelocityEngine();
285         ve2.setProperty(RuntimeConstants.EVENTHANDLER_METHODEXCEPTION, "org.apache.velocity.app.event.implement.PrintExceptions");
286         ve2.setProperty("eventhandler.methodexception.message","true");
287         ve2.init();
288 
289         VelocityEngine ve3 = new VelocityEngine();
290         ve3.setProperty(RuntimeConstants.EVENTHANDLER_METHODEXCEPTION, "org.apache.velocity.app.event.implement.PrintExceptions");
291         ve3.setProperty("eventhandler.methodexception.stacktrace","true");
292         ve3.init();
293 
294         Context context;
295         StringWriter writer;
296 
297         context = new VelocityContext();
298         context.put("list",new ArrayList());
299 
300         // exception only
301         writer = new StringWriter();
302         ve1.evaluate(context,writer,"test","$list.get(0)");
303         assertTrue(writer.toString().indexOf("IndexOutOfBoundsException") != -1);
304         assertTrue(writer.toString().indexOf("Index: 0, Size: 0") == -1);
305         assertTrue(writer.toString().indexOf("ArrayList") == -1);
306 
307         // message
308         writer = new StringWriter();
309         ve2.evaluate(context,writer,"test","$list.get(0)");
310         assertTrue(writer.toString().indexOf("IndexOutOfBoundsException") != -1);
311         assertTrue(writer.toString().indexOf("Index: 0, Size: 0") != -1);
312         assertTrue(writer.toString().indexOf("ArrayList") == -1);
313 
314         // stack trace
315         writer = new StringWriter();
316         ve3.evaluate(context,writer,"test","$list.get(0)");
317         assertTrue(writer.toString().indexOf("IndexOutOfBoundsException") != -1);
318         assertTrue(writer.toString().indexOf("ArrayList") != -1);
319     }
320 
321     public void testIncludeNotFound() throws Exception
322     {
323         VelocityEngine ve = new VelocityEngine();
324         ve.setProperty(RuntimeConstants.EVENTHANDLER_INCLUDE, "org.apache.velocity.app.event.implement.IncludeNotFound");
325         ve.addProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, FILE_RESOURCE_LOADER_PATH);
326         ve.init();
327 
328         Template template;
329         FileOutputStream fos;
330         Writer fwriter;
331         Context context;
332 
333         template = ve.getTemplate( getFileName(null, "test6", TMPL_FILE_EXT) );
334 
335         fos = new FileOutputStream (
336                 getFileName(RESULTS_DIR, "test6", RESULT_FILE_EXT));
337 
338         fwriter = new BufferedWriter( new OutputStreamWriter(fos) );
339 
340         context = new VelocityContext();
341         template.merge(context, fwriter);
342         fwriter.flush();
343         fwriter.close();
344 
345         if (!isMatch(RESULTS_DIR, COMPARE_DIR, "test6", RESULT_FILE_EXT, CMP_FILE_EXT))
346         {
347             fail("Output incorrect.");
348         }
349     }
350 
351     public void testIncludeRelativePath() throws Exception
352     {
353         VelocityEngine ve = new VelocityEngine();
354         ve.setProperty(RuntimeConstants.EVENTHANDLER_INCLUDE, "org.apache.velocity.app.event.implement.IncludeRelativePath");
355         ve.addProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, FILE_RESOURCE_LOADER_PATH);
356         ve.init();
357 
358         Template template;
359         FileOutputStream fos;
360         Writer fwriter;
361         Context context;
362 
363         template = ve.getTemplate( getFileName(null, "subdir/test2", TMPL_FILE_EXT) );
364 
365         fos = new FileOutputStream (
366                 getFileName(RESULTS_DIR, "test2", RESULT_FILE_EXT));
367 
368         fwriter = new BufferedWriter( new OutputStreamWriter(fos) );
369 
370         context = new VelocityContext();
371         template.merge(context, fwriter);
372         fwriter.flush();
373         fwriter.close();
374 
375         if (!isMatch(RESULTS_DIR, COMPARE_DIR, "test2", RESULT_FILE_EXT, CMP_FILE_EXT))
376         {
377             fail("Output incorrect.");
378         }
379     }
380 }