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.Writer;
26  
27  import junit.framework.Test;
28  import junit.framework.TestSuite;
29  
30  import org.apache.velocity.Template;
31  import org.apache.velocity.VelocityContext;
32  import org.apache.velocity.app.Velocity;
33  import org.apache.velocity.app.event.EventCartridge;
34  import org.apache.velocity.app.event.IncludeEventHandler;
35  import org.apache.velocity.context.Context;
36  import org.apache.velocity.runtime.RuntimeServices;
37  import org.apache.velocity.runtime.RuntimeSingleton;
38  import org.apache.velocity.runtime.log.NullLogChute;
39  import org.apache.velocity.util.RuntimeServicesAware;
40  
41  /**
42   *  Tests event handling
43   *
44   * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
45   * @version $Id: IncludeEventHandlingTestCase.java 477002 2006-11-20 01:07:43Z henning $
46   */
47  public class IncludeEventHandlingTestCase extends BaseTestCase implements IncludeEventHandler,RuntimeServicesAware
48  {
49  
50       /**
51       * VTL file extension.
52       */
53      private static final String TMPL_FILE_EXT = "vm";
54  
55      /**
56       * Comparison file extension.
57       */
58      private static final String CMP_FILE_EXT = "cmp";
59  
60      /**
61       * Comparison file extension.
62       */
63      private static final String RESULT_FILE_EXT = "res";
64  
65      /**
66       * Path for templates. This property will override the
67       * value in the default velocity properties file.
68       */
69      private final static String FILE_RESOURCE_LOADER_PATH = TEST_COMPARE_DIR + "/includeevent";
70  
71      /**
72       * Results relative to the build directory.
73       */
74      private static final String RESULTS_DIR = TEST_RESULT_DIR + "/includeevent";
75  
76      /**
77       * Results relative to the build directory.
78       */
79      private static final String COMPARE_DIR = TEST_COMPARE_DIR + "/includeevent/compare";
80  
81  
82      private static final int PASS_THROUGH=0;
83      private static final int RELATIVE_PATH=1;
84      private static final int BLOCK=2;
85  
86      private int EventHandlerBehavior = PASS_THROUGH;
87  
88      /**
89       * Default constructor.
90       */
91      public IncludeEventHandlingTestCase(String name)
92      {
93          super(name);
94      }
95  
96      public void setUp()
97              throws Exception
98      {
99          assureResultsDirectoryExists(RESULTS_DIR);
100 
101         Velocity.addProperty(
102             Velocity.FILE_RESOURCE_LOADER_PATH, FILE_RESOURCE_LOADER_PATH);
103 
104         Velocity.setProperty(
105                 Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS, NullLogChute.class.getName());
106 
107         Velocity.init();
108 
109 
110     }
111 
112 
113     public static Test suite ()
114     {
115         return new TestSuite(IncludeEventHandlingTestCase.class);
116     }
117 
118     /**
119      * Runs the test.
120      */
121     public void testIncludeEventHandling ()
122             throws Exception
123     {
124         Template template1 = RuntimeSingleton.getTemplate(
125             getFileName(null, "test1", TMPL_FILE_EXT));
126 
127         Template template2 = RuntimeSingleton.getTemplate(
128             getFileName(null, "subdir/test2", TMPL_FILE_EXT));
129 
130         Template template3 = RuntimeSingleton.getTemplate(
131             getFileName(null, "test3", TMPL_FILE_EXT));
132 
133         FileOutputStream fos1 =
134             new FileOutputStream (
135                 getFileName(RESULTS_DIR, "test1", RESULT_FILE_EXT));
136 
137         FileOutputStream fos2 =
138             new FileOutputStream (
139                 getFileName(RESULTS_DIR, "test2", RESULT_FILE_EXT));
140 
141         FileOutputStream fos3 =
142             new FileOutputStream (
143                 getFileName(RESULTS_DIR, "test3", RESULT_FILE_EXT));
144 
145         Writer writer1 = new BufferedWriter(new OutputStreamWriter(fos1));
146         Writer writer2 = new BufferedWriter(new OutputStreamWriter(fos2));
147         Writer writer3 = new BufferedWriter(new OutputStreamWriter(fos3));
148 
149         /*
150          *  lets make a Context and add the event cartridge
151          */
152 
153         Context context = new VelocityContext();
154 
155         /*
156          *  Now make an event cartridge, register the
157          *  input event handler and attach it to the
158          *  Context
159          */
160 
161         EventCartridge ec = new EventCartridge();
162         ec.addEventHandler(this);
163         ec.attachToContext( context );
164 
165 
166         // BEHAVIOR A: pass through #input and #parse with no change
167         EventHandlerBehavior = PASS_THROUGH;
168 
169         template1.merge(context, writer1);
170         writer1.flush();
171         writer1.close();
172 
173         // BEHAVIOR B: pass through #input and #parse with using a relative path
174         EventHandlerBehavior = RELATIVE_PATH;
175 
176         template2.merge(context, writer2);
177         writer2.flush();
178         writer2.close();
179 
180         // BEHAVIOR C: refuse to pass through #input and #parse
181         EventHandlerBehavior = BLOCK;
182 
183         template3.merge(context, writer3);
184         writer3.flush();
185         writer3.close();
186 
187         if (!isMatch(RESULTS_DIR, COMPARE_DIR, "test1",
188                 RESULT_FILE_EXT, CMP_FILE_EXT) ||
189             !isMatch(RESULTS_DIR, COMPARE_DIR, "test2",
190                 RESULT_FILE_EXT, CMP_FILE_EXT) ||
191             !isMatch(RESULTS_DIR, COMPARE_DIR, "test3",
192                 RESULT_FILE_EXT, CMP_FILE_EXT)
193                 )
194         {
195             fail("Output incorrect.");
196         }
197     }
198 
199 
200     public void setRuntimeServices( RuntimeServices rs )
201      {
202      }
203 
204     /**
205      * Sample handler with different behaviors for the different tests.
206      */
207     public String includeEvent( String includeResourcePath, String currentResourcePath, String directiveName)
208     {
209         if (EventHandlerBehavior == PASS_THROUGH)
210             return includeResourcePath;
211 
212 
213         // treat as relative path
214         else if (EventHandlerBehavior == RELATIVE_PATH)
215         {
216             // if the resource name starts with a slash, it's not a relative path
217             if (includeResourcePath.startsWith("/") || includeResourcePath.startsWith("\\") ) {
218                 return includeResourcePath;
219             }
220 
221             int lastslashpos = Math.max(
222                     currentResourcePath.lastIndexOf("/"),
223                     currentResourcePath.lastIndexOf("\\")
224                     );
225 
226             // root of resource tree
227             if ( (lastslashpos == -1))
228                 return includeResourcePath;
229 
230             // prepend path to the input path
231             else
232                 return currentResourcePath.substring(0,lastslashpos) + "/" + includeResourcePath;
233 
234 
235 
236         } else if (EventHandlerBehavior == BLOCK)
237             return null;
238 
239         // should never happen
240         else
241             return null;
242 
243 
244     }
245 
246 
247 }