001/* 002 * Copyright 2002-2013 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.servlet.tags.form; 018 019import java.beans.PropertyEditor; 020import javax.servlet.jsp.JspException; 021 022import org.springframework.util.ObjectUtils; 023import org.springframework.web.servlet.tags.HtmlEscapingAwareTag; 024 025/** 026 * Base class for all JSP form tags. Provides utility methods for 027 * null-safe EL evaluation and for accessing and working with a {@link TagWriter}. 028 * 029 * <p>Subclasses should implement the {@link #writeTagContent(TagWriter)} to perform 030 * actual tag rendering. 031 * 032 * <p>Subclasses (or test classes) can override the {@link #createTagWriter()} method to 033 * redirect output to a {@link java.io.Writer} other than the {@link javax.servlet.jsp.JspWriter} 034 * associated with the current {@link javax.servlet.jsp.PageContext}. 035 * 036 * @author Rob Harrop 037 * @author Juergen Hoeller 038 * @since 2.0 039 */ 040@SuppressWarnings("serial") 041public abstract class AbstractFormTag extends HtmlEscapingAwareTag { 042 043 /** 044 * Evaluate the supplied value for the supplied attribute name. 045 * <p>The default implementation simply returns the given value as-is. 046 */ 047 protected Object evaluate(String attributeName, Object value) throws JspException { 048 return value; 049 } 050 051 /** 052 * Optionally writes the supplied value under the supplied attribute name into the supplied 053 * {@link TagWriter}. In this case, the supplied value is {@link #evaluate evaluated} first 054 * and then the {@link ObjectUtils#getDisplayString String representation} is written as the 055 * attribute value. If the resultant {@code String} representation is {@code null} 056 * or empty, no attribute is written. 057 * @see TagWriter#writeOptionalAttributeValue(String, String) 058 */ 059 protected final void writeOptionalAttribute(TagWriter tagWriter, String attributeName, String value) 060 throws JspException { 061 062 if (value != null) { 063 tagWriter.writeOptionalAttributeValue(attributeName, getDisplayString(evaluate(attributeName, value))); 064 } 065 } 066 067 /** 068 * Create the {@link TagWriter} which all output will be written to. By default, 069 * the {@link TagWriter} writes its output to the {@link javax.servlet.jsp.JspWriter} 070 * for the current {@link javax.servlet.jsp.PageContext}. Subclasses may choose to 071 * change the {@link java.io.Writer} to which output is actually written. 072 */ 073 protected TagWriter createTagWriter() { 074 return new TagWriter(this.pageContext); 075 } 076 077 /** 078 * Provide a simple template method that calls {@link #createTagWriter()} and passes 079 * the created {@link TagWriter} to the {@link #writeTagContent(TagWriter)} method. 080 * @return the value returned by {@link #writeTagContent(TagWriter)} 081 */ 082 @Override 083 protected final int doStartTagInternal() throws Exception { 084 return writeTagContent(createTagWriter()); 085 } 086 087 /** 088 * Get the display value of the supplied {@code Object}, HTML escaped 089 * as required. This version is <strong>not</strong> {@link PropertyEditor}-aware. 090 */ 091 protected String getDisplayString(Object value) { 092 return ValueFormatter.getDisplayString(value, isHtmlEscape()); 093 } 094 095 /** 096 * Get the display value of the supplied {@code Object}, HTML escaped 097 * as required. If the supplied value is not a {@link String} and the supplied 098 * {@link PropertyEditor} is not null then the {@link PropertyEditor} is used 099 * to obtain the display value. 100 */ 101 protected String getDisplayString(Object value, PropertyEditor propertyEditor) { 102 return ValueFormatter.getDisplayString(value, propertyEditor, isHtmlEscape()); 103 } 104 105 /** 106 * Overridden to default to {@code true} in case of no explicit default given. 107 */ 108 @Override 109 protected boolean isDefaultHtmlEscape() { 110 Boolean defaultHtmlEscape = getRequestContext().getDefaultHtmlEscape(); 111 return (defaultHtmlEscape == null || defaultHtmlEscape.booleanValue()); 112 } 113 114 115 /** 116 * Subclasses should implement this method to perform tag content rendering. 117 * @return valid tag render instruction as per {@link javax.servlet.jsp.tagext.Tag#doStartTag()}. 118 */ 119 protected abstract int writeTagContent(TagWriter tagWriter) throws JspException; 120 121}