1 package org.apache.velocity.app.event; 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 org.apache.velocity.context.InternalContextAdapter; 23 import org.apache.velocity.exception.VelocityException; 24 import org.apache.velocity.runtime.RuntimeServices; 25 import org.apache.velocity.util.introspection.Info; 26 27 28 /** 29 * Calls on request all registered event handlers for a particular event. Each 30 * method accepts two event cartridges (typically one from the application and 31 * one from the context). All appropriate event handlers are executed in order 32 * until a stopping condition is met. See the docs for the individual methods to 33 * see what the stopping condition is for that method. 34 * 35 * @author <a href="mailto:wglass@wglass@forio.com">Will Glass-Husain </a> 36 * @version $Id$ 37 * @since 1.5 38 */ 39 public class EventHandlerUtil { 40 41 42 /** 43 * Called before a reference is inserted. All event handlers are called in 44 * sequence. The default implementation inserts the reference as is. 45 * 46 * This is a major hotspot method called by ASTReference render. 47 * 48 * @param reference reference from template about to be inserted 49 * @param value value about to be inserted (after toString() ) 50 * @param rsvc current instance of RuntimeServices 51 * @param context The internal context adapter. 52 * @return Object on which toString() should be called for output. 53 */ referenceInsert(RuntimeServices rsvc, InternalContextAdapter context, String reference, Object value)54 public static Object referenceInsert(RuntimeServices rsvc, 55 InternalContextAdapter context, String reference, Object value) 56 { 57 try 58 { 59 value = rsvc.getApplicationEventCartridge().referenceInsert(context, reference, value); 60 EventCartridge contextCartridge = context.getEventCartridge(); 61 if (contextCartridge != null) 62 { 63 contextCartridge.setRuntimeServices(rsvc); 64 value = contextCartridge.referenceInsert(context, reference, value); 65 } 66 return value; 67 } 68 catch (RuntimeException e) 69 { 70 throw e; 71 } 72 catch (Exception e) 73 { 74 throw new VelocityException("Exception in event handler.",e, rsvc.getLogContext().getStackTrace()); 75 } 76 } 77 78 /** 79 * Called when a method exception is generated during Velocity merge. Only 80 * the first valid event handler in the sequence is called. The default 81 * implementation simply rethrows the exception. 82 * 83 * @param claz 84 * Class that is causing the exception 85 * @param method 86 * method called that causes the exception 87 * @param e 88 * Exception thrown by the method 89 * @param rsvc current instance of RuntimeServices 90 * @param context The internal context adapter. 91 * @param info exception location informations 92 * @return Object to return as method result 93 * @throws Exception 94 * to be wrapped and propagated to app 95 */ methodException(RuntimeServices rsvc, InternalContextAdapter context, Class<?> claz, String method, Exception e, Info info)96 public static Object methodException(RuntimeServices rsvc, 97 InternalContextAdapter context, Class<?> claz, String method, 98 Exception e, Info info) throws Exception 99 { 100 try 101 { 102 EventCartridge ev = rsvc.getApplicationEventCartridge(); 103 if (ev.hasMethodExceptionEventHandler()) 104 { 105 return ev.methodException(context, claz, method, e, info); 106 } 107 EventCartridge contextCartridge = context.getEventCartridge(); 108 if (contextCartridge != null) 109 { 110 contextCartridge.setRuntimeServices(rsvc); 111 return contextCartridge.methodException(context, claz, method, e, info); 112 } 113 } 114 catch (RuntimeException re) 115 { 116 throw re; 117 } 118 catch (Exception ex) 119 { 120 throw new VelocityException("Exception in event handler.", ex, rsvc.getLogContext().getStackTrace()); 121 } 122 123 /* default behaviour is to re-throw exception */ 124 throw e; 125 } 126 127 /** 128 * Called when an include-type directive is encountered (#include or 129 * #parse). All the registered event handlers are called unless null is 130 * returned. The default implementation always processes the included 131 * resource. 132 * 133 * @param includeResourcePath 134 * the path as given in the include directive. 135 * @param currentResourcePath 136 * the path of the currently rendering template that includes the 137 * include directive. 138 * @param directiveName 139 * name of the directive used to include the resource. (With the 140 * standard directives this is either "parse" or "include"). 141 * @param rsvc current instance of RuntimeServices 142 * @param context The internal context adapter. 143 * 144 * @return a new resource path for the directive, or null to block the 145 * include from occurring. 146 */ includeEvent(RuntimeServices rsvc, InternalContextAdapter context, String includeResourcePath, String currentResourcePath, String directiveName)147 public static String includeEvent(RuntimeServices rsvc, 148 InternalContextAdapter context, String includeResourcePath, 149 String currentResourcePath, String directiveName) 150 { 151 try 152 { 153 includeResourcePath = rsvc.getApplicationEventCartridge().includeEvent(context, includeResourcePath, currentResourcePath, directiveName); 154 EventCartridge contextCartridge = context.getEventCartridge(); 155 if (contextCartridge != null) 156 { 157 contextCartridge.setRuntimeServices(rsvc); 158 includeResourcePath = contextCartridge.includeEvent(context, includeResourcePath, currentResourcePath, directiveName); 159 } 160 return includeResourcePath; 161 } 162 catch (RuntimeException e) 163 { 164 throw e; 165 } 166 catch (Exception e) 167 { 168 throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace()); 169 } 170 } 171 172 173 /** 174 * Called when an invalid get method is encountered. 175 * 176 * @param rsvc current instance of RuntimeServices 177 * @param context the context when the reference was found invalid 178 * @param reference complete invalid reference 179 * @param object object from reference, or null if not available 180 * @param property name of property, or null if not relevant 181 * @param info contains info on template, line, col 182 * @return substitute return value for missing reference, or null if no substitute 183 */ invalidGetMethod(RuntimeServices rsvc, InternalContextAdapter context, String reference, Object object, String property, Info info)184 public static Object invalidGetMethod(RuntimeServices rsvc, 185 InternalContextAdapter context, String reference, 186 Object object, String property, Info info) 187 { 188 try 189 { 190 Object result = rsvc.getApplicationEventCartridge().invalidGetMethod(context, reference, object, property, info); 191 EventCartridge contextCartridge = context.getEventCartridge(); 192 if (contextCartridge != null) 193 { 194 contextCartridge.setRuntimeServices(rsvc); 195 result = contextCartridge.invalidGetMethod(context, reference, object, property, info); 196 } 197 return result; 198 } 199 catch (RuntimeException e) 200 { 201 throw e; 202 } 203 catch (Exception e) 204 { 205 throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace()); 206 } 207 } 208 209 /** 210 * Called when an invalid set method is encountered. 211 * 212 * @param rsvc current instance of RuntimeServices 213 * @param context the context when the reference was found invalid 214 * @param leftreference left reference being assigned to 215 * @param rightreference invalid reference on the right 216 * @param info contains info on template, line, col 217 */ invalidSetMethod(RuntimeServices rsvc, InternalContextAdapter context, String leftreference, String rightreference, Info info)218 public static void invalidSetMethod(RuntimeServices rsvc, 219 InternalContextAdapter context, String leftreference, 220 String rightreference, Info info) 221 { 222 try 223 { 224 if (!rsvc.getApplicationEventCartridge().invalidSetMethod(context, leftreference, rightreference, info)) 225 { 226 EventCartridge contextCartridge = context.getEventCartridge(); 227 if (contextCartridge != null) 228 { 229 contextCartridge.setRuntimeServices(rsvc); 230 contextCartridge.invalidSetMethod(context, leftreference, rightreference, info); 231 } 232 } 233 } 234 catch (RuntimeException e) 235 { 236 throw e; 237 } 238 catch (Exception e) 239 { 240 throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace()); 241 } 242 } 243 244 /** 245 * Called when an invalid method is encountered. 246 * 247 * @param rsvc current instance of RuntimeServices 248 * @param context the context when the reference was found invalid 249 * @param reference complete invalid reference 250 * @param object object from reference, or null if not available 251 * @param method name of method, or null if not relevant 252 * @param info contains info on template, line, col 253 * @return substitute return value for missing reference, or null if no substitute 254 */ invalidMethod(RuntimeServices rsvc, InternalContextAdapter context, String reference, Object object, String method, Info info)255 public static Object invalidMethod(RuntimeServices rsvc, 256 InternalContextAdapter context, String reference, 257 Object object, String method, Info info) 258 { 259 try 260 { 261 Object result = rsvc.getApplicationEventCartridge().invalidMethod(context, reference, object, method, info); 262 EventCartridge contextCartridge = context.getEventCartridge(); 263 if (contextCartridge != null) 264 { 265 contextCartridge.setRuntimeServices(rsvc); 266 result = contextCartridge.invalidMethod(context, reference, object, method, info); 267 } 268 return result; 269 } 270 catch (RuntimeException e) 271 { 272 throw e; 273 } 274 catch (Exception e) 275 { 276 throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace()); 277 } 278 } 279 } 280