diff options
Diffstat (limited to 'velocity-engine-core/src/test/java/org/apache/velocity/test/EventHandlingTestCase.java')
-rw-r--r-- | velocity-engine-core/src/test/java/org/apache/velocity/test/EventHandlingTestCase.java | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/velocity-engine-core/src/test/java/org/apache/velocity/test/EventHandlingTestCase.java b/velocity-engine-core/src/test/java/org/apache/velocity/test/EventHandlingTestCase.java new file mode 100644 index 00000000..ef3bfcdf --- /dev/null +++ b/velocity-engine-core/src/test/java/org/apache/velocity/test/EventHandlingTestCase.java @@ -0,0 +1,271 @@ +package org.apache.velocity.test; + +/* + * 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.VelocityContext; +import org.apache.velocity.app.event.EventCartridge; +import org.apache.velocity.app.event.MethodExceptionEventHandler; +import org.apache.velocity.app.event.ReferenceInsertionEventHandler; +import org.apache.velocity.context.Context; +import org.apache.velocity.exception.MethodInvocationException; +import org.apache.velocity.runtime.RuntimeConstants; +import org.apache.velocity.runtime.RuntimeServices; +import org.apache.velocity.util.ContextAware; +import org.apache.velocity.util.RuntimeServicesAware; +import org.apache.velocity.util.introspection.Info; + +/** + * Tests event handling for all event handlers except IncludeEventHandler. This is tested + * separately due to its complexity. + * + * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a> + * @version $Id$ + */ +public class EventHandlingTestCase extends BaseTestCase +{ + private static String NO_REFERENCE_VALUE = "<no reference value>"; + private static String REFERENCE_VALUE = "<reference value>"; + + public EventHandlingTestCase(String name) + { + super(name); + } + + public void testManualEventHandlers() + throws Exception + { + TestEventCartridge te = new TestEventCartridge(); + /* + * Test attaching the event cartridge to the context. + * Make an event cartridge, register all the + * event handlers (at once) and attach it to the + * Context + */ + + EventCartridge ec = new EventCartridge(); + ec.addEventHandler(te); + ec.attachToContext(context); + + /* + * now wrap the event cartridge - we want to make sure that + * we can do this w/o harm + */ + doTestReferenceInsertionEventHandler1(); + doTestReferenceInsertionEventHandler2(); + doTestMethodExceptionEventHandler1(); + doTestMethodExceptionEventHandler2(); + } + + /** + * Test assigning the event handlers via properties + */ + public void testConfigurationEventHandlers() + throws Exception + { + engine.setProperty(RuntimeConstants.EVENTHANDLER_METHODEXCEPTION, TestEventCartridge.class.getName()); + engine.setProperty(RuntimeConstants.EVENTHANDLER_REFERENCEINSERTION, TestEventCartridge.class.getName()); + + doTestReferenceInsertionEventHandler1(); + doTestReferenceInsertionEventHandler2(); + doTestMethodExceptionEventHandler1(); + doTestMethodExceptionEventHandler2(); + } + + /** + * Test all the event handlers using the given engine. + */ + private void doTestReferenceInsertionEventHandler1() + throws Exception + { + VelocityContext outer = context; + context = new VelocityContext(context); + context.put("name", "Velocity"); + + /* + * First, the reference insertion handler + */ + String expected = REFERENCE_VALUE + REFERENCE_VALUE + REFERENCE_VALUE; + assertEvalEquals(expected, "$name$name$name"); + + context = outer; + } + + private void doTestReferenceInsertionEventHandler2() + throws Exception + { + VelocityContext outer = context; + context = new VelocityContext(context); + context.put("name", "Velocity"); + + /* + * using the same handler, we can deal with + * null references as well + */ + assertEvalEquals(NO_REFERENCE_VALUE, "$floobie"); + + context = outer; + } + + private void doTestMethodExceptionEventHandler1() + throws Exception + { + VelocityContext outer = context; + context = new VelocityContext(context); + + /* + * finally, we test a method exception event - we do this + * by putting this class in the context, and calling + * a method that does nothing but throw an exception. + * we use flag in the context to turn the event handling + * on and off + * + * Note also how the reference insertion process + * happens as well + */ + context.put("allow_exception",Boolean.TRUE); + context.put("this", this ); + + evaluate(" $this.throwException()"); + + context = outer; + } + + private void doTestMethodExceptionEventHandler2() + throws Exception + { + VelocityContext outer = context; + context = new VelocityContext(context); + context.put("this", this ); + + /* + * now, we remove the exception flag, and we can see that the + * exception will propgate all the way up here, and + * wil be caught by the catch() block below + */ + assertEvalException("$this.throwException()", MethodInvocationException.class); + + context = outer; + } + + /** + * silly method to throw an exception to test + * the method invocation exception event handling + */ + public void throwException() + throws Exception + { + throw new Exception("Hello from throwException()"); + } + + + + public static class TestEventCartridge + implements ReferenceInsertionEventHandler, + MethodExceptionEventHandler, + RuntimeServicesAware,ContextAware + { + private RuntimeServices rs; + + /** + * Required by EventHandler + */ + @Override + public void setRuntimeServices(RuntimeServices rs ) + { + // make sure this is only called once + if (this.rs == null) + this.rs = rs; + + else + fail("initialize called more than once."); + } + + /** + * Event handler for when a reference is inserted into the output stream. + */ + @Override + public Object referenceInsert(Context context, String reference, Object value ) + { + // as a test, make sure this EventHandler is initialized + if (rs == null) + fail ("Event handler not initialized!"); + + + /* + * if we have a value + * return a known value + */ + String s = null; + + if( value != null ) + { + s = REFERENCE_VALUE; + } + else + { + /* + * we only want to deal with $floobie - anything + * else we let go + */ + if ( reference.equals("$floobie") ) + { + s = NO_REFERENCE_VALUE; + } + } + return s; + } + + /** + * Handles exceptions thrown during in-template method access + */ + @Override + public Object methodException(Context context, Class claz, String method, Exception e, Info info ) + { + // as a test, make sure this EventHandler is initialized + if (rs == null) + fail ("Event handler not initialized!"); + + // only do processing if the switch is on + if (context != null) + { + boolean exceptionSwitch = context.containsKey("allow_exception"); + + if( exceptionSwitch && method.equals("throwException")) + { + return "handler"; + } + else + throw new RuntimeException(e); + + } else + + throw new RuntimeException(e); + } + + Context context; + + + @Override + public void setContext(Context context) + { + this.context = context; + } + } +} |