1 16 17 package org.springframework.web.servlet.view.freemarker; 18 19 import java.io.IOException ; 20 import java.util.Locale ; 21 import java.util.Map ; 22 23 import javax.servlet.GenericServlet ; 24 import javax.servlet.ServletContext ; 25 import javax.servlet.ServletRequest ; 26 import javax.servlet.ServletResponse ; 27 import javax.servlet.http.HttpServletRequest ; 28 import javax.servlet.http.HttpServletResponse ; 29 import javax.servlet.http.HttpSession ; 30 31 import freemarker.core.ParseException; 32 import freemarker.ext.jsp.TaglibFactory; 33 import freemarker.ext.servlet.FreemarkerServlet; 34 import freemarker.ext.servlet.HttpRequestHashModel; 35 import freemarker.ext.servlet.HttpRequestParametersHashModel; 36 import freemarker.ext.servlet.HttpSessionHashModel; 37 import freemarker.ext.servlet.ServletContextHashModel; 38 import freemarker.template.Configuration; 39 import freemarker.template.ObjectWrapper; 40 import freemarker.template.Template; 41 import freemarker.template.TemplateException; 42 43 import org.springframework.beans.BeansException; 44 import org.springframework.beans.factory.BeanFactoryUtils; 45 import org.springframework.beans.factory.NoSuchBeanDefinitionException; 46 import org.springframework.context.ApplicationContextException; 47 import org.springframework.web.servlet.support.RequestContextUtils; 48 import org.springframework.web.servlet.view.AbstractTemplateView; 49 50 78 public class FreeMarkerView extends AbstractTemplateView { 79 80 private String encoding; 81 82 private Configuration configuration; 83 84 private TaglibFactory taglibFactory; 85 86 private ServletContextHashModel servletContextHashModel; 87 88 89 95 public void setEncoding(String encoding) { 96 this.encoding = encoding; 97 } 98 99 102 protected String getEncoding() { 103 return encoding; 104 } 105 106 115 public void setConfiguration(Configuration configuration) { 116 this.configuration = configuration; 117 } 118 119 122 protected Configuration getConfiguration() { 123 return this.configuration; 124 } 125 126 127 135 protected void initApplicationContext() throws BeansException { 136 super.initApplicationContext(); 137 138 if (getConfiguration() != null) { 139 this.taglibFactory = new TaglibFactory(getServletContext()); 140 } 141 else { 142 FreeMarkerConfig config = autodetectConfiguration(); 143 setConfiguration(config.getConfiguration()); 144 this.taglibFactory = config.getTaglibFactory(); 145 } 146 147 this.servletContextHashModel = new ServletContextHashModel( 148 new GenericServletAdapter(getServletContext()), getObjectWrapper()); 149 150 checkTemplate(); 151 } 152 153 160 protected FreeMarkerConfig autodetectConfiguration() throws BeansException { 161 try { 162 return (FreeMarkerConfig) BeanFactoryUtils.beanOfTypeIncludingAncestors( 163 getApplicationContext(), FreeMarkerConfig.class, true, false); 164 } 165 catch (NoSuchBeanDefinitionException ex) { 166 throw new ApplicationContextException( 167 "Must define a single FreeMarkerConfig bean in this web application context " + 168 "(may be inherited): FreeMarkerConfigurer is the usual implementation. " + 169 "This bean may be given any name.", ex); 170 } 171 } 172 173 178 protected ObjectWrapper getObjectWrapper() { 179 ObjectWrapper ow = getConfiguration().getObjectWrapper(); 180 return (ow != null ? ow : ObjectWrapper.DEFAULT_WRAPPER); 181 } 182 183 189 protected void checkTemplate() throws ApplicationContextException { 190 try { 191 getTemplate(getConfiguration().getLocale()); 193 } 194 catch (ParseException ex) { 195 throw new ApplicationContextException( 196 "Failed to parse FreeMarker template for URL [" + getUrl() + "]", ex); 197 } 198 catch (IOException ex) { 199 throw new ApplicationContextException( 200 "Could not load FreeMarker template for URL [" + getUrl() + "]", ex); 201 } 202 } 203 204 205 210 protected void renderMergedTemplateModel( 211 Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { 212 213 exposeHelpers(model, request); 214 doRender(model, request, response); 215 } 216 217 227 protected void exposeHelpers(Map model, HttpServletRequest request) throws Exception { 228 } 229 230 253 protected void doRender(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { 254 exposeModelAsRequestAttributes(model, request); 256 257 model.put(FreemarkerServlet.KEY_JSP_TAGLIBS, this.taglibFactory); 259 model.put(FreemarkerServlet.KEY_APPLICATION, this.servletContextHashModel); 260 model.put(FreemarkerServlet.KEY_SESSION, buildSessionModel(request, response)); 261 model.put(FreemarkerServlet.KEY_REQUEST, new HttpRequestHashModel(request, response, getObjectWrapper())); 262 model.put(FreemarkerServlet.KEY_REQUEST_PARAMETERS, new HttpRequestParametersHashModel(request)); 263 264 if (logger.isDebugEnabled()) { 265 logger.debug("Rendering FreeMarker template [" + getUrl() + "] in FreeMarkerView '" + getBeanName() + "'"); 266 } 267 Locale locale = RequestContextUtils.getLocale(request); 269 processTemplate(getTemplate(locale), model, response); 270 } 271 272 279 private HttpSessionHashModel buildSessionModel(HttpServletRequest request, HttpServletResponse response) { 280 HttpSession session = request.getSession(false); 281 if (session != null) { 282 return new HttpSessionHashModel(session, getObjectWrapper()); 283 } 284 else { 285 return new HttpSessionHashModel(null, request, response, getObjectWrapper()); 286 } 287 } 288 289 300 protected Template getTemplate(Locale locale) throws IOException { 301 return getTemplate(getUrl(), locale); 302 } 303 304 314 protected Template getTemplate(String name, Locale locale) throws IOException { 315 return (getEncoding() != null ? 316 getConfiguration().getTemplate(name, locale, getEncoding()) : 317 getConfiguration().getTemplate(name, locale)); 318 } 319 320 330 protected void processTemplate(Template template, Map model, HttpServletResponse response) 331 throws IOException , TemplateException { 332 333 template.process(model, response.getWriter()); 334 } 335 336 337 341 private static final class GenericServletAdapter extends GenericServlet { 342 343 private final ServletContext servletContext; 344 345 public GenericServletAdapter(ServletContext servletContext) { 346 this.servletContext = servletContext; 347 } 348 349 public void service(ServletRequest servletRequest, ServletResponse servletResponse) { 350 } 352 353 public ServletContext getServletContext() { 354 return this.servletContext; 355 } 356 } 357 358 } 359 | Popular Tags |