Repository: incubator-freemarker Updated Branches: refs/heads/3 b63e44880 -> 5f6a9174d
FREEMARKER-55: trying with a directive to replace spring:bind jsp tag. Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/67091176 Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/67091176 Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/67091176 Branch: refs/heads/3 Commit: 6709117683e29b34a6e155cac30a160f86f95745 Parents: e3e7f1e Author: Woonsan Ko <[email protected]> Authored: Sat Aug 26 01:17:07 2017 -0400 Committer: Woonsan Ko <[email protected]> Committed: Sat Aug 26 01:17:07 2017 -0400 ---------------------------------------------------------------------- .../freemarker/spring/model/BindDirective.java | 120 +++++++++++++++++++ .../spring/web/view/FreeMarkerView.java | 15 +++ 2 files changed, 135 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/67091176/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/BindDirective.java ---------------------------------------------------------------------- diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/BindDirective.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/BindDirective.java new file mode 100644 index 0000000..967344d --- /dev/null +++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/BindDirective.java @@ -0,0 +1,120 @@ +/* + * 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.spring.model; + +import java.io.IOException; +import java.io.Writer; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.freemarker.core.CallPlace; +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.TemplateException; +import org.apache.freemarker.core.model.ArgumentArrayLayout; +import org.apache.freemarker.core.model.ObjectWrapper; +import org.apache.freemarker.core.model.TemplateDirectiveModel; +import org.apache.freemarker.core.model.TemplateModel; +import org.apache.freemarker.core.model.impl.BeanModel; +import org.apache.freemarker.core.model.impl.DefaultObjectWrapper; +import org.apache.freemarker.core.util.CallableUtils; +import org.apache.freemarker.core.util.StringToIndexMap; +import org.springframework.web.servlet.support.BindStatus; +import org.springframework.web.servlet.support.RequestContext; +import org.springframework.web.servlet.view.AbstractTemplateView; + +public class BindDirective implements TemplateDirectiveModel { + + public static final String STATUS_VARIABLE_NAME = "status"; + + /** + * @see <code>org.springframework.web.servlet.tags.NestedPathTag#NESTED_PATH_VARIABLE_NAME</code> + */ + private static final String NESTED_PATH_VARIABLE_NAME = "nestedPath"; + + private static final int PATH_PARAM_IDX = 0; + private static final int IGNORE_NESTED_PATH_PARAM_IDX = 1; + + private static final String IGNORE_NESTED_PATH_PARAM_NAME = "ignoreNestedPath"; + + private static final ArgumentArrayLayout ARGS_LAYOUT = ArgumentArrayLayout.create( + 1, + true, + StringToIndexMap.of( + IGNORE_NESTED_PATH_PARAM_NAME, IGNORE_NESTED_PATH_PARAM_IDX + ), + false + ); + + private final HttpServletRequest request; + private final HttpServletResponse response; + + public BindDirective(HttpServletRequest request, HttpServletResponse response) { + this.request = request; + this.response = response; + } + + @Override + public void execute(TemplateModel[] args, CallPlace callPlace, Writer out, Environment env) + throws TemplateException, IOException { + final ObjectWrapper objectWrapper = env.getObjectWrapper(); + + if (!(objectWrapper instanceof DefaultObjectWrapper)) { + throw new TemplateException("The ObjectWrapper of environment wasn't instance of " + DefaultObjectWrapper.class.getName()); + } + + TemplateModel model = env.getDataModel().get(AbstractTemplateView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE); + RequestContext requestContext = (RequestContext) ((DefaultObjectWrapper) objectWrapper).unwrap(model); + + String resolvedPath = CallableUtils.getStringArgument(args, PATH_PARAM_IDX, this); + boolean ignoreNestedPath = CallableUtils.getOptionalBooleanArgument(args, IGNORE_NESTED_PATH_PARAM_IDX, this, + false); + + if (!ignoreNestedPath) { + resolvedPath = resolveNestedPath(resolvedPath); + } + + BindStatus status = requestContext.getBindStatus(resolvedPath); + env.setLocalVariable(STATUS_VARIABLE_NAME, new BeanModel(status, (DefaultObjectWrapper) objectWrapper)); + + callPlace.executeNestedContent(null, out, env); + } + + @Override + public boolean isNestedContentSupported() { + return true; + } + + @Override + public ArgumentArrayLayout getDirectiveArgumentArrayLayout() { + return ARGS_LAYOUT; + } + + private String resolveNestedPath(final String path) { + String nestedPath = (String) request.getAttribute(NESTED_PATH_VARIABLE_NAME); + + if (nestedPath != null && !path.startsWith(nestedPath) + && !path.equals(nestedPath.substring(0, nestedPath.length() - 1))) { + return nestedPath + path; + } + + return path; + } +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/67091176/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 e827db5..1e94a97 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 @@ -25,15 +25,20 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper; import org.apache.freemarker.core.model.TemplateHashModel; +import org.apache.freemarker.core.model.TemplateHashModelEx2; +import org.apache.freemarker.core.model.impl.SimpleHash; import org.apache.freemarker.servlet.AllHttpScopesHashModel; import org.apache.freemarker.servlet.FreemarkerServlet; import org.apache.freemarker.servlet.HttpRequestHashModel; import org.apache.freemarker.servlet.HttpRequestParametersHashModel; import org.apache.freemarker.servlet.HttpSessionHashModel; +import org.apache.freemarker.servlet.IncludePage; import org.apache.freemarker.servlet.ServletContextHashModel; import org.apache.freemarker.servlet.jsp.TaglibFactory; +import org.apache.freemarker.spring.model.BindDirective; /** * FreeMarker template based view implementation, with being able to provide a {@link ServletContextHashModel} @@ -134,6 +139,10 @@ public class FreeMarkerView extends AbstractFreeMarkerView { model.putUnlistedModel(FreemarkerServlet.KEY_JSP_TAGLIBS, getTaglibFactory()); + model.putUnlistedModel(FreemarkerServlet.KEY_INCLUDE, new IncludePage(request, response)); + + model.putUnlistedModel("spring", createSpringCallableHashModel(objectWrapper, request, response)); + model.putAll(map); return model; @@ -165,4 +174,10 @@ public class FreeMarkerView extends AbstractFreeMarkerView { return sessionModel; } + private TemplateHashModelEx2 createSpringCallableHashModel(final ObjectWrapper objectWrapper, + final HttpServletRequest request, final HttpServletResponse response) { + final SimpleHash springCallableHash = new SimpleHash(objectWrapper); + springCallableHash.put("bind", new BindDirective(request, response)); + return springCallableHash; + } }
