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/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/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/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.
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..dab5f8cd861 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
@@ -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/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");
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());
}