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