| /* |
| * 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. |
| */ |
| package freemarker.ext.servlet; |
| |
| import static freemarker.ext.servlet.FreemarkerServlet.*; |
| import static org.hamcrest.Matchers.*; |
| import static org.junit.Assert.*; |
| |
| import java.io.IOException; |
| import java.nio.charset.UnsupportedCharsetException; |
| import java.util.Locale; |
| |
| import javax.servlet.ServletContext; |
| import javax.servlet.ServletException; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.springframework.mock.web.MockHttpServletRequest; |
| import org.springframework.mock.web.MockHttpServletResponse; |
| import org.springframework.mock.web.MockServletConfig; |
| import org.springframework.mock.web.MockServletContext; |
| |
| import freemarker.cache.ConditionalTemplateConfigurationFactory; |
| import freemarker.cache.FileNameGlobMatcher; |
| import freemarker.cache.FirstMatchTemplateConfigurationFactory; |
| import freemarker.cache.StringTemplateLoader; |
| import freemarker.cache.TemplateLoader; |
| import freemarker.core.Environment; |
| import freemarker.core.TemplateConfiguration; |
| import freemarker.template.Configuration; |
| import freemarker.template.Template; |
| import freemarker.template.TemplateException; |
| |
| public class FreemarkerServletTest { |
| |
| private static final String OUTPUT_FORMAT_HEADER_FTL = "outputFormatHeader.ftl"; |
| private static final String CONTENT_TYPE_ATTR_FTL = "contentTypeAttr.ftl"; |
| private static final String CONTENT_TYPE_ATTR_WITH_CHARSET_FTL = "contentTypeAttrWithCharset.ftl"; |
| private static final String FOO_FTL = "foo.ftl"; |
| private static final String FOO_SRC_UTF8_FTL = "foo-src-utf8.ftl"; |
| private static final String FOO_OUT_UTF8_FTL = "foo-out-utf8.ftl"; |
| private static final String STD_OUTPUT_FORMAT_HTML_FTL = "stdOutputFormatHTML.ftl"; |
| private static final String STD_OUTPUT_FORMAT_XML_FTL = "stdOutputFormatXML.ftl"; |
| private static final String STD_OUTPUT_FORMAT_XHTML_FTL = "stdOutputFormatXHTML.ftl"; |
| private static final String STD_OUTPUT_FORMAT_JAVA_SCRIPT_FTL = "stdOutputFormatJavaScript.ftl"; |
| private static final String STD_OUTPUT_FORMAT_JSON_FTL = "stdOutputFormatJSON.ftl"; |
| private static final String STD_OUTPUT_FORMAT_CSS_FTL = "stdOutputFormatCSS.ftl"; |
| private static final String STD_OUTPUT_FORMAT_PLAIN_TEXT_FTL = "stdOutputFormatPlainText.ftl"; |
| private static final String STD_OUTPUT_FORMAT_RTF_FTL = "stdOutputFormatRTF.ftl"; |
| |
| private static final Locale DEFAULT_LOCALE = Locale.US; |
| private static final String CFG_DEFAULT_ENCODING = "US-ASCII"; |
| /** According to the Servlet Specification */ |
| private static final String SERVLET_RESPONSE_DEFAULT_CHARSET = "ISO-8859-1"; |
| private static final String DEFAULT_CONTENT_TYPE = "text/html"; |
| |
| private MockServletContext servletContext; |
| |
| @Before |
| public void setUp() throws Exception { |
| servletContext = new MockServletContext(); |
| servletContext.setContextPath("/"); |
| } |
| |
| @Test |
| public void testContentTypeInitParams() throws Exception { |
| // Default is INIT_PARAM_VALUE_ALWAYS, hence null is the same: |
| for (String overrideCT : new String[] { null, INIT_PARAM_VALUE_ALWAYS }) { |
| assertResponseContentTypeEquals( |
| DEFAULT_CONTENT_TYPE + "; charset=UTF-8", // <- expected |
| null, overrideCT, // <- init-params |
| FOO_FTL, null); // <- request |
| assertResponseContentTypeEquals( |
| "text/css; charset=UTF-8", // <- expected |
| "text/css", overrideCT, // <- init-params |
| FOO_FTL, null); // <- request |
| assertResponseContentTypeEquals( |
| DEFAULT_CONTENT_TYPE + "; charset=UTF-8", // <- expected |
| null, overrideCT, // <- init-params |
| FOO_FTL, "application/json"); // <- request |
| assertResponseContentTypeEquals( |
| "text/css; charset=UTF-8", // <- expected |
| "text/css", overrideCT, // <- init-params |
| FOO_FTL, "application/json"); // <- request |
| assertResponseContentTypeEquals( |
| "text/plain", // <- expected |
| null, overrideCT, // <- init-params |
| CONTENT_TYPE_ATTR_FTL, "application/json"); // <- request |
| assertResponseContentTypeEquals( |
| "text/plain; charset=UTF-8", // <- expected |
| null, overrideCT, // <- init-params |
| OUTPUT_FORMAT_HEADER_FTL, "application/json"); // <- request |
| } |
| |
| assertResponseContentTypeEquals( |
| DEFAULT_CONTENT_TYPE + "; charset=UTF-8", // <- expected |
| null, INIT_PARAM_VALUE_WHEN_TEMPLATE_HAS_MIME_TYPE, // <- init-params |
| FOO_FTL, null); // <- request |
| assertResponseContentTypeEquals( |
| "text/css; charset=UTF-8", // <- expected |
| "text/css", INIT_PARAM_VALUE_WHEN_TEMPLATE_HAS_MIME_TYPE, // <- init-params |
| FOO_FTL, null); // <- request |
| assertResponseContentTypeEquals( |
| "application/json", // <- expected |
| null, INIT_PARAM_VALUE_WHEN_TEMPLATE_HAS_MIME_TYPE, // <- init-params |
| FOO_FTL, "application/json"); // <- request |
| assertResponseContentTypeEquals( |
| "application/json", // <- expected |
| "text/css", INIT_PARAM_VALUE_WHEN_TEMPLATE_HAS_MIME_TYPE, // <- init-params |
| FOO_FTL, "application/json"); // <- request |
| assertResponseContentTypeEquals( |
| "text/plain", // <- expected |
| null, INIT_PARAM_VALUE_WHEN_TEMPLATE_HAS_MIME_TYPE, // <- init-params |
| CONTENT_TYPE_ATTR_FTL, "application/json"); // <- request |
| assertResponseContentTypeEquals( |
| "text/plain; charset=UTF-8", // <- expected |
| null, INIT_PARAM_VALUE_WHEN_TEMPLATE_HAS_MIME_TYPE, // <- init-params |
| OUTPUT_FORMAT_HEADER_FTL, "application/json"); // <- request |
| |
| assertResponseContentTypeEquals( |
| DEFAULT_CONTENT_TYPE + "; charset=UTF-8", // <- expected |
| null, INIT_PARAM_VALUE_NEVER, // <- init-params |
| FOO_FTL, null); // <- request |
| assertResponseContentTypeEquals( |
| "text/css; charset=UTF-8", // <- expected |
| "text/css", INIT_PARAM_VALUE_NEVER, // <- init-params |
| FOO_FTL, null); // <- request |
| assertResponseContentTypeEquals( |
| "application/json", // <- expected |
| null, INIT_PARAM_VALUE_NEVER, // <- init-params |
| FOO_FTL, "application/json"); // <- request |
| assertResponseContentTypeEquals( |
| "application/json", // <- expected |
| "text/css", INIT_PARAM_VALUE_NEVER, // <- init-params |
| FOO_FTL, "application/json"); // <- request |
| assertResponseContentTypeEquals( |
| "application/json", // <- expected |
| null, INIT_PARAM_VALUE_NEVER, // <- init-params |
| CONTENT_TYPE_ATTR_FTL, "application/json"); // <- request |
| assertResponseContentTypeEquals( |
| "application/json", // <- expected |
| null, INIT_PARAM_VALUE_NEVER, // <- init-params |
| OUTPUT_FORMAT_HEADER_FTL, "application/json"); // <- request |
| } |
| |
| @Test |
| public void testStandardContentType() throws Exception { |
| assertResponseContentTypeEquals( |
| "text/html; charset=UTF-8", // <- expected |
| null, null, // <- init-params |
| STD_OUTPUT_FORMAT_HTML_FTL, null); // <- request |
| assertResponseContentTypeEquals( |
| "application/xhtml+xml; charset=UTF-8", // <- expected |
| null, null, // <- init-params |
| STD_OUTPUT_FORMAT_XHTML_FTL, null); // <- request |
| assertResponseContentTypeEquals( |
| "application/xml; charset=UTF-8", // <- expected |
| null, null, // <- init-params |
| STD_OUTPUT_FORMAT_XML_FTL, null); // <- request |
| assertResponseContentTypeEquals( |
| "application/javascript; charset=UTF-8", // <- expected |
| null, null, // <- init-params |
| STD_OUTPUT_FORMAT_JAVA_SCRIPT_FTL, null); // <- request |
| assertResponseContentTypeEquals( |
| "application/json; charset=UTF-8", // <- expected |
| null, null, // <- init-params |
| STD_OUTPUT_FORMAT_JSON_FTL, null); // <- request |
| assertResponseContentTypeEquals( |
| "text/css; charset=UTF-8", // <- expected |
| null, null, // <- init-params |
| STD_OUTPUT_FORMAT_CSS_FTL, null); // <- request |
| assertResponseContentTypeEquals( |
| "text/plain; charset=UTF-8", // <- expected |
| null, null, // <- init-params |
| STD_OUTPUT_FORMAT_PLAIN_TEXT_FTL, null); // <- request |
| assertResponseContentTypeEquals( |
| "application/rtf; charset=UTF-8", // <- expected |
| null, null, // <- init-params |
| STD_OUTPUT_FORMAT_RTF_FTL, null); // <- request |
| } |
| |
| @Test |
| public void testResponseLocaleInitParams() throws Exception { |
| assertTemplateLocaleEquals( |
| DEFAULT_LOCALE, // <- expected template locale |
| null, // <- request locale |
| null, // <- init-param |
| FOO_FTL); |
| assertTemplateLocaleEquals( |
| DEFAULT_LOCALE, // <- expected template locale |
| Locale.FRENCH, // <- request locale |
| null, // <- init-param |
| FOO_FTL); |
| assertTemplateLocaleEquals( |
| DEFAULT_LOCALE, // <- expected template locale |
| Locale.FRENCH, // <- request locale |
| INIT_PARAM_VALUE_ALWAYS, // <- init-param |
| FOO_FTL); |
| assertTemplateLocaleEquals( |
| DEFAULT_LOCALE, // <- expected template locale |
| null, // <- request locale |
| INIT_PARAM_VALUE_NEVER, // <- init-param |
| FOO_FTL); |
| assertTemplateLocaleEquals( |
| Locale.FRENCH, // <- expected template locale |
| Locale.FRENCH, // <- request locale |
| INIT_PARAM_VALUE_NEVER, // <- init-param |
| FOO_FTL); |
| } |
| |
| @Test |
| public void testResponseOutputCharsetInitParam() throws Exception { |
| for (String initParamValue : new String[] { null, FreemarkerServlet.INIT_PARAM_VALUE_LEGACY }) { |
| // Legacy mode is not aware of the outputEncoding, thus it doesn't set it: |
| assertOutputEncodingEquals( |
| CFG_DEFAULT_ENCODING, // <- expected response.characterEncoding |
| null, // <- expected env.outputEncoding |
| initParamValue, // <- init-param |
| FOO_FTL); |
| assertOutputEncodingEquals( |
| CFG_DEFAULT_ENCODING, // <- expected response.characterEncoding |
| null, // <- expected env.outputEncoding |
| initParamValue, // <- init-param |
| FOO_FTL); |
| // Legacy mode follows the source encoding of the template: |
| assertOutputEncodingEquals( |
| "UTF-8", // <- expected response.characterEncoding |
| null, // <- expected env.outputEncoding |
| initParamValue, // <- init-param |
| FOO_SRC_UTF8_FTL); |
| // Legacy mode doesn't deal with outputEncoding, but it's inherited by the Environment from the Template: |
| assertOutputEncodingEquals( |
| CFG_DEFAULT_ENCODING, // <- expected response.characterEncoding |
| "UTF-8", // <- expected env.outputEncoding |
| initParamValue, // <- init-param |
| FOO_OUT_UTF8_FTL); |
| // Charset in content type is the strongest: |
| assertOutputEncodingEquals( |
| "ISO-8859-2", // <- expected response.characterEncoding |
| null, // <- expected env.outputEncoding |
| initParamValue, // <- init-param |
| "text/html; charset=ISO-8859-2", // ContentType init-param |
| FOO_FTL); |
| assertOutputEncodingEquals( |
| "ISO-8859-2", // <- expected response.characterEncoding |
| null, // <- expected env.outputEncoding |
| initParamValue, // <- init-param |
| "text/html; charset=ISO-8859-2", // ContentType init-param |
| FOO_SRC_UTF8_FTL); |
| assertOutputEncodingEquals( |
| "UTF-8", // <- expected response.characterEncoding |
| null, // <- expected env.outputEncoding |
| initParamValue, // <- init-param |
| CONTENT_TYPE_ATTR_WITH_CHARSET_FTL); |
| assertOutputEncodingEquals( |
| "UTF-8", // <- expected response.characterEncoding |
| null, // <- expected env.outputEncoding |
| initParamValue, // <- init-param |
| "text/html; charset=ISO-8859-2", // ContentType init-param |
| CONTENT_TYPE_ATTR_WITH_CHARSET_FTL); |
| } |
| |
| // Non-legacy mode always keeps env.outputEncoding in sync. with the Servlet response encoding: |
| assertOutputEncodingEquals( |
| CFG_DEFAULT_ENCODING, // <- expected response.characterEncoding |
| CFG_DEFAULT_ENCODING, // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_FROM_TEMPLATE, // <- init-param |
| FOO_FTL); |
| // Non-legacy mode considers the template-specific outputEncoding: |
| assertOutputEncodingEquals( |
| "UTF-8", // <- expected response.characterEncoding |
| "UTF-8", // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_FROM_TEMPLATE, // <- init-param |
| FOO_OUT_UTF8_FTL); |
| // Non-legacy mode uses the template source encoding as a fallback for outputEncoding: |
| assertOutputEncodingEquals( |
| "UTF-8", // <- expected response.characterEncoding |
| "UTF-8", // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_FROM_TEMPLATE, // <- init-param |
| FOO_SRC_UTF8_FTL); |
| // Not allowed to specify the charset in the contentType init-param: |
| try { |
| assertOutputEncodingEquals( |
| null, // <- expected response.characterEncoding |
| null, // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_FROM_TEMPLATE, // <- init-param |
| "text/html; charset=ISO-8859-2", // ContentType init-param |
| FOO_FTL); |
| fail(); |
| } catch (ServletException e) { |
| assertThat(e.getCause().getCause().getMessage(), containsString(FreemarkerServlet.INIT_PARAM_VALUE_LEGACY)); |
| } |
| // But the legacy content_type template attribute can still set the output charset: |
| assertOutputEncodingEquals( |
| "UTF-8", // <- expected response.characterEncoding |
| "UTF-8", // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_FROM_TEMPLATE, // <- init-param |
| CONTENT_TYPE_ATTR_WITH_CHARSET_FTL); |
| |
| // Do not set mode: |
| assertOutputEncodingEquals( |
| SERVLET_RESPONSE_DEFAULT_CHARSET, // <- expected response.characterEncoding |
| SERVLET_RESPONSE_DEFAULT_CHARSET, // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_DO_NOT_SET, // <- init-param |
| FOO_FTL); |
| assertOutputEncodingEquals( |
| SERVLET_RESPONSE_DEFAULT_CHARSET, // <- expected response.characterEncoding |
| SERVLET_RESPONSE_DEFAULT_CHARSET, // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_DO_NOT_SET, // <- init-param |
| FOO_SRC_UTF8_FTL); |
| assertOutputEncodingEquals( |
| SERVLET_RESPONSE_DEFAULT_CHARSET, // <- expected response.characterEncoding |
| SERVLET_RESPONSE_DEFAULT_CHARSET, // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_DO_NOT_SET, // <- init-param |
| FOO_OUT_UTF8_FTL); |
| // Not allowed to specify the charset in the contentType init-param: |
| try { |
| assertOutputEncodingEquals( |
| SERVLET_RESPONSE_DEFAULT_CHARSET, // <- expected response.characterEncoding |
| SERVLET_RESPONSE_DEFAULT_CHARSET, // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_DO_NOT_SET, // <- init-param |
| "text/html; charset=ISO-8859-2", // ContentType init-param |
| FOO_FTL); |
| fail(); |
| } catch (ServletException e) { |
| assertThat(e.getCause().getCause().getMessage(), containsString(FreemarkerServlet.INIT_PARAM_VALUE_LEGACY)); |
| } |
| // The legacy content_type template attribute can still specify an output charset, though it will be ignored: |
| assertOutputEncodingEquals( |
| SERVLET_RESPONSE_DEFAULT_CHARSET, // <- expected response.characterEncoding |
| SERVLET_RESPONSE_DEFAULT_CHARSET, // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_DO_NOT_SET, // <- init-param |
| CONTENT_TYPE_ATTR_WITH_CHARSET_FTL); |
| |
| // Forced mode: |
| assertOutputEncodingEquals( |
| "UTF-16LE", // <- expected response.characterEncoding |
| "UTF-16LE", // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param |
| FOO_FTL); |
| assertOutputEncodingEquals( |
| "UTF-16LE", // <- expected response.characterEncoding |
| "UTF-16LE", // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param |
| FOO_SRC_UTF8_FTL); |
| assertOutputEncodingEquals( |
| "UTF-16LE", // <- expected response.characterEncoding |
| "UTF-16LE", // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param |
| FOO_OUT_UTF8_FTL); |
| try { |
| assertOutputEncodingEquals( |
| null, // <- expected response.characterEncoding |
| null, // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "noSuchCharset", // <- init-param |
| FOO_FTL); |
| fail(); |
| } catch (ServletException e) { |
| assertThat(e.getCause().getCause(), instanceOf(UnsupportedCharsetException.class)); |
| } |
| // Not allowed to specify the charset in the contentType init-param: |
| try { |
| assertOutputEncodingEquals( |
| "UTF-16LE", // <- expected response.characterEncoding |
| "UTF-16LE", // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param |
| "text/html; charset=ISO-8859-2", // ContentType init-param |
| FOO_FTL); |
| fail(); |
| } catch (ServletException e) { |
| assertThat(e.getCause().getCause().getMessage(), containsString(FreemarkerServlet.INIT_PARAM_VALUE_LEGACY)); |
| } |
| // The legacy content_type template attribute can still specify an output charset, though it will be overridden: |
| assertOutputEncodingEquals( |
| "UTF-16LE", // <- expected response.characterEncoding |
| "UTF-16LE", // <- expected env.outputEncoding |
| FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param |
| CONTENT_TYPE_ATTR_WITH_CHARSET_FTL); |
| } |
| |
| private void assertResponseContentTypeEquals( |
| String exptectContentType, |
| String ctInitParam, String overrideCTInitParam, |
| String templateName, String responseCT) |
| throws ServletException, IOException { |
| MockHttpServletRequest request = createMockHttpServletRequest(servletContext, templateName, null); |
| |
| MockHttpServletResponse response = new MockHttpServletResponse(); |
| if (responseCT != null) { |
| response.setContentType(responseCT); |
| assertEquals(responseCT, response.getContentType()); |
| } else { |
| assertNull(response.getContentType()); |
| } |
| |
| MockServletConfig servletConfig = new MockServletConfig(servletContext); |
| servletConfig.addInitParameter(Configuration.DEFAULT_ENCODING_KEY, "UTF-8"); |
| if (ctInitParam != null) { |
| servletConfig.addInitParameter(INIT_PARAM_CONTENT_TYPE, ctInitParam); |
| } |
| if (overrideCTInitParam != null) { |
| servletConfig.addInitParameter(INIT_PARAM_OVERRIDE_RESPONSE_CONTENT_TYPE, overrideCTInitParam); |
| } |
| |
| TestFreemarkerServlet freemarkerServlet = new TestFreemarkerServlet(); |
| try { |
| freemarkerServlet.init(servletConfig); |
| |
| freemarkerServlet.doGet(request, response); |
| |
| assertEquals(HttpServletResponse.SC_OK, response.getStatus()); |
| assertEquals(exptectContentType, response.getContentType()); |
| } finally { |
| freemarkerServlet.destroy(); |
| } |
| } |
| |
| private void assertTemplateLocaleEquals( |
| Locale exptectLocale, |
| Locale requestLocale, |
| String overrideResponseLocaleInitParam, |
| String templateName) |
| throws ServletException, IOException { |
| MockHttpServletRequest request = createMockHttpServletRequest(servletContext, templateName, requestLocale); |
| MockHttpServletResponse response = new MockHttpServletResponse(); |
| |
| MockServletConfig servletConfig = new MockServletConfig(servletContext); |
| |
| if (overrideResponseLocaleInitParam != null) { |
| servletConfig.addInitParameter(INIT_PARAM_OVERRIDE_RESPONSE_LOCALE, overrideResponseLocaleInitParam); |
| } |
| |
| TestFreemarkerServlet freemarkerServlet = new TestFreemarkerServlet(); |
| |
| try { |
| freemarkerServlet.init(servletConfig); |
| freemarkerServlet.doGet(request, response); |
| |
| assertEquals(HttpServletResponse.SC_OK, response.getStatus()); |
| assertEquals(exptectLocale, freemarkerServlet.lastLocale); |
| assertEquals(freemarkerServlet.lastLocale, freemarkerServlet.lastMainTemplate.getLocale()); |
| } finally { |
| freemarkerServlet.destroy(); |
| } |
| } |
| |
| private void assertOutputEncodingEquals( |
| String exptectRespCharacterEncoding, |
| String exptectEnvOutputEncoding, |
| String responseCharacterEncodingInitParam, |
| String templateName) throws ServletException, IOException { |
| assertOutputEncodingEquals( |
| exptectRespCharacterEncoding, exptectEnvOutputEncoding, |
| responseCharacterEncodingInitParam, null, |
| templateName); |
| } |
| |
| private void assertOutputEncodingEquals( |
| String exptectRespCharacterEncoding, |
| String exptectEnvOutputEncoding, |
| String responseCharacterEncodingInitParam, |
| String contentTypeInitParam, |
| String templateName) |
| throws ServletException, IOException { |
| MockHttpServletRequest request = createMockHttpServletRequest(servletContext, templateName, null); |
| MockHttpServletResponse response = new MockHttpServletResponse(); |
| |
| MockServletConfig servletConfig = new MockServletConfig(servletContext); |
| |
| if (responseCharacterEncodingInitParam != null) { |
| servletConfig.addInitParameter(INIT_PARAM_RESPONSE_CHARACTER_ENCODING, responseCharacterEncodingInitParam); |
| } |
| |
| if (contentTypeInitParam != null) { |
| servletConfig.addInitParameter(INIT_PARAM_CONTENT_TYPE, contentTypeInitParam); |
| } |
| |
| TestFreemarkerServlet freemarkerServlet = new TestFreemarkerServlet(); |
| |
| try { |
| freemarkerServlet.init(servletConfig); |
| freemarkerServlet.doGet(request, response); |
| |
| assertEquals(HttpServletResponse.SC_OK, response.getStatus()); |
| assertEquals(exptectEnvOutputEncoding, freemarkerServlet.lastOutputEncoding); |
| assertEquals(exptectRespCharacterEncoding, response.getCharacterEncoding()); |
| } finally { |
| freemarkerServlet.destroy(); |
| } |
| } |
| |
| private MockHttpServletRequest createMockHttpServletRequest(final ServletContext servletContext, |
| final String pathInfo, final Locale requestLocale) { |
| MockHttpServletRequest servletRequest = new MockHttpServletRequest(servletContext) { |
| |
| @Override |
| public Locale getLocale() { |
| return requestLocale; |
| } |
| }; |
| |
| servletRequest.setServerName("localhost"); |
| servletRequest.setServerPort(8080); |
| servletRequest.setContextPath(""); |
| servletRequest.setRequestURI(pathInfo); |
| servletRequest.setPathInfo(pathInfo); |
| |
| return servletRequest; |
| } |
| |
| static class TestFreemarkerServlet extends FreemarkerServlet { |
| |
| private Template lastMainTemplate; |
| private Locale lastLocale; |
| private String lastOutputEncoding; |
| |
| @Override |
| protected Configuration createConfiguration() { |
| Configuration cfg = super.createConfiguration(); |
| // Needed for the TemplateConfiguration that sets outputEncoding: |
| cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_22); |
| |
| // Set a test runner environment independent default locale: |
| cfg.setLocale(DEFAULT_LOCALE); |
| cfg.setDefaultEncoding(CFG_DEFAULT_ENCODING); |
| |
| { |
| TemplateConfiguration outUtf8TC = new TemplateConfiguration(); |
| outUtf8TC.setOutputEncoding("UTF-8"); |
| |
| TemplateConfiguration srcUtf8TC = new TemplateConfiguration(); |
| srcUtf8TC.setEncoding("UTF-8"); |
| |
| cfg.setTemplateConfigurations( |
| new FirstMatchTemplateConfigurationFactory( |
| new ConditionalTemplateConfigurationFactory( |
| new FileNameGlobMatcher(FOO_SRC_UTF8_FTL), srcUtf8TC), |
| new ConditionalTemplateConfigurationFactory( |
| new FileNameGlobMatcher(FOO_OUT_UTF8_FTL), outUtf8TC) |
| ) |
| .allowNoMatch(true) |
| ); |
| } |
| |
| return cfg; |
| } |
| |
| @Override |
| protected TemplateLoader createTemplateLoader(String templatePath) throws IOException { |
| // Override default template loader |
| if (templatePath.equals("class://")) { |
| StringTemplateLoader tl = new StringTemplateLoader(); |
| |
| tl.putTemplate(FOO_FTL, "foo"); |
| tl.putTemplate(FOO_SRC_UTF8_FTL, "foo"); |
| tl.putTemplate(FOO_OUT_UTF8_FTL, "foo"); |
| tl.putTemplate(CONTENT_TYPE_ATTR_FTL, "<#ftl attributes={ 'content_type': 'text/plain' }>foo"); |
| tl.putTemplate(CONTENT_TYPE_ATTR_WITH_CHARSET_FTL, "<#ftl attributes={ 'content_type': 'text/plain; charset=UTF-8' }>foo"); |
| tl.putTemplate(OUTPUT_FORMAT_HEADER_FTL, "<#ftl outputFormat='plainText'>foo"); |
| |
| tl.putTemplate(STD_OUTPUT_FORMAT_HTML_FTL, "<#ftl outputFormat='HTML'>"); |
| tl.putTemplate(STD_OUTPUT_FORMAT_XHTML_FTL, "<#ftl outputFormat='XHTML'>"); |
| tl.putTemplate(STD_OUTPUT_FORMAT_XML_FTL, "<#ftl outputFormat='XML'>"); |
| tl.putTemplate(STD_OUTPUT_FORMAT_JAVA_SCRIPT_FTL, "<#ftl outputFormat='JavaScript'>"); |
| tl.putTemplate(STD_OUTPUT_FORMAT_JSON_FTL, "<#ftl outputFormat='JSON'>"); |
| tl.putTemplate(STD_OUTPUT_FORMAT_CSS_FTL, "<#ftl outputFormat='CSS'>"); |
| tl.putTemplate(STD_OUTPUT_FORMAT_PLAIN_TEXT_FTL, "<#ftl outputFormat='plainText'>"); |
| tl.putTemplate(STD_OUTPUT_FORMAT_RTF_FTL, "<#ftl outputFormat='RTF'>"); |
| |
| return tl; |
| } else { |
| return super.createTemplateLoader(templatePath); |
| } |
| } |
| |
| @Override |
| protected void processEnvironment(Environment env, HttpServletRequest request, HttpServletResponse response) |
| throws TemplateException, IOException { |
| lastMainTemplate = env.getMainTemplate(); |
| lastLocale = env.getLocale(); |
| lastOutputEncoding = env.getOutputEncoding(); |
| super.processEnvironment(env, request, response); |
| } |
| |
| } |
| |
| } |