From 56bd995d9cb0eb6fbfeac88d16bbc7c6ae1df850 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 18 Feb 2009 23:55:32 +0000 Subject: [PATCH] "url" macro in "spring.ftl" performs standard Servlet URL encoding automatically --- .../support/JspAwareRequestContext.java | 4 +- .../web/servlet/support/RequestContext.java | 40 ++++++++++++++----- .../servlet/view/AbstractTemplateView.java | 4 +- .../web/servlet/view/AbstractView.java | 10 +++-- .../web/servlet/view/freemarker/spring.ftl | 2 +- .../view/DummyMacroRequestContext.java | 11 +++-- 6 files changed, 51 insertions(+), 20 deletions(-) diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/JspAwareRequestContext.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/JspAwareRequestContext.java index 1fc7a5f36a5..0db0668ab51 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/JspAwareRequestContext.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/JspAwareRequestContext.java @@ -19,6 +19,7 @@ package org.springframework.web.servlet.support; import java.util.Locale; import java.util.Map; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.PageContext; import javax.servlet.jsp.jstl.core.Config; @@ -70,7 +71,8 @@ public class JspAwareRequestContext extends RequestContext { throw new IllegalArgumentException("RequestContext only supports HTTP requests"); } this.pageContext = pageContext; - initContext((HttpServletRequest) pageContext.getRequest(), pageContext.getServletContext(), model); + initContext((HttpServletRequest) pageContext.getRequest(), (HttpServletResponse) pageContext.getResponse(), + pageContext.getServletContext(), model); } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/RequestContext.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/RequestContext.java index 2256c5c15ea..7a2d13d77aa 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/RequestContext.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/RequestContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +20,9 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; - import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.servlet.jsp.jstl.core.Config; @@ -86,11 +86,13 @@ public class RequestContext { protected static final boolean jstlPresent = ClassUtils.isPresent( - "javax.servlet.jsp.jstl.core.Config", JspAwareRequestContext.class.getClassLoader()); + "javax.servlet.jsp.jstl.core.Config", RequestContext.class.getClassLoader()); private HttpServletRequest request; + private HttpServletResponse response; + private Map model; private WebApplicationContext webApplicationContext; @@ -119,7 +121,7 @@ public class RequestContext { * @see #RequestContext(javax.servlet.http.HttpServletRequest, javax.servlet.ServletContext) */ public RequestContext(HttpServletRequest request) { - initContext(request, null, null); + initContext(request, null, null, null); } /** @@ -137,7 +139,7 @@ public class RequestContext { * @see org.springframework.web.servlet.DispatcherServlet */ public RequestContext(HttpServletRequest request, ServletContext servletContext) { - initContext(request, servletContext, null); + initContext(request, null, servletContext, null); } /** @@ -154,7 +156,7 @@ public class RequestContext { * @see #RequestContext(javax.servlet.http.HttpServletRequest, javax.servlet.ServletContext, Map) */ public RequestContext(HttpServletRequest request, Map model) { - initContext(request, null, model); + initContext(request, null, null, model); } /** @@ -165,6 +167,7 @@ public class RequestContext { *

If a ServletContext is specified, the RequestContext will also * work with a root WebApplicationContext (outside a DispatcherServlet). * @param request current HTTP request + * @param response current HTTP response * @param servletContext the servlet context of the web application * (can be null; necessary for fallback to root WebApplicationContext) * @param model the model attributes for the current view @@ -172,8 +175,10 @@ public class RequestContext { * @see org.springframework.web.context.WebApplicationContext * @see org.springframework.web.servlet.DispatcherServlet */ - public RequestContext(HttpServletRequest request, ServletContext servletContext, Map model) { - initContext(request, servletContext, model); + public RequestContext(HttpServletRequest request, HttpServletResponse response, + ServletContext servletContext, Map model) { + + initContext(request, response, servletContext, model); } /** @@ -199,8 +204,11 @@ public class RequestContext { * @see org.springframework.web.servlet.DispatcherServlet#LOCALE_RESOLVER_ATTRIBUTE * @see org.springframework.web.servlet.DispatcherServlet#THEME_RESOLVER_ATTRIBUTE */ - protected void initContext(HttpServletRequest request, ServletContext servletContext, Map model) { + protected void initContext(HttpServletRequest request, HttpServletResponse response, + ServletContext servletContext, Map model) { + this.request = request; + this.response = response; this.model = model; // Fetch WebApplicationContext, either from DispatcherServlet or the root context. @@ -378,6 +386,20 @@ public class RequestContext { return this.urlPathHelper.getOriginatingContextPath(this.request); } + /** + * Return a context-aware URl for the given relative URL. + * @param relativeUrl the relative URL part + * @return a URL that points back to the server with an absolute path + * (also URL-encoded accordingly) + */ + public String getContextUrl(String relativeUrl) { + String url = getContextPath() + relativeUrl; + if (this.response != null) { + url = this.response.encodeURL(url); + } + return url; + } + /** * Return the request URI of the original request, that is, the invoked URL * without parameters. This is particularly useful as HTML form action target, diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/AbstractTemplateView.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/AbstractTemplateView.java index 39268daf51f..c613e2124c7 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/AbstractTemplateView.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/AbstractTemplateView.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -159,7 +159,7 @@ public abstract class AbstractTemplateView extends AbstractUrlBasedView { } // Expose RequestContext instance for Spring macros. model.put(SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE, - new RequestContext(request, getServletContext(), model)); + new RequestContext(request, response, getServletContext(), model)); } applyContentType(response); diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/AbstractView.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/AbstractView.java index 25074f97411..2a2d29d10a7 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/AbstractView.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/AbstractView.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -243,7 +243,7 @@ public abstract class AbstractView extends WebApplicationObjectSupport implement // Expose RequestContext? if (this.requestContextAttribute != null) { - mergedModel.put(this.requestContextAttribute, createRequestContext(request, mergedModel)); + mergedModel.put(this.requestContextAttribute, createRequestContext(request, response, mergedModel)); } prepareResponse(request, response); @@ -261,8 +261,10 @@ public abstract class AbstractView extends WebApplicationObjectSupport implement * @see #setRequestContextAttribute * @see org.springframework.web.servlet.support.RequestContext */ - protected RequestContext createRequestContext(HttpServletRequest request, Map model) { - return new RequestContext(request, getServletContext(), model); + protected RequestContext createRequestContext( + HttpServletRequest request, HttpServletResponse response, Map model) { + + return new RequestContext(request, response, getServletContext(), model); } /** diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/freemarker/spring.ftl b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/freemarker/spring.ftl index d980cef2de9..c69850a6b24 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/freemarker/spring.ftl +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/view/freemarker/spring.ftl @@ -86,7 +86,7 @@ * Takes a relative URL and makes it absolute from the server root by * adding the context root for the web application. --> -<#macro url relativeUrl>${springMacroRequestContext.getContextPath()}${relativeUrl} +<#macro url relativeUrl>${springMacroRequestContext.getContextUrl(relativeUrl)} <#-- * bind diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/DummyMacroRequestContext.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/DummyMacroRequestContext.java index 3c177562436..6aa6a0671af 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/DummyMacroRequestContext.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/view/DummyMacroRequestContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,10 +18,8 @@ package org.springframework.web.servlet.view; import java.util.List; import java.util.Map; - import javax.servlet.http.HttpServletRequest; -import org.springframework.beans.TestBean; import org.springframework.web.servlet.support.BindStatus; import org.springframework.web.servlet.support.RequestContext; @@ -129,6 +127,13 @@ public class DummyMacroRequestContext { return this.contextPath; } + /** + * @see org.springframework.web.servlet.support.RequestContext#getContextUrl(String) + */ + public String getContextUrl(String relativeUrl) { + return getContextPath() + relativeUrl; + } + /** * @see org.springframework.web.servlet.support.RequestContext#getBindStatus(String) */