Add <spring:argument> subtag for message/theme
Add a new <spring:argument> tag that cab be nested within <spring:message> and <spring:theme>. The tag is based on the <fmt:param> tag and uses conventions found throughout other Spring tags. Issue: SPR-9678
This commit is contained in:
committed by
Phillip Webb
parent
50bd70f13d
commit
f9b17a708f
@@ -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;
|
||||
}
|
||||
@@ -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.
|
||||
*
|
||||
* <p>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
|
||||
*
|
||||
* <p>
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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<Object> 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<Object>();
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
* <p>If "code" isn't set or cannot be resolved, "text" will be used
|
||||
* as default message.
|
||||
*
|
||||
* <p>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 {
|
||||
|
||||
Reference in New Issue
Block a user