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 832302 2009-11-03 05:32:31Z wglass $
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("b1",new Integer(5));
191         context.put("a4",new Integer(5));
192         context.put("b4",new Integer(5));
193         context.put("z1","abc");
194         
195         String s;
196         Writer w;
197         
198         // good object, bad method
199         s = "$a1.afternoon()";
200         w = new StringWriter();
201         try {
202             ve.evaluate( context, w, "mystring", s );
203             fail("Expected exception.");
204         } catch (RuntimeException e) {}
205         
206         // good object, bad method
207         s = "$!b1.afternoon()";
208         w = new StringWriter();
209         try {
210             ve.evaluate( context, w, "mystring", s );
211             fail("Expected exception.");
212         } catch (RuntimeException e) {}
213         
214         // bad object, bad method -- fails on get
215         s = "$zz.daylight()";
216         w = new StringWriter();
217         try {
218             ve.evaluate( context, w, "mystring", s );
219             fail("Expected exception.");
220         } catch (RuntimeException e) {}
221 
222         // change result
223         s = "$z1.baby()";
224         w = new StringWriter();
225         ve.evaluate( context, w, "mystring", s );
226         assertEquals("www",w.toString());        
227     }
228     
229     /**
230      * Test invalid gets/references
231      * @param ve
232      * @param vc
233      * @throws Exception
234      */
235     private void doTestInvalidReferenceEventHandler1(VelocityEngine ve, VelocityContext vc)
236     throws Exception
237     {
238         String result;
239         
240         VelocityContext context = new VelocityContext(vc);
241         context.put("a1",new Integer(5));
242         context.put("b1",new Integer(5));
243         context.put("a4",new Integer(5));
244         context.put("b4",new Integer(5));
245         context.put("z1","abc");
246         
247         // normal - should be no calls to handler
248         String s = "$a1 $a1.intValue() $z1 $z1.length() #set($c1 = '5')";
249         Writer w = new StringWriter();
250         ve.evaluate( context, w, "mystring", s );
251         
252         // good object, bad property
253         s = "$a1.foobar";
254         w = new StringWriter();
255         try {
256             ve.evaluate( context, w, "mystring", s );
257             fail("Expected exception.");
258         } catch (RuntimeException e) {}
259         
260         // good object, bad property / silent
261         s = "$!b1.foobar";
262         w = new StringWriter();
263         try {
264             ve.evaluate( context, w, "mystring", s );
265             fail("Expected exception.");
266         } catch (RuntimeException e) {}
267         
268         // bad object, bad property            
269         s = "$a2.foobar";
270         w = new StringWriter();
271         try {
272             ve.evaluate( context, w, "mystring", s );
273             fail("Expected exception.");
274         } catch (RuntimeException e) {}
275         
276         // bad object, bad property / silent            
277         s = "$!b2.foobar";
278         w = new StringWriter();
279         try {
280             ve.evaluate( context, w, "mystring", s );
281             fail("Expected exception.");
282         } catch (RuntimeException e) {}
283         
284         // bad object, no property            
285         s = "$a3";
286         w = new StringWriter();
287         try {
288             ve.evaluate( context, w, "mystring", s );
289             fail("Expected exception.");
290         } catch (RuntimeException e) {}
291         
292         // bad object, no property / silent            
293         s = "$!b3";
294         w = new StringWriter();
295         try {
296             ve.evaluate( context, w, "mystring", s );
297             fail("Expected exception.");
298         } catch (RuntimeException e) {}
299         
300         // good object, bad property; change the value
301         s = "$a4.foobar";
302         w = new StringWriter();
303         ve.evaluate( context, w, "mystring", s );
304         result = w.toString();
305         assertEquals("zzz", result);
306 
307     }
308     
309     
310 
311     /**
312      * Test assigning the event handlers via properties
313      */
314     
315     public static class TestEventCartridge
316     implements InvalidReferenceEventHandler,
317     RuntimeServicesAware
318     {
319         private RuntimeServices rs;
320         
321         public TestEventCartridge()
322         {
323         }
324         
325         /**
326          * Required by EventHandler
327          */
328         public void setRuntimeServices( RuntimeServices rs )
329         {
330             // make sure this is only called once
331             if (this.rs == null)
332                 this.rs = rs;
333             
334             else
335                 fail("initialize called more than once.");
336         }
337         
338         
339         public Object invalidGetMethod(Context context, String reference, Object object, String property, Info info)
340         {
341             // as a test, make sure this EventHandler is initialized
342             if (rs == null)
343                 fail ("Event handler not initialized!");
344             
345             // good object, bad property
346             if (reference.equals("$a1.foobar"))
347             {
348                 assertEquals(new Integer(5),object);
349                 assertEquals("foobar",property);
350                 throw new RuntimeException("expected exception");
351             }
352             
353             // good object, bad property
354             else if (reference.equals("$!b1.foobar"))
355             {
356                 assertEquals(new Integer(5),object);
357                 assertEquals("foobar",property);
358                 throw new RuntimeException("expected exception");
359             }
360             
361             // good object, bad property
362             else if (reference.equals("$a1.foobar"))
363             {
364                 assertEquals(new Integer(5),object);
365                 assertEquals("foobar",property);
366                 throw new RuntimeException("expected exception");
367             }
368             
369             // good object, bad property
370             else if (reference.equals("$!b1.foobar"))
371             {
372                 assertEquals(new Integer(5),object);
373                 assertEquals("foobar",property);
374                 throw new RuntimeException("expected exception");
375             }
376             
377             // bad object, bad property            
378             else if (reference.equals("$a2"))
379             {
380                 assertNull(object);
381                 assertNull(property);
382                 throw new RuntimeException("expected exception");
383             }
384 
385             // bad object, bad property            
386             else if (reference.equals("$!b2"))
387             {
388                 assertNull(object);
389                 assertNull(property);
390                 throw new RuntimeException("expected exception");
391             }
392 
393             // bad object, no property            
394             else if (reference.equals("$a3"))
395             {
396                 assertNull(object);
397                 assertNull(property);
398                 throw new RuntimeException("expected exception");
399             }
400             
401             // bad object, no property            
402             else if (reference.equals("$!b3"))
403             {
404                 assertNull(object);
405                 assertNull(property);
406                 throw new RuntimeException("expected exception");
407             }
408             
409             // good object, bad property; change the value
410             else if (reference.equals("$a4.foobar"))
411             {
412                 assertEquals(new Integer(5),object);
413                 assertEquals("foobar",property);
414                 return "zzz";
415             }
416 
417             // bad object, bad method -- fail on the object
418             else if (reference.equals("$zz"))
419             {
420                 assertNull(object);
421                 assertNull(property);
422                 throw new RuntimeException("expected exception");
423             }
424 
425             // pass q1 through
426             else if (reference.equals("$q1"))
427             {
428 
429             }
430 
431             
432             else if (reference.equals("$tree.x"))
433             {
434                 assertEquals("x",property);
435             }
436 
437             else if (reference.equals("$tree.field.x"))
438             {
439                 assertEquals("x",property);
440             }
441 
442             else if (reference.equals("$tree.child.y"))
443             {
444                 assertEquals("y",property);
445             }
446             
447             else if (reference.equals("$tree.child.Field.y"))
448             {
449                 assertEquals("y",property);
450             }
451             
452             else
453             {
454                 fail("invalidGetMethod: unexpected reference: " + reference);
455             }
456             return null;
457         }
458         
459         public Object invalidMethod(Context context, String reference, Object object, String method, Info info)
460         {
461             // as a test, make sure this EventHandler is initialized
462             if (rs == null)
463                 fail ("Event handler not initialized!");
464 
465             // good reference, bad method
466             if (object.getClass().equals(Integer.class))
467             {
468                 if (reference.equals("$a1.afternoon()"))
469                 {
470                     assertEquals("afternoon",method);
471                     throw new RuntimeException("expected exception");                    
472                 }
473                 else if (reference.equals("$!b1.afternoon()"))
474                 {
475                     assertEquals("afternoon",method);
476                     throw new RuntimeException("expected exception");                    
477                 }
478                 else
479                 {
480                     fail("Unexpected invalid method.  " + method);
481                     
482                 }
483             }
484 
485 
486             else if (object.getClass().equals(String.class) && "baby".equals(method))
487             {
488                 return "www";
489             }
490 
491             else
492             { 
493                 fail("Unexpected invalid method.  " + method);
494             }
495 
496             return null;
497         }        
498     
499 
500         public boolean invalidSetMethod(Context context, String leftreference, String rightreference, Info info)
501         {
502 
503             // as a test, make sure this EventHandler is initialized
504             if (rs == null)
505                 fail ("Event handler not initialized!");
506 
507             // good object, bad method
508             if (leftreference.equals("xx"))
509             {
510                 assertEquals("q1.afternoon()",rightreference);
511                 throw new RuntimeException("expected exception");
512             }
513             if (leftreference.equals("yy"))
514             {
515                 assertEquals("$q1",rightreference);
516                 throw new RuntimeException("expected exception");
517             }
518             else
519             { 
520                 fail("Unexpected left hand side.  " + leftreference);
521             }
522             
523             return false;
524         }
525 
526     }
527 
528     public static class Tree
529     {
530         String field;
531         Tree child;
532         
533         public Tree()
534         {
535             
536         }
537 
538         public String getField()
539         {
540             return field;
541         }
542 
543         public void setField(String field)
544         {
545             this.field = field;
546         }
547 
548         public Tree getChild()
549         {
550             return child;
551         }
552 
553         public void setChild(Tree child)
554         {
555             this.child = child;
556         }
557 
558         public String testMethod() 
559         {
560             return "123";
561         }
562     }
563     
564 }