SPR-5298 JSP tag for building URLs with URI templates

Created spring:url and spring:param tags that enhance the functionality of the JSTL c:url tag.  URI templates are supported in the url value attribute.  They are resolved against the params defined inside the url tag body.  Params that are unable to be applied as URI template are added to the query string.
This commit is contained in:
Scott Andrews
2008-11-16 21:04:46 +00:00
parent ecb86b46a4
commit 912c1234cd
8 changed files with 1364 additions and 0 deletions

View File

@@ -0,0 +1,109 @@
/*
* Copyright 2008 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.
* 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.springframework.web.servlet.tags;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;
import org.springframework.mock.web.MockBodyContent;
import org.springframework.mock.web.MockHttpServletResponse;
/**
* Unit tests for ParamTag
*
* @author Scott Andrews
*/
public class ParamTagTests extends AbstractTagTests {
private ParamTag tag;
private MockParamSupportTag parent;
@Override
protected void setUp() throws Exception {
PageContext context = createPageContext();
parent = new MockParamSupportTag();
tag = new ParamTag();
tag.setPageContext(context);
tag.setParent(parent);
}
public void testParamWithNameAndValue() throws JspException {
tag.setName("name");
tag.setValue("value");
int action = tag.doEndTag();
assertEquals(Tag.EVAL_PAGE, action);
assertEquals("name", parent.getParam().getName());
assertEquals("value", parent.getParam().getValue());
}
public void testParamWithBodyValue() throws JspException {
tag.setName("name");
tag.setBodyContent(new MockBodyContent("value",
new MockHttpServletResponse()));
int action = tag.doEndTag();
assertEquals(Tag.EVAL_PAGE, action);
assertEquals("name", parent.getParam().getName());
assertEquals("value", parent.getParam().getValue());
}
public void testParamWithNullValue() throws JspException {
tag.setName("name");
int action = tag.doEndTag();
assertEquals(Tag.EVAL_PAGE, action);
assertEquals("name", parent.getParam().getName());
assertNull(parent.getParam().getValue());
}
public void testParamWithNoParent() {
tag.setName("name");
tag.setValue("value");
tag.setParent(null);
try {
tag.doEndTag();
fail("expected JspException");
}
catch (JspException e) {
// we want this
}
}
private class MockParamSupportTag extends TagSupport implements ParamAware {
private Param param;
public void addParam(Param param) {
this.param = param;
}
public Param getParam() {
return param;
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2008 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.
* 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.springframework.web.servlet.tags;
import junit.framework.TestCase;
/**
* Unit tests for Param
*
* @author Scott Andrews
*/
public class ParamTests extends TestCase {
private Param param;
@Override
protected void setUp() throws Exception {
param = new Param();
}
public void testName() {
param.setName("name");
assertEquals("name", param.getName());
}
public void testValue() {
param.setValue("value");
assertEquals("value", param.getValue());
}
public void testNullDefaults() {
assertNull(param.getName());
assertNull(param.getValue());
}
}

View File

@@ -0,0 +1,571 @@
/*
* Copyright 2008 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.
* 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.springframework.web.servlet.tags;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.Tag;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockPageContext;
import org.springframework.util.ReflectionUtils;
/**
* Unit tests for UrlTag
*
* @author Scott Andrews
*/
public class UrlTagTests extends AbstractTagTests {
private UrlTag tag;
private MockPageContext context;
@Override
protected void setUp() throws Exception {
context = createPageContext();
tag = new UrlTag();
tag.setPageContext(context);
}
public void testParamSupport() {
assertTrue(tag instanceof ParamAware);
}
public void testDoStartTag() throws JspException {
int action = tag.doStartTag();
assertEquals(Tag.EVAL_BODY_INCLUDE, action);
}
public void testDoEndTag() throws JspException {
tag.setValue("url/path");
tag.doStartTag();
int action = tag.doEndTag();
assertEquals(Tag.EVAL_PAGE, action);
}
public void testVarDefaultScope() throws JspException {
tag.setValue("url/path");
tag.setVar("var");
tag.doStartTag();
tag.doEndTag();
assertEquals("url/path", context.getAttribute("var",
PageContext.PAGE_SCOPE));
}
public void testVarExplicitScope() throws JspException {
tag.setValue("url/path");
tag.setVar("var");
tag.setScope("request");
tag.doStartTag();
tag.doEndTag();
assertEquals("url/path", context.getAttribute("var",
PageContext.REQUEST_SCOPE));
}
public void testSetEscapeXmlDefault() throws JspException {
tag.setValue("url/path");
tag.setVar("var");
tag.doStartTag();
Param param = new Param();
param.setName("n me");
param.setValue("v&l=e");
tag.addParam(param);
param = new Param();
param.setName("name");
param.setValue("value2");
tag.addParam(param);
tag.doEndTag();
assertEquals("url/path?n+me=v%26l%3De&name=value2", context
.getAttribute("var"));
}
public void testSetEscapeXmlFalse() throws JspException {
tag.setValue("url/path");
tag.setVar("var");
tag.setEscapeXml("false");
tag.doStartTag();
Param param = new Param();
param.setName("n me");
param.setValue("v&l=e");
tag.addParam(param);
param = new Param();
param.setName("name");
param.setValue("value2");
tag.addParam(param);
tag.doEndTag();
assertEquals("url/path?n+me=v%26l%3De&name=value2", context
.getAttribute("var"));
}
public void testSetEscapeXmlTrue() throws JspException {
tag.setValue("url/path");
tag.setVar("var");
tag.setEscapeXml("true");
tag.doStartTag();
Param param = new Param();
param.setName("n me");
param.setValue("v&l=e");
tag.addParam(param);
param = new Param();
param.setName("name");
param.setValue("value2");
tag.addParam(param);
tag.doEndTag();
assertEquals("url/path?n+me=v%26l%3De&name=value2", context
.getAttribute("var"));
}
public void testCreateQueryStringNoParams() throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("", queryString);
}
public void testCreateQueryStringOneParam() throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param();
param.setName("name");
param.setValue("value");
params.add(param);
String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("?name=value", queryString);
}
public void testCreateQueryStringOneParamForExsistingQueryString()
throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param();
param.setName("name");
param.setValue("value");
params.add(param);
String queryString = tag.createQueryString(params, usedParams, false);
assertEquals("&name=value", queryString);
}
public void testCreateQueryStringOneParamEmptyValue() throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param();
param.setName("name");
param.setValue("");
params.add(param);
String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("?name=", queryString);
}
public void testCreateQueryStringOneParamNullValue() throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param();
param.setName("name");
param.setValue(null);
params.add(param);
String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("?name", queryString);
}
public void testCreateQueryStringOneParamAlreadyUsed() throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param();
param.setName("name");
param.setValue("value");
params.add(param);
usedParams.add("name");
String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("", queryString);
}
public void testCreateQueryStringTwoParams() throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param();
param.setName("name");
param.setValue("value");
params.add(param);
param = new Param();
param.setName("name");
param.setValue("value2");
params.add(param);
String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("?name=value&name=value2", queryString);
}
public void testCreateQueryStringUrlEncoding() throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param();
param.setName("n me");
param.setValue("v&l=e");
params.add(param);
param = new Param();
param.setName("name");
param.setValue("value2");
params.add(param);
String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("?n+me=v%26l%3De&name=value2", queryString);
}
public void testCreateQueryStringParamNullName() throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param();
param.setName(null);
param.setValue("value");
params.add(param);
String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("", queryString);
}
public void testCreateQueryStringParamEmptyName() throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param();
param.setName("");
param.setValue("value");
params.add(param);
String queryString = tag.createQueryString(params, usedParams, true);
assertEquals("", queryString);
}
public void testReplaceUriTemplateParamsNoParams() throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
String uri = tag.replaceUriTemplateParams("url/path", params,
usedParams);
assertEquals("url/path", uri);
assertEquals(0, usedParams.size());
}
public void testReplaceUriTemplateParamsTemplateWithoutParamMatch()
throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
String uri = tag.replaceUriTemplateParams("url/{path}", params,
usedParams);
assertEquals("url/{path}", uri);
assertEquals(0, usedParams.size());
}
public void testReplaceUriTemplateParamsTemplateWithParamMatch()
throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param();
param.setName("name");
param.setValue("value");
params.add(param);
String uri = tag.replaceUriTemplateParams("url/{name}", params,
usedParams);
assertEquals("url/value", uri);
assertEquals(1, usedParams.size());
assertTrue(usedParams.contains("name"));
}
public void testReplaceUriTemplateParamsTemplateWithParamMatchNamePreEncoding()
throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param();
param.setName("n me");
param.setValue("value");
params.add(param);
String uri = tag.replaceUriTemplateParams("url/{n me}", params,
usedParams);
assertEquals("url/value", uri);
assertEquals(1, usedParams.size());
assertTrue(usedParams.contains("n me"));
}
public void testReplaceUriTemplateParamsTemplateWithParamMatchValueEncoded()
throws JspException {
List<Param> params = new LinkedList<Param>();
Set<String> usedParams = new HashSet<String>();
Param param = new Param();
param.setName("name");
param.setValue("v lue");
params.add(param);
String uri = tag.replaceUriTemplateParams("url/{name}", params,
usedParams);
assertEquals("url/v+lue", uri);
assertEquals(1, usedParams.size());
assertTrue(usedParams.contains("name"));
}
public void testCreateUrlRemoteServer() throws JspException {
tag.setValue("http://www.springframework.org/");
tag.doStartTag();
// String uri = tag.createUrl();
String uri = invokeCreateUrl(tag);
assertEquals("http://www.springframework.org/", uri);
}
public void testCreateUrlRelative() throws JspException {
tag.setValue("url/path");
tag.doStartTag();
String uri = invokeCreateUrl(tag);
assertEquals("url/path", uri);
}
public void testCreateUrlLocalContext() throws JspException {
((MockHttpServletRequest) context.getRequest())
.setContextPath("/app-context");
tag.setValue("/url/path");
tag.doStartTag();
String uri = invokeCreateUrl(tag);
assertEquals("/app-context/url/path", uri);
}
public void testCreateUrlRemoteContext() throws JspException {
((MockHttpServletRequest) context.getRequest())
.setContextPath("/app-context");
tag.setValue("/url/path");
tag.setContext("some-other-context");
tag.doStartTag();
String uri = invokeCreateUrl(tag);
assertEquals("/some-other-context/url/path", uri);
}
public void testCreateUrlRemoteContextWithSlash() throws JspException {
((MockHttpServletRequest) context.getRequest())
.setContextPath("/app-context");
tag.setValue("/url/path");
tag.setContext("/some-other-context");
tag.doStartTag();
String uri = invokeCreateUrl(tag);
assertEquals("/some-other-context/url/path", uri);
}
public void testCreateUrlWithParams() throws JspException {
tag.setValue("url/path");
tag.doStartTag();
Param param = new Param();
param.setName("name");
param.setValue("value");
tag.addParam(param);
param = new Param();
param.setName("n me");
param.setValue("v lue");
tag.addParam(param);
String uri = invokeCreateUrl(tag);
assertEquals("url/path?name=value&n+me=v+lue", uri);
}
public void testCreateUrlWithTemplateParams() throws JspException {
tag.setValue("url/{name}");
tag.doStartTag();
Param param = new Param();
param.setName("name");
param.setValue("value");
tag.addParam(param);
param = new Param();
param.setName("n me");
param.setValue("v lue");
tag.addParam(param);
String uri = invokeCreateUrl(tag);
assertEquals("url/value?n+me=v+lue", uri);
}
public void testCreateUrlWithParamAndExsistingQueryString()
throws JspException {
tag.setValue("url/path?foo=bar");
tag.doStartTag();
Param param = new Param();
param.setName("name");
param.setValue("value");
tag.addParam(param);
String uri = invokeCreateUrl(tag);
assertEquals("url/path?foo=bar&name=value", uri);
}
public void testUrlEncode() throws JspException {
assertEquals("my+name", tag.urlEncode("my name"));
}
public void testUrlEncodeNull() throws JspException {
assertNull(tag.urlEncode(null));
}
public void testUrlEncodeBadEncoding() {
context.getResponse().setCharacterEncoding("bad encoding");
try {
tag.urlEncode("my name");
fail("expected JspException");
}
catch (JspException e) {
// we want this
}
}
public void testEscapeXml() {
assertEquals("&#60;script type=&#34;text/javascript&#34;&#62;", tag
.escapeXml("<script type=\"text/javascript\">"));
}
public void testEscapeXmlNull() {
assertNull(tag.escapeXml(null));
}
public void testEntityValueAmpersand() {
assertEquals("&#38;", tag.entityValue('&'));
}
public void testEntityValueLessThan() {
assertEquals("&#60;", tag.entityValue('<'));
}
public void testEntityValueGreaterThan() {
assertEquals("&#62;", tag.entityValue('>'));
}
public void testEntityValueSingleQuote() {
assertEquals("&#39;", tag.entityValue('\''));
}
public void testEntityValueDoubleQuote() {
assertEquals("&#34;", tag.entityValue('"'));
}
public void testJspWriterOutput() {
// TODO assert that the output to the JspWriter is the expected output
}
public void testServletRepsonseEncodeUrl() {
// TODO assert that HttpServletResponse.encodeURL(String) is invoked for
// non absolute urls
}
// support methods
private String invokeCreateUrl(UrlTag tag) {
Method createUrl = ReflectionUtils.findMethod(tag.getClass(),
"createUrl");
ReflectionUtils.makeAccessible(createUrl);
return (String) ReflectionUtils.invokeMethod(createUrl, tag);
}
}