Author: cbrisson Date: Wed Jun 20 00:47:45 2018 New Revision: 1833882 URL: http://svn.apache.org/viewvc?rev=1833882&view=rev Log: [tools] Review webapp config files access, increment dependencies versions, introduce some privileged actions
Modified: velocity/tools/trunk/pom.xml velocity/tools/trunk/velocity-tools-generic/pom.xml velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/ClassUtils.java velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/config/ConfigurationUtils.java velocity/tools/trunk/velocity-tools-view/pom.xml velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/ServletUtils.java velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/VelocityView.java velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/WebappResourceLoader.java velocity/tools/trunk/velocity-tools-view/src/test/java/org/apache/velocity/tools/view/VelocityViewTest.java Modified: velocity/tools/trunk/pom.xml URL: http://svn.apache.org/viewvc/velocity/tools/trunk/pom.xml?rev=1833882&r1=1833881&r2=1833882&view=diff ============================================================================== --- velocity/tools/trunk/pom.xml (original) +++ velocity/tools/trunk/pom.xml Wed Jun 20 00:47:45 2018 @@ -46,9 +46,10 @@ <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <junit.version>4.12</junit.version> - <slf4j.version>1.7.23</slf4j.version> - <surefire.plugin.version>2.19.1</surefire.plugin.version> - <servlet.api.version>3.0.1</servlet.api.version> + <slf4j.version>1.7.25</slf4j.version> + <surefire.plugin.version>2.22.0</surefire.plugin.version> + <servlet.api.version>3.1.0</servlet.api.version> + <velocity.engine.version>2.0</velocity.engine.version> </properties> <!-- java 8 doclint checks are too strict for our current javadoc state... --> @@ -119,7 +120,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> - <version>2.10.4</version> + <version>3.0.1</version> <configuration> <aggregate>true</aggregate> <excludePackageNames>org.apache.velocity.tools.examples</excludePackageNames> Modified: velocity/tools/trunk/velocity-tools-generic/pom.xml URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-generic/pom.xml?rev=1833882&r1=1833881&r2=1833882&view=diff ============================================================================== --- velocity/tools/trunk/velocity-tools-generic/pom.xml (original) +++ velocity/tools/trunk/velocity-tools-generic/pom.xml Wed Jun 20 00:47:45 2018 @@ -35,7 +35,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>2.4.3</version> + <version>3.1.1</version> <executions> <execution> <id>shade</id> @@ -70,7 +70,7 @@ <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> - <version>2.0</version> + <version>${velocity.engine.version}</version> </dependency> <dependency> <groupId>commons-beanutils</groupId> Modified: velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/ClassUtils.java URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/ClassUtils.java?rev=1833882&r1=1833881&r2=1833882&view=diff ============================================================================== --- velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/ClassUtils.java (original) +++ velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/ClassUtils.java Wed Jun 20 00:47:45 2018 @@ -27,6 +27,8 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.MalformedURLException; import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -212,6 +214,52 @@ public class ClassUtils return foundSome; } + private static URL getResourceImpl(final String name, final Object caller) + { + URL url = getThreadContextLoader().getResource(name); + if (url == null) + { + url = getClassLoader().getResource(name); + if (url == null) + { + url = ClassUtils.class.getResource(name); + if (url == null && caller != null) + { + Class callingClass = caller.getClass(); + if (callingClass == Class.class) + { + callingClass = (Class)caller; + } + url = callingClass.getResource(name); + } + } + } + return url; + } + + private static InputStream getResourceAsStreamImpl(final String name, final Object caller) + { + InputStream inputStream = getThreadContextLoader().getResourceAsStream(name); + if (inputStream == null) + { + inputStream = getClassLoader().getResourceAsStream(name); + if (inputStream == null) + { + inputStream = ClassUtils.class.getResourceAsStream(name); + if (inputStream == null && caller != null) + { + Class callingClass = caller.getClass(); + if (callingClass == Class.class) + { + callingClass = (Class)caller; + } + inputStream = callingClass.getResourceAsStream(name); + } + } + } + return inputStream; + } + /** * Load a given resource. * <p/> @@ -227,25 +275,24 @@ public class ClassUtils * @param name The name of the resource to load * @param caller The instance or {@link Class} calling this method */ - public static URL getResource(String name, Object caller) + public static URL getResource(final String name, final Object caller) { - URL url = getThreadContextLoader().getResource(name); - if (url == null) + URL url = null; + if (System.getSecurityManager() != null) { - url = getClassLoader().getResource(name); - if (url == null) - { - url = ClassUtils.class.getResource(name); - if (url == null && caller != null) + url = AccessController.doPrivileged( + new PrivilegedAction<URL>() { - Class callingClass = caller.getClass(); - if (callingClass == Class.class) + @Override + public URL run() { - callingClass = (Class)caller; + return getResourceImpl(name, caller); } - url = callingClass.getResource(name); - } - } + }); + } + else + { + url = getResourceImpl(name, caller); } return url; } @@ -258,17 +305,26 @@ public class ClassUtils * @param name The name of the resource to load * @param caller The instance or {@link Class} calling this method */ - public static InputStream getResourceAsStream(String name, Object caller) + public static InputStream getResourceAsStream(final String name, final Object caller) { - URL url = getResource(name, caller); - try + InputStream inputStream = null; + if (System.getSecurityManager() != null) { - return (url == null) ? null : url.openStream(); + inputStream = AccessController.doPrivileged( + new PrivilegedAction<InputStream>() + { + @Override + public InputStream run() + { + return getResourceAsStreamImpl(name, caller); + } + }); } - catch (IOException e) + else { - return null; + inputStream = getResourceAsStreamImpl(name, caller); } + return inputStream; } public static Method findMethod(Class clazz, String name, Class[] params) Modified: velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/config/ConfigurationUtils.java URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/config/ConfigurationUtils.java?rev=1833882&r1=1833881&r2=1833882&view=diff ============================================================================== --- velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/config/ConfigurationUtils.java (original) +++ velocity/tools/trunk/velocity-tools-generic/src/main/java/org/apache/velocity/tools/config/ConfigurationUtils.java Wed Jun 20 00:47:45 2018 @@ -163,20 +163,33 @@ public class ConfigurationUtils } /** + * Returns a {@link FactoryConfiguration} including all + * {@link #getDefaultTools()} (only if includeDefaults is {@code true}) as well as any tools that can be + * automatically loaded from "tools.xml" or "tools.properties" found + * at the root of the classpath or in the current directory. + * + * @see #getAutoLoaded(boolean includeDefaults) + */ + public static FactoryConfiguration getAutoLoaded(boolean includeDefaults) + { + return getAutoLoaded(includeDefaults, true, true); + } + + /** * Returns a {@link FactoryConfiguration} composed, in order of the * following configurations: * <ul> * <li>{@link #getDefaultTools()} (only if includeDefaults is {@code true})</li> - * <li>All "tools.xml" configurations found in the classpath root, in the order found</li> - * <li>All "tools.properties" configurations found in the classpath root, in the order found</li> - * <li>The "tools.xml" file in the current directory (if any)</li> - * <li>The "tools.properties" file in the current directory (if any)</li> + * <li>All "tools.xml" configurations found in the classpath root, in the order found (only if searchClasspath is true)</li> + * <li>All "tools.properties" configurations found in the classpath root, in the order found (only if searchClasspath is true)</li> + * <li>The "tools.xml" file in the current directory (if any, and only if searchCurrentDirectory is true)</li> + * <li>The "tools.properties" file in the current directory (if any, and only if searchCurrentDirectory is true)</li> * </ul> * If the includeDefaults parameter is null and no such files described above * can be found, then the configuration returned by this method will be * empty, but it should never be {@code null}. */ - public static FactoryConfiguration getAutoLoaded(boolean includeDefaults) + public static FactoryConfiguration getAutoLoaded(boolean includeDefaults, boolean searchClasspath, boolean searchCurrentDirectory) { FactoryConfiguration auto; if (includeDefaults) @@ -192,32 +205,38 @@ public class ConfigurationUtils //TODO: look for any Tools classes in the root of the classpath - // look for all tools.xml in the classpath - FactoryConfiguration cpXml = findInClasspath(AUTOLOADED_XML_PATH); - if (cpXml != null) - { - auto.addConfiguration(cpXml); - } - - // look for all tools.properties in the classpath - FactoryConfiguration cpProps = findInClasspath(AUTOLOADED_PROPS_PATH); - if (cpProps != null) - { - auto.addConfiguration(cpProps); - } - - // look for tools.xml in the current file system - FactoryConfiguration fsXml = findInFileSystem(AUTOLOADED_XML_PATH); - if (fsXml != null) - { - auto.addConfiguration(fsXml); - } - - // look for tools.properties in the file system - FactoryConfiguration fsProps = findInFileSystem(AUTOLOADED_PROPS_PATH); - if (fsProps != null) + if (searchClasspath) { - auto.addConfiguration(fsProps); + // look for all tools.xml in the classpath + FactoryConfiguration cpXml = findInClasspath(AUTOLOADED_XML_PATH); + if (cpXml != null) + { + auto.addConfiguration(cpXml); + } + + // look for all tools.properties in the classpath + FactoryConfiguration cpProps = findInClasspath(AUTOLOADED_PROPS_PATH); + if (cpProps != null) + { + auto.addConfiguration(cpProps); + } + } + + if (searchCurrentDirectory) + { + // look for tools.xml in the current file system + FactoryConfiguration fsXml = findInFileSystem(AUTOLOADED_XML_PATH); + if (fsXml != null) + { + auto.addConfiguration(fsXml); + } + + // look for tools.properties in the file system + FactoryConfiguration fsProps = findInFileSystem(AUTOLOADED_PROPS_PATH); + if (fsProps != null) + { + auto.addConfiguration(fsProps); + } } // return the config we've accumulated Modified: velocity/tools/trunk/velocity-tools-view/pom.xml URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-view/pom.xml?rev=1833882&r1=1833881&r2=1833882&view=diff ============================================================================== --- velocity/tools/trunk/velocity-tools-view/pom.xml (original) +++ velocity/tools/trunk/velocity-tools-view/pom.xml Wed Jun 20 00:47:45 2018 @@ -79,7 +79,7 @@ <dependency> <groupId>org.easymock</groupId> <artifactId>easymock</artifactId> - <version>3.4</version> + <version>3.6</version> <scope>test</scope> </dependency> <dependency> Modified: velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/ServletUtils.java URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/ServletUtils.java?rev=1833882&r1=1833881&r2=1833882&view=diff ============================================================================== --- velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/ServletUtils.java (original) +++ velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/ServletUtils.java Wed Jun 20 00:47:45 2018 @@ -25,6 +25,8 @@ import java.io.FileNotFoundException; import java.io.InputStream; import java.io.IOException; import java.lang.reflect.Constructor; +import java.security.AccessController; +import java.security.PrivilegedAction; import javax.servlet.FilterConfig; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; @@ -295,32 +297,38 @@ public class ServletUtils return null; } - public static InputStream getInputStream(String path, ServletContext application) + public static InputStream getInputStream(final String path, ServletContext application) { - // first, search the classpath - InputStream inputStream = ClassUtils.getResourceAsStream(path, ServletUtils.class); - if (inputStream == null) - { - // then, try the servlet context - inputStream = application.getResourceAsStream(path); + return getInputStream(path, application, true, true); + } - if (inputStream == null) + public static InputStream getInputStream(final String path, final ServletContext application, boolean searchClasspath, boolean searchWebapp) + { + InputStream inputStream = null; + // first search classpath if asked so + if (searchClasspath) + { + inputStream = ClassUtils.getResourceAsStream(path, ServletUtils.class); + } + if (inputStream == null && searchWebapp) + { + // then webapp + if (System.getSecurityManager() != null) { - // then, try the file system directly - File file = new File(path); - if (file.exists()) - { - try - { - inputStream = new FileInputStream(file); - } - catch (FileNotFoundException fnfe) + inputStream = AccessController.doPrivileged( + new PrivilegedAction<InputStream>() { - // we should not be able to get here - // since we already checked whether the file exists - throw new IllegalStateException(fnfe); - } - } + @Override + public InputStream run() + { + + return application.getResourceAsStream(path); + } + }); + } + else + { + inputStream = application.getResourceAsStream(path); } } return inputStream; Modified: velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/VelocityView.java URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/VelocityView.java?rev=1833882&r1=1833881&r2=1833882&view=diff ============================================================================== --- velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/VelocityView.java (original) +++ velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/VelocityView.java Wed Jun 20 00:47:45 2018 @@ -22,6 +22,8 @@ package org.apache.velocity.tools.view; import java.io.InputStream; import java.io.IOException; import java.io.Writer; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.List; import java.util.Properties; import javax.servlet.FilterConfig; @@ -305,7 +307,23 @@ public class VelocityView extends ViewTo // now all is ready - init Velocity try { - velocity.init(); + if (System.getSecurityManager() != null) + { + AccessController.doPrivileged( + new PrivilegedAction<Void>() + { + @Override + public Void run() + { + velocity.init(); + return null; + } + }); + } + else + { + velocity.init(); + } } catch(Exception e) { @@ -318,26 +336,40 @@ public class VelocityView extends ViewTo protected void configure(final JeeConfig config, final VelocityEngine velocity) { - // first get the default properties, and bail if we don't find them - Properties defaultProperties = getProperties(DEFAULT_PROPERTIES_PATH, true); + // first get the default properties from the classpath, and bail if we don't find them + Properties defaultProperties = getProperties(DEFAULT_PROPERTIES_PATH, true, true, false); velocity.setProperties(defaultProperties); // check for application-wide user props in the context init params String appPropsPath = servletContext.getInitParameter(PROPERTIES_KEY); - setProps(velocity, appPropsPath, true); + if (appPropsPath != null) + { + boolean isInWebInf = appPropsPath.startsWith("/WEB-INF") || appPropsPath.startsWith("WEB-INF"); + Properties appProperties = getProperties(DEFAULT_PROPERTIES_PATH, true, !isInWebInf, isInWebInf); + getLog().debug("Configuring Velocity with properties at: {}", appPropsPath); + velocity.setProperties(appProperties); + } // check for servlet-wide user props in the config init params at the // conventional location, and be silent if they're missing if (!USER_PROPERTIES_PATH.equals(appPropsPath)) { - setProps(velocity, USER_PROPERTIES_PATH, false); + Properties appProperties = getProperties(USER_PROPERTIES_PATH, false, false, true); + if (appProperties != null) + { + getLog().debug("Configuring Velocity with properties at: {}", appPropsPath); + velocity.setProperties(defaultProperties); + } } // check for a custom location for servlet-wide user props String servletPropsPath = config.getInitParameter(PROPERTIES_KEY); - if (!USER_PROPERTIES_PATH.equals(servletPropsPath) && (appPropsPath == null || !appPropsPath.equals(servletPropsPath))) + if (servletPropsPath != null && !USER_PROPERTIES_PATH.equals(servletPropsPath) && (appPropsPath == null || !appPropsPath.equals(servletPropsPath))) { - setProps(velocity, servletPropsPath, true); + boolean isInWebInf = servletPropsPath.startsWith("/WEB-INF") || servletPropsPath.startsWith("WEB-INF"); + Properties servletProperties = getProperties(DEFAULT_PROPERTIES_PATH, true, !isInWebInf, isInWebInf); + getLog().debug("Configuring Velocity with properties at: {}", servletPropsPath); + velocity.setProperties(servletProperties); } /* now that velocity engine is initialized, re-initialize our logger @@ -347,32 +379,6 @@ public class VelocityView extends ViewTo initLog(); } - private boolean setProps(VelocityEngine velocity, String path, boolean require) - { - if (path == null) - { - // only bother with this if a path was given - return false; - } - - // this will throw an exception if require is true and there - // are no properties at the path. if require is false, this - // will return null when there's no properties at the path - Properties props = getProperties(path, require); - if (props == null) - { - return false; - } - - getLog().debug("Configuring Velocity with properties at: {}", path); - - // these props will override those already set - velocity.setProperties(props); - // notify that new props were set - return true; - } - - /** * Here's the configuration lookup/loading order: * <ol> @@ -408,9 +414,7 @@ public class VelocityView extends ViewTo // this gets the auto loaded config from the classpath // this doesn't include defaults since they're handled already - // and it could theoretically pick up an auto-loaded config from the - // filesystem, but that is highly unlikely to happen in a webapp env - FactoryConfiguration autoLoaded = ConfigurationUtils.getAutoLoaded(false); + FactoryConfiguration autoLoaded = ConfigurationUtils.getAutoLoaded(false, true, false); factoryConfig.addConfiguration(autoLoaded); // check for application-wide user config in the context init params @@ -475,7 +479,6 @@ public class VelocityView extends ViewTo protected InputStream getInputStream(String path, boolean required) { - // first, search the classpath InputStream inputStream = ServletUtils.getInputStream(path, this.servletContext); // if we didn't find one @@ -499,19 +502,33 @@ public class VelocityView extends ViewTo protected Properties getProperties(String path) { - return getProperties(path, false); + return getProperties(path, false, true, true); } protected Properties getProperties(String path, boolean required) { + return getProperties(path, required, true, true); + } + + protected Properties getProperties(String path, boolean required, boolean searchClasspath, boolean searchWebapp) + { if (getLog().isTraceEnabled()) { getLog().trace("Searching for properties at {} ", path); } - - InputStream inputStream = getInputStream(path, required); + InputStream inputStream = ServletUtils.getInputStream(path, this.servletContext, searchClasspath, searchWebapp); if (inputStream == null) { + String msg = "Did not find resource at: "+path; + if (required) + { + getLog().error(msg); + throw new ResourceNotFoundException(msg); + } + else + { + getLog().debug(msg); + } return null; } @@ -589,15 +606,9 @@ public class VelocityView extends ViewTo } catch (RuntimeException re) { - if (required) - { - getLog().error(re.getMessage(), re); - throw re; - } - else - { - getLog().debug(re.getMessage(), re); - } + // even if the file is not required, an error inside it is considered fatal + getLog().error(re.getMessage(), re); + throw re; } return config; } Modified: velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/WebappResourceLoader.java URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/WebappResourceLoader.java?rev=1833882&r1=1833881&r2=1833882&view=diff ============================================================================== --- velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/WebappResourceLoader.java (original) +++ velocity/tools/trunk/velocity-tools-view/src/main/java/org/apache/velocity/tools/view/WebappResourceLoader.java Wed Jun 20 00:47:45 2018 @@ -22,6 +22,8 @@ package org.apache.velocity.tools.view; import java.io.File; import java.io.InputStream; import java.io.Reader; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.HashMap; import javax.servlet.ServletContext; import org.apache.velocity.exception.ResourceNotFoundException; @@ -142,11 +144,26 @@ public class WebappResourceLoader extend Exception exception = null; for (int i = 0; i < paths.length; i++) { - String path = paths[i] + name; + final String path = paths[i] + name; InputStream rawStream = null; try { - rawStream = servletContext.getResourceAsStream(path); + if (System.getSecurityManager() != null) + { + rawStream = AccessController.doPrivileged( + new PrivilegedAction<InputStream>() + { + @Override + public InputStream run() + { + return servletContext.getResourceAsStream(path); + } + }); + } + else + { + rawStream = servletContext.getResourceAsStream(path); + } if (rawStream != null) { result = buildReader(rawStream, encoding); Modified: velocity/tools/trunk/velocity-tools-view/src/test/java/org/apache/velocity/tools/view/VelocityViewTest.java URL: http://svn.apache.org/viewvc/velocity/tools/trunk/velocity-tools-view/src/test/java/org/apache/velocity/tools/view/VelocityViewTest.java?rev=1833882&r1=1833881&r2=1833882&view=diff ============================================================================== --- velocity/tools/trunk/velocity-tools-view/src/test/java/org/apache/velocity/tools/view/VelocityViewTest.java (original) +++ velocity/tools/trunk/velocity-tools-view/src/test/java/org/apache/velocity/tools/view/VelocityViewTest.java Wed Jun 20 00:47:45 2018 @@ -22,6 +22,7 @@ package org.apache.velocity.tools.view; import static org.junit.Assert.*; import static org.easymock.EasyMock.*; +import java.io.File; import java.io.IOException; import java.io.StringWriter; @@ -64,6 +65,14 @@ public class VelocityViewTest expect(config.findInitParameter(VelocityView.USER_OVERWRITE_KEY)).andReturn(null); expect(config.findInitParameter(VelocityView.LOAD_DEFAULTS_KEY)).andReturn("false"); expect(servletContext.getInitParameter(VelocityView.PROPERTIES_KEY)).andReturn(null); + expect(servletContext.getResourceAsStream(VelocityView.USER_PROPERTIES_PATH)) + .andReturn(getClass().getResourceAsStream("/WEB-INF/velocity.properties")); + expect(servletContext.getResourceAsStream("/VM_global_library.vm")) + .andReturn(getClass().getResourceAsStream("/VM_global_library.vm")); + expect(servletContext.getResourceAsStream("/VM_global_library.vm")) + .andReturn(getClass().getResourceAsStream("/VM_global_library.vm")); + String root = new File(getClass().getResource("/").getFile()).getAbsolutePath(); + expect(servletContext.getRealPath("/")).andReturn(root); expect(config.getInitParameter(VelocityView.PROPERTIES_KEY)).andReturn(null); expect(config.findInitParameter(VelocityView.CLEAN_CONFIGURATION_KEY)).andReturn(null); expect(servletContext.getInitParameter(VelocityView.TOOLS_KEY)).andReturn(null); @@ -71,9 +80,11 @@ public class VelocityViewTest expect(servletContext.getAttribute(ServletUtils.CONFIGURATION_KEY)).andReturn(null); expect(servletContext.getResourceAsStream(VelocityView.USER_TOOLS_PATH)) .andReturn(getClass().getResourceAsStream("/org/apache/velocity/tools/view/tools.xml")); - expect(request.getAttribute("javax.servlet.include.servlet_path")).andReturn("/charset-test.vm"); expect(request.getAttribute("javax.servlet.include.path_info")).andReturn(null); + expect(servletContext.getResourceAsStream("/charset-test.vm")) + .andReturn(getClass().getResourceAsStream("/charset-test.vm")); + expect(servletContext.getRealPath("/")).andReturn(root); // This was necessary to verify the bug, now it is not called at all. // expect(response.getCharacterEncoding()).andReturn("ISO-8859-1");