From 915e93cc813508b6e7839d06b66d225fbb685ac7 Mon Sep 17 00:00:00 2001 From: Nicholas Williams Date: Sun, 21 Jul 2013 22:57:51 -0700 Subject: [PATCH 1/4] Update TLD versions to 4.0 --- spring-webmvc/src/main/resources/META-INF/spring-form.tld | 2 +- spring-webmvc/src/main/resources/META-INF/spring.tld | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-webmvc/src/main/resources/META-INF/spring-form.tld b/spring-webmvc/src/main/resources/META-INF/spring-form.tld index e038581039d..f4aafdee64c 100644 --- a/spring-webmvc/src/main/resources/META-INF/spring-form.tld +++ b/spring-webmvc/src/main/resources/META-INF/spring-form.tld @@ -5,7 +5,7 @@ version="2.0"> Spring Framework JSP Form Tag Library - 3.0 + 4.0 form http://www.springframework.org/tags/form diff --git a/spring-webmvc/src/main/resources/META-INF/spring.tld b/spring-webmvc/src/main/resources/META-INF/spring.tld index a0a8c6f7fc7..06a142fcf44 100644 --- a/spring-webmvc/src/main/resources/META-INF/spring.tld +++ b/spring-webmvc/src/main/resources/META-INF/spring.tld @@ -5,7 +5,7 @@ version="2.0"> Spring Framework JSP Tag Library - 3.0 + 4.0 spring http://www.springframework.org/tags From 110db37f1c8790b75d80844fa743014c4fd3fcab Mon Sep 17 00:00:00 2001 From: Nicholas Williams Date: Mon, 22 Jul 2013 10:21:58 -0700 Subject: [PATCH 2/4] Fix malformed UrlTag Javadoc --- .../main/java/org/springframework/web/servlet/tags/UrlTag.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/UrlTag.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/UrlTag.java index 4d6cd703e0d..30b15bf6cfe 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/UrlTag.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/UrlTag.java @@ -57,7 +57,7 @@ import org.springframework.web.util.UriUtils; * over direct EL substitution as the values are URL encoded. Failure to properly * encode URL can leave an application vulnerable to XSS and other injection attacks. * - *

URLs can be HTML/XML escaped by setting the {@link #setHtmlEscape(String) + *

URLs can be HTML/XML escaped by setting the {@link #setHtmlEscape(boolean) * 'htmlEscape'} attribute to 'true'. Detects an HTML escaping setting, either on * this tag instance, the page level, or the {@code web.xml} level. The default * is 'false'. When setting the URL value into a variable, escaping is not recommended. From 50bd70f13de33b6ee61f9bcba83585c1eb2e2456 Mon Sep 17 00:00:00 2001 From: Nicholas Williams Date: Sun, 21 Jul 2013 23:12:00 -0700 Subject: [PATCH 3/4] Ensure ParamTag release resources Update ParamTag to reset values when resources are released. This prevents problems in containers that pool tags. Issue: SPR-10769 --- .../web/servlet/tags/ParamTag.java | 22 +++++++--- .../web/servlet/tags/ParamTagTests.java | 44 +++++++++++++++++-- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ParamTag.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ParamTag.java index a0b62747ea2..29b1f5084c7 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ParamTag.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ParamTag.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -26,6 +26,7 @@ import javax.servlet.jsp.tagext.BodyTagSupport; *

This tag must be nested under a param aware tag. * * @author Scott Andrews + * @author Nicholas Williams * @since 3.0 * @see Param * @see UrlTag @@ -37,16 +38,16 @@ public class ParamTag extends BodyTagSupport { private String value; - private Param param; + private boolean valueSet; // tag lifecycle @Override public int doEndTag() throws JspException { - param = new Param(); - param.setName(name); - if (value != null) { - param.setValue(value); + Param param = new Param(); + param.setName(this.name); + if (this.valueSet) { + param.setValue(this.value); } else if (getBodyContent() != null) { // get the value from the tag body @@ -90,6 +91,15 @@ public class ParamTag extends BodyTagSupport { */ public void setValue(String value) { this.value = value; + this.valueSet = true; + } + + @Override + public void release() { + super.release(); + this.name = null; + this.value = null; + this.valueSet = false; } } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/ParamTagTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/ParamTagTests.java index fc6321a2c4d..2be185550b2 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/ParamTagTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/ParamTagTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -25,9 +25,10 @@ import org.springframework.mock.web.test.MockBodyContent; import org.springframework.mock.web.test.MockHttpServletResponse; /** - * Unit tests for ParamTag + * Unit tests for {@link ParamTag} * * @author Scott Andrews + * @author Nicholas Williams */ public class ParamTagTests extends AbstractTagTests { @@ -67,7 +68,7 @@ public class ParamTagTests extends AbstractTagTests { assertEquals("value", parent.getParam().getValue()); } - public void testParamWithNullValue() throws JspException { + public void testParamWithImplicitNullValue() throws JspException { tag.setName("name"); int action = tag.doEndTag(); @@ -77,6 +78,43 @@ public class ParamTagTests extends AbstractTagTests { assertNull(parent.getParam().getValue()); } + public void testParamWithExplicitNullValue() throws JspException { + tag.setName("name"); + tag.setValue(null); + + int action = tag.doEndTag(); + + assertEquals(Tag.EVAL_PAGE, action); + assertEquals("name", parent.getParam().getName()); + assertNull(parent.getParam().getValue()); + } + + public void testParamWithValueThenReleaseThenBodyValue() throws JspException { + tag.setName("name1"); + tag.setValue("value1"); + + int action = tag.doEndTag(); + + assertEquals(Tag.EVAL_PAGE, action); + assertEquals("name1", parent.getParam().getName()); + assertEquals("value1", parent.getParam().getValue()); + + tag.release(); + + parent = new MockParamSupportTag(); + tag.setPageContext(createPageContext()); + tag.setParent(parent); + tag.setName("name2"); + tag.setBodyContent(new MockBodyContent("value2", + new MockHttpServletResponse())); + + action = tag.doEndTag(); + + assertEquals(Tag.EVAL_PAGE, action); + assertEquals("name2", parent.getParam().getName()); + assertEquals("value2", parent.getParam().getValue()); + } + public void testParamWithNoParent() { tag.setName("name"); tag.setValue("value"); From f9b17a708f14869074b3ab4e86e46be56d24c0bd Mon Sep 17 00:00:00 2001 From: Nicholas Williams Date: Mon, 22 Jul 2013 10:28:30 -0700 Subject: [PATCH 4/4] Add subtag for message/theme Add a new tag that cab be nested within and . The tag is based on the tag and uses conventions found throughout other Spring tags. Issue: SPR-9678 --- .../web/servlet/tags/ArgumentAware.java | 36 ++++++ .../web/servlet/tags/ArgumentTag.java | 88 +++++++++++++ .../web/servlet/tags/MessageTag.java | 51 +++++++- .../web/servlet/tags/ThemeTag.java | 6 +- .../src/main/resources/META-INF/spring.tld | 22 +++- .../web/servlet/tags/ArgumentTagTests.java | 119 ++++++++++++++++++ .../web/servlet/tags/MessageTagTests.java | 82 +++++++++++- .../web/servlet/tags/ThemeTagTests.java | 3 +- 8 files changed, 396 insertions(+), 11 deletions(-) create mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ArgumentAware.java create mode 100644 spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ArgumentTag.java create mode 100644 spring-webmvc/src/test/java/org/springframework/web/servlet/tags/ArgumentTagTests.java diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ArgumentAware.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ArgumentAware.java new file mode 100644 index 00000000000..03701501f4a --- /dev/null +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ArgumentAware.java @@ -0,0 +1,36 @@ +/* + * Copyright 2002-2013 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.JspTagException; + +/** + * Allows implementing tag to utilize nested {@code spring:argument} tags. + * + * @author Nicholas Williams + * @since 4.0 + * @see ArgumentTag + */ +public interface ArgumentAware { + + /** + * Callback hook for nested spring:argument tags to pass their value + * to the parent tag. + * @param argument the result of the nested {@code spring:argument} tag + */ + void addArgument(Object argument) throws JspTagException; +} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ArgumentTag.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ArgumentTag.java new file mode 100644 index 00000000000..bf3a398b1ec --- /dev/null +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ArgumentTag.java @@ -0,0 +1,88 @@ +/* + * Copyright 2002-2013 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.tagext.BodyTagSupport; + +/** + * JSP tag for collecting arguments and passing them to an {@link ArgumentAware} ancestor + * in the tag hierarchy. + * + *

This tag must be nested under an argument aware tag. + * + * @author Nicholas Williams + * @since 4.0 + * @see MessageTag + * @see ThemeTag + */ +@SuppressWarnings("serial") +public class ArgumentTag extends BodyTagSupport { + + private Object value; + + private boolean valueSet; + + // tag lifecycle + + @Override + public int doEndTag() throws JspException { + Object argument = null; + if (this.valueSet) { + argument = this.value; + } + else if (getBodyContent() != null) { + // get the value from the tag body + argument = getBodyContent().getString().trim(); + } + + // find a param aware ancestor + ArgumentAware argumentAwareTag = (ArgumentAware) findAncestorWithClass(this, + ArgumentAware.class); + if (argumentAwareTag == null) { + throw new JspException( + "The argument tag must be a descendant of a tag that supports arguments"); + } + + argumentAwareTag.addArgument(argument); + + return EVAL_PAGE; + } + + // tag attribute mutators + + /** + * Sets the value of the argument + * + *

+ * Optional. If not set, the tag's body content is evaluated. + * + * @param value the parameter value + */ + public void setValue(Object value) { + this.value = value; + this.valueSet = true; + } + + @Override + public void release() { + super.release(); + this.value = null; + this.valueSet = false; + } + +} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/MessageTag.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/MessageTag.java index a861da494be..d9448fd3941 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/MessageTag.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/MessageTag.java @@ -18,6 +18,9 @@ package org.springframework.web.servlet.tags; import java.io.IOException; import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspTagException; @@ -40,17 +43,22 @@ import org.springframework.web.util.TagUtils; *

If "code" isn't set or cannot be resolved, "text" will be used as default * message. Thus, this tag can also be used for HTML escaping of any texts. * + *

Message arguments can be specified via the {@link #setArguments(Object) arguments} + * attribute or by using nested {@code <spring:argument>} tags. + * * @author Rod Johnson * @author Juergen Hoeller + * @author Nicholas Williams * @see #setCode * @see #setText * @see #setHtmlEscape * @see #setJavaScriptEscape * @see HtmlEscapeTag#setDefaultHtmlEscape * @see org.springframework.web.util.WebUtils#HTML_ESCAPE_CONTEXT_PARAM + * @see ArgumentTag */ @SuppressWarnings("serial") -public class MessageTag extends HtmlEscapingAwareTag { +public class MessageTag extends HtmlEscapingAwareTag implements ArgumentAware { /** * Default separator for splitting an arguments String: a comma (",") @@ -66,6 +74,8 @@ public class MessageTag extends HtmlEscapingAwareTag { private String argumentSeparator = DEFAULT_ARGUMENT_SEPARATOR; + private List nestedArguments; + private String text; private String var; @@ -109,6 +119,11 @@ public class MessageTag extends HtmlEscapingAwareTag { this.argumentSeparator = argumentSeparator; } + @Override + public void addArgument(Object argument) throws JspTagException { + this.nestedArguments.add(argument); + } + /** * Set the message text for this tag. */ @@ -146,6 +161,12 @@ public class MessageTag extends HtmlEscapingAwareTag { } + @Override + protected final int doStartTagInternal() throws JspException, IOException { + this.nestedArguments = new LinkedList(); + return EVAL_BODY_INCLUDE; + } + /** * Resolves the message, escapes it if demanded, * and writes it to the page (or exposes it as variable). @@ -155,7 +176,7 @@ public class MessageTag extends HtmlEscapingAwareTag { * @see #writeMessage(String) */ @Override - protected final int doStartTagInternal() throws JspException, IOException { + public int doEndTag() throws JspException { try { // Resolve the unescaped message. String msg = resolveMessage(); @@ -172,13 +193,22 @@ public class MessageTag extends HtmlEscapingAwareTag { writeMessage(msg); } - return EVAL_BODY_INCLUDE; + return EVAL_PAGE; + } + catch (IOException ex) { + throw new JspTagException(ex.getMessage(), ex); } catch (NoSuchMessageException ex) { throw new JspTagException(getNoSuchMessageExceptionDescription(ex)); } } + @Override + public void release() { + super.release(); + this.arguments = null; + } + /** * Resolve the specified message into a concrete message String. * The returned message String should be unescaped. @@ -198,6 +228,11 @@ public class MessageTag extends HtmlEscapingAwareTag { if (this.code != null || this.text != null) { // We have a code or default text that we need to resolve. Object[] argumentsArray = resolveArguments(this.arguments); + if(!this.nestedArguments.isEmpty()) { + argumentsArray = appendArguments(argumentsArray, + this.nestedArguments.toArray()); + } + if (this.text != null) { // We have a fallback text to consider. return messageSource.getMessage( @@ -214,6 +249,16 @@ public class MessageTag extends HtmlEscapingAwareTag { return this.text; } + private Object[] appendArguments(Object[] sourceArguments, Object[] additionalArguments) { + if(ObjectUtils.isEmpty(sourceArguments)) { + return additionalArguments; + } + Object[] arguments = new Object[sourceArguments.length + additionalArguments.length]; + System.arraycopy(sourceArguments, 0, arguments, 0, sourceArguments.length); + System.arraycopy(additionalArguments, 0, arguments, sourceArguments.length, additionalArguments.length); + return arguments; + } + /** * Resolve the given arguments Object into an arguments array. * @param arguments the specified arguments Object diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ThemeTag.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ThemeTag.java index 182247bf6f6..f7fc101e386 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ThemeTag.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/tags/ThemeTag.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -30,6 +30,9 @@ import org.springframework.context.NoSuchMessageException; *

If "code" isn't set or cannot be resolved, "text" will be used * as default message. * + *

Message arguments can be specified via the {@link #setArguments(Object) arguments} + * attribute or by using nested {@code <spring:argument>} tags. + * * @author Jean-Pierre Pawlak * @author Juergen Hoeller * @see org.springframework.ui.context.Theme @@ -39,6 +42,7 @@ import org.springframework.context.NoSuchMessageException; * @see #setHtmlEscape * @see HtmlEscapeTag#setDefaultHtmlEscape * @see org.springframework.web.util.WebUtils#HTML_ESCAPE_CONTEXT_PARAM + * @see ArgumentTag */ @SuppressWarnings("serial") public class ThemeTag extends MessageTag { diff --git a/spring-webmvc/src/main/resources/META-INF/spring.tld b/spring-webmvc/src/main/resources/META-INF/spring.tld index 06a142fcf44..dab5f8cd861 100644 --- a/spring-webmvc/src/main/resources/META-INF/spring.tld +++ b/spring-webmvc/src/main/resources/META-INF/spring.tld @@ -83,7 +83,8 @@ Set optional message arguments for this tag, as a (comma-)delimited String (each String argument can contain JSP EL), an Object array (used as argument array), or a single Object (used - as single argument). + as single argument). You can additionally use nested spring:argument + tags. arguments false true @@ -160,7 +161,8 @@ Set optional message arguments for this tag, as a (comma-)delimited String (each String argument can contain JSP EL), an Object array (used as argument array), or a single Object (used - as single argument). + as single argument). You can additionally use nested spring:argument + tags. arguments false true @@ -211,6 +213,22 @@ + + Argument tag based on the JSTL fmt:param tag. The purpose is to + support arguments inside the spring:message and spring:theme + tags. + argument + org.springframework.web.servlet.tags.ArgumentTag + JSP + + The value of the argument. + value + false + true + java.lang.Object + + + Provides Errors instance in case of bind errors. diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/ArgumentTagTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/ArgumentTagTests.java new file mode 100644 index 00000000000..2b3a5a00c6d --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/ArgumentTagTests.java @@ -0,0 +1,119 @@ +/* + * Copyright 2002-2013 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.test.MockBodyContent; +import org.springframework.mock.web.test.MockHttpServletResponse; + +/** + * Unit tests for ArgumentTag + * + * @author Nicholas Williams + */ +public class ArgumentTagTests extends AbstractTagTests { + + private ArgumentTag tag; + + private MockArgumentSupportTag parent; + + @Override + protected void setUp() throws Exception { + PageContext context = createPageContext(); + parent = new MockArgumentSupportTag(); + tag = new ArgumentTag(); + tag.setPageContext(context); + tag.setParent(parent); + } + + public void testArgumentWithStringValue() throws JspException { + tag.setValue("value1"); + + int action = tag.doEndTag(); + + assertEquals(Tag.EVAL_PAGE, action); + assertEquals("value1", parent.getArgument()); + } + + public void testArgumentWithImplicitNullValue() throws JspException { + int action = tag.doEndTag(); + + assertEquals(Tag.EVAL_PAGE, action); + assertNull(parent.getArgument()); + } + + public void testArgumentWithExplicitNullValue() throws JspException { + tag.setValue(null); + + int action = tag.doEndTag(); + + assertEquals(Tag.EVAL_PAGE, action); + assertNull(parent.getArgument()); + } + + public void testArgumentWithBodyValue() throws JspException { + tag.setBodyContent(new MockBodyContent("value2", + new MockHttpServletResponse())); + + int action = tag.doEndTag(); + + assertEquals(Tag.EVAL_PAGE, action); + assertEquals("value2", parent.getArgument()); + } + + public void testArgumentWithValueThenReleaseThenBodyValue() throws JspException { + tag.setValue("value3"); + + int action = tag.doEndTag(); + + assertEquals(Tag.EVAL_PAGE, action); + assertEquals("value3", parent.getArgument()); + + tag.release(); + + parent = new MockArgumentSupportTag(); + tag.setPageContext(createPageContext()); + tag.setParent(parent); + tag.setBodyContent(new MockBodyContent("value4", + new MockHttpServletResponse())); + + action = tag.doEndTag(); + + assertEquals(Tag.EVAL_PAGE, action); + assertEquals("value4", parent.getArgument()); + } + + @SuppressWarnings("serial") + private class MockArgumentSupportTag extends TagSupport implements ArgumentAware { + + Object argument; + + @Override + public void addArgument(Object argument) { + this.argument = argument; + } + + private Object getArgument() { + return argument; + } + } + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/MessageTagTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/MessageTagTests.java index d3e39f38454..3eeeb07f3d8 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/MessageTagTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/MessageTagTests.java @@ -18,7 +18,6 @@ package org.springframework.web.servlet.tags; import java.util.Arrays; import java.util.List; -import java.util.Locale; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; @@ -27,14 +26,16 @@ import javax.servlet.jsp.tagext.Tag; import org.springframework.context.MessageSourceResolvable; import org.springframework.context.support.DefaultMessageSourceResolvable; -import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.web.context.ConfigurableWebApplicationContext; import org.springframework.web.servlet.support.RequestContext; import org.springframework.web.servlet.support.RequestContextUtils; /** + * Tests for {@link MessageTag}. + * * @author Juergen Hoeller * @author Alef Arendsen + * @author Nicholas Williams */ public class MessageTagTests extends AbstractTagTests { @@ -51,6 +52,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setPageContext(pc); tag.setMessage(new DefaultMessageSourceResolvable("test")); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "test message", message.toString()); } @@ -67,6 +69,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setPageContext(pc); tag.setCode("test"); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "test message", message.toString()); } @@ -83,6 +86,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setPageContext(pc); tag.setCode(null); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "null", message.toString()); } @@ -100,6 +104,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setCode("testArgs"); tag.setArguments("arg1"); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "test arg1 message {1}", message.toString()); } @@ -117,6 +122,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setCode("testArgs"); tag.setArguments("arg1,arg2"); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "test arg1 message arg2", message.toString()); } @@ -135,6 +141,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setArguments("arg1,1;arg2,2"); tag.setArgumentSeparator(";"); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "test arg1,1 message arg2,2", message.toString()); } @@ -150,8 +157,9 @@ public class MessageTagTests extends AbstractTagTests { }; tag.setPageContext(pc); tag.setCode("testArgs"); - tag.setArguments(new Object[] {"arg1", new Integer(5)}); + tag.setArguments(new Object[] {"arg1", 5}); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "test arg1 message 5", message.toString()); } @@ -167,11 +175,68 @@ public class MessageTagTests extends AbstractTagTests { }; tag.setPageContext(pc); tag.setCode("testArgs"); - tag.setArguments(new Integer(5)); + tag.setArguments(5); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "test 5 message {1}", message.toString()); } + @SuppressWarnings("serial") + public void testMessageTagWithCodeAndArgumentAndNestedArgument() throws JspException { + PageContext pc = createPageContext(); + final StringBuffer message = new StringBuffer(); + MessageTag tag = new MessageTag() { + @Override + protected void writeMessage(String msg) { + message.append(msg); + } + }; + tag.setPageContext(pc); + tag.setCode("testArgs"); + assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + tag.setArguments(5); + tag.addArgument(7); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); + assertEquals("Correct message", "test 5 message 7", message.toString()); + } + + @SuppressWarnings("serial") + public void testMessageTagWithCodeAndNestedArgument() throws JspException { + PageContext pc = createPageContext(); + final StringBuffer message = new StringBuffer(); + MessageTag tag = new MessageTag() { + @Override + protected void writeMessage(String msg) { + message.append(msg); + } + }; + tag.setPageContext(pc); + tag.setCode("testArgs"); + assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + tag.addArgument(7); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); + assertEquals("Correct message", "test 7 message {1}", message.toString()); + } + + @SuppressWarnings("serial") + public void testMessageTagWithCodeAndNestedArguments() throws JspException { + PageContext pc = createPageContext(); + final StringBuffer message = new StringBuffer(); + MessageTag tag = new MessageTag() { + @Override + protected void writeMessage(String msg) { + message.append(msg); + } + }; + tag.setPageContext(pc); + tag.setCode("testArgs"); + assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + tag.addArgument("arg1"); + tag.addArgument(6); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); + assertEquals("Correct message", "test arg1 message 6", message.toString()); + } + @SuppressWarnings("serial") public void testMessageTagWithCodeAndText() throws JspException { PageContext pc = createPageContext(); @@ -186,6 +251,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setCode("test"); tag.setText("testtext"); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "test message", (message.toString())); } @@ -203,6 +269,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setText("test & text"); tag.setHtmlEscape(true); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "test & text", message.toString()); } @@ -220,6 +287,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setText("' test & text \\"); tag.setJavaScriptEscape(true); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "\\' test & text \\\\", message.toString()); } @@ -238,6 +306,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setHtmlEscape(true); tag.setJavaScriptEscape(true); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "' test & text \\\\", message.toString()); } @@ -249,6 +318,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setVar("testvar"); tag.setScope("page"); tag.doStartTag(); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("text & text", pc.getAttribute("testvar")); tag.release(); @@ -257,6 +327,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setCode("test"); tag.setVar("testvar2"); tag.doStartTag(); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "test message", pc.getAttribute("testvar2")); tag.release(); } @@ -268,6 +339,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setText("text & text"); tag.setVar("testvar"); tag.doStartTag(); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("text & text", pc.getAttribute("testvar")); tag.release(); @@ -277,6 +349,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setVar("testvar"); tag.doStartTag(); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("Correct message", "test message", pc.getAttribute("testvar")); } @@ -291,6 +364,7 @@ public class MessageTagTests extends AbstractTagTests { tag.setCode("test"); tag.setVar("testvar2"); tag.doStartTag(); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); } public void testRequestContext() throws ServletException { diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/ThemeTagTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/ThemeTagTests.java index d0113f95fe4..b7d0dc49e37 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/ThemeTagTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/tags/ThemeTagTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -48,6 +48,7 @@ public class ThemeTagTests extends AbstractTagTests { tag.setPageContext(pc); tag.setCode("themetest"); assertTrue("Correct doStartTag return value", tag.doStartTag() == Tag.EVAL_BODY_INCLUDE); + assertEquals("Correct doEndTag return value", Tag.EVAL_PAGE, tag.doEndTag()); assertEquals("theme test message", message.toString()); }