/*
* Copyright 2002-2018 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
*
* https://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.form;
import java.nio.charset.UnsupportedCharsetException;
import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import org.springframework.beans.PropertyAccessor;
import org.springframework.core.Conventions;
import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.support.RequestDataValueProcessor;
import org.springframework.web.util.HtmlUtils;
import org.springframework.web.util.UriUtils;
The <form>
tag renders an HTML 'form' tag and exposes a binding path to inner tags for binding. Users should place the form object into the ModelAndView
when populating the data for their view. The name of this form object can be configured using the "modelAttribute"
property.
Attribute Summary
Attribute
Required?
Runtime Expression?
Description
acceptCharset
false
true
Specifies the list of character encodings for input data that is accepted
by the server processing this form. The value is a space- and/or comma-delimited
list of charset values. The client must interpret this list as an exclusive-or
list, i.e., the server is able to accept any single character encoding per
entity received.
action
false
true
HTML Required Attribute
cssClass
false
true
HTML Optional Attribute
cssStyle
false
true
HTML Optional Attribute
dir
false
true
HTML Standard Attribute
enctype
false
true
HTML Optional Attribute
htmlEscape
false
true
Enable/disable HTML escaping of rendered values.
id
false
true
HTML Standard Attribute
lang
false
true
HTML Standard Attribute
method
false
true
HTML Optional Attribute
methodParam
false
true
The parameter name used for HTTP methods other then GET and POST.
Default is '_method'.
modelAttribute
false
true
Name of the model attribute under which the form object is exposed.
Defaults to 'command'.
name
false
true
HTML Standard Attribute - added for backwards compatibility cases
onclick
false
true
HTML Event Attribute
ondblclick
false
true
HTML Event Attribute
onkeydown
false
true
HTML Event Attribute
onkeypress
false
true
HTML Event Attribute
onkeyup
false
true
HTML Event Attribute
onmousedown
false
true
HTML Event Attribute
onmousemove
false
true
HTML Event Attribute
onmouseout
false
true
HTML Event Attribute
onmouseover
false
true
HTML Event Attribute
onmouseup
false
true
HTML Event Attribute
onreset
false
true
HTML Event Attribute
onsubmit
false
true
HTML Event Attribute
servletRelativeAction
false
true
Action reference to be appended to the current servlet path
target
false
true
HTML Optional Attribute
title
false
true
HTML Standard Attribute
Author: Rob Harrop, Juergen Hoeller, Scott Andrews, Rossen Stoyanchev Since: 2.0
/**
* The {@code <form>} tag renders an HTML 'form' tag and exposes a binding path to
* inner tags for binding.
*
* <p>Users should place the form object into the
* {@link org.springframework.web.servlet.ModelAndView ModelAndView} when
* populating the data for their view. The name of this form object can be
* configured using the {@link #setModelAttribute "modelAttribute"} property.
*
* <p>
* <table>
* <caption>Attribute Summary</caption>
* <thead>
* <tr>
* <th class="colFirst">Attribute</th>
* <th class="colOne">Required?</th>
* <th class="colOne">Runtime Expression?</th>
* <th class="colLast">Description</th>
* </tr>
* </thead>
* <tbody>
* <tr class="altColor">
* <td><p>acceptCharset</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>Specifies the list of character encodings for input data that is accepted
* by the server processing this form. The value is a space- and/or comma-delimited
* list of charset values. The client must interpret this list as an exclusive-or
* list, i.e., the server is able to accept any single character encoding per
* entity received.</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>action</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Required Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>cssClass</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Optional Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>cssStyle</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Optional Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>dir</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Standard Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>enctype</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Optional Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>htmlEscape</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>Enable/disable HTML escaping of rendered values.</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>id</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Standard Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>lang</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Standard Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>method</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Optional Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>methodParam</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>The parameter name used for HTTP methods other then GET and POST.
* Default is '_method'.</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>modelAttribute</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>Name of the model attribute under which the form object is exposed.
* Defaults to 'command'.</p></td>
* </tr>
* <tr class="altColor">
* <td><p>name</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Standard Attribute - added for backwards compatibility cases</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>onclick</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>ondblclick</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>onkeydown</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>onkeypress</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>onkeyup</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>onmousedown</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>onmousemove</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>onmouseout</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>onmouseover</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>onmouseup</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>onreset</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="altColor">
* <td><p>onsubmit</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Event Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>servletRelativeAction</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>Action reference to be appended to the current servlet path</p></td>
* </tr>
* <tr class="altColor">
* <td><p>target</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Optional Attribute</p></td>
* </tr>
* <tr class="rowColor">
* <td><p>title</p></td>
* <td><p>false</p></td>
* <td><p>true</p></td>
* <td><p>HTML Standard Attribute</p></td>
* </tr>
* </tbody>
* </table>
*
* @author Rob Harrop
* @author Juergen Hoeller
* @author Scott Andrews
* @author Rossen Stoyanchev
* @since 2.0
*/
@SuppressWarnings("serial")
public class FormTag extends AbstractHtmlElementTag {
The default HTTP method using which form values are sent to the server: "post". /** The default HTTP method using which form values are sent to the server: "post". */
private static final String DEFAULT_METHOD = "post";
The default attribute name: "command". /** The default attribute name: "command". */
public static final String DEFAULT_COMMAND_NAME = "command";
The name of the 'modelAttribute
' setting. /** The name of the '{@code modelAttribute}' setting. */
private static final String MODEL_ATTRIBUTE = "modelAttribute";
The name of the PageContext
attribute under which the form object name is exposed. /**
* The name of the {@link javax.servlet.jsp.PageContext} attribute under which the
* form object name is exposed.
*/
public static final String MODEL_ATTRIBUTE_VARIABLE_NAME =
Conventions.getQualifiedAttributeName(AbstractFormTag.class, MODEL_ATTRIBUTE);
Default method parameter, i.e. _method
. /** Default method parameter, i.e. {@code _method}. */
private static final String DEFAULT_METHOD_PARAM = "_method";
private static final String FORM_TAG = "form";
private static final String INPUT_TAG = "input";
private static final String ACTION_ATTRIBUTE = "action";
private static final String METHOD_ATTRIBUTE = "method";
private static final String TARGET_ATTRIBUTE = "target";
private static final String ENCTYPE_ATTRIBUTE = "enctype";
private static final String ACCEPT_CHARSET_ATTRIBUTE = "accept-charset";
private static final String ONSUBMIT_ATTRIBUTE = "onsubmit";
private static final String ONRESET_ATTRIBUTE = "onreset";
private static final String AUTOCOMPLETE_ATTRIBUTE = "autocomplete";
private static final String NAME_ATTRIBUTE = "name";
private static final String VALUE_ATTRIBUTE = "value";
private static final String TYPE_ATTRIBUTE = "type";
@Nullable
private TagWriter tagWriter;
private String modelAttribute = DEFAULT_COMMAND_NAME;
@Nullable
private String name;
@Nullable
private String action;
@Nullable
private String servletRelativeAction;
private String method = DEFAULT_METHOD;
@Nullable
private String target;
@Nullable
private String enctype;
@Nullable
private String acceptCharset;
@Nullable
private String onsubmit;
@Nullable
private String onreset;
@Nullable
private String autocomplete;
private String methodParam = DEFAULT_METHOD_PARAM;
Caching a previous nested path, so that it may be reset. /** Caching a previous nested path, so that it may be reset. */
@Nullable
private String previousNestedPath;
Set the name of the form attribute in the model.
May be a runtime expression.
/**
* Set the name of the form attribute in the model.
* <p>May be a runtime expression.
*/
public void setModelAttribute(String modelAttribute) {
this.modelAttribute = modelAttribute;
}
Get the name of the form attribute in the model.
/**
* Get the name of the form attribute in the model.
*/
protected String getModelAttribute() {
return this.modelAttribute;
}
Set the value of the 'name
' attribute. May be a runtime expression.
Name is not a valid attribute for form on XHTML 1.0. However,
it is sometimes needed for backward compatibility.
/**
* Set the value of the '{@code name}' attribute.
* <p>May be a runtime expression.
* <p>Name is not a valid attribute for form on XHTML 1.0. However,
* it is sometimes needed for backward compatibility.
*/
public void setName(String name) {
this.name = name;
}
Get the value of the 'name
' attribute. /**
* Get the value of the '{@code name}' attribute.
*/
@Override
@Nullable
protected String getName() throws JspException {
return this.name;
}
Set the value of the 'action
' attribute. May be a runtime expression.
/**
* Set the value of the '{@code action}' attribute.
* <p>May be a runtime expression.
*/
public void setAction(@Nullable String action) {
this.action = (action != null ? action : "");
}
Get the value of the 'action
' attribute. /**
* Get the value of the '{@code action}' attribute.
*/
@Nullable
protected String getAction() {
return this.action;
}
Set the value of the 'action
' attribute through a value that is to be appended to the current servlet path. May be a runtime expression.
Since: 3.2.3
/**
* Set the value of the '{@code action}' attribute through a value
* that is to be appended to the current servlet path.
* <p>May be a runtime expression.
* @since 3.2.3
*/
public void setServletRelativeAction(@Nullable String servletRelativeAction) {
this.servletRelativeAction = servletRelativeAction;
}
Get the servlet-relative value of the 'action
' attribute. Since: 3.2.3
/**
* Get the servlet-relative value of the '{@code action}' attribute.
* @since 3.2.3
*/
@Nullable
protected String getServletRelativeAction() {
return this.servletRelativeAction;
}
Set the value of the 'method
' attribute. May be a runtime expression.
/**
* Set the value of the '{@code method}' attribute.
* <p>May be a runtime expression.
*/
public void setMethod(String method) {
this.method = method;
}
Get the value of the 'method
' attribute. /**
* Get the value of the '{@code method}' attribute.
*/
protected String getMethod() {
return this.method;
}
Set the value of the 'target
' attribute. May be a runtime expression.
/**
* Set the value of the '{@code target}' attribute.
* <p>May be a runtime expression.
*/
public void setTarget(String target) {
this.target = target;
}
Get the value of the 'target
' attribute. /**
* Get the value of the '{@code target}' attribute.
*/
@Nullable
public String getTarget() {
return this.target;
}
Set the value of the 'enctype
' attribute. May be a runtime expression.
/**
* Set the value of the '{@code enctype}' attribute.
* <p>May be a runtime expression.
*/
public void setEnctype(String enctype) {
this.enctype = enctype;
}
Get the value of the 'enctype
' attribute. /**
* Get the value of the '{@code enctype}' attribute.
*/
@Nullable
protected String getEnctype() {
return this.enctype;
}
Set the value of the 'acceptCharset
' attribute. May be a runtime expression.
/**
* Set the value of the '{@code acceptCharset}' attribute.
* <p>May be a runtime expression.
*/
public void setAcceptCharset(String acceptCharset) {
this.acceptCharset = acceptCharset;
}
Get the value of the 'acceptCharset
' attribute. /**
* Get the value of the '{@code acceptCharset}' attribute.
*/
@Nullable
protected String getAcceptCharset() {
return this.acceptCharset;
}
Set the value of the 'onsubmit
' attribute. May be a runtime expression.
/**
* Set the value of the '{@code onsubmit}' attribute.
* <p>May be a runtime expression.
*/
public void setOnsubmit(String onsubmit) {
this.onsubmit = onsubmit;
}
Get the value of the 'onsubmit
' attribute. /**
* Get the value of the '{@code onsubmit}' attribute.
*/
@Nullable
protected String getOnsubmit() {
return this.onsubmit;
}
Set the value of the 'onreset
' attribute. May be a runtime expression.
/**
* Set the value of the '{@code onreset}' attribute.
* <p>May be a runtime expression.
*/
public void setOnreset(String onreset) {
this.onreset = onreset;
}
Get the value of the 'onreset
' attribute. /**
* Get the value of the '{@code onreset}' attribute.
*/
@Nullable
protected String getOnreset() {
return this.onreset;
}
Set the value of the 'autocomplete
' attribute. May be a runtime expression. /**
* Set the value of the '{@code autocomplete}' attribute.
* May be a runtime expression.
*/
public void setAutocomplete(String autocomplete) {
this.autocomplete = autocomplete;
}
Get the value of the 'autocomplete
' attribute. /**
* Get the value of the '{@code autocomplete}' attribute.
*/
@Nullable
protected String getAutocomplete() {
return this.autocomplete;
}
Set the name of the request param for non-browser supported HTTP methods.
/**
* Set the name of the request param for non-browser supported HTTP methods.
*/
public void setMethodParam(String methodParam) {
this.methodParam = methodParam;
}
Get the name of the request param for non-browser supported HTTP methods.
Since: 4.2.3
/**
* Get the name of the request param for non-browser supported HTTP methods.
* @since 4.2.3
*/
protected String getMethodParam() {
return this.methodParam;
}
Determine if the HTTP method is supported by browsers (i.e. GET or POST).
/**
* Determine if the HTTP method is supported by browsers (i.e. GET or POST).
*/
protected boolean isMethodBrowserSupported(String method) {
return ("get".equalsIgnoreCase(method) || "post".equalsIgnoreCase(method));
}
Writes the opening part of the block 'form
' tag and exposes the form object name in the PageContext
. Params: - tagWriter – the
TagWriter
to which the form content is to be written
Returns: EVAL_BODY_INCLUDE.EVAL_BODY_INCLUDE
/**
* Writes the opening part of the block '{@code form}' tag and exposes
* the form object name in the {@link javax.servlet.jsp.PageContext}.
* @param tagWriter the {@link TagWriter} to which the form content is to be written
* @return {@link javax.servlet.jsp.tagext.Tag#EVAL_BODY_INCLUDE}
*/
@Override
protected int writeTagContent(TagWriter tagWriter) throws JspException {
this.tagWriter = tagWriter;
tagWriter.startTag(FORM_TAG);
writeDefaultAttributes(tagWriter);
tagWriter.writeAttribute(ACTION_ATTRIBUTE, resolveAction());
writeOptionalAttribute(tagWriter, METHOD_ATTRIBUTE, getHttpMethod());
writeOptionalAttribute(tagWriter, TARGET_ATTRIBUTE, getTarget());
writeOptionalAttribute(tagWriter, ENCTYPE_ATTRIBUTE, getEnctype());
writeOptionalAttribute(tagWriter, ACCEPT_CHARSET_ATTRIBUTE, getAcceptCharset());
writeOptionalAttribute(tagWriter, ONSUBMIT_ATTRIBUTE, getOnsubmit());
writeOptionalAttribute(tagWriter, ONRESET_ATTRIBUTE, getOnreset());
writeOptionalAttribute(tagWriter, AUTOCOMPLETE_ATTRIBUTE, getAutocomplete());
tagWriter.forceBlock();
if (!isMethodBrowserSupported(getMethod())) {
assertHttpMethod(getMethod());
String inputName = getMethodParam();
String inputType = "hidden";
tagWriter.startTag(INPUT_TAG);
writeOptionalAttribute(tagWriter, TYPE_ATTRIBUTE, inputType);
writeOptionalAttribute(tagWriter, NAME_ATTRIBUTE, inputName);
writeOptionalAttribute(tagWriter, VALUE_ATTRIBUTE, processFieldValue(inputName, getMethod(), inputType));
tagWriter.endTag();
}
// Expose the form object name for nested tags...
String modelAttribute = resolveModelAttribute();
this.pageContext.setAttribute(MODEL_ATTRIBUTE_VARIABLE_NAME, modelAttribute, PageContext.REQUEST_SCOPE);
// Save previous nestedPath value, build and expose current nestedPath value.
// Use request scope to expose nestedPath to included pages too.
this.previousNestedPath =
(String) this.pageContext.getAttribute(NESTED_PATH_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
this.pageContext.setAttribute(NESTED_PATH_VARIABLE_NAME,
modelAttribute + PropertyAccessor.NESTED_PROPERTY_SEPARATOR, PageContext.REQUEST_SCOPE);
return EVAL_BODY_INCLUDE;
}
private String getHttpMethod() {
return (isMethodBrowserSupported(getMethod()) ? getMethod() : DEFAULT_METHOD);
}
private void assertHttpMethod(String method) {
for (HttpMethod httpMethod : HttpMethod.values()) {
if (httpMethod.name().equalsIgnoreCase(method)) {
return;
}
}
throw new IllegalArgumentException("Invalid HTTP method: " + method);
}
Autogenerated IDs correspond to the form object name.
/**
* Autogenerated IDs correspond to the form object name.
*/
@Override
protected String autogenerateId() throws JspException {
return resolveModelAttribute();
}
Resolves
and returns the name of the form object. Throws: - IllegalArgumentException – if the form object resolves to
null
/**
* {@link #evaluate Resolves} and returns the name of the form object.
* @throws IllegalArgumentException if the form object resolves to {@code null}
*/
protected String resolveModelAttribute() throws JspException {
Object resolvedModelAttribute = evaluate(MODEL_ATTRIBUTE, getModelAttribute());
if (resolvedModelAttribute == null) {
throw new IllegalArgumentException(MODEL_ATTRIBUTE + " must not be null");
}
return (String) resolvedModelAttribute;
}
Resolve the value of the 'action
' attribute. If the user configured an 'action
' value then the result of evaluating this value is used. If the user configured an 'servletRelativeAction
' value then the value is prepended with the context and servlet paths, and the result is used. Otherwise, the
originating URI
is used.
Returns: the value that is to be used for the 'action
' attribute
/**
* Resolve the value of the '{@code action}' attribute.
* <p>If the user configured an '{@code action}' value then the result of
* evaluating this value is used. If the user configured an
* '{@code servletRelativeAction}' value then the value is prepended
* with the context and servlet paths, and the result is used. Otherwise, the
* {@link org.springframework.web.servlet.support.RequestContext#getRequestUri()
* originating URI} is used.
* @return the value that is to be used for the '{@code action}' attribute
*/
protected String resolveAction() throws JspException {
String action = getAction();
String servletRelativeAction = getServletRelativeAction();
if (StringUtils.hasText(action)) {
action = getDisplayString(evaluate(ACTION_ATTRIBUTE, action));
return processAction(action);
}
else if (StringUtils.hasText(servletRelativeAction)) {
String pathToServlet = getRequestContext().getPathToServlet();
if (servletRelativeAction.startsWith("/") &&
!servletRelativeAction.startsWith(getRequestContext().getContextPath())) {
servletRelativeAction = pathToServlet + servletRelativeAction;
}
servletRelativeAction = getDisplayString(evaluate(ACTION_ATTRIBUTE, servletRelativeAction));
return processAction(servletRelativeAction);
}
else {
String requestUri = getRequestContext().getRequestUri();
String encoding = this.pageContext.getResponse().getCharacterEncoding();
try {
requestUri = UriUtils.encodePath(requestUri, encoding);
}
catch (UnsupportedCharsetException ex) {
// shouldn't happen - if it does, proceed with requestUri as-is
}
ServletResponse response = this.pageContext.getResponse();
if (response instanceof HttpServletResponse) {
requestUri = ((HttpServletResponse) response).encodeURL(requestUri);
String queryString = getRequestContext().getQueryString();
if (StringUtils.hasText(queryString)) {
requestUri += "?" + HtmlUtils.htmlEscape(queryString);
}
}
if (StringUtils.hasText(requestUri)) {
return processAction(requestUri);
}
else {
throw new IllegalArgumentException("Attribute 'action' is required. " +
"Attempted to resolve against current request URI but request URI was null.");
}
}
}
Process the action through a RequestDataValueProcessor
instance if one is configured or otherwise returns the action unmodified. /**
* Process the action through a {@link RequestDataValueProcessor} instance
* if one is configured or otherwise returns the action unmodified.
*/
private String processAction(String action) {
RequestDataValueProcessor processor = getRequestContext().getRequestDataValueProcessor();
ServletRequest request = this.pageContext.getRequest();
if (processor != null && request instanceof HttpServletRequest) {
action = processor.processAction((HttpServletRequest) request, action, getHttpMethod());
}
return action;
}
Closes the 'form
' block tag and removes the form object name from the PageContext
. /**
* Closes the '{@code form}' block tag and removes the form object name
* from the {@link javax.servlet.jsp.PageContext}.
*/
@Override
public int doEndTag() throws JspException {
RequestDataValueProcessor processor = getRequestContext().getRequestDataValueProcessor();
ServletRequest request = this.pageContext.getRequest();
if (processor != null && request instanceof HttpServletRequest) {
writeHiddenFields(processor.getExtraHiddenFields((HttpServletRequest) request));
}
Assert.state(this.tagWriter != null, "No TagWriter set");
this.tagWriter.endTag();
return EVAL_PAGE;
}
Writes the given values as hidden fields.
/**
* Writes the given values as hidden fields.
*/
private void writeHiddenFields(@Nullable Map<String, String> hiddenFields) throws JspException {
if (!CollectionUtils.isEmpty(hiddenFields)) {
Assert.state(this.tagWriter != null, "No TagWriter set");
this.tagWriter.appendValue("<div>\n");
for (Map.Entry<String, String> entry : hiddenFields.entrySet()) {
this.tagWriter.appendValue("<input type=\"hidden\" ");
this.tagWriter.appendValue("name=\"" + entry.getKey() + "\" value=\"" + entry.getValue() + "\" ");
this.tagWriter.appendValue("/>\n");
}
this.tagWriter.appendValue("</div>");
}
}
Clears the stored TagWriter
. /**
* Clears the stored {@link TagWriter}.
*/
@Override
public void doFinally() {
super.doFinally();
this.pageContext.removeAttribute(MODEL_ATTRIBUTE_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
if (this.previousNestedPath != null) {
// Expose previous nestedPath value.
this.pageContext.setAttribute(NESTED_PATH_VARIABLE_NAME, this.previousNestedPath, PageContext.REQUEST_SCOPE);
}
else {
// Remove exposed nestedPath value.
this.pageContext.removeAttribute(NESTED_PATH_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
}
this.tagWriter = null;
this.previousNestedPath = null;
}
Override resolve CSS class since error class is not supported.
/**
* Override resolve CSS class since error class is not supported.
*/
@Override
protected String resolveCssClass() throws JspException {
return ObjectUtils.getDisplayString(evaluate("cssClass", getCssClass()));
}
Unsupported for forms.
Throws: - UnsupportedOperationException – always
/**
* Unsupported for forms.
* @throws UnsupportedOperationException always
*/
@Override
public void setPath(String path) {
throw new UnsupportedOperationException("The 'path' attribute is not supported for forms");
}
Unsupported for forms.
Throws: - UnsupportedOperationException – always
/**
* Unsupported for forms.
* @throws UnsupportedOperationException always
*/
@Override
public void setCssErrorClass(String cssErrorClass) {
throw new UnsupportedOperationException("The 'cssErrorClass' attribute is not supported for forms");
}
}