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.StringWriter;
23  import java.io.Writer;
24  
25  import junit.framework.Test;
26  import junit.framework.TestCase;
27  import junit.framework.TestSuite;
28  
29  import org.apache.velocity.VelocityContext;
30  import org.apache.velocity.app.VelocityEngine;
31  import org.apache.velocity.app.event.EventCartridge;
32  import org.apache.velocity.app.event.InvalidReferenceEventHandler;
33  import org.apache.velocity.context.Context;
34  import org.apache.velocity.runtime.RuntimeConstants;
35  import org.apache.velocity.runtime.RuntimeServices;
36  import org.apache.velocity.util.RuntimeServicesAware;
37  import org.apache.velocity.util.introspection.Info;
38  
39  /**
40   * Tests event handling for all event handlers except IncludeEventHandler.  This is tested
41   * separately due to its complexity.
42   *
43   * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
44   * @version $Id: InvalidEventHandlerTestCase.java 463298 2006-10-12 16:10:32Z henning $
45   */
46  public class InvalidEventHandlerTestCase
47  extends TestCase
48  {
49      /**
50       * Default constructor.
51       */
52      public InvalidEventHandlerTestCase(String name)
53      {
54          super(name);
55      }
56      
57      public static Test suite ()
58      {
59          return new TestSuite(InvalidEventHandlerTestCase.class);
60      }
61      
62      public void testManualEventHandlers()
63      throws Exception
64      {
65          TestEventCartridge te = new TestEventCartridge();
66          
67          /**
68           * Test attaching the event cartridge to the context
69           */
70          VelocityEngine ve = new VelocityEngine();
71          ve.init();
72          
73          /*
74           *  lets make a Context and add the event cartridge
75           */
76          
77          VelocityContext inner = new VelocityContext();
78          
79          /*
80           *  Now make an event cartridge, register all the
81           *  event handlers (at once) and attach it to the
82           *  Context
83           */
84          
85          EventCartridge ec = new EventCartridge();
86          ec.addEventHandler(te);
87          ec.attachToContext( inner );
88          
89          doTestInvalidReferenceEventHandler1(ve, inner);
90          doTestInvalidReferenceEventHandler2(ve, inner);
91          doTestInvalidReferenceEventHandler3(ve, inner);
92          doTestInvalidReferenceEventHandler4(ve, inner);
93      }
94  
95      /**
96       * Test assigning the event handlers via properties
97       */
98  
99      public void testConfigurationEventHandlers()
100             throws Exception
101     {
102         VelocityEngine ve = new VelocityEngine();
103         ve.setProperty(RuntimeConstants.EVENTHANDLER_INVALIDREFERENCES, TestEventCartridge.class.getName());
104 
105         ve.init();
106         doTestInvalidReferenceEventHandler1(ve, null);
107         doTestInvalidReferenceEventHandler2(ve, null);
108         doTestInvalidReferenceEventHandler3(ve, null);
109         doTestInvalidReferenceEventHandler4(ve, null);
110     }
111 
112     /**
113      * Test deeper structures
114      * @param ve
115      * @param vc
116      * @throws Exception
117      */
118     private void doTestInvalidReferenceEventHandler4(VelocityEngine ve, VelocityContext vc)
119     throws Exception
120     {
121         VelocityContext context = new VelocityContext(vc);
122 
123         Tree test = new Tree();
124         test.setField("10");
125         Tree test2 = new Tree();
126         test2.setField("12");
127         test.setChild(test2);
128         
129         context.put("tree",test);
130         String s;
131         Writer w;
132         
133         // show work fine
134         s = "$tree.Field $tree.field $tree.child.Field";
135         w = new StringWriter();
136         ve.evaluate( context, w, "mystring", s );
137         
138         s = "$tree.x $tree.field.x $tree.child.y $tree.child.Field.y";
139         w = new StringWriter();
140         ve.evaluate( context, w, "mystring", s );
141         
142     }
143     
144     /**
145      * Test invalid #set
146      * @param ve
147      * @param vc
148      * @throws Exception
149      */
150     private void doTestInvalidReferenceEventHandler3(VelocityEngine ve, VelocityContext vc)
151     throws Exception
152     {
153         VelocityContext context = new VelocityContext(vc);
154         context.put("a1",new Integer(5));
155         context.put("a4",new Integer(5));
156         context.put("b1","abc");
157         
158         String s;
159         Writer w;
160         
161         // good object, bad right hand side
162         s = "#set($xx = $a1.afternoon())";
163         w = new StringWriter();
164         try {
165             ve.evaluate( context, w, "mystring", s );
166             fail("Expected exception.");
167         } catch (RuntimeException e) {}
168         
169         // good object, bad right hand reference
170         s = "#set($yy = $q1)";
171         w = new StringWriter();
172         try {
173             ve.evaluate( context, w, "mystring", s );
174             fail("Expected exception.");
175         } catch (RuntimeException e) {}
176         
177     }
178 
179     /**
180      * Test invalid method calls
181      * @param ve
182      * @param vc
183      * @throws Exception
184      */
185     private void doTestInvalidReferenceEventHandler2(VelocityEngine ve, VelocityContext vc)
186     throws Exception
187     {
188         VelocityContext context = new VelocityContext(vc);
189         context.put("a1",new Integer(5));
190         context.put("a4",new Integer(5));
191         context.put("b1","abc");
192         
193         String s;
194         Writer w;
195         
196         // good object, bad method
197         s = "$a1.afternoon()";
198         w = new StringWriter();
199         try {
200             ve.evaluate( context, w, "mystring", s );
201             fail("Expected exception.");
202         } catch (RuntimeException e) {}
203         
204         // bad object, bad method -- fails on get
205         s = "$zz.daylight()";
206         w = new StringWriter();
207         try {
208             ve.evaluate( context, w, "mystring", s );
209             fail("Expected exception.");
210         } catch (RuntimeException e) {}
211 
212         // change result
213         s = "$b1.baby()";
214         w = new StringWriter();
215         ve.evaluate( context, w, "mystring", s );
216         assertEquals("www",w.toString());        
217     }
218     
219     /**
220      * Test invalid gets/references
221      * @param ve
222      * @param vc
223      * @throws Exception
224      */
225     private void doTestInvalidReferenceEventHandler1(VelocityEngine ve, VelocityContext vc)
226     throws Exception
227     {
228         String result;
229         
230         VelocityContext context = new VelocityContext(vc);
231         context.put("a1",new Integer(5));
232         context.put("a4",new Integer(5));
233         context.put("b1","abc");
234         
235         // normal - should be no calls to handler
236         String s = "$a1 $a1.intValue() $b1 $b1.length() #set($c1 = '5')";
237         Writer w = new StringWriter();
238         ve.evaluate( context, w, "mystring", s );
239         
240         // good object, bad property
241         s = "$a1.foobar";
242         w = new StringWriter();
243         try {
244             ve.evaluate( context, w, "mystring", s );
245             fail("Expected exception.");
246         } catch (RuntimeException e) {}
247         
248         // bad object, bad property            
249         s = "$a2.foobar";
250         w = new StringWriter();
251         try {
252             ve.evaluate( context, w, "mystring", s );
253             fail("Expected exception.");
254         } catch (RuntimeException e) {}
255         
256         // bad object, no property            
257         s = "$a3";
258         w = new StringWriter();
259         try {
260             ve.evaluate( context, w, "mystring", s );
261             fail("Expected exception.");
262         } catch (RuntimeException e) {}
263         
264         // good object, bad property; change the value
265         s = "$a4.foobar";
266         w = new StringWriter();
267         ve.evaluate( context, w, "mystring", s );
268         result = w.toString();
269         assertEquals("zzz", result);
270         
271     }
272     
273     
274 
275     /**
276      * Test assigning the event handlers via properties
277      */
278     
279     public static class TestEventCartridge
280     implements InvalidReferenceEventHandler,
281     RuntimeServicesAware
282     {
283         private RuntimeServices rs;
284         
285         public TestEventCartridge()
286         {
287         }
288         
289         /**
290          * Required by EventHandler
291          */
292         public void setRuntimeServices( RuntimeServices rs )
293         {
294             // make sure this is only called once
295             if (this.rs == null)
296                 this.rs = rs;
297             
298             else
299                 fail("initialize called more than once.");
300         }
301         
302         
303         public Object invalidGetMethod(Context context, String reference, Object object, String property, Info info)
304         {
305             // as a test, make sure this EventHandler is initialized
306             if (rs == null)
307                 fail ("Event handler not initialized!");
308             
309             // good object, bad property
310             if (reference.equals("$a1.foobar"))
311             {
312                 assertEquals(new Integer(5),object);
313                 assertEquals("foobar",property);
314                 throw new RuntimeException("expected exception");
315             }
316             
317             // bad object, bad property            
318             else if (reference.equals("$a2"))
319             {
320                 assertNull(object);
321                 assertNull(property);
322                 throw new RuntimeException("expected exception");
323             }
324             
325             // bad object, no property            
326             else if (reference.equals("$a3"))
327             {
328                 assertNull(object);
329                 assertNull(property);
330                 throw new RuntimeException("expected exception");
331             }
332             
333             // good object, bad property; change the value
334             else if (reference.equals("$a4.foobar"))
335             {
336                 assertEquals(new Integer(5),object);
337                 assertEquals("foobar",property);
338                 return "zzz";
339             }
340 
341             // bad object, bad method -- fail on the object
342             else if (reference.equals("$zz"))
343             {
344                 assertNull(object);
345                 assertNull(property);
346                 throw new RuntimeException("expected exception");
347             }
348 
349             // pass q1 through
350             else if (reference.equals("$q1"))
351             {
352 
353             }
354 
355             
356             else if (reference.equals("$tree.x"))
357             {
358                 assertEquals("x",property);
359             }
360 
361             else if (reference.equals("$tree.field.x"))
362             {
363                 assertEquals("x",property);
364             }
365 
366             else if (reference.equals("$tree.child.y"))
367             {
368                 assertEquals("y",property);
369             }
370             
371             else if (reference.equals("$tree.child.Field.y"))
372             {
373                 assertEquals("y",property);
374             }
375             
376             else
377             {
378                 fail("invalidGetMethod: unexpected reference: " + reference);
379             }
380             return null;
381         }
382         
383         public Object invalidMethod(Context context, String reference, Object object, String method, Info info)
384         {
385             // as a test, make sure this EventHandler is initialized
386             if (rs == null)
387                 fail ("Event handler not initialized!");
388 
389             // good reference, bad method
390             if (object.getClass().equals(Integer.class))
391             {
392                 assertEquals("$a1.afternoon()",reference);
393                 assertEquals("afternoon",method);
394                 throw new RuntimeException("expected exception");
395             }
396 
397             else if (object.getClass().equals(String.class) && "baby".equals(method))
398             {
399                 return "www";
400             }
401 
402             else
403             { 
404                 fail("Unexpected invalid method.  " + method);
405             }
406 
407             return null;
408         }        
409     
410 
411         public boolean invalidSetMethod(Context context, String leftreference, String rightreference, Info info)
412         {
413 
414             // as a test, make sure this EventHandler is initialized
415             if (rs == null)
416                 fail ("Event handler not initialized!");
417 
418             // good object, bad method
419             if (leftreference.equals("xx"))
420             {
421                 assertEquals("q1.afternoon()",rightreference);
422                 throw new RuntimeException("expected exception");
423             }
424             if (leftreference.equals("yy"))
425             {
426                 assertEquals("$q1",rightreference);
427                 throw new RuntimeException("expected exception");
428             }
429             else
430             { 
431                 fail("Unexpected left hand side.  " + leftreference);
432             }
433             
434             return false;
435         }
436 
437     }
438 
439     public static class Tree
440     {
441         String field;
442         Tree child;
443         
444         public Tree()
445         {
446             
447         }
448 
449         public String getField()
450         {
451             return field;
452         }
453 
454         public void setField(String field)
455         {
456             this.field = field;
457         }
458 
459         public Tree getChild()
460         {
461             return child;
462         }
463 
464         public void setChild(Tree child)
465         {
466             this.child = child;
467         }
468 
469         public String testMethod() 
470         {
471             return "123";
472         }
473     }
474     
475 }