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.TestCase; 24 import junit.framework.TestSuite; 25 import org.apache.commons.io.IOUtils; 26 import org.apache.velocity.VelocityContext; 27 import org.apache.velocity.app.VelocityEngine; 28 import org.apache.velocity.test.misc.TestLogger; 29 import org.apache.velocity.util.introspection.IntrospectorCache; 30 31 import java.io.ByteArrayOutputStream; 32 import java.io.InputStream; 33 import java.io.StringWriter; 34 35 /** 36 * Tests if we can hand Velocity an arbitrary class for logging. 37 * 38 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a> 39 * @version $Id$ 40 */ 41 public class ClassloaderChangeTestCase extends TestCase 42 { 43 private VelocityEngine ve = null; 44 private TestLogger logger = null; 45 46 private static String OUTPUT = "Hello From Foo"; 47 48 /** 49 * Default constructor. 50 */ ClassloaderChangeTestCase(String name)51 public ClassloaderChangeTestCase(String name) 52 { 53 super(name); 54 } 55 56 @Override setUp()57 public void setUp() 58 throws Exception 59 { 60 ve = new VelocityEngine(); 61 logger = new TestLogger(false, true); 62 logger.setEnabledLevel(TestLogger.LOG_LEVEL_DEBUG); 63 ve.setProperty(VelocityEngine.RUNTIME_LOG_INSTANCE, logger); 64 ve.init(); 65 } 66 suite()67 public static Test suite () 68 { 69 return new TestSuite(ClassloaderChangeTestCase.class); 70 } 71 72 /** 73 * Runs the test. 74 */ testClassloaderChange()75 public void testClassloaderChange() 76 throws Exception 77 { 78 logger.on(); 79 80 VelocityContext vc = new VelocityContext(); 81 Object foo = null; 82 83 /* 84 * first, we need a classloader to make our foo object 85 */ 86 87 TestClassloader cl = new TestClassloader(); 88 Class<?> fooclass = cl.loadClass("Foo"); 89 foo = fooclass.newInstance(); 90 91 /* 92 * put it into the context 93 */ 94 vc.put("foo", foo); 95 96 /* 97 * and render something that would use it 98 * that will get it into the introspector cache 99 */ 100 StringWriter writer = new StringWriter(); 101 ve.evaluate( vc, writer, "test", "$foo.doIt()"); 102 103 /* 104 * Check to make sure ok. note the obvious 105 * dependency on the Foo class... 106 */ 107 108 if ( !writer.toString().equals( OUTPUT )) 109 { 110 fail("Output from doIt() incorrect"); 111 } 112 113 /* 114 * and do it again :) 115 */ 116 cl = new TestClassloader(); 117 fooclass = cl.loadClass("Foo"); 118 foo = fooclass.newInstance(); 119 120 vc.put("foo", foo); 121 122 writer = new StringWriter(); 123 ve.evaluate( vc, writer, "test", "$foo.doIt()"); 124 125 if ( !writer.toString().equals( OUTPUT )) 126 { 127 fail("Output from doIt() incorrect"); 128 } 129 130 if (!logger.getLog().contains(IntrospectorCache.CACHEDUMP_MSG)) 131 { 132 fail("Didn't see introspector cache dump."); 133 } 134 } 135 136 /** 137 * Simple (real simple...) classloader that depends 138 * on a Foo.class being located in the classloader 139 * directory under test 140 */ 141 public static class TestClassloader extends ClassLoader 142 { 143 private final static String testclass = 144 "classloader/Foo.class"; 145 146 private Class<?> fooClass = null; 147 TestClassloader()148 public TestClassloader() 149 throws Exception 150 { 151 ByteArrayOutputStream os = new ByteArrayOutputStream(); 152 InputStream fis = getClass().getResourceAsStream("/" + testclass); 153 IOUtils.copy(fis, os); 154 fis.close(); 155 os.close(); 156 157 byte[] barr = os.toByteArray(); 158 159 fooClass = defineClass("classloader.Foo", barr, 0, barr.length); 160 } 161 162 163 @Override findClass(String name)164 public Class<?> findClass(String name) 165 { 166 return fooClass; 167 } 168 } 169 } 170