001/* 002 * Copyright 2002-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.servlet.view.freemarker; 018 019import java.io.IOException; 020import java.util.List; 021import javax.servlet.ServletContext; 022 023import freemarker.cache.ClassTemplateLoader; 024import freemarker.cache.TemplateLoader; 025import freemarker.ext.jsp.TaglibFactory; 026import freemarker.template.Configuration; 027import freemarker.template.TemplateException; 028 029import org.springframework.beans.factory.InitializingBean; 030import org.springframework.context.ResourceLoaderAware; 031import org.springframework.ui.freemarker.FreeMarkerConfigurationFactory; 032import org.springframework.web.context.ServletContextAware; 033 034/** 035 * JavaBean to configure FreeMarker for web usage, via the "configLocation" 036 * and/or "freemarkerSettings" and/or "templateLoaderPath" properties. 037 * The simplest way to use this class is to specify just a "templateLoaderPath"; 038 * you do not need any further configuration then. 039 * 040 * <pre class="code"> 041 * <bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> 042 * <property name="templateLoaderPath"><value>/WEB-INF/freemarker/</value></property> 043 * </bean></pre> 044 * 045 * This bean must be included in the application context of any application 046 * using Spring's FreeMarkerView for web MVC. It exists purely to configure FreeMarker. 047 * It is not meant to be referenced by application components but just internally 048 * by FreeMarkerView. Implements FreeMarkerConfig to be found by FreeMarkerView without 049 * depending on the bean name the configurer. Each DispatcherServlet can define its 050 * own FreeMarkerConfigurer if desired. 051 * 052 * <p>Note that you can also refer to a preconfigured FreeMarker Configuration 053 * instance, for example one set up by FreeMarkerConfigurationFactoryBean, via 054 * the "configuration" property. This allows to share a FreeMarker Configuration 055 * for web and email usage, for example. 056 * 057 * <p>This configurer registers a template loader for this package, allowing to 058 * reference the "spring.ftl" macro library (contained in this package and thus 059 * in spring.jar) like this: 060 * 061 * <pre class="code"> 062 * <#import "/spring.ftl" as spring/> 063 * <@spring.bind "person.age"/> 064 * age is ${spring.status.value}</pre> 065 * 066 * Note: Spring's FreeMarker support requires FreeMarker 2.3 or higher. 067 * 068 * @author Darren Davison 069 * @author Rob Harrop 070 * @since 03.03.2004 071 * @see #setConfigLocation 072 * @see #setFreemarkerSettings 073 * @see #setTemplateLoaderPath 074 * @see #setConfiguration 075 * @see org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean 076 * @see FreeMarkerView 077 */ 078public class FreeMarkerConfigurer extends FreeMarkerConfigurationFactory 079 implements FreeMarkerConfig, InitializingBean, ResourceLoaderAware, ServletContextAware { 080 081 private Configuration configuration; 082 083 private TaglibFactory taglibFactory; 084 085 086 /** 087 * Set a preconfigured Configuration to use for the FreeMarker web config, e.g. a 088 * shared one for web and email usage, set up via FreeMarkerConfigurationFactoryBean. 089 * If this is not set, FreeMarkerConfigurationFactory's properties (inherited by 090 * this class) have to be specified. 091 * @see org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean 092 */ 093 public void setConfiguration(Configuration configuration) { 094 this.configuration = configuration; 095 } 096 097 /** 098 * Initialize the {@link TaglibFactory} for the given ServletContext. 099 */ 100 @Override 101 public void setServletContext(ServletContext servletContext) { 102 this.taglibFactory = new TaglibFactory(servletContext); 103 } 104 105 106 /** 107 * Initialize FreeMarkerConfigurationFactory's Configuration 108 * if not overridden by a preconfigured FreeMarker Configuation. 109 * <p>Sets up a ClassTemplateLoader to use for loading Spring macros. 110 * @see #createConfiguration 111 * @see #setConfiguration 112 */ 113 @Override 114 public void afterPropertiesSet() throws IOException, TemplateException { 115 if (this.configuration == null) { 116 this.configuration = createConfiguration(); 117 } 118 } 119 120 /** 121 * This implementation registers an additional ClassTemplateLoader 122 * for the Spring-provided macros, added to the end of the list. 123 */ 124 @Override 125 protected void postProcessTemplateLoaders(List<TemplateLoader> templateLoaders) { 126 templateLoaders.add(new ClassTemplateLoader(FreeMarkerConfigurer.class, "")); 127 logger.info("ClassTemplateLoader for Spring macros added to FreeMarker configuration"); 128 } 129 130 131 /** 132 * Return the Configuration object wrapped by this bean. 133 */ 134 @Override 135 public Configuration getConfiguration() { 136 return this.configuration; 137 } 138 139 /** 140 * Return the TaglibFactory object wrapped by this bean. 141 */ 142 @Override 143 public TaglibFactory getTaglibFactory() { 144 return this.taglibFactory; 145 } 146 147}