You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2017/07/04 07:44:17 UTC
[06/16] incubator-freemarker git commit: FREEMARKER-55: Add
TaglibFactoryBuilder to reuse TaglibFactory creation logic
FREEMARKER-55: Add TaglibFactoryBuilder to reuse TaglibFactory creation logic
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/cb4fab3a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/cb4fab3a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/cb4fab3a
Branch: refs/heads/3
Commit: cb4fab3ae483d2fb645d296aff0ab94c78a8d4b9
Parents: 8e8c724
Author: Woonsan Ko <wo...@apache.org>
Authored: Thu Jun 29 23:30:47 2017 -0400
Committer: Woonsan Ko <wo...@apache.org>
Committed: Thu Jun 29 23:30:47 2017 -0400
----------------------------------------------------------------------
.../freemarker/servlet/FreemarkerServlet.java | 170 +++++--------------
.../servlet/HttpSessionHashModel.java | 26 +--
.../servlet/jsp/TaglibFactoryBuilder.java | 149 ++++++++++++++++
.../spring/web/view/FreemarkerView.java | 112 +++++++++---
.../spring/web/view/FreemarkerViewTest.java | 1 -
5 files changed, 295 insertions(+), 163 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/cb4fab3a/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
----------------------------------------------------------------------
diff --git a/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java b/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
index cbd2fd7..923f9d4 100644
--- a/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
+++ b/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
@@ -27,9 +27,9 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.GregorianCalendar;
-import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;
@@ -65,10 +65,8 @@ import org.apache.freemarker.core.templateresolver.impl.MultiTemplateLoader;
import org.apache.freemarker.core.util._SecurityUtil;
import org.apache.freemarker.core.util._StringUtil;
import org.apache.freemarker.servlet.jsp.TaglibFactory;
-import org.apache.freemarker.servlet.jsp.TaglibFactory.ClasspathMetaInfTldSource;
-import org.apache.freemarker.servlet.jsp.TaglibFactory.ClearMetaInfTldSource;
import org.apache.freemarker.servlet.jsp.TaglibFactory.MetaInfTldSource;
-import org.apache.freemarker.servlet.jsp.TaglibFactory.WebInfPerLibJarMetaInfTldSource;
+import org.apache.freemarker.servlet.jsp.TaglibFactoryBuilder;
import org.slf4j.Logger;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -448,9 +446,9 @@ public class FreemarkerServlet extends HttpServlet {
// Note these names start with dot, so they're essentially invisible from
// a freemarker script.
- private static final String ATTR_REQUEST_MODEL = ".freemarker.Request";
- private static final String ATTR_REQUEST_PARAMETERS_MODEL = ".freemarker.RequestParameters";
- private static final String ATTR_SESSION_MODEL = ".freemarker.Session";
+ public static final String ATTR_REQUEST_MODEL = ".freemarker.Request";
+ public static final String ATTR_REQUEST_PARAMETERS_MODEL = ".freemarker.RequestParameters";
+ public static final String ATTR_SESSION_MODEL = ".freemarker.Session";
/** @deprecated We only keeps this attribute for backward compatibility, but actually aren't using it. */
@Deprecated
@@ -642,7 +640,7 @@ public class FreemarkerServlet extends HttpServlet {
} else if (name.equals(INIT_PARAM_EXCEPTION_ON_MISSING_TEMPLATE)) {
exceptionOnMissingTemplate = _StringUtil.getYesNo(value);
} else if (name.equals(INIT_PARAM_META_INF_TLD_LOCATIONS)) {
- metaInfTldSources = parseAsMetaInfTldLocations(value);
+ metaInfTldSources = TaglibFactoryBuilder.parseMetaInfTldLocations(InitParamParser.parseCommaSeparatedList(value));
} else if (name.equals(INIT_PARAM_CLASSPATH_TLDS)) {
List newClasspathTlds = new ArrayList();
if (classpathTlds != null) {
@@ -678,44 +676,6 @@ public class FreemarkerServlet extends HttpServlet {
}
LOG.debug("Using object wrapper {}", config.getObjectWrapper());
}
-
- private List/*<MetaInfTldSource>*/ parseAsMetaInfTldLocations(String value) throws ParseException {
- List/*<MetaInfTldSource>*/ metaInfTldSources = null;
-
- List/*<String>*/ values = InitParamParser.parseCommaSeparatedList(value);
- for (Iterator it = values.iterator(); it.hasNext(); ) {
- final String itemStr = (String) it.next();
- final MetaInfTldSource metaInfTldSource;
- if (itemStr.equals(META_INF_TLD_LOCATION_WEB_INF_PER_LIB_JARS)) {
- metaInfTldSource = WebInfPerLibJarMetaInfTldSource.INSTANCE;
- } else if (itemStr.startsWith(META_INF_TLD_LOCATION_CLASSPATH)) {
- String itemRightSide = itemStr.substring(META_INF_TLD_LOCATION_CLASSPATH.length()).trim();
- if (itemRightSide.length() == 0) {
- metaInfTldSource = new ClasspathMetaInfTldSource(Pattern.compile(".*", Pattern.DOTALL));
- } else if (itemRightSide.startsWith(":")) {
- final String regexpStr = itemRightSide.substring(1).trim();
- if (regexpStr.length() == 0) {
- throw new ParseException("Empty regular expression after \""
- + META_INF_TLD_LOCATION_CLASSPATH + ":\"", -1);
- }
- metaInfTldSource = new ClasspathMetaInfTldSource(Pattern.compile(regexpStr));
- } else {
- throw new ParseException("Invalid \"" + META_INF_TLD_LOCATION_CLASSPATH
- + "\" value syntax: " + value, -1);
- }
- } else if (itemStr.startsWith(META_INF_TLD_LOCATION_CLEAR)) {
- metaInfTldSource = ClearMetaInfTldSource.INSTANCE;
- } else {
- throw new ParseException("Item has no recognized source type prefix: " + itemStr, -1);
- }
- if (metaInfTldSources == null) {
- metaInfTldSources = new ArrayList();
- }
- metaInfTldSources.add(metaInfTldSource);
- }
-
- return metaInfTldSources;
- }
/**
* Create the template loader. The default implementation will create a {@link ClassTemplateLoader} if the template
@@ -1000,8 +960,8 @@ public class FreemarkerServlet extends HttpServlet {
sessionModel = (HttpSessionHashModel) session.getAttribute(ATTR_SESSION_MODEL);
if (sessionModel == null || sessionModel.isOrphaned(session)) {
sessionModel = new HttpSessionHashModel(session, objectWrapper);
- initializeSessionAndInstallModel(request, response,
- sessionModel, session);
+ session.setAttribute(ATTR_SESSION_MODEL, sessionModel);
+ initializeSession(request, response);
}
} else {
sessionModel = new HttpSessionHashModel(this, request, response, objectWrapper);
@@ -1040,73 +1000,47 @@ public class FreemarkerServlet extends HttpServlet {
* The default implementation configures it based on the servlet-init parameters and various other environmental
* settings, so if you override this method, you should call super, then adjust the result.
*/
- protected TaglibFactory createTaglibFactory(ObjectWrapper objectWrapper,
- ServletContext servletContext) throws TemplateModelException {
- TaglibFactory taglibFactory = new TaglibFactory(servletContext);
-
- taglibFactory.setObjectWrapper(objectWrapper);
-
- {
- List/*<MetaInfTldSource>*/ mergedMetaInfTldSources = new ArrayList();
+ @SuppressWarnings("unchecked")
+ protected TaglibFactory createTaglibFactory(ObjectWrapper objectWrapper, ServletContext servletContext)
+ throws TemplateModelException {
- if (metaInfTldSources != null) {
- mergedMetaInfTldSources.addAll(metaInfTldSources);
- }
-
- String sysPropVal = _SecurityUtil.getSystemProperty(SYSTEM_PROPERTY_META_INF_TLD_SOURCES, null);
- if (sysPropVal != null) {
- try {
- List metaInfTldSourcesSysProp = parseAsMetaInfTldLocations(sysPropVal);
- if (metaInfTldSourcesSysProp != null) {
- mergedMetaInfTldSources.addAll(metaInfTldSourcesSysProp);
- }
- } catch (ParseException e) {
- throw new TemplateModelException("Failed to parse system property \""
- + SYSTEM_PROPERTY_META_INF_TLD_SOURCES + "\"", e);
- }
- }
+ List<MetaInfTldSource> metaInfTldSourcesFromSysProp = null;
+ try {
+ final String prop = _SecurityUtil.getSystemProperty(SYSTEM_PROPERTY_META_INF_TLD_SOURCES, null);
+ metaInfTldSourcesFromSysProp = (List<MetaInfTldSource>) ((prop != null)
+ ? TaglibFactoryBuilder.parseMetaInfTldLocations(InitParamParser.parseCommaSeparatedList(prop))
+ : Collections.emptyList());
+ } catch (ParseException e) {
+ throw new TemplateModelException(
+ "Failed to parse system property \"" + SYSTEM_PROPERTY_META_INF_TLD_SOURCES + "\"", e);
+ }
- List/*<Pattern>*/ jettyTaglibJarPatterns = null;
- try {
- final String attrVal = (String) servletContext.getAttribute(ATTR_JETTY_CP_TAGLIB_JAR_PATTERNS);
- jettyTaglibJarPatterns = attrVal != null ? InitParamParser.parseCommaSeparatedPatterns(attrVal) : null;
- } catch (Exception e) {
- LOG.error("Failed to parse application context attribute \""
- + ATTR_JETTY_CP_TAGLIB_JAR_PATTERNS + "\" - it will be ignored", e);
- }
- if (jettyTaglibJarPatterns != null) {
- for (Iterator/*<Pattern>*/ it = jettyTaglibJarPatterns.iterator(); it.hasNext(); ) {
- Pattern pattern = (Pattern) it.next();
- mergedMetaInfTldSources.add(new ClasspathMetaInfTldSource(pattern));
- }
- }
-
- taglibFactory.setMetaInfTldSources(mergedMetaInfTldSources);
+ List<Pattern> jettyTaglibJarPatterns = null;
+ try {
+ final String attrVal = (String) servletContext.getAttribute(ATTR_JETTY_CP_TAGLIB_JAR_PATTERNS);
+ jettyTaglibJarPatterns = (attrVal != null) ? InitParamParser.parseCommaSeparatedPatterns(attrVal)
+ : Collections.emptyList();
+ } catch (Exception e) {
+ LOG.error("Failed to parse application context attribute \"" + ATTR_JETTY_CP_TAGLIB_JAR_PATTERNS
+ + "\" - it will be ignored", e);
}
-
- {
- List/*<String>*/ mergedClassPathTlds = new ArrayList();
- if (classpathTlds != null) {
- mergedClassPathTlds.addAll(classpathTlds);
- }
-
- String sysPropVal = _SecurityUtil.getSystemProperty(SYSTEM_PROPERTY_CLASSPATH_TLDS, null);
- if (sysPropVal != null) {
- try {
- List/*<String>*/ classpathTldsSysProp = InitParamParser.parseCommaSeparatedList(sysPropVal);
- if (classpathTldsSysProp != null) {
- mergedClassPathTlds.addAll(classpathTldsSysProp);
- }
- } catch (ParseException e) {
- throw new TemplateModelException("Failed to parse system property \""
- + SYSTEM_PROPERTY_CLASSPATH_TLDS + "\"", e);
- }
- }
-
- taglibFactory.setClasspathTlds(mergedClassPathTlds);
+
+ List<String> classpathTldsFromSysProp = null;
+ try {
+ final String prop = _SecurityUtil.getSystemProperty(SYSTEM_PROPERTY_CLASSPATH_TLDS, null);
+ classpathTldsFromSysProp = (prop != null) ? InitParamParser.parseCommaSeparatedList(prop)
+ : Collections.emptyList();
+ } catch (ParseException e) {
+ throw new TemplateModelException(
+ "Failed to parse system property \"" + SYSTEM_PROPERTY_CLASSPATH_TLDS + "\"", e);
}
-
- return taglibFactory;
+
+ return new TaglibFactoryBuilder(servletContext, objectWrapper)
+ .addAllMetaInfTldSources(metaInfTldSources)
+ .addAllMetaInfTldSources(metaInfTldSourcesFromSysProp)
+ .addAllJettyMetaInfTldJarPatterns(jettyTaglibJarPatterns)
+ .addAllClasspathTlds(classpathTlds)
+ .addAllClasspathTlds(classpathTldsFromSysProp).build();
}
/**
@@ -1134,14 +1068,6 @@ public class FreemarkerServlet extends HttpServlet {
protected List/*<MetaInfTldSource>*/ createDefaultMetaInfTldSources() {
return TaglibFactory.DEFAULT_META_INF_TLD_SOURCES;
}
-
- void initializeSessionAndInstallModel(HttpServletRequest request,
- HttpServletResponse response, HttpSessionHashModel sessionModel,
- HttpSession session)
- throws ServletException, IOException {
- session.setAttribute(ATTR_SESSION_MODEL, sessionModel);
- initializeSession(request, response);
- }
/**
* Maps the request URL to a template path (template name) that is passed to
@@ -1279,10 +1205,8 @@ public class FreemarkerServlet extends HttpServlet {
* @param request the actual HTTP request
* @param response the actual HTTP response
*/
- protected void initializeSession(
- HttpServletRequest request,
- HttpServletResponse response)
- throws ServletException, IOException {
+ protected void initializeSession(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/cb4fab3a/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/HttpSessionHashModel.java
----------------------------------------------------------------------
diff --git a/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/HttpSessionHashModel.java b/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/HttpSessionHashModel.java
index 216fd94..469dc29 100644
--- a/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/HttpSessionHashModel.java
+++ b/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/HttpSessionHashModel.java
@@ -21,6 +21,7 @@ package org.apache.freemarker.servlet;
import java.io.Serializable;
+import javax.servlet.GenericServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@@ -40,7 +41,7 @@ public final class HttpSessionHashModel implements TemplateHashModel, Serializab
private transient final ObjectWrapper wrapper;
// These are required for lazy initializing session
- private transient final FreemarkerServlet servlet;
+ private transient final GenericServlet servlet;
private transient final HttpServletRequest request;
private transient final HttpServletResponse response;
@@ -62,16 +63,15 @@ public final class HttpSessionHashModel implements TemplateHashModel, Serializab
* Use this constructor when the session isn't already created. It is passed
* enough parameters so that the session can be properly initialized after
* it's detected that it was created.
- * @param servlet the FreemarkerServlet that created this model. If the
- * model is not created through FreemarkerServlet, leave this argument as
- * null.
+ * @param servlet the servlet (e.g, FreemarkerServlet) that created this model. If the
+ * model is not created through FreemarkerServlet, this argument can be left as null.
* @param request the actual request
* @param response the actual response
* @param wrapper an object wrapper used to wrap session attributes
*/
- public HttpSessionHashModel(FreemarkerServlet servlet, HttpServletRequest request, HttpServletResponse response, ObjectWrapper wrapper) {
+ public HttpSessionHashModel(GenericServlet servlet, HttpServletRequest request, HttpServletResponse response, ObjectWrapper wrapper) {
this.wrapper = wrapper;
-
+
this.servlet = servlet;
this.request = request;
this.response = response;
@@ -88,8 +88,11 @@ public final class HttpSessionHashModel implements TemplateHashModel, Serializab
session = request.getSession(false);
if (session != null && servlet != null) {
try {
- servlet.initializeSessionAndInstallModel(request, response,
- this, session);
+ session.setAttribute(FreemarkerServlet.ATTR_SESSION_MODEL, this);
+
+ if (servlet instanceof FreemarkerServlet) {
+ ((FreemarkerServlet) servlet).initializeSession(request, response);
+ }
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
@@ -99,14 +102,13 @@ public final class HttpSessionHashModel implements TemplateHashModel, Serializab
}
}
- boolean isOrphaned(HttpSession currentSession) {
+ public boolean isOrphaned(HttpSession currentSession) {
return (session != null && session != currentSession) ||
(session == null && request == null);
}
-
+
@Override
- public boolean isEmpty()
- throws TemplateModelException {
+ public boolean isEmpty() throws TemplateModelException {
checkSessionExistence();
return session == null || !session.getAttributeNames().hasMoreElements();
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/cb4fab3a/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/jsp/TaglibFactoryBuilder.java
----------------------------------------------------------------------
diff --git a/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/jsp/TaglibFactoryBuilder.java b/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/jsp/TaglibFactoryBuilder.java
new file mode 100644
index 0000000..6d4405d
--- /dev/null
+++ b/freemarker-servlet/src/main/java/org/apache/freemarker/servlet/jsp/TaglibFactoryBuilder.java
@@ -0,0 +1,149 @@
+/*
+ * 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 org.apache.freemarker.servlet.jsp;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import javax.servlet.ServletContext;
+
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.servlet.FreemarkerServlet;
+import org.apache.freemarker.servlet.jsp.TaglibFactory.ClasspathMetaInfTldSource;
+import org.apache.freemarker.servlet.jsp.TaglibFactory.ClearMetaInfTldSource;
+import org.apache.freemarker.servlet.jsp.TaglibFactory.MetaInfTldSource;
+import org.apache.freemarker.servlet.jsp.TaglibFactory.WebInfPerLibJarMetaInfTldSource;
+
+public class TaglibFactoryBuilder {
+
+ private final ServletContext servletContext;
+ private final ObjectWrapper objectWrapper;
+ private List<MetaInfTldSource> metaInfTldSources = new ArrayList<>();
+ private List<String> classPathTlds = new ArrayList<>();
+
+ public TaglibFactoryBuilder(ServletContext servletContext, ObjectWrapper objectWrapper) {
+ this.servletContext = servletContext;
+ this.objectWrapper = objectWrapper;
+ }
+
+ public TaglibFactoryBuilder addMetaInfTldSource(MetaInfTldSource metaInfTldSource) {
+ metaInfTldSources.add(metaInfTldSource);
+ return this;
+ }
+
+ public TaglibFactoryBuilder addAllMetaInfTldSources(List<MetaInfTldSource> metaInfTldSources) {
+ this.metaInfTldSources.addAll(metaInfTldSources);
+ return this;
+ }
+
+ public TaglibFactoryBuilder addMetaInfTldLocation(String metaInfTldLocation) throws ParseException {
+ return addMetaInfTldSource(parseMetaInfTldLocation(metaInfTldLocation));
+ }
+
+ public TaglibFactoryBuilder addMetaInfTldLocations(List<String> metaInfTldLocations) throws ParseException {
+ return addAllMetaInfTldSources(parseMetaInfTldLocations(metaInfTldLocations));
+ }
+
+ public TaglibFactoryBuilder addJettyMetaInfTldJarPattern(Pattern pattern) {
+ return addMetaInfTldSource(new ClasspathMetaInfTldSource(pattern));
+ }
+
+ public TaglibFactoryBuilder addAllJettyMetaInfTldJarPatterns(List<Pattern> patterns) {
+ for (Pattern pattern : patterns) {
+ addJettyMetaInfTldJarPattern(pattern);
+ }
+
+ return this;
+ }
+
+ public TaglibFactoryBuilder addClasspathTld(String classpathTld) {
+ classPathTlds.add(classpathTld);
+ return this;
+ }
+
+ public TaglibFactoryBuilder addAllClasspathTlds(List<String> classpathTlds) {
+ classPathTlds.addAll(classpathTlds);
+ return this;
+ }
+
+ public TaglibFactory build() {
+ TaglibFactory taglibFactory = new TaglibFactory(servletContext);
+ taglibFactory.setObjectWrapper(objectWrapper);
+ taglibFactory.setMetaInfTldSources(metaInfTldSources);
+ taglibFactory.setClasspathTlds(classPathTlds);
+ return taglibFactory;
+ }
+
+ public static MetaInfTldSource parseMetaInfTldLocation(String value) throws ParseException {
+ MetaInfTldSource metaInfTldSource;
+
+ if (value.equals(FreemarkerServlet.META_INF_TLD_LOCATION_WEB_INF_PER_LIB_JARS)) {
+ metaInfTldSource = WebInfPerLibJarMetaInfTldSource.INSTANCE;
+ } else if (value.startsWith(FreemarkerServlet.META_INF_TLD_LOCATION_CLASSPATH)) {
+ String itemRightSide = value.substring(FreemarkerServlet.META_INF_TLD_LOCATION_CLASSPATH.length())
+ .trim();
+
+ if (itemRightSide.length() == 0) {
+ metaInfTldSource = new ClasspathMetaInfTldSource(Pattern.compile(".*", Pattern.DOTALL));
+ } else if (itemRightSide.startsWith(":")) {
+ final String regexpStr = itemRightSide.substring(1).trim();
+ if (regexpStr.length() == 0) {
+ throw new ParseException("Empty regular expression after \""
+ + FreemarkerServlet.META_INF_TLD_LOCATION_CLASSPATH + ":\"", -1);
+ }
+ metaInfTldSource = new ClasspathMetaInfTldSource(Pattern.compile(regexpStr));
+ } else {
+ throw new ParseException("Invalid \"" + FreemarkerServlet.META_INF_TLD_LOCATION_CLASSPATH
+ + "\" value syntax: " + value, -1);
+ }
+ } else if (value.startsWith(FreemarkerServlet.META_INF_TLD_LOCATION_CLEAR)) {
+ metaInfTldSource = ClearMetaInfTldSource.INSTANCE;
+ } else {
+ throw new ParseException("Item has no recognized source type prefix: " + value, -1);
+ }
+
+ return metaInfTldSource;
+ }
+
+ public static List<MetaInfTldSource> parseMetaInfTldLocations(List<String> values) throws ParseException {
+ List<MetaInfTldSource> metaInfTldSources = null;
+
+ if (values != null) {
+ for (String value : values) {
+ final MetaInfTldSource metaInfTldSource = parseMetaInfTldLocation(value);
+
+ if (metaInfTldSources == null) {
+ metaInfTldSources = new ArrayList();
+ }
+
+ metaInfTldSources.add(metaInfTldSource);
+ }
+ }
+
+ if (metaInfTldSources == null) {
+ metaInfTldSources = Collections.emptyList();
+ }
+
+ return metaInfTldSources;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/cb4fab3a/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 934a458..64b3158 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
@@ -31,6 +31,7 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
import org.apache.freemarker.core.model.TemplateHashModel;
@@ -41,31 +42,38 @@ import org.apache.freemarker.servlet.HttpRequestParametersHashModel;
import org.apache.freemarker.servlet.HttpSessionHashModel;
import org.apache.freemarker.servlet.ServletContextHashModel;
import org.apache.freemarker.servlet.jsp.TaglibFactory;
+import org.apache.freemarker.servlet.jsp.TaglibFactoryBuilder;
public class FreemarkerView extends AbstractFreemarkerView {
- private PageContextServletConfig pageContextServletConfig;
+ private volatile PageContextServlet pageContextServlet;
- private PageContextServlet pageContextServlet;
+ private volatile ServletContextHashModel servletContextModel;
- private ServletContextHashModel servletContextModel;
-
- private TaglibFactory taglibFactory;
+ private volatile TaglibFactory taglibFactory;
public PageContextServlet getPageContextServlet() {
- // TODO: proper locking...
- if (pageContextServlet == null) {
- pageContextServlet = new PageContextServlet();
- pageContextServletConfig = new PageContextServletConfig(getServletContext(), getBeanName());
-
- try {
- pageContextServlet.init(pageContextServletConfig);
- } catch (ServletException e) {
- // never happen
+ PageContextServlet servlet = pageContextServlet;
+
+ if (servlet == null) {
+ synchronized (this) {
+ servlet = pageContextServlet;
+
+ if (servlet == null) {
+ servlet = new PageContextServlet();
+
+ try {
+ servlet.init(new PageContextServletConfig(getServletContext(), getBeanName()));
+ } catch (ServletException e) {
+ // never happens...
+ }
+
+ pageContextServlet = servlet;
+ }
}
}
- return pageContextServlet;
+ return servlet;
}
public void setPageContextServlet(PageContextServlet pageContextServlet) {
@@ -73,12 +81,20 @@ public class FreemarkerView extends AbstractFreemarkerView {
}
public ServletContextHashModel getServletContextModel() {
- // TODO: proper locking...
- if (servletContextModel == null) {
- servletContextModel = new ServletContextHashModel(getPageContextServlet(), getObjectWrapperForModel());
+ ServletContextHashModel contextModel = servletContextModel;
+
+ if (contextModel == null) {
+ synchronized (this) {
+ contextModel = servletContextModel;
+
+ if (contextModel == null) {
+ contextModel = new ServletContextHashModel(getPageContextServlet(), getObjectWrapperForModel());
+ servletContextModel = contextModel;
+ }
+ }
}
- return servletContextModel;
+ return contextModel;
}
public void setServletContextModel(ServletContextHashModel servletContextModel) {
@@ -86,8 +102,22 @@ public class FreemarkerView extends AbstractFreemarkerView {
}
public TaglibFactory getTaglibFactory() {
- // TODO
- return taglibFactory;
+ TaglibFactory tlFactory = taglibFactory;
+
+ if (tlFactory == null) {
+ synchronized (this) {
+ tlFactory = taglibFactory;
+
+ if (tlFactory == null) {
+ tlFactory = new TaglibFactoryBuilder(getServletContext(), getObjectWrapperForModel())
+ .build();
+
+ taglibFactory = tlFactory;
+ }
+ }
+ }
+
+ return tlFactory;
}
public void setTaglibFactory(TaglibFactory taglibFactory) {
@@ -97,23 +127,51 @@ public class FreemarkerView extends AbstractFreemarkerView {
@Override
protected TemplateHashModel createModel(Map<String, Object> map, ObjectWrapperAndUnwrapper objectWrapperForModel,
HttpServletRequest request, HttpServletResponse response) {
+
AllHttpScopesHashModel model = new AllHttpScopesHashModel(objectWrapperForModel, getServletContext(), request);
+
model.putUnlistedModel(FreemarkerServlet.KEY_APPLICATION, getServletContextModel());
+
model.putUnlistedModel(FreemarkerServlet.KEY_SESSION,
getHttpSessionModel(objectWrapperForModel, request, response));
- model.putUnlistedModel(FreemarkerServlet.KEY_REQUEST,
- new HttpRequestHashModel(request, response, objectWrapperForModel));
- model.putUnlistedModel(FreemarkerServlet.KEY_REQUEST_PARAMETERS,
- new HttpRequestParametersHashModel(request, objectWrapperForModel));
+
+ HttpRequestHashModel requestModel = (HttpRequestHashModel) request
+ .getAttribute(FreemarkerServlet.ATTR_REQUEST_MODEL);
+ HttpRequestParametersHashModel requestParametersModel = (HttpRequestParametersHashModel) request
+ .getAttribute(FreemarkerServlet.ATTR_REQUEST_PARAMETERS_MODEL);
+
+ if (requestModel == null || requestModel.getRequest() != request) {
+ requestModel = new HttpRequestHashModel(request, response, objectWrapperForModel);
+ request.setAttribute(FreemarkerServlet.ATTR_REQUEST_MODEL, requestModel);
+ requestParametersModel = new HttpRequestParametersHashModel(request, objectWrapperForModel);
+ }
+
+ model.putUnlistedModel(FreemarkerServlet.KEY_REQUEST, requestModel);
+ model.putUnlistedModel(FreemarkerServlet.KEY_REQUEST_PARAMETERS, requestParametersModel);
+
model.putUnlistedModel(FreemarkerServlet.KEY_JSP_TAGLIBS, getTaglibFactory());
+
model.putAll(map);
+
return model;
}
protected HttpSessionHashModel getHttpSessionModel(ObjectWrapperAndUnwrapper objectWrapperForModel,
HttpServletRequest request, HttpServletResponse response) {
- // TODO
- HttpSessionHashModel sessionModel = new HttpSessionHashModel(null, request, response, objectWrapperForModel);
+ HttpSessionHashModel sessionModel;
+ HttpSession session = request.getSession(false);
+
+ if (session != null) {
+ sessionModel = (HttpSessionHashModel) session.getAttribute(FreemarkerServlet.ATTR_SESSION_MODEL);
+
+ if (sessionModel == null || sessionModel.isOrphaned(session)) {
+ sessionModel = new HttpSessionHashModel(session, objectWrapperForModel);
+ session.setAttribute(FreemarkerServlet.ATTR_SESSION_MODEL, sessionModel);
+ }
+ } else {
+ sessionModel = new HttpSessionHashModel(getPageContextServlet(), request, response, objectWrapperForModel);
+ }
+
return sessionModel;
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/cb4fab3a/freemarker-spring/src/test/java/org/apache/freemarker/spring/web/view/FreemarkerViewTest.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/test/java/org/apache/freemarker/spring/web/view/FreemarkerViewTest.java b/freemarker-spring/src/test/java/org/apache/freemarker/spring/web/view/FreemarkerViewTest.java
index 4f21e58..80fc2b3 100644
--- a/freemarker-spring/src/test/java/org/apache/freemarker/spring/web/view/FreemarkerViewTest.java
+++ b/freemarker-spring/src/test/java/org/apache/freemarker/spring/web/view/FreemarkerViewTest.java
@@ -95,7 +95,6 @@ public class FreemarkerViewTest {
request.setSession(session);
request.setAttribute("promotion", "Fresh blue berries");
- // TODO: Add 'Application.attributeName' example, too.
templateLoader.putTemplate("default-model.ftl",
"${name!}, you have ${Session.itemCountInCart!0} items in cart. " + "Hot deal: ${Request.promotion}. "
+ "BTW, you're ${Application.visitorCount}th visitor. "