polishing API and javadocs.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/c5e9fe30 Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/c5e9fe30 Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/c5e9fe30 Branch: refs/heads/3 Commit: c5e9fe30857c3175a777df62416caff283ed6fea Parents: 6ff7849 Author: Woonsan Ko <[email protected]> Authored: Tue Jul 4 00:03:43 2017 -0400 Committer: Woonsan Ko <[email protected]> Committed: Tue Jul 4 00:03:43 2017 -0400 ---------------------------------------------------------------------- .../spring/web/view/AbstractFreemarkerView.java | 107 +++++++++++++++---- .../spring/web/view/FreemarkerView.java | 56 +++++++++- .../spring/web/view/FreemarkerViewResolver.java | 98 +++++++++++------ .../spring/web/view/PageContextServlet.java | 5 +- .../web/view/PageContextServletConfig.java | 6 +- 5 files changed, 214 insertions(+), 58 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c5e9fe30/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/AbstractFreemarkerView.java ---------------------------------------------------------------------- diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/AbstractFreemarkerView.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/AbstractFreemarkerView.java index cb13ac4..2996aa9 100644 --- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/AbstractFreemarkerView.java +++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/AbstractFreemarkerView.java @@ -19,7 +19,6 @@ package org.apache.freemarker.spring.web.view; import java.io.IOException; -import java.io.Serializable; import java.util.Locale; import java.util.Map; @@ -33,56 +32,103 @@ import org.apache.freemarker.core.TemplateNotFoundException; import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper; import org.apache.freemarker.core.model.TemplateHashModel; import org.apache.freemarker.core.templateresolver.MalformedTemplateNameException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContextException; import org.springframework.web.servlet.view.AbstractTemplateView; +/** + * Adapter base class for FreeMarker template-based views, with the ability to access {@link Configuration} + * and {@link ObjectWrapperAndUnwrapper}. + */ public abstract class AbstractFreemarkerView extends AbstractTemplateView { + private static Logger log = LoggerFactory.getLogger(AbstractFreemarkerView.class); + + /** + * FreeMarker {@link Configuration} instance. + */ private Configuration configuration; + + /** + * {@link ObjectWrapperAndUnwrapper} instance to use in model building. + */ private ObjectWrapperAndUnwrapper objectWrapper; - // TODO: how to determine locale, customLookupCondition and ignoreMissing? From viewResolver settings? + /** + * Template {@link Locale}. + */ private Locale locale; - private Serializable customLookupCondition; - private boolean ignoreMissing; + /** + * Get FreeMarker {@link Configuration} instance. + * @return {@link Configuration} instance + */ public Configuration getConfiguration() { return configuration; } + /** + * Set FreeMarker {@link Configuration} instance. + * @param configuration {@link Configuration} instance + */ public void setConfiguration(Configuration configuration) { this.configuration = configuration; } + /** + * Get {@link ObjectWrapperAndUnwrapper} that is used in model building. + * @return {@link ObjectWrapperAndUnwrapper} that is used in model building + */ public ObjectWrapperAndUnwrapper getObjectWrapper() { return objectWrapper; } + /** + * Set {@link ObjectWrapperAndUnwrapper} that is used in model building. + * @param objectWrapper {@link ObjectWrapperAndUnwrapper} that is used in model building + */ public void setObjectWrapper(ObjectWrapperAndUnwrapper objectWrapper) { this.objectWrapper = objectWrapper; } + /** + * Get template locale. + * @return template locale + */ public Locale getLocale() { return locale; } + /** + * Set template locale. + * @param locale template locale + */ public void setLocale(Locale locale) { this.locale = locale; } - public Serializable getCustomLookupCondition() { - return customLookupCondition; - } - - public void setCustomLookupCondition(Serializable customLookupCondition) { - this.customLookupCondition = customLookupCondition; - } - - public boolean isIgnoreMissing() { - return ignoreMissing; - } - - public void setIgnoreMissing(boolean ignoreMissing) { - this.ignoreMissing = ignoreMissing; + @Override + public boolean checkResource(Locale locale) throws Exception { + if (this.locale == null) { + this.locale = locale; + } + + try { + // Check whether the underlying resource exists by trying to get the template. + getTemplate(); + return true; + } catch (TemplateNotFoundException e) { + log.debug("No view found for URL: {}", getUrl()); + } catch (MalformedTemplateNameException e) { + throw new ApplicationContextException("Malformed template name: " + getUrl(), e); + } catch (ParseException e) { + throw new ApplicationContextException("Template parsing exception: " + getUrl(), e); + } catch (IOException e) { + throw new ApplicationContextException("Template IO exception: " + getUrl(), e); + } + + return false; } @Override @@ -91,11 +137,34 @@ public abstract class AbstractFreemarkerView extends AbstractTemplateView { getTemplate().process(createModel(model, getObjectWrapper(), request, response), response.getWriter()); } + /** + * Get template from the FreeMarker {@link Configuration} instance. + * @return template from the FreeMarker {@link Configuration} instance + * @throws TemplateNotFoundException if template is not found + * @throws MalformedTemplateNameException if template name is malformed + * @throws ParseException if the template is syntactically bad + * @throws IOException if template cannot be read due to IO error + */ protected Template getTemplate() throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException { - return getConfiguration().getTemplate(getUrl(), getLocale(), getCustomLookupCondition(), isIgnoreMissing()); + return getConfiguration().getTemplate(normalizeTemplateName(getUrl()), getLocale()); } + /** + * Create model for the template. + * @param map map as initial source for the template model + * @param objectWrapperForModel ObjectWrapper to be used in model building + * @param request request + * @param response response + * @return model for the template + */ protected abstract TemplateHashModel createModel(Map<String, Object> map, ObjectWrapperAndUnwrapper objectWrapperForModel, HttpServletRequest request, HttpServletResponse response); + + private String normalizeTemplateName(String name) { + if (name != null) { + return (name.startsWith("/")) ? name.substring(1) : name; + } + return null; + } } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c5e9fe30/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/FreemarkerView.java ---------------------------------------------------------------------- diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/FreemarkerView.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/FreemarkerView.java index 2210b98..f3ac63b 100644 --- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/FreemarkerView.java +++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/FreemarkerView.java @@ -20,6 +20,7 @@ package org.apache.freemarker.spring.web.view; import java.util.Map; +import javax.servlet.GenericServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @@ -34,32 +35,74 @@ import org.apache.freemarker.servlet.HttpSessionHashModel; import org.apache.freemarker.servlet.ServletContextHashModel; import org.apache.freemarker.servlet.jsp.TaglibFactory; +/** + * FreeMarker template based view implementation, with being able to provide a {@link ServletContextHashModel} + * and {@link TaglibFactory} models to the templates. + */ public class FreemarkerView extends AbstractFreemarkerView { - private PageContextServlet pageContextServlet; + /** + * Internal servlet instance to provide a page object in JSP tag library usages. + * @see {@link javax.servlet.jsp.PageContext#getPage()} + */ + private GenericServlet pageContextServlet; + + /** + * {@link ServletContextHashModel} instance for templates to access servlet context attributes. + */ private ServletContextHashModel servletContextModel; + + /** + * {@link TaglibFactory} instance for templates to be able to use JSP tag libraries. + */ private TaglibFactory taglibFactory; - public PageContextServlet getPageContextServlet() { + /** + * Get {@link GenericServlet} instance which is a page object in JSP tag library usages. + * @return {@link GenericServlet} instance which is a page object in JSP tag library usages + */ + public GenericServlet getPageContextServlet() { return pageContextServlet; } - public void setPageContextServlet(PageContextServlet pageContextServlet) { + /** + * Set {@link GenericServlet} instance which is a page object in JSP tag library usages. + * @param pageContextServlet {@link GenericServlet} instance which is a page object in JSP tag library + * usages + */ + public void setPageContextServlet(GenericServlet pageContextServlet) { this.pageContextServlet = pageContextServlet; } + /** + * Get {@link ServletContextHashModel} instance by which templates can access servlet context attributes. + * @return {@link ServletContextHashModel} instance by which templates can access servlet context attributes + */ public ServletContextHashModel getServletContextModel() { return servletContextModel; } + /** + * Set {@link ServletContextHashModel} instance by which templates can access servlet context attributes. + * @param servletContextModel {@link ServletContextHashModel} instance by which templates can access servlet + * context attributes + */ public void setServletContextModel(ServletContextHashModel servletContextModel) { this.servletContextModel = servletContextModel; } + /** + * Get {@link TaglibFactory} instance by which templates can use JSP tag libraries. + * @return {@link TaglibFactory} instance by which templates can use JSP tag libraries. + */ public TaglibFactory getTaglibFactory() { return taglibFactory; } + /** + * Set {@link TaglibFactory} instance by which templates can use JSP tag libraries. + * @param taglibFactory {@link TaglibFactory} instance by which templates can use JSP tag libraries. + */ public void setTaglibFactory(TaglibFactory taglibFactory) { this.taglibFactory = taglibFactory; } @@ -96,6 +139,13 @@ public class FreemarkerView extends AbstractFreemarkerView { return model; } + /** + * Get {@link HttpSessionHashModel} instance by which templates can access session attributes. + * @param objectWrapperForModel ObjectWrapper to be used in model building + * @param request request + * @param response response + * @return {@link HttpSessionHashModel} instance by which templates can access session attributes + */ protected HttpSessionHashModel getHttpSessionModel(ObjectWrapperAndUnwrapper objectWrapperForModel, HttpServletRequest request, HttpServletResponse response) { HttpSessionHashModel sessionModel; http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c5e9fe30/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/FreemarkerViewResolver.java ---------------------------------------------------------------------- diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/FreemarkerViewResolver.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/FreemarkerViewResolver.java index 5f7d6fb..57e6c4c 100644 --- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/FreemarkerViewResolver.java +++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/FreemarkerViewResolver.java @@ -18,6 +18,7 @@ */ package org.apache.freemarker.spring.web.view; +import javax.servlet.GenericServlet; import javax.servlet.ServletException; import org.apache.freemarker.core.Configuration; @@ -29,50 +30,72 @@ import org.apache.freemarker.servlet.jsp.TaglibFactoryBuilder; import org.springframework.beans.factory.InitializingBean; import org.springframework.web.servlet.view.AbstractTemplateViewResolver; import org.springframework.web.servlet.view.AbstractUrlBasedView; - +import org.springframework.web.servlet.view.UrlBasedViewResolver; + +/** + * FreeMarker template view resolver implementation, extending {@link AbstractTemplateViewResolver} that extends + * {@link UrlBasedViewResolver}. + * <p> + * The FreeMarker {@link Configuration} property must be set at least. Otherwise this throws {@link IllegalStateException} + * during initialization. In the bean initialization phase, this retrieves {@link ObjectWrapperAndUnwrapper} from + * the {@link Configuration} and instantiate the internal page object ({@link PageContextServlet}) for JSP tag + * library usages, {@link ServletContextHashModel} property for servlet context attribute accesses and {@link TaglibFactory} + * property for JSP tag library usages. + * </p> + */ public class FreemarkerViewResolver extends AbstractTemplateViewResolver implements InitializingBean { + /** + * FreeMarker {@link Configuration} instance. + */ private Configuration configuration; + /** + * {@link ObjectWrapperAndUnwrapper} instance to be used in model building. + */ private ObjectWrapperAndUnwrapper objectWrapper; - private PageContextServlet pageContextServlet; + + /** + * Internal servlet instance to provide a page object in JSP tag library usages. + * @see {@link javax.servlet.jsp.PageContext#getPage()} + */ + private GenericServlet pageContextServlet; + + /** + * {@link ServletContextHashModel} instance for templates to access servlet context attributes. + */ private ServletContextHashModel servletContextModel; - private TaglibFactory taglibFactory; - private String normalizedPrefix; + /** + * {@link TaglibFactory} instance for templates to be able to use JSP tag libraries. + */ + private TaglibFactory taglibFactory; + /** + * Constructs view resolver. + */ public FreemarkerViewResolver() { - setViewClass(requiredViewClass()); - } - - public FreemarkerViewResolver(String prefix, String suffix) { - this(); - setPrefix(prefix); - setSuffix(suffix); + super(); + setViewClass(FreemarkerView.class); } + /** + * Get FreeMarker {@link Configuration} instance. + * @return FreeMarker {@link Configuration} instance + */ public Configuration getConfiguration() { return configuration; } + /** + * Set FreeMarker {@link Configuration} instance. + * @param configuration FreeMarker {@link Configuration} instance + */ public void setConfiguration(Configuration configuration) { this.configuration = configuration; } @Override - public void setPrefix(String prefix) { - super.setPrefix(prefix); - - final String prefixValue = getPrefix(); - - if (prefixValue.startsWith("/")) { - normalizedPrefix = prefixValue.substring(1); - } else { - normalizedPrefix = prefixValue; - } - } - - @Override public void afterPropertiesSet() throws Exception { if (configuration == null) { throw new IllegalStateException("Configuration is not set."); @@ -98,7 +121,7 @@ public class FreemarkerViewResolver extends AbstractTemplateViewResolver impleme try { pageContextServlet - .init(new PageContextServletConfig(getServletContext(), FreemarkerViewResolver.class.getName())); + .init(new PageContextServletConfig(getServletContext(), PageContextServlet.class.getSimpleName())); } catch (ServletException e) { // never happens... } @@ -116,13 +139,6 @@ public class FreemarkerViewResolver extends AbstractTemplateViewResolver impleme @Override protected AbstractUrlBasedView buildView(String viewName) throws Exception { FreemarkerView view = (FreemarkerView) super.buildView(viewName); - final String url; - if (normalizedPrefix != null) { - url = normalizedPrefix + viewName + getSuffix(); - } else { - url = viewName + getSuffix(); - } - view.setUrl(url); view.setConfiguration(configuration); view.setObjectWrapper(objectWrapper); view.setPageContextServlet(pageContextServlet); @@ -131,18 +147,34 @@ public class FreemarkerViewResolver extends AbstractTemplateViewResolver impleme return view; } + /** + * Get {@link ObjectWrapperAndUnwrapper} that is used in model building. + * @return {@link ObjectWrapperAndUnwrapper} that is used in model building + */ protected ObjectWrapperAndUnwrapper getObjectWrapper() { return objectWrapper; } - protected PageContextServlet getPageContextServlet() { + /** + * Get {@link GenericServlet} instance which is a page object in JSP tag library usages. + * @return {@link GenericServlet} instance which is a page object in JSP tag library usages + */ + protected GenericServlet getPageContextServlet() { return pageContextServlet; } + /** + * Get {@link ServletContextHashModel} instance by which templates can access servlet context attributes. + * @return {@link ServletContextHashModel} instance by which templates can access servlet context attributes + */ protected ServletContextHashModel getServletContextModel() { return servletContextModel; } + /** + * Get {@link TaglibFactory} instance by which templates can use JSP tag libraries. + * @return {@link TaglibFactory} instance by which templates can use JSP tag libraries. + */ protected TaglibFactory getTaglibFactory() { return taglibFactory; } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c5e9fe30/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/PageContextServlet.java ---------------------------------------------------------------------- diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/PageContextServlet.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/PageContextServlet.java index 94b586b..d2b7868 100644 --- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/PageContextServlet.java +++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/PageContextServlet.java @@ -26,10 +26,11 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; /** - * <code>GenericServlet</code> to support {@link javax.servlet.jsp.PageContext#getPage()} when JspTaglibs is used. + * A built-in internal servlet class to be used as page object in JSP tag libraries used in FreeMarker templates. + * @see {@link javax.servlet.jsp.PageContext#getPage()} */ @SuppressWarnings("serial") -class PageContextServlet extends GenericServlet { +final class PageContextServlet extends GenericServlet { @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c5e9fe30/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/PageContextServletConfig.java ---------------------------------------------------------------------- diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/PageContextServletConfig.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/PageContextServletConfig.java index 0d42ba4..de94649 100644 --- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/PageContextServletConfig.java +++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/web/view/PageContextServletConfig.java @@ -24,7 +24,11 @@ import java.util.Enumeration; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; -class PageContextServletConfig implements ServletConfig { +/** + * A built-in internal {@link ServletConfig} class used when initializing the page context servlet + * ({@link PageContextServlet}) internally. + */ +final class PageContextServletConfig implements ServletConfig { private ServletContext servletContext; private String servletName;
