package org.apache.velocity.app.event; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.velocity.context.InternalContextAdapter; import org.apache.velocity.exception.VelocityException; import org.apache.velocity.runtime.RuntimeServices; import org.apache.velocity.util.introspection.Info; /** * Calls on request all registered event handlers for a particular event. Each * method accepts two event cartridges (typically one from the application and * one from the context). All appropriate event handlers are executed in order * until a stopping condition is met. See the docs for the individual methods to * see what the stopping condition is for that method. * * @author Will Glass-Husain * @version $Id$ * @since 1.5 */ public class EventHandlerUtil { /** * Called before a reference is inserted. All event handlers are called in * sequence. The default implementation inserts the reference as is. * * This is a major hotspot method called by ASTReference render. * * @param reference reference from template about to be inserted * @param value value about to be inserted (after toString() ) * @param rsvc current instance of RuntimeServices * @param context The internal context adapter. * @return Object on which toString() should be called for output. */ public static Object referenceInsert(RuntimeServices rsvc, InternalContextAdapter context, String reference, Object value) { try { value = rsvc.getApplicationEventCartridge().referenceInsert(context, reference, value); EventCartridge contextCartridge = context.getEventCartridge(); if (contextCartridge != null) { contextCartridge.setRuntimeServices(rsvc); value = contextCartridge.referenceInsert(context, reference, value); } return value; } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new VelocityException("Exception in event handler.",e, rsvc.getLogContext().getStackTrace()); } } /** * Called when a method exception is generated during Velocity merge. Only * the first valid event handler in the sequence is called. The default * implementation simply rethrows the exception. * * @param claz * Class that is causing the exception * @param method * method called that causes the exception * @param e * Exception thrown by the method * @param rsvc current instance of RuntimeServices * @param context The internal context adapter. * @param info exception location informations * @return Object to return as method result * @throws Exception * to be wrapped and propagated to app */ public static Object methodException(RuntimeServices rsvc, InternalContextAdapter context, Class claz, String method, Exception e, Info info) throws Exception { try { EventCartridge ev = rsvc.getApplicationEventCartridge(); if (ev.hasMethodExceptionEventHandler()) { return ev.methodException(context, claz, method, e, info); } EventCartridge contextCartridge = context.getEventCartridge(); if (contextCartridge != null) { contextCartridge.setRuntimeServices(rsvc); return contextCartridge.methodException(context, claz, method, e, info); } } catch (RuntimeException re) { throw re; } catch (Exception ex) { throw new VelocityException("Exception in event handler.", ex, rsvc.getLogContext().getStackTrace()); } /* default behaviour is to re-throw exception */ throw e; } /** * Called when an include-type directive is encountered (#include or * #parse). All the registered event handlers are called unless null is * returned. The default implementation always processes the included * resource. * * @param includeResourcePath * the path as given in the include directive. * @param currentResourcePath * the path of the currently rendering template that includes the * include directive. * @param directiveName * name of the directive used to include the resource. (With the * standard directives this is either "parse" or "include"). * @param rsvc current instance of RuntimeServices * @param context The internal context adapter. * * @return a new resource path for the directive, or null to block the * include from occurring. */ public static String includeEvent(RuntimeServices rsvc, InternalContextAdapter context, String includeResourcePath, String currentResourcePath, String directiveName) { try { includeResourcePath = rsvc.getApplicationEventCartridge().includeEvent(context, includeResourcePath, currentResourcePath, directiveName); EventCartridge contextCartridge = context.getEventCartridge(); if (contextCartridge != null) { contextCartridge.setRuntimeServices(rsvc); includeResourcePath = contextCartridge.includeEvent(context, includeResourcePath, currentResourcePath, directiveName); } return includeResourcePath; } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace()); } } /** * Called when an invalid get method is encountered. * * @param rsvc current instance of RuntimeServices * @param context the context when the reference was found invalid * @param reference complete invalid reference * @param object object from reference, or null if not available * @param property name of property, or null if not relevant * @param info contains info on template, line, col * @return substitute return value for missing reference, or null if no substitute */ public static Object invalidGetMethod(RuntimeServices rsvc, InternalContextAdapter context, String reference, Object object, String property, Info info) { try { Object result = rsvc.getApplicationEventCartridge().invalidGetMethod(context, reference, object, property, info); EventCartridge contextCartridge = context.getEventCartridge(); if (contextCartridge != null) { contextCartridge.setRuntimeServices(rsvc); result = contextCartridge.invalidGetMethod(context, reference, object, property, info); } return result; } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace()); } } /** * Called when an invalid set method is encountered. * * @param rsvc current instance of RuntimeServices * @param context the context when the reference was found invalid * @param leftreference left reference being assigned to * @param rightreference invalid reference on the right * @param info contains info on template, line, col */ public static void invalidSetMethod(RuntimeServices rsvc, InternalContextAdapter context, String leftreference, String rightreference, Info info) { try { if (!rsvc.getApplicationEventCartridge().invalidSetMethod(context, leftreference, rightreference, info)) { EventCartridge contextCartridge = context.getEventCartridge(); if (contextCartridge != null) { contextCartridge.setRuntimeServices(rsvc); contextCartridge.invalidSetMethod(context, leftreference, rightreference, info); } } } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace()); } } /** * Called when an invalid method is encountered. * * @param rsvc current instance of RuntimeServices * @param context the context when the reference was found invalid * @param reference complete invalid reference * @param object object from reference, or null if not available * @param method name of method, or null if not relevant * @param info contains info on template, line, col * @return substitute return value for missing reference, or null if no substitute */ public static Object invalidMethod(RuntimeServices rsvc, InternalContextAdapter context, String reference, Object object, String method, Info info) { try { Object result = rsvc.getApplicationEventCartridge().invalidMethod(context, reference, object, method, info); EventCartridge contextCartridge = context.getEventCartridge(); if (contextCartridge != null) { contextCartridge.setRuntimeServices(rsvc); result = contextCartridge.invalidMethod(context, reference, object, method, info); } return result; } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new VelocityException("Exception in event handler.", e, rsvc.getLogContext().getStackTrace()); } } }