Browse Source

Nullability refinements in spring-webmvc

Includes revision of web.servlet.tags.form for non-null conventions.

Issue: SPR-15540

(cherry picked from commit f74a631ea1)
pull/1916/head
Juergen Hoeller 6 years ago
parent
commit
2a32c6cf57
  1. 8
      spring-context/src/main/java/org/springframework/ui/ModelMap.java
  2. 24
      spring-webmvc/src/main/java/org/springframework/web/servlet/ModelAndView.java
  3. 9
      spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestDataValueProcessor.java
  4. 16
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractCheckedElementTag.java
  5. 15
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractDataBoundFormElementTag.java
  6. 10
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractFormTag.java
  7. 11
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractHtmlElementBodyTag.java
  8. 43
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractHtmlElementTag.java
  9. 12
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractHtmlInputElementTag.java
  10. 24
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractMultiCheckedElementTag.java
  11. 17
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractSingleCheckedElementTag.java
  12. 16
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/ButtonTag.java
  13. 6
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/ErrorsTag.java
  14. 34
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/FormTag.java
  15. 31
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/InputTag.java
  16. 10
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/LabelTag.java
  17. 16
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/OptionTag.java
  18. 37
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/OptionWriter.java
  19. 15
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/OptionsTag.java
  20. 2
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/RadioButtonTag.java
  21. 22
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/SelectTag.java
  22. 37
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/SelectedValueComparator.java
  23. 9
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/TagWriter.java
  24. 10
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/TextareaTag.java
  25. 9
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/ValueFormatter.java
  26. 8
      spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/package-info.java

8
spring-context/src/main/java/org/springframework/ui/ModelMap.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* 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.
@ -51,7 +51,7 @@ public class ModelMap extends LinkedHashMap<String, Object> { @@ -51,7 +51,7 @@ public class ModelMap extends LinkedHashMap<String, Object> {
* under the supplied name.
* @see #addAttribute(String, Object)
*/
public ModelMap(String attributeName, Object attributeValue) {
public ModelMap(String attributeName, @Nullable Object attributeValue) {
addAttribute(attributeName, attributeValue);
}
@ -80,10 +80,10 @@ public class ModelMap extends LinkedHashMap<String, Object> { @@ -80,10 +80,10 @@ public class ModelMap extends LinkedHashMap<String, Object> {
/**
* Add the supplied attribute to this {@code Map} using a
* {@link org.springframework.core.Conventions#getVariableName generated name}.
* <p><emphasis>Note: Empty {@link Collection Collections} are not added to
* <p><i>Note: Empty {@link Collection Collections} are not added to
* the model when using this method because we cannot correctly determine
* the true convention name. View code should check for {@code null} rather
* than for empty collections as is already done by JSTL tags.</emphasis>
* than for empty collections as is already done by JSTL tags.</i>
* @param attributeValue the model attribute value (never {@code null})
*/
public ModelMap addAttribute(Object attributeValue) {

24
spring-webmvc/src/main/java/org/springframework/web/servlet/ModelAndView.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* 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.
@ -85,7 +85,7 @@ public class ModelAndView { @@ -85,7 +85,7 @@ public class ModelAndView {
/**
* Convenient constructor when there is no model data to expose.
* Can also be used in conjunction with {@code addObject}.
* @param view View object to render
* @param view the View object to render
* @see #addObject
*/
public ModelAndView(View view) {
@ -96,7 +96,7 @@ public class ModelAndView { @@ -96,7 +96,7 @@ public class ModelAndView {
* Create a new ModelAndView given a view name and a model.
* @param viewName name of the View to render, to be resolved
* by the DispatcherServlet's ViewResolver
* @param model Map of model names (Strings) to model objects
* @param model a Map of model names (Strings) to model objects
* (Objects). Model entries may not be {@code null}, but the
* model Map may be {@code null} if there is no model data.
*/
@ -109,11 +109,11 @@ public class ModelAndView { @@ -109,11 +109,11 @@ public class ModelAndView {
/**
* Create a new ModelAndView given a View object and a model.
* <emphasis>Note: the supplied model data is copied into the internal
* <em>Note: the supplied model data is copied into the internal
* storage of this class. You should not consider to modify the supplied
* Map after supplying it to this class</emphasis>
* @param view View object to render
* @param model Map of model names (Strings) to model objects
* Map after supplying it to this class</em>
* @param view the View object to render
* @param model a Map of model names (Strings) to model objects
* (Objects). Model entries may not be {@code null}, but the
* model Map may be {@code null} if there is no model data.
*/
@ -141,7 +141,7 @@ public class ModelAndView { @@ -141,7 +141,7 @@ public class ModelAndView {
* Create a new ModelAndView given a view name, model, and HTTP status.
* @param viewName name of the View to render, to be resolved
* by the DispatcherServlet's ViewResolver
* @param model Map of model names (Strings) to model objects
* @param model a Map of model names (Strings) to model objects
* (Objects). Model entries may not be {@code null}, but the
* model Map may be {@code null} if there is no model data.
* @param status an HTTP status code to use for the response
@ -170,7 +170,7 @@ public class ModelAndView { @@ -170,7 +170,7 @@ public class ModelAndView {
/**
* Convenient constructor to take a single model object.
* @param view View object to render
* @param view the View object to render
* @param modelName name of the single entry in the model
* @param modelObject the single model object
*/
@ -280,12 +280,12 @@ public class ModelAndView { @@ -280,12 +280,12 @@ public class ModelAndView {
/**
* Add an attribute to the model.
* @param attributeName name of the object to add to the model
* @param attributeValue object to add to the model (never {@code null})
* @param attributeName name of the object to add to the model (never {@code null})
* @param attributeValue object to add to the model (can be {@code null})
* @see ModelMap#addAttribute(String, Object)
* @see #getModelMap()
*/
public ModelAndView addObject(String attributeName, Object attributeValue) {
public ModelAndView addObject(String attributeName, @Nullable Object attributeValue) {
getModelMap().addAttribute(attributeName, attributeValue);
return this;
}

9
spring-webmvc/src/main/java/org/springframework/web/servlet/support/RequestDataValueProcessor.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* 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.
@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
package org.springframework.web.servlet.support;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.lang.Nullable;
@ -52,17 +51,17 @@ public interface RequestDataValueProcessor { @@ -52,17 +51,17 @@ public interface RequestDataValueProcessor {
/**
* Invoked when a form field value is rendered.
* @param request the current request
* @param name the form field name
* @param name the form field name (if any)
* @param value the form field value
* @param type the form field type ("text", "hidden", etc.)
* @return the form field value to use, possibly modified
*/
String processFormFieldValue(HttpServletRequest request, String name, String value, String type);
String processFormFieldValue(HttpServletRequest request, @Nullable String name, String value, String type);
/**
* Invoked after all form fields have been rendered.
* @param request the current request
* @return additional hidden form fields to be added, or {@code null}
* @return additional hidden form fields to be added, or {@code null} if none
*/
@Nullable
Map<String, String> getExtraHiddenFields(HttpServletRequest request);

16
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractCheckedElementTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* 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.
@ -18,6 +18,8 @@ package org.springframework.web.servlet.tags.form; @@ -18,6 +18,8 @@ package org.springframework.web.servlet.tags.form;
import javax.servlet.jsp.JspException;
import org.springframework.lang.Nullable;
/**
* Abstract base class to provide common methods for
* implementing databinding-aware JSP tags for rendering an HTML '{@code input}'
@ -36,7 +38,7 @@ public abstract class AbstractCheckedElementTag extends AbstractHtmlInputElement @@ -36,7 +38,7 @@ public abstract class AbstractCheckedElementTag extends AbstractHtmlInputElement
* '{@code input}' element as 'checked' if the supplied value matches the
* bound value.
*/
protected void renderFromValue(Object value, TagWriter tagWriter) throws JspException {
protected void renderFromValue(@Nullable Object value, TagWriter tagWriter) throws JspException {
renderFromValue(value, value, tagWriter);
}
@ -45,7 +47,9 @@ public abstract class AbstractCheckedElementTag extends AbstractHtmlInputElement @@ -45,7 +47,9 @@ public abstract class AbstractCheckedElementTag extends AbstractHtmlInputElement
* '{@code input}' element as 'checked' if the supplied value matches the
* bound value.
*/
protected void renderFromValue(Object item, Object value, TagWriter tagWriter) throws JspException {
protected void renderFromValue(@Nullable Object item, @Nullable Object value, TagWriter tagWriter)
throws JspException {
String displayValue = convertToDisplayString(value);
tagWriter.writeAttribute("value", processFieldValue(getName(), displayValue, getInputType()));
if (isOptionSelected(value) || (value != item && isOptionSelected(item))) {
@ -57,7 +61,7 @@ public abstract class AbstractCheckedElementTag extends AbstractHtmlInputElement @@ -57,7 +61,7 @@ public abstract class AbstractCheckedElementTag extends AbstractHtmlInputElement
* Determines whether the supplied value matched the selected value
* through delegating to {@link SelectedValueComparator#isSelected}.
*/
private boolean isOptionSelected(Object value) throws JspException {
private boolean isOptionSelected(@Nullable Object value) throws JspException {
return SelectedValueComparator.isSelected(getBindStatus(), value);
}
@ -77,8 +81,10 @@ public abstract class AbstractCheckedElementTag extends AbstractHtmlInputElement @@ -77,8 +81,10 @@ public abstract class AbstractCheckedElementTag extends AbstractHtmlInputElement
* Return a unique ID for the bound name within the current PageContext.
*/
@Override
@Nullable
protected String autogenerateId() throws JspException {
return TagIdGenerator.nextId(super.autogenerateId(), this.pageContext);
String id = super.autogenerateId();
return (id != null ? TagIdGenerator.nextId(id, this.pageContext) : null);
}

15
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractDataBoundFormElementTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* 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.
@ -55,16 +55,19 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im @@ -55,16 +55,19 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im
/**
* The property path from the {@link FormTag#setModelAttribute form object}.
*/
@Nullable
private String path;
/**
* The value of the '{@code id}' attribute.
*/
@Nullable
private String id;
/**
* The {@link BindStatus} of this tag.
*/
@Nullable
private BindStatus bindStatus;
@ -91,7 +94,7 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im @@ -91,7 +94,7 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im
* Note that the default value may not be valid for certain tags.
*/
@Override
public void setId(String id) {
public void setId(@Nullable String id) {
this.id = id;
}
@ -99,6 +102,7 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im @@ -99,6 +102,7 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im
* Get the value of the '{@code id}' attribute.
*/
@Override
@Nullable
public String getId() {
return this.id;
}
@ -179,6 +183,7 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im @@ -179,6 +183,7 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im
* Get the value of the nested path that may have been exposed by the
* {@link NestedPathTag}.
*/
@Nullable
protected String getNestedPath() {
return (String) this.pageContext.getAttribute(NESTED_PATH_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
}
@ -225,7 +230,7 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im @@ -225,7 +230,7 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im
* Get a display String for the given value, converted by a PropertyEditor
* that the BindStatus may have registered for the value's Class.
*/
protected String convertToDisplayString(Object value) throws JspException {
protected String convertToDisplayString(@Nullable Object value) throws JspException {
PropertyEditor editor = (value != null ? getBindStatus().findEditor(value.getClass()) : null);
return getDisplayString(value, editor);
}
@ -234,10 +239,10 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im @@ -234,10 +239,10 @@ public abstract class AbstractDataBoundFormElementTag extends AbstractFormTag im
* Process the given form field through a {@link RequestDataValueProcessor}
* instance if one is configured or otherwise returns the same value.
*/
protected final String processFieldValue(String name, String value, String type) {
protected final String processFieldValue(@Nullable String name, String value, String type) {
RequestDataValueProcessor processor = getRequestContext().getRequestDataValueProcessor();
ServletRequest request = this.pageContext.getRequest();
if (processor != null && (request instanceof HttpServletRequest)) {
if (processor != null && request instanceof HttpServletRequest) {
value = processor.processFormFieldValue((HttpServletRequest) request, name, value, type);
}
return value;

10
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractFormTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* 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.
@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
package org.springframework.web.servlet.tags.form;
import java.beans.PropertyEditor;
import javax.servlet.jsp.JspException;
import org.springframework.lang.Nullable;
@ -46,7 +45,8 @@ public abstract class AbstractFormTag extends HtmlEscapingAwareTag { @@ -46,7 +45,8 @@ public abstract class AbstractFormTag extends HtmlEscapingAwareTag {
* Evaluate the supplied value for the supplied attribute name.
* <p>The default implementation simply returns the given value as-is.
*/
protected Object evaluate(String attributeName, Object value) throws JspException {
@Nullable
protected Object evaluate(String attributeName, @Nullable Object value) throws JspException {
return value;
}
@ -90,7 +90,7 @@ public abstract class AbstractFormTag extends HtmlEscapingAwareTag { @@ -90,7 +90,7 @@ public abstract class AbstractFormTag extends HtmlEscapingAwareTag {
* Get the display value of the supplied {@code Object}, HTML escaped
* as required. This version is <strong>not</strong> {@link PropertyEditor}-aware.
*/
protected String getDisplayString(Object value) {
protected String getDisplayString(@Nullable Object value) {
return ValueFormatter.getDisplayString(value, isHtmlEscape());
}
@ -100,7 +100,7 @@ public abstract class AbstractFormTag extends HtmlEscapingAwareTag { @@ -100,7 +100,7 @@ public abstract class AbstractFormTag extends HtmlEscapingAwareTag {
* {@link PropertyEditor} is not null then the {@link PropertyEditor} is used
* to obtain the display value.
*/
protected String getDisplayString(Object value, PropertyEditor propertyEditor) {
protected String getDisplayString(@Nullable Object value, @Nullable PropertyEditor propertyEditor) {
return ValueFormatter.getDisplayString(value, propertyEditor, isHtmlEscape());
}

11
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractHtmlElementBodyTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@ -21,6 +21,8 @@ import javax.servlet.jsp.JspException; @@ -21,6 +21,8 @@ import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTag;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@ -35,8 +37,10 @@ import org.springframework.util.StringUtils; @@ -35,8 +37,10 @@ import org.springframework.util.StringUtils;
@SuppressWarnings("serial")
public abstract class AbstractHtmlElementBodyTag extends AbstractHtmlElementTag implements BodyTag {
@Nullable
private BodyContent bodyContent;
@Nullable
private TagWriter tagWriter;
@ -57,11 +61,12 @@ public abstract class AbstractHtmlElementBodyTag extends AbstractHtmlElementTag @@ -57,11 +61,12 @@ public abstract class AbstractHtmlElementBodyTag extends AbstractHtmlElementTag
* If {@link #shouldRender rendering}, flush any buffered
* {@link BodyContent} or, if no {@link BodyContent} is supplied,
* {@link #renderDefaultContent render the default content}.
* @return Tag#EVAL_PAGE
* @return a {@link javax.servlet.jsp.tagext.Tag#EVAL_PAGE} result
*/
@Override
public int doEndTag() throws JspException {
if (shouldRender()) {
Assert.state(this.tagWriter != null, "No TagWriter set");
if (this.bodyContent != null && StringUtils.hasText(this.bodyContent.getString())) {
renderFromBodyContent(this.bodyContent, this.tagWriter);
}
@ -79,7 +84,7 @@ public abstract class AbstractHtmlElementBodyTag extends AbstractHtmlElementTag @@ -79,7 +84,7 @@ public abstract class AbstractHtmlElementBodyTag extends AbstractHtmlElementTag
* override this to add additional content to the output.
*/
protected void renderFromBodyContent(BodyContent bodyContent, TagWriter tagWriter) throws JspException {
flushBufferedBodyContent(this.bodyContent);
flushBufferedBodyContent(bodyContent);
}
/**

43
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractHtmlElementTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@ -21,6 +21,7 @@ import java.util.Map; @@ -21,6 +21,7 @@ import java.util.Map;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.DynamicAttributes;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@ -76,40 +77,58 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -76,40 +77,58 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
public static final String ONKEYDOWN_ATTRIBUTE = "onkeydown";
@Nullable
private String cssClass;
@Nullable
private String cssErrorClass;
@Nullable
private String cssStyle;
@Nullable
private String lang;
@Nullable
private String title;
@Nullable
private String dir;
@Nullable
private String tabindex;
@Nullable
private String onclick;
@Nullable
private String ondblclick;
@Nullable
private String onmousedown;
@Nullable
private String onmouseup;
@Nullable
private String onmouseover;
@Nullable
private String onmousemove;
@Nullable
private String onmouseout;
@Nullable
private String onkeypress;
@Nullable
private String onkeyup;
@Nullable
private String onkeydown;
@Nullable
private Map<String, Object> dynamicAttributes;
@ -125,6 +144,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -125,6 +144,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code class}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getCssClass() {
return this.cssClass;
}
@ -141,6 +161,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -141,6 +161,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* The CSS class to use when the field bound to a particular tag has errors.
* May be a runtime expression.
*/
@Nullable
protected String getCssErrorClass() {
return this.cssErrorClass;
}
@ -157,6 +178,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -157,6 +178,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code style}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getCssStyle() {
return this.cssStyle;
}
@ -173,6 +195,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -173,6 +195,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code lang}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getLang() {
return this.lang;
}
@ -189,6 +212,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -189,6 +212,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code title}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getTitle() {
return this.title;
}
@ -205,6 +229,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -205,6 +229,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code dir}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getDir() {
return this.dir;
}
@ -221,6 +246,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -221,6 +246,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code tabindex}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getTabindex() {
return this.tabindex;
}
@ -237,6 +263,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -237,6 +263,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code onclick}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getOnclick() {
return this.onclick;
}
@ -253,6 +280,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -253,6 +280,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code ondblclick}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getOndblclick() {
return this.ondblclick;
}
@ -269,6 +297,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -269,6 +297,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code onmousedown}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getOnmousedown() {
return this.onmousedown;
}
@ -285,6 +314,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -285,6 +314,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code onmouseup}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getOnmouseup() {
return this.onmouseup;
}
@ -301,6 +331,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -301,6 +331,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code onmouseover}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getOnmouseover() {
return this.onmouseover;
}
@ -317,6 +348,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -317,6 +348,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code onmousemove}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getOnmousemove() {
return this.onmousemove;
}
@ -332,6 +364,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -332,6 +364,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code onmouseout}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getOnmouseout() {
return this.onmouseout;
}
@ -348,6 +381,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -348,6 +381,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code onkeypress}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getOnkeypress() {
return this.onkeypress;
}
@ -364,6 +398,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -364,6 +398,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code onkeyup}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getOnkeyup() {
return this.onkeyup;
}
@ -380,6 +415,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -380,6 +415,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* Get the value of the '{@code onkeydown}' attribute.
* May be a runtime expression.
*/
@Nullable
protected String getOnkeydown() {
return this.onkeydown;
}
@ -387,6 +423,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -387,6 +423,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
/**
* Get the map of dynamic attributes.
*/
@Nullable
protected Map<String, Object> getDynamicAttributes() {
return this.dynamicAttributes;
}
@ -395,7 +432,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -395,7 +432,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
* {@inheritDoc}
*/
@Override
public void setDynamicAttribute(String uri, String localName, Object value ) throws JspException {
public void setDynamicAttribute(String uri, String localName, Object value) throws JspException {
if (this.dynamicAttributes == null) {
this.dynamicAttributes = new HashMap<>();
}
@ -403,7 +440,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen @@ -403,7 +440,7 @@ public abstract class AbstractHtmlElementTag extends AbstractDataBoundFormElemen
throw new IllegalArgumentException(
"Attribute " + localName + "=\"" + value + "\" is not allowed");
}
dynamicAttributes.put(localName, value);
this.dynamicAttributes.put(localName, value);
}
/**

12
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractHtmlInputElementTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* 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.
@ -18,6 +18,8 @@ package org.springframework.web.servlet.tags.form; @@ -18,6 +18,8 @@ package org.springframework.web.servlet.tags.form;
import javax.servlet.jsp.JspException;
import org.springframework.lang.Nullable;
/**
* Base class for databinding-aware JSP tags that render HTML form input element.
*
@ -63,12 +65,16 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag @@ -63,12 +65,16 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag
public static final String READONLY_ATTRIBUTE = "readonly";
@Nullable
private String onfocus;
@Nullable
private String onblur;
@Nullable
private String onchange;
@Nullable
private String accesskey;
private boolean disabled;
@ -87,6 +93,7 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag @@ -87,6 +93,7 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag
/**
* Get the value of the '{@code onfocus}' attribute.
*/
@Nullable
protected String getOnfocus() {
return this.onfocus;
}
@ -102,6 +109,7 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag @@ -102,6 +109,7 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag
/**
* Get the value of the '{@code onblur}' attribute.
*/
@Nullable
protected String getOnblur() {
return this.onblur;
}
@ -117,6 +125,7 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag @@ -117,6 +125,7 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag
/**
* Get the value of the '{@code onchange}' attribute.
*/
@Nullable
protected String getOnchange() {
return this.onchange;
}
@ -132,6 +141,7 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag @@ -132,6 +141,7 @@ public abstract class AbstractHtmlInputElementTag extends AbstractHtmlElementTag
/**
* Get the value of the '{@code accesskey}' attribute.
*/
@Nullable
protected String getAccesskey() {
return this.accesskey;
}

24
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractMultiCheckedElementTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* 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.
@ -23,6 +23,7 @@ import javax.servlet.jsp.JspException; @@ -23,6 +23,7 @@ import javax.servlet.jsp.JspException;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@ -50,17 +51,20 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem @@ -50,17 +51,20 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
* The {@link java.util.Collection}, {@link java.util.Map} or array of objects
* used to generate the '{@code input type="checkbox/radio"}' tags.
*/
@Nullable
private Object items;
/**
* The name of the property mapped to the '{@code value}' attribute
* of the '{@code input type="checkbox/radio"}' tag.
*/
@Nullable
private String itemValue;
/**
* The value to be displayed as part of the '{@code input type="checkbox/radio"}' tag.
*/
@Nullable
private String itemLabel;
/**
@ -71,6 +75,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem @@ -71,6 +75,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
/**
* Delimiter to use between each '{@code input type="checkbox/radio"}' tags.
*/
@Nullable
private String delimiter;
@ -89,6 +94,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem @@ -89,6 +94,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
* Get the {@link java.util.Collection}, {@link java.util.Map} or array of objects
* used to generate the '{@code input type="checkbox/radio"}' tags.
*/
@Nullable
protected Object getItems() {
return this.items;
}
@ -107,6 +113,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem @@ -107,6 +113,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
* Get the name of the property mapped to the '{@code value}' attribute
* of the '{@code input type="checkbox/radio"}' tag.
*/
@Nullable
protected String getItemValue() {
return this.itemValue;
}
@ -125,6 +132,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem @@ -125,6 +132,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
* Get the value to be displayed as part of the
* '{@code input type="checkbox/radio"}' tag.
*/
@Nullable
protected String getItemLabel() {
return this.itemLabel;
}
@ -142,6 +150,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem @@ -142,6 +150,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
* Return the delimiter to be used between each
* '{@code input type="radio"}' tag.
*/
@Nullable
public String getDelimiter() {
return this.delimiter;
}
@ -236,8 +245,8 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem @@ -236,8 +245,8 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
return SKIP_BODY;
}
private void writeObjectEntry(TagWriter tagWriter, String valueProperty,
String labelProperty, Object item, int itemIndex) throws JspException {
private void writeObjectEntry(TagWriter tagWriter, @Nullable String valueProperty,
@Nullable String labelProperty, Object item, int itemIndex) throws JspException {
BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(item);
Object renderValue;
@ -254,8 +263,8 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem @@ -254,8 +263,8 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
writeElementTag(tagWriter, item, renderValue, renderLabel, itemIndex);
}
private void writeMapEntry(TagWriter tagWriter, String valueProperty,
String labelProperty, Map.Entry<?, ?> entry, int itemIndex) throws JspException {
private void writeMapEntry(TagWriter tagWriter, @Nullable String valueProperty,
@Nullable String labelProperty, Map.Entry<?, ?> entry, int itemIndex) throws JspException {
Object mapKey = entry.getKey();
Object mapValue = entry.getValue();
@ -268,8 +277,8 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem @@ -268,8 +277,8 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
writeElementTag(tagWriter, mapKey, renderValue, renderLabel, itemIndex);
}
private void writeElementTag(TagWriter tagWriter, Object item, Object value, Object label, int itemIndex)
throws JspException {
private void writeElementTag(TagWriter tagWriter, Object item, @Nullable Object value,
@Nullable Object label, int itemIndex) throws JspException {
tagWriter.startTag(getElement());
if (itemIndex > 0) {
@ -280,6 +289,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem @@ -280,6 +289,7 @@ public abstract class AbstractMultiCheckedElementTag extends AbstractCheckedElem
}
tagWriter.startTag("input");
String id = resolveId();
Assert.state(id != null, "Attribute 'id' is required");
writeOptionalAttribute(tagWriter, "id", id);
writeOptionalAttribute(tagWriter, "name", getName());
writeOptionalAttributes(tagWriter);

17
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/AbstractSingleCheckedElementTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* 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.
@ -18,11 +18,13 @@ package org.springframework.web.servlet.tags.form; @@ -18,11 +18,13 @@ package org.springframework.web.servlet.tags.form;
import javax.servlet.jsp.JspException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Abstract base class to provide common methods for implementing
* databinding-aware JSP tags for rendering a <i>single</i>
* HTML '{@code input}' element with a '{@code type}'
* of '{@code checkbox}' or '{@code radio}'.
* Abstract base class to provide common methods for implementing databinding-aware
* JSP tags for rendering a <i>single</i> HTML '{@code input}' element with a
* '{@code type}' of '{@code checkbox}' or '{@code radio}'.
*
* @author Juergen Hoeller
* @since 2.5.2
@ -33,11 +35,13 @@ public abstract class AbstractSingleCheckedElementTag extends AbstractCheckedEle @@ -33,11 +35,13 @@ public abstract class AbstractSingleCheckedElementTag extends AbstractCheckedEle
/**
* The value of the '{@code value}' attribute.
*/
@Nullable
private Object value;
/**
* The value of the '{@code label}' attribute.
*/
@Nullable
private Object label;
@ -52,6 +56,7 @@ public abstract class AbstractSingleCheckedElementTag extends AbstractCheckedEle @@ -52,6 +56,7 @@ public abstract class AbstractSingleCheckedElementTag extends AbstractCheckedEle
/**
* Get the value of the '{@code value}' attribute.
*/
@Nullable
protected Object getValue() {
return this.value;
}
@ -67,6 +72,7 @@ public abstract class AbstractSingleCheckedElementTag extends AbstractCheckedEle @@ -67,6 +72,7 @@ public abstract class AbstractSingleCheckedElementTag extends AbstractCheckedEle
/**
* Get the value of the '{@code label}' attribute.
*/
@Nullable
protected Object getLabel() {
return this.label;
}
@ -89,6 +95,7 @@ public abstract class AbstractSingleCheckedElementTag extends AbstractCheckedEle @@ -89,6 +95,7 @@ public abstract class AbstractSingleCheckedElementTag extends AbstractCheckedEle
Object resolvedLabel = evaluate("label", getLabel());
if (resolvedLabel != null) {
Assert.state(id != null, "Label id is required");
tagWriter.startTag("label");
tagWriter.writeAttribute("for", id);
tagWriter.appendValue(convertToDisplayString(resolvedLabel));

16
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/ButtonTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* 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.
@ -18,6 +18,8 @@ package org.springframework.web.servlet.tags.form; @@ -18,6 +18,8 @@ package org.springframework.web.servlet.tags.form;
import javax.servlet.jsp.JspException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.servlet.support.RequestDataValueProcessor;
/**
@ -77,10 +79,13 @@ public class ButtonTag extends AbstractHtmlElementTag { @@ -77,10 +79,13 @@ public class ButtonTag extends AbstractHtmlElementTag {
public static final String DISABLED_ATTRIBUTE = "disabled";
@Nullable
private TagWriter tagWriter;
@Nullable
private String name;
@Nullable
private String value;
private boolean disabled;
@ -97,6 +102,7 @@ public class ButtonTag extends AbstractHtmlElementTag { @@ -97,6 +102,7 @@ public class ButtonTag extends AbstractHtmlElementTag {
* Set the value of the '{@code name}' attribute.
*/
@Override
@Nullable
public String getName() {
return this.name;
}
@ -104,13 +110,14 @@ public class ButtonTag extends AbstractHtmlElementTag { @@ -104,13 +110,14 @@ public class ButtonTag extends AbstractHtmlElementTag {
/**
* Set the value of the '{@code value}' attribute.
*/
public void setValue(String value) {
public void setValue(@Nullable String value) {
this.value = value;
}
/**
* Get the value of the '{@code value}' attribute.
*/
@Nullable
public String getValue() {
return this.value;
}
@ -150,13 +157,13 @@ public class ButtonTag extends AbstractHtmlElementTag { @@ -150,13 +157,13 @@ public class ButtonTag extends AbstractHtmlElementTag {
* when the value is written.
*/
protected void writeValue(TagWriter tagWriter) throws JspException {
String valueToUse = (getValue() != null) ? getValue() : getDefaultValue();
String valueToUse = (getValue() != null ? getValue() : getDefaultValue());
tagWriter.writeAttribute("value", processFieldValue(getName(), valueToUse, getType()));
}
/**
* Return the default value.
* @return The default value if none supplied.
* @return the default value if none supplied
*/
protected String getDefaultValue() {
return "Submit";
@ -176,6 +183,7 @@ public class ButtonTag extends AbstractHtmlElementTag { @@ -176,6 +183,7 @@ public class ButtonTag extends AbstractHtmlElementTag {
*/
@Override
public int doEndTag() throws JspException {
Assert.state(this.tagWriter != null, "No TagWriter set");
this.tagWriter.endTag();
return EVAL_PAGE;
}

6
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/ErrorsTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@ -19,11 +19,11 @@ package org.springframework.web.servlet.tags.form; @@ -19,11 +19,11 @@ package org.springframework.web.servlet.tags.form;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.BodyTag;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@ -210,6 +210,7 @@ public class ErrorsTag extends AbstractHtmlElementBodyTag implements BodyTag { @@ -210,6 +210,7 @@ public class ErrorsTag extends AbstractHtmlElementBodyTag implements BodyTag {
/**
* Stores any value that existed in the 'errors messages' before the tag was started.
*/
@Nullable
private Object oldMessages;
private boolean errorMessagesWereExposed;
@ -271,6 +272,7 @@ public class ErrorsTag extends AbstractHtmlElementBodyTag implements BodyTag { @@ -271,6 +272,7 @@ public class ErrorsTag extends AbstractHtmlElementBodyTag implements BodyTag {
* is not a validate attribute for the '{@code span}' element.
*/
@Override
@Nullable
protected String getName() throws JspException {
return null;
}

34
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/FormTag.java

@ -28,6 +28,8 @@ import javax.servlet.jsp.PageContext; @@ -28,6 +28,8 @@ 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;
@ -288,33 +290,44 @@ public class FormTag extends AbstractHtmlElementTag { @@ -288,33 +290,44 @@ public class FormTag extends AbstractHtmlElementTag {
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;
@ -347,6 +360,7 @@ public class FormTag extends AbstractHtmlElementTag { @@ -347,6 +360,7 @@ public class FormTag extends AbstractHtmlElementTag {
* Get the value of the '{@code name}' attribute.
*/
@Override
@Nullable
protected String getName() throws JspException {
return this.name;
}
@ -355,13 +369,14 @@ public class FormTag extends AbstractHtmlElementTag { @@ -355,13 +369,14 @@ public class FormTag extends AbstractHtmlElementTag {
* Set the value of the '{@code action}' attribute.
* <p>May be a runtime expression.
*/
public void setAction(String action) {
public void setAction(@Nullable String action) {
this.action = (action != null ? action : "");
}
/**
* Get the value of the '{@code action}' attribute.
*/
@Nullable
protected String getAction() {
return this.action;
}
@ -372,14 +387,15 @@ public class FormTag extends AbstractHtmlElementTag { @@ -372,14 +387,15 @@ public class FormTag extends AbstractHtmlElementTag {
* <p>May be a runtime expression.
* @since 3.2.3
*/
public void setServletRelativeAction(String servletRelativeAction) {
this.servletRelativeAction = (servletRelativeAction != null ? servletRelativeAction : "");
public void setServletRelativeAction(@Nullable String servletRelativeAction) {
this.servletRelativeAction = servletRelativeAction;
}
/**
* Get the servlet-relative value of the '{@code action}' attribute.
* @since 3.2.3
*/
@Nullable
protected String getServletRelativeAction() {
return this.servletRelativeAction;
}
@ -410,6 +426,7 @@ public class FormTag extends AbstractHtmlElementTag { @@ -410,6 +426,7 @@ public class FormTag extends AbstractHtmlElementTag {
/**
* Get the value of the '{@code target}' attribute.
*/
@Nullable
public String getTarget() {
return this.target;
}
@ -425,6 +442,7 @@ public class FormTag extends AbstractHtmlElementTag { @@ -425,6 +442,7 @@ public class FormTag extends AbstractHtmlElementTag {
/**
* Get the value of the '{@code enctype}' attribute.
*/
@Nullable
protected String getEnctype() {
return this.enctype;
}
@ -440,6 +458,7 @@ public class FormTag extends AbstractHtmlElementTag { @@ -440,6 +458,7 @@ public class FormTag extends AbstractHtmlElementTag {
/**
* Get the value of the '{@code acceptCharset}' attribute.
*/
@Nullable
protected String getAcceptCharset() {
return this.acceptCharset;
}
@ -455,6 +474,7 @@ public class FormTag extends AbstractHtmlElementTag { @@ -455,6 +474,7 @@ public class FormTag extends AbstractHtmlElementTag {
/**
* Get the value of the '{@code onsubmit}' attribute.
*/
@Nullable
protected String getOnsubmit() {
return this.onsubmit;
}
@ -470,6 +490,7 @@ public class FormTag extends AbstractHtmlElementTag { @@ -470,6 +490,7 @@ public class FormTag extends AbstractHtmlElementTag {
/**
* Get the value of the '{@code onreset}' attribute.
*/
@Nullable
protected String getOnreset() {
return this.onreset;
}
@ -485,6 +506,7 @@ public class FormTag extends AbstractHtmlElementTag { @@ -485,6 +506,7 @@ public class FormTag extends AbstractHtmlElementTag {
/**
* Get the value of the '{@code autocomplete}' attribute.
*/
@Nullable
protected String getAutocomplete() {
return this.autocomplete;
}
@ -670,6 +692,7 @@ public class FormTag extends AbstractHtmlElementTag { @@ -670,6 +692,7 @@ public class FormTag extends AbstractHtmlElementTag {
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;
}
@ -677,8 +700,9 @@ public class FormTag extends AbstractHtmlElementTag { @@ -677,8 +700,9 @@ public class FormTag extends AbstractHtmlElementTag {
/**
* Writes the given values as hidden fields.
*/
private void writeHiddenFields(Map<String, String> hiddenFields) throws JspException {
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 (String name : hiddenFields.keySet()) {
this.tagWriter.appendValue("<input type=\"hidden\" ");

31
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/InputTag.java

@ -16,8 +16,11 @@ @@ -16,8 +16,11 @@
package org.springframework.web.servlet.tags.form;
import java.util.Map;
import javax.servlet.jsp.JspException;
import org.springframework.lang.Nullable;
/**
* The {@code <input>} tag renders an HTML 'input' tag with type 'text' using
* the bound value.
@ -241,19 +244,22 @@ public class InputTag extends AbstractHtmlInputElementTag { @@ -241,19 +244,22 @@ public class InputTag extends AbstractHtmlInputElementTag {
public static final String ONSELECT_ATTRIBUTE = "onselect";
public static final String READONLY_ATTRIBUTE = "readonly";
public static final String AUTOCOMPLETE_ATTRIBUTE = "autocomplete";
@Nullable
private String size;
@Nullable
private String maxlength;
@Nullable
private String alt;
@Nullable
private String onselect;
@Nullable
private String autocomplete;
@ -268,6 +274,7 @@ public class InputTag extends AbstractHtmlInputElementTag { @@ -268,6 +274,7 @@ public class InputTag extends AbstractHtmlInputElementTag {
/**
* Get the value of the '{@code size}' attribute.
*/
@Nullable
protected String getSize() {
return this.size;
}
@ -283,6 +290,7 @@ public class InputTag extends AbstractHtmlInputElementTag { @@ -283,6 +290,7 @@ public class InputTag extends AbstractHtmlInputElementTag {
/**
* Get the value of the '{@code maxlength}' attribute.
*/
@Nullable
protected String getMaxlength() {
return this.maxlength;
}
@ -298,6 +306,7 @@ public class InputTag extends AbstractHtmlInputElementTag { @@ -298,6 +306,7 @@ public class InputTag extends AbstractHtmlInputElementTag {
/**
* Get the value of the '{@code alt}' attribute.
*/
@Nullable
protected String getAlt() {
return this.alt;
}
@ -313,6 +322,7 @@ public class InputTag extends AbstractHtmlInputElementTag { @@ -313,6 +322,7 @@ public class InputTag extends AbstractHtmlInputElementTag {
/**
* Get the value of the '{@code onselect}' attribute.
*/
@Nullable
protected String getOnselect() {
return this.onselect;
}
@ -328,6 +338,7 @@ public class InputTag extends AbstractHtmlInputElementTag { @@ -328,6 +338,7 @@ public class InputTag extends AbstractHtmlInputElementTag {
/**
* Get the value of the '{@code autocomplete}' attribute.
*/
@Nullable
protected String getAutocomplete() {
return this.autocomplete;
}
@ -343,7 +354,8 @@ public class InputTag extends AbstractHtmlInputElementTag { @@ -343,7 +354,8 @@ public class InputTag extends AbstractHtmlInputElementTag {
tagWriter.startTag("input");
writeDefaultAttributes(tagWriter);
if (!hasDynamicTypeAttribute()) {
Map<String, Object> attributes = getDynamicAttributes();
if (attributes == null || !attributes.containsKey("type")) {
tagWriter.writeAttribute("type", getType());
}
writeValue(tagWriter);
@ -359,10 +371,6 @@ public class InputTag extends AbstractHtmlInputElementTag { @@ -359,10 +371,6 @@ public class InputTag extends AbstractHtmlInputElementTag {
return SKIP_BODY;
}
private boolean hasDynamicTypeAttribute() {
return getDynamicAttributes() != null && getDynamicAttributes().containsKey("type");
}
/**
* Writes the '{@code value}' attribute to the supplied {@link TagWriter}.
* Subclasses may choose to override this implementation to control exactly
@ -370,7 +378,14 @@ public class InputTag extends AbstractHtmlInputElementTag { @@ -370,7 +378,14 @@ public class InputTag extends AbstractHtmlInputElementTag {
*/
protected void writeValue(TagWriter tagWriter) throws JspException {
String value = getDisplayString(getBoundValue(), getPropertyEditor());
String type = hasDynamicTypeAttribute() ? (String) getDynamicAttributes().get("type") : getType();
String type = null;
Map<String, Object> attributes = getDynamicAttributes();
if (attributes != null) {
type = (String) getDynamicAttributes().get("type");
}
if (type == null) {
type = getType();
}
tagWriter.writeAttribute("value", processFieldValue(getName(), value, type));
}

10
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/LabelTag.java

@ -18,6 +18,7 @@ package org.springframework.web.servlet.tags.form; @@ -18,6 +18,7 @@ package org.springframework.web.servlet.tags.form;
import javax.servlet.jsp.JspException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@ -190,21 +191,21 @@ public class LabelTag extends AbstractHtmlElementTag { @@ -190,21 +191,21 @@ public class LabelTag extends AbstractHtmlElementTag {
* The {@link TagWriter} instance being used.
* <p>Stored so we can close the tag on {@link #doEndTag()}.
*/
@Nullable
private TagWriter tagWriter;
/**
* The value of the '{@code for}' attribute.
*/
@Nullable
private String forId;
/**
* Set the value of the '{@code for}' attribute.
* <p>Defaults to the value of {@link #getPath}; may be a runtime expression.
* @throws IllegalArgumentException if the supplied value is {@code null}
*/
public void setFor(String forId) {
Assert.notNull(forId, "'forId' must not be null");
this.forId = forId;
}
@ -212,7 +213,8 @@ public class LabelTag extends AbstractHtmlElementTag { @@ -212,7 +213,8 @@ public class LabelTag extends AbstractHtmlElementTag {
* Get the value of the '{@code id}' attribute.
* <p>May be a runtime expression.
*/
public String getFor() {
@Nullable
protected String getFor() {
return this.forId;
}
@ -239,6 +241,7 @@ public class LabelTag extends AbstractHtmlElementTag { @@ -239,6 +241,7 @@ public class LabelTag extends AbstractHtmlElementTag {
* @return the value for the HTML '{@code name}' attribute
*/
@Override
@Nullable
protected String getName() throws JspException {
// This also suppresses the 'id' attribute (which is okay for a <label/>)
return null;
@ -273,6 +276,7 @@ public class LabelTag extends AbstractHtmlElementTag { @@ -273,6 +276,7 @@ public class LabelTag extends AbstractHtmlElementTag {
*/
@Override
public int doEndTag() throws JspException {
Assert.state(this.tagWriter != null, "No TagWriter set");
this.tagWriter.endTag();
return EVAL_PAGE;
}

16
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/OptionTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* 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.
@ -20,7 +20,7 @@ import javax.servlet.jsp.JspException; @@ -20,7 +20,7 @@ import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTag;
import org.springframework.util.Assert;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.support.BindStatus;
import org.springframework.web.util.TagUtils;
@ -228,15 +228,19 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag { @@ -228,15 +228,19 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag {
/**
* The 'value' attribute of the rendered HTML {@code <option>} tag.
*/
@Nullable
private Object value;
/**
* The text body of the rendered HTML {@code <option>} tag.
*/
@Nullable
private String label;
@Nullable
private Object oldValue;
@Nullable
private Object oldDisplayValue;
private boolean disabled;
@ -252,6 +256,7 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag { @@ -252,6 +256,7 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag {
/**
* Get the 'value' attribute of the rendered HTML {@code <option>} tag.
*/
@Nullable
protected Object getValue() {
return this.value;
}
@ -275,13 +280,13 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag { @@ -275,13 +280,13 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag {
* <p>May be a runtime expression.
*/
public void setLabel(String label) {
Assert.notNull(label, "'label' must not be null");
this.label = label;
}
/**
* Get the text body of the rendered HTML {@code <option>} tag.
*/
@Nullable
protected String getLabel() {
return this.label;
}
@ -365,8 +370,8 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag { @@ -365,8 +370,8 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag {
}
/**
* Returns the value of the label for this '{@code option}' element.
* If the {@link #setLabel label} property is set then the resolved value
* Return the value of the label for this '{@code option}' element.
* <p>If the {@link #setLabel label} property is set then the resolved value
* of that property is used, otherwise the value of the {@code resolvedValue}
* argument is used.
*/
@ -388,6 +393,7 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag { @@ -388,6 +393,7 @@ public class OptionTag extends AbstractHtmlElementBodyTag implements BodyTag {
return SelectedValueComparator.isSelected(getBindStatus(), resolvedValue);
}
@Nullable
private Object resolveValue() throws JspException {
return evaluate(VALUE_VARIABLE_NAME, getValue());
}

37
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/OptionWriter.java

@ -23,6 +23,7 @@ import javax.servlet.jsp.JspException; @@ -23,6 +23,7 @@ import javax.servlet.jsp.JspException;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.support.BindStatus;
@ -92,15 +93,17 @@ class OptionWriter { @@ -92,15 +93,17 @@ class OptionWriter {
private final BindStatus bindStatus;
@Nullable
private final String valueProperty;
@Nullable
private final String labelProperty;
private final boolean htmlEscape;
/**
* Creates a new {@code OptionWriter} for the supplied {@code objectSource}.
* Create a new {@code OptionWriter} for the supplied {@code objectSource}.
* @param optionSource the source of the {@code options} (never {@code null})
* @param bindStatus the {@link BindStatus} for the bound value (never {@code null})
* @param valueProperty the name of the property used to render {@code option} values
@ -108,8 +111,8 @@ class OptionWriter { @@ -108,8 +111,8 @@ class OptionWriter {
* @param labelProperty the name of the property used to render {@code option} labels
* (optional)
*/
public OptionWriter(
Object optionSource, BindStatus bindStatus, String valueProperty, String labelProperty, boolean htmlEscape) {
public OptionWriter(Object optionSource, BindStatus bindStatus,
@Nullable String valueProperty, @Nullable String labelProperty, boolean htmlEscape) {
Assert.notNull(optionSource, "'optionSource' must not be null");
Assert.notNull(bindStatus, "'bindStatus' must not be null");
@ -145,7 +148,7 @@ class OptionWriter { @@ -145,7 +148,7 @@ class OptionWriter {
}
/**
* Renders the inner '{@code option}' tags using the {@link #optionSource}.
* Render the inner '{@code option}' tags using the {@link #optionSource}.
* @see #doRenderFromCollection(java.util.Collection, TagWriter)
*/
private void renderFromArray(TagWriter tagWriter) throws JspException {
@ -153,7 +156,7 @@ class OptionWriter { @@ -153,7 +156,7 @@ class OptionWriter {
}
/**
* Renders the inner '{@code option}' tags using the supplied
* Render the inner '{@code option}' tags using the supplied
* {@link Map} as the source.
* @see #renderOption(TagWriter, Object, Object, Object)
*/
@ -173,7 +176,7 @@ class OptionWriter { @@ -173,7 +176,7 @@ class OptionWriter {
}
/**
* Renders the inner '{@code option}' tags using the {@link #optionSource}.
* Render the inner '{@code option}' tags using the {@link #optionSource}.
* @see #doRenderFromCollection(java.util.Collection, TagWriter)
*/
private void renderFromCollection(TagWriter tagWriter) throws JspException {
@ -181,7 +184,7 @@ class OptionWriter { @@ -181,7 +184,7 @@ class OptionWriter {
}
/**
* Renders the inner '{@code option}' tags using the {@link #optionSource}.
* Render the inner '{@code option}' tags using the {@link #optionSource}.
* @see #doRenderFromCollection(java.util.Collection, TagWriter)
*/
private void renderFromEnum(TagWriter tagWriter) throws JspException {
@ -189,7 +192,7 @@ class OptionWriter { @@ -189,7 +192,7 @@ class OptionWriter {
}
/**
* Renders the inner '{@code option}' tags using the supplied {@link Collection} of
* Render the inner '{@code option}' tags using the supplied {@link Collection} of
* objects as the source. The value of the {@link #valueProperty} field is used
* when rendering the '{@code value}' of the '{@code option}' and the value of the
* {@link #labelProperty} property is used when rendering the label.
@ -213,10 +216,12 @@ class OptionWriter { @@ -213,10 +216,12 @@ class OptionWriter {
}
/**
* Renders an HTML '{@code option}' with the supplied value and label. Marks the
* Render an HTML '{@code option}' with the supplied value and label. Marks the
* value as 'selected' if either the item itself or its value match the bound value.
*/
private void renderOption(TagWriter tagWriter, Object item, Object value, Object label) throws JspException {
private void renderOption(TagWriter tagWriter, Object item, @Nullable Object value, @Nullable Object label)
throws JspException {
tagWriter.startTag("option");
writeCommonAttributes(tagWriter);
@ -239,17 +244,17 @@ class OptionWriter { @@ -239,17 +244,17 @@ class OptionWriter {
}
/**
* Determines the display value of the supplied {@code Object},
* Determine the display value of the supplied {@code Object},
* HTML-escaped as required.
*/
private String getDisplayString(Object value) {
private String getDisplayString(@Nullable Object value) {
PropertyEditor editor = (value != null ? this.bindStatus.findEditor(value.getClass()) : null);
return ValueFormatter.getDisplayString(value, editor, this.htmlEscape);
}
/**
* Process the option value before it is written.
* The default implementation simply returns the same value unchanged.
* <p>The default implementation simply returns the same value unchanged.
*/
protected String processOptionValue(String resolvedValue) {
return resolvedValue;
@ -257,9 +262,9 @@ class OptionWriter { @@ -257,9 +262,9 @@ class OptionWriter {
/**
* Determine whether the supplied values matched the selected value.
* Delegates to {@link SelectedValueComparator#isSelected}.
* <p>Delegates to {@link SelectedValueComparator#isSelected}.
*/
private boolean isOptionSelected(Object resolvedValue) {
private boolean isOptionSelected(@Nullable Object resolvedValue) {
return SelectedValueComparator.isSelected(this.bindStatus, resolvedValue);
}
@ -271,7 +276,7 @@ class OptionWriter { @@ -271,7 +276,7 @@ class OptionWriter {
}
/**
* Writes default attributes configured to the supplied {@link TagWriter}.
* Write default attributes configured to the supplied {@link TagWriter}.
*/
protected void writeCommonAttributes(TagWriter tagWriter) throws JspException {
}

15
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/OptionsTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* 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.
@ -18,6 +18,7 @@ package org.springframework.web.servlet.tags.form; @@ -18,6 +18,7 @@ package org.springframework.web.servlet.tags.form;
import javax.servlet.jsp.JspException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
@ -196,18 +197,21 @@ public class OptionsTag extends AbstractHtmlElementTag { @@ -196,18 +197,21 @@ public class OptionsTag extends AbstractHtmlElementTag {
* The {@link java.util.Collection}, {@link java.util.Map} or array of
* objects used to generate the inner '{@code option}' tags.
*/
@Nullable
private Object items;
/**
* The name of the property mapped to the '{@code value}' attribute
* of the '{@code option}' tag.
*/
@Nullable
private String itemValue;
/**
* The name of the property mapped to the inner text of the
* '{@code option}' tag.
*/
@Nullable
private String itemLabel;
private boolean disabled;
@ -229,6 +233,7 @@ public class OptionsTag extends AbstractHtmlElementTag { @@ -229,6 +233,7 @@ public class OptionsTag extends AbstractHtmlElementTag {
* of objects used to generate the inner '{@code option}' tags.
* <p>Typically a runtime expression.
*/
@Nullable
protected Object getItems() {
return this.items;
}
@ -248,6 +253,7 @@ public class OptionsTag extends AbstractHtmlElementTag { @@ -248,6 +253,7 @@ public class OptionsTag extends AbstractHtmlElementTag {
* Return the name of the property mapped to the '{@code value}'
* attribute of the '{@code option}' tag.
*/
@Nullable
protected String getItemValue() {
return this.itemValue;
}
@ -265,6 +271,7 @@ public class OptionsTag extends AbstractHtmlElementTag { @@ -265,6 +271,7 @@ public class OptionsTag extends AbstractHtmlElementTag {
* Get the name of the property mapped to the label (inner text) of the
* '{@code option}' tag.
*/
@Nullable
protected String getItemLabel() {
return this.itemLabel;
}
@ -342,9 +349,12 @@ public class OptionsTag extends AbstractHtmlElementTag { @@ -342,9 +349,12 @@ public class OptionsTag extends AbstractHtmlElementTag {
*/
private class OptionsWriter extends OptionWriter {
@Nullable
private final String selectName;
public OptionsWriter(String selectName, Object optionSource, String valueProperty, String labelProperty) {
public OptionsWriter(@Nullable String selectName, Object optionSource,
@Nullable String valueProperty, @Nullable String labelProperty) {
super(optionSource, getBindStatus(), valueProperty, labelProperty, isHtmlEscape());
this.selectName = selectName;
}
@ -364,7 +374,6 @@ public class OptionsTag extends AbstractHtmlElementTag { @@ -364,7 +374,6 @@ public class OptionsTag extends AbstractHtmlElementTag {
protected String processOptionValue(String value) {
return processFieldValue(this.selectName, value, "option");
}
}
}

2
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/RadioButtonTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* 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.

22
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/SelectTag.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* 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.
@ -20,6 +20,7 @@ import java.util.Collection; @@ -20,6 +20,7 @@ import java.util.Collection;
import java.util.Map;
import javax.servlet.jsp.JspException;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.servlet.support.BindStatus;
@ -255,39 +256,45 @@ public class SelectTag extends AbstractHtmlInputElementTag { @@ -255,39 +256,45 @@ public class SelectTag extends AbstractHtmlInputElementTag {
/**
* The {@link Collection}, {@link Map} or array of objects used to generate the inner
* '{@code option}' tags.
* The {@link Collection}, {@link Map} or array of objects used to generate
* the inner '{@code option}' tags.
*/
@Nullable
private Object items;
/**
* The name of the property mapped to the '{@code value}' attribute
* of the '{@code option}' tag.
*/
@Nullable
private String itemValue;
/**
* The name of the property mapped to the inner text of the
* '{@code option}' tag.
*/
@Nullable
private String itemLabel;
/**
* The value of the HTML '{@code size}' attribute rendered
* on the final '{@code select}' element.
*/
@Nullable
private String size;
/**
* Indicates whether or not the '{@code select}' tag allows
* multiple-selections.
*/
@Nullable
private Object multiple;
/**
* The {@link TagWriter} instance that the output is being written.
* <p>Only used in conjunction with nested {@link OptionTag OptionTags}.
*/
@Nullable
private TagWriter tagWriter;
@ -299,7 +306,7 @@ public class SelectTag extends AbstractHtmlInputElementTag { @@ -299,7 +306,7 @@ public class SelectTag extends AbstractHtmlInputElementTag {
* <p>Typically a runtime expression.
* @param items the items that comprise the options of this selection
*/
public void setItems(Object items) {
public void setItems(@Nullable Object items) {
this.items = (items != null ? items : EMPTY);
}
@ -307,6 +314,7 @@ public class SelectTag extends AbstractHtmlInputElementTag { @@ -307,6 +314,7 @@ public class SelectTag extends AbstractHtmlInputElementTag {
* Get the value of the '{@code items}' attribute.
* <p>May be a runtime expression.
*/
@Nullable
protected Object getItems() {
return this.items;
}
@ -326,6 +334,7 @@ public class SelectTag extends AbstractHtmlInputElementTag { @@ -326,6 +334,7 @@ public class SelectTag extends AbstractHtmlInputElementTag {
* Get the value of the '{@code itemValue}' attribute.
* <p>May be a runtime expression.
*/
@Nullable
protected String getItemValue() {
return this.itemValue;
}
@ -343,6 +352,7 @@ public class SelectTag extends AbstractHtmlInputElementTag { @@ -343,6 +352,7 @@ public class SelectTag extends AbstractHtmlInputElementTag {
* Get the value of the '{@code itemLabel}' attribute.
* <p>May be a runtime expression.
*/
@Nullable
protected String getItemLabel() {
return this.itemLabel;
}
@ -358,6 +368,7 @@ public class SelectTag extends AbstractHtmlInputElementTag { @@ -358,6 +368,7 @@ public class SelectTag extends AbstractHtmlInputElementTag {
/**
* Get the value of the '{@code size}' attribute.
*/
@Nullable
protected String getSize() {
return this.size;
}
@ -374,6 +385,7 @@ public class SelectTag extends AbstractHtmlInputElementTag { @@ -374,6 +385,7 @@ public class SelectTag extends AbstractHtmlInputElementTag {
* Get the value of the HTML '{@code multiple}' attribute rendered
* on the final '{@code select}' element.
*/
@Nullable
protected Object getMultiple() {
return this.multiple;
}
@ -489,7 +501,7 @@ public class SelectTag extends AbstractHtmlInputElementTag { @@ -489,7 +501,7 @@ public class SelectTag extends AbstractHtmlInputElementTag {
public int doEndTag() throws JspException {
if (this.tagWriter != null) {
this.tagWriter.endTag();
writeHiddenTagIfNecessary(tagWriter);
writeHiddenTagIfNecessary(this.tagWriter);
}
return EVAL_PAGE;
}

37
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/SelectedValueComparator.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* 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.
@ -21,6 +21,7 @@ import java.util.Collection; @@ -21,6 +21,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.servlet.support.BindStatus;
@ -59,11 +60,7 @@ abstract class SelectedValueComparator { @@ -59,11 +60,7 @@ abstract class SelectedValueComparator {
* the supplied {@link BindStatus}. Equality in this case differs from standard Java equality and
* is described in more detail <a href="#equality-contract">here</a>.
*/
public static boolean isSelected(BindStatus bindStatus, Object candidateValue) {
if (bindStatus == null) {
return (candidateValue == null);
}
public static boolean isSelected(BindStatus bindStatus, @Nullable Object candidateValue) {
// Check obvious equality matches with the candidate first,
// both with the rendered value and with the original value.
Object boundValue = bindStatus.getValue();
@ -85,14 +82,16 @@ abstract class SelectedValueComparator { @@ -85,14 +82,16 @@ abstract class SelectedValueComparator {
// Non-null value but no obvious equality with the candidate value:
// go into more exhaustive comparisons.
boolean selected = false;
if (boundValue.getClass().isArray()) {
selected = collectionCompare(CollectionUtils.arrayToList(boundValue), candidateValue, bindStatus);
}
else if (boundValue instanceof Collection) {
selected = collectionCompare((Collection<?>) boundValue, candidateValue, bindStatus);
}
else if (boundValue instanceof Map) {
selected = mapCompare((Map<?, ?>) boundValue, candidateValue, bindStatus);
if (candidateValue != null) {
if (boundValue.getClass().isArray()) {
selected = collectionCompare(CollectionUtils.arrayToList(boundValue), candidateValue, bindStatus);
}
else if (boundValue instanceof Collection) {
selected = collectionCompare((Collection<?>) boundValue, candidateValue, bindStatus);
}
else if (boundValue instanceof Map) {
selected = mapCompare((Map<?, ?>) boundValue, candidateValue, bindStatus);
}
}
if (!selected) {
selected = exhaustiveCompare(boundValue, candidateValue, bindStatus.getEditor(), null);
@ -100,8 +99,8 @@ abstract class SelectedValueComparator { @@ -100,8 +99,8 @@ abstract class SelectedValueComparator {
return selected;
}
private static boolean collectionCompare(Collection<?> boundCollection, Object candidateValue,
BindStatus bindStatus) {
private static boolean collectionCompare(
Collection<?> boundCollection, Object candidateValue, BindStatus bindStatus) {
try {
if (boundCollection.contains(candidateValue)) {
return true;
@ -128,7 +127,7 @@ abstract class SelectedValueComparator { @@ -128,7 +127,7 @@ abstract class SelectedValueComparator {
private static boolean exhaustiveCollectionCompare(
Collection<?> collection, Object candidateValue, BindStatus bindStatus) {
Map<PropertyEditor, Object> convertedValueCache = new HashMap<>(1);
Map<PropertyEditor, Object> convertedValueCache = new HashMap<>();
PropertyEditor editor = null;
boolean candidateIsString = (candidateValue instanceof String);
if (!candidateIsString) {
@ -145,8 +144,8 @@ abstract class SelectedValueComparator { @@ -145,8 +144,8 @@ abstract class SelectedValueComparator {
return false;
}
private static boolean exhaustiveCompare(Object boundValue, Object candidate,
PropertyEditor editor, Map<PropertyEditor, Object> convertedValueCache) {
private static boolean exhaustiveCompare(@Nullable Object boundValue, @Nullable Object candidate,
@Nullable PropertyEditor editor, @Nullable Map<PropertyEditor, Object> convertedValueCache) {
String candidateDisplayString = ValueFormatter.getDisplayString(candidate, editor, false);
if (boundValue != null && boundValue.getClass().isEnum()) {

9
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/TagWriter.java

@ -20,7 +20,6 @@ import java.io.IOException; @@ -20,7 +20,6 @@ import java.io.IOException;
import java.io.Writer;
import java.util.ArrayDeque;
import java.util.Deque;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
@ -196,7 +195,7 @@ public class TagWriter { @@ -196,7 +195,7 @@ public class TagWriter {
}
private TagStateEntry currentState() {
return this.tagState.peek();
return this.tagState.element();
}
@ -233,8 +232,10 @@ public class TagWriter { @@ -233,8 +232,10 @@ public class TagWriter {
*/
private static final class SafeWriter {
@Nullable
private PageContext pageContext;
@Nullable
private Writer writer;
public SafeWriter(PageContext pageContext) {
@ -256,7 +257,9 @@ public class TagWriter { @@ -256,7 +257,9 @@ public class TagWriter {
}
private Writer getWriterToUse() {
return (this.pageContext != null ? this.pageContext.getOut() : this.writer);
Writer writer = (this.pageContext != null ? this.pageContext.getOut() : this.writer);
Assert.state(writer != null, "No Writer available");
return writer;
}
}

10
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/TextareaTag.java

@ -18,6 +18,8 @@ package org.springframework.web.servlet.tags.form; @@ -18,6 +18,8 @@ package org.springframework.web.servlet.tags.form;
import javax.servlet.jsp.JspException;
import org.springframework.lang.Nullable;
/**
* The {@code <textarea>} tag renders an HTML 'textarea'.
*
@ -225,13 +227,14 @@ public class TextareaTag extends AbstractHtmlInputElementTag { @@ -225,13 +227,14 @@ public class TextareaTag extends AbstractHtmlInputElementTag {
public static final String ONSELECT_ATTRIBUTE = "onselect";
public static final String READONLY_ATTRIBUTE = "readonly";
@Nullable
private String rows;
@Nullable
private String cols;
@Nullable
private String onselect;
@ -246,6 +249,7 @@ public class TextareaTag extends AbstractHtmlInputElementTag { @@ -246,6 +249,7 @@ public class TextareaTag extends AbstractHtmlInputElementTag {
/**
* Get the value of the '{@code rows}' attribute.
*/
@Nullable
protected String getRows() {
return this.rows;
}
@ -261,6 +265,7 @@ public class TextareaTag extends AbstractHtmlInputElementTag { @@ -261,6 +265,7 @@ public class TextareaTag extends AbstractHtmlInputElementTag {
/**
* Get the value of the '{@code cols}' attribute.
*/
@Nullable
protected String getCols() {
return this.cols;
}
@ -276,6 +281,7 @@ public class TextareaTag extends AbstractHtmlInputElementTag { @@ -276,6 +281,7 @@ public class TextareaTag extends AbstractHtmlInputElementTag {
/**
* Get the value of the '{@code onselect}' attribute.
*/
@Nullable
protected String getOnselect() {
return this.onselect;
}

9
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/ValueFormatter.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* 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.
@ -18,6 +18,7 @@ package org.springframework.web.servlet.tags.form; @@ -18,6 +18,7 @@ package org.springframework.web.servlet.tags.form;
import java.beans.PropertyEditor;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.web.util.HtmlUtils;
@ -43,7 +44,7 @@ abstract class ValueFormatter { @@ -43,7 +44,7 @@ abstract class ValueFormatter {
* as required. This version is <strong>not</strong> {@link PropertyEditor}-aware.
* @see #getDisplayString(Object, java.beans.PropertyEditor, boolean)
*/
public static String getDisplayString(Object value, boolean htmlEscape) {
public static String getDisplayString(@Nullable Object value, boolean htmlEscape) {
String displayValue = ObjectUtils.getDisplayString(value);
return (htmlEscape ? HtmlUtils.htmlEscape(displayValue) : displayValue);
}
@ -55,7 +56,9 @@ abstract class ValueFormatter { @@ -55,7 +56,9 @@ abstract class ValueFormatter {
* to obtain the display value.
* @see #getDisplayString(Object, boolean)
*/
public static String getDisplayString(Object value, PropertyEditor propertyEditor, boolean htmlEscape) {
public static String getDisplayString(
@Nullable Object value, @Nullable PropertyEditor propertyEditor, boolean htmlEscape) {
if (propertyEditor != null && !(value instanceof String)) {
try {
propertyEditor.setValue(value);

8
spring-webmvc/src/main/java/org/springframework/web/servlet/tags/form/package-info.java

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
/**
* Spring's form tag library for JSP 2.0+.
* Supports JSP view implementations for Spring's web MVC framework.
* Spring's form tag library for JSP views in Spring's Web MVC framework.
* For more details on each tag, see the list of tags below with links to
* individual tag classes, or check the {@code spring-form.tld} file:
*
@ -22,4 +21,9 @@ @@ -22,4 +21,9 @@
* <li>{@link org.springframework.web.servlet.tags.form.TextareaTag The textarea tag}
* </ul>
*/
@NonNullApi
@NonNullFields
package org.springframework.web.servlet.tags.form;
import org.springframework.lang.NonNullApi;
import org.springframework.lang.NonNullFields;

Loading…
Cancel
Save