You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by wo...@apache.org on 2018/01/04 19:49:27 UTC
[04/13] incubator-freemarker git commit: FREEMARKER-55: make
attribute arguments explicit
FREEMARKER-55: make attribute arguments explicit
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/2b5e9b7c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/2b5e9b7c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/2b5e9b7c
Branch: refs/heads/3
Commit: 2b5e9b7cb8bda5065e475339f3ec9dd854848b0a
Parents: ff2feb0
Author: Woonsan Ko <wo...@apache.org>
Authored: Thu Dec 28 01:26:54 2017 -0500
Committer: Woonsan Ko <wo...@apache.org>
Committed: Thu Dec 28 01:26:54 2017 -0500
----------------------------------------------------------------------
...aBoundFormElementTemplateDirectiveModel.java | 76 +++-
.../AbstractFormTemplateDirectiveModel.java | 41 ++-
...stractHtmlElementTemplateDirectiveModel.java | 349 +++++++++++++------
...tHtmlInputElementTemplateDirectiveModel.java | 126 +++++++
.../model/form/InputTemplateDirectiveModel.java | 152 +++++---
.../spring/model/form/TagOutputter.java | 11 +-
.../test/model/form/input-directive-usages.ftlh | 2 +-
7 files changed, 582 insertions(+), 175 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2b5e9b7c/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractDataBoundFormElementTemplateDirectiveModel.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractDataBoundFormElementTemplateDirectiveModel.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractDataBoundFormElementTemplateDirectiveModel.java
index 7bfac9b..f50f81d 100644
--- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractDataBoundFormElementTemplateDirectiveModel.java
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractDataBoundFormElementTemplateDirectiveModel.java
@@ -20,38 +20,88 @@
package org.apache.freemarker.spring.model.form;
import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.freemarker.core.CallPlace;
import org.apache.freemarker.core.Environment;
import org.apache.freemarker.core.TemplateException;
+import org.apache.freemarker.core.model.ArgumentArrayLayout;
import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.util.CallableUtils;
+import org.apache.freemarker.core.util.StringToIndexMap;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.support.BindStatus;
import org.springframework.web.servlet.support.RequestContext;
+import org.springframework.web.servlet.support.RequestDataValueProcessor;
/**
* Corresponds to <code>org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag</code>.
*/
public abstract class AbstractDataBoundFormElementTemplateDirectiveModel extends AbstractFormTemplateDirectiveModel {
+ private static final int PATH_PARAM_IDX = 0;
+
+ private static final int ID_PARAM_IDX = 1;
+
+ private static final String ID_PARAM_NAME = "id";
+
+ protected static List<StringToIndexMap.Entry> NAMED_ARGS_ENTRY_LIST = Arrays.asList(
+ new StringToIndexMap.Entry(ID_PARAM_NAME, ID_PARAM_IDX)
+ );
+
+ private static final ArgumentArrayLayout ARGS_LAYOUT =
+ ArgumentArrayLayout.create(
+ 1,
+ false,
+ StringToIndexMap.of(NAMED_ARGS_ENTRY_LIST.toArray(new StringToIndexMap.Entry[NAMED_ARGS_ENTRY_LIST.size()])),
+ true
+ );
+
+ private String path;
private String id;
+ private BindStatus bindStatus;
+
+ protected AbstractDataBoundFormElementTemplateDirectiveModel(HttpServletRequest request,
+ HttpServletResponse response) {
+ super(request, response);
+ }
+
+ public String getPath() {
+ return path;
+ }
+
public String getId() {
return id;
}
- public void setId(String id) {
- this.id = id;
+ @Override
+ public ArgumentArrayLayout getDirectiveArgumentArrayLayout() {
+ return ARGS_LAYOUT;
}
- protected AbstractDataBoundFormElementTemplateDirectiveModel(HttpServletRequest request,
- HttpServletResponse response) {
- super(request, response);
+ @Override
+ protected void executeInternal(TemplateModel[] args, CallPlace callPlace, Writer out, Environment env,
+ ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, RequestContext requestContext)
+ throws TemplateException, IOException {
+
+ path = CallableUtils.getOptionalStringArgument(args, PATH_PARAM_IDX, this);
+ id = CallableUtils.getOptionalStringArgument(args, ID_PARAM_IDX, this);
+
+ bindStatus = getBindStatus(env, objectWrapperAndUnwrapper, requestContext, path, false);
+ }
+
+ protected BindStatus getBindStatus() {
+ return bindStatus;
}
- protected void writeDefaultHtmlElementAttributes(TagOutputter tagOut) throws TemplateException, IOException {
+ protected void writeDefaultAttributes(TagOutputter tagOut) throws TemplateException, IOException {
// FIXME
writeOptionalAttribute(tagOut, "id", resolveId());
writeOptionalAttribute(tagOut, "name", getName());
@@ -86,4 +136,18 @@ public abstract class AbstractDataBoundFormElementTemplateDirectiveModel extends
return (expression != null ? expression : "");
}
+ protected final String processFieldValue(Environment env, String name, String value, String type) throws TemplateException {
+ RequestContext requestContext = getRequestContext(env, false);
+ RequestDataValueProcessor processor = requestContext.getRequestDataValueProcessor();
+
+ // FIXME
+// ServletRequest request = this.pageContext.getRequest();
+//
+// if (processor != null && (request instanceof HttpServletRequest)) {
+// value = processor.processFormFieldValue((HttpServletRequest) request, name, value, type);
+// }
+
+ return value;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2b5e9b7c/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractFormTemplateDirectiveModel.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractFormTemplateDirectiveModel.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractFormTemplateDirectiveModel.java
index 756fdb7..28dd1bf 100644
--- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractFormTemplateDirectiveModel.java
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractFormTemplateDirectiveModel.java
@@ -19,20 +19,16 @@
package org.apache.freemarker.spring.model.form;
+import java.beans.PropertyEditor;
import java.io.IOException;
-import java.io.Writer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.apache.freemarker.core.CallPlace;
-import org.apache.freemarker.core.Environment;
import org.apache.freemarker.core.TemplateException;
-import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
-import org.apache.freemarker.core.model.TemplateModel;
import org.apache.freemarker.spring.model.AbstractSpringTemplateDirectiveModel;
import org.springframework.util.ObjectUtils;
-import org.springframework.web.servlet.support.RequestContext;
+import org.springframework.web.util.HtmlUtils;
/**
* Corresponds to <code>org.springframework.web.servlet.tags.form.AbstractFormTag</code>.
@@ -43,31 +39,34 @@ public abstract class AbstractFormTemplateDirectiveModel extends AbstractSpringT
super(request, response);
}
- @Override
- protected final void executeInternal(TemplateModel[] args, CallPlace callPlace, Writer out, Environment env,
- ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, RequestContext requestContext)
- throws TemplateException, IOException {
- final TagOutputter tagOut = new TagOutputter(out);
- writeDirectiveContent(args, callPlace, tagOut, env, objectWrapperAndUnwrapper, requestContext);
- }
-
- protected abstract void writeDirectiveContent(TemplateModel[] args, CallPlace callPlace, TagOutputter tagOut,
- Environment env, ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, RequestContext requestContext)
- throws TemplateException;
-
protected Object evaluate(String attributeName, Object value) throws TemplateException {
return value;
}
- protected String getDisplayString(Object value) {
+ public static String getDisplayString(Object value, boolean htmlEscape) {
String displayValue = ObjectUtils.getDisplayString(value);
- return displayValue;
+ return (htmlEscape ? HtmlUtils.htmlEscape(displayValue) : displayValue);
+ }
+
+ public static String getDisplayString(Object value, PropertyEditor propertyEditor, boolean htmlEscape) {
+ if (propertyEditor != null && !(value instanceof String)) {
+ try {
+ propertyEditor.setValue(value);
+ String text = propertyEditor.getAsText();
+ if (text != null) {
+ return getDisplayString(text, htmlEscape);
+ }
+ } catch (Throwable ex) {
+ // The PropertyEditor might not support this value... pass through.
+ }
+ }
+ return getDisplayString(value, htmlEscape);
}
protected final void writeOptionalAttribute(TagOutputter tagOut, String attrName, Object attrValue)
throws TemplateException, IOException {
if (attrValue != null) {
- tagOut.writeOptionalAttributeValue(attrName, getDisplayString(evaluate(attrName, attrValue)));
+ tagOut.writeOptionalAttributeValue(attrName, getDisplayString(evaluate(attrName, attrValue), false));
}
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2b5e9b7c/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractHtmlElementTemplateDirectiveModel.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractHtmlElementTemplateDirectiveModel.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractHtmlElementTemplateDirectiveModel.java
index a91a67c..d982111 100644
--- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractHtmlElementTemplateDirectiveModel.java
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractHtmlElementTemplateDirectiveModel.java
@@ -20,14 +20,18 @@
package org.apache.freemarker.spring.model.form;
import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.freemarker.core.CallPlace;
+import org.apache.freemarker.core.Environment;
import org.apache.freemarker.core.TemplateException;
import org.apache.freemarker.core.model.ArgumentArrayLayout;
import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
@@ -35,6 +39,11 @@ import org.apache.freemarker.core.model.TemplateHashModelEx;
import org.apache.freemarker.core.model.TemplateModel;
import org.apache.freemarker.core.model.TemplateStringModel;
import org.apache.freemarker.core.util.CallableUtils;
+import org.apache.freemarker.core.util.StringToIndexMap;
+import org.apache.freemarker.core.util._CollectionUtils;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+import org.springframework.web.servlet.support.RequestContext;
/**
* Corresponds to <code>org.springframework.web.servlet.tags.form.AbstractHtmlElementTag</code>.
@@ -42,46 +51,110 @@ import org.apache.freemarker.core.util.CallableUtils;
public abstract class AbstractHtmlElementTemplateDirectiveModel
extends AbstractDataBoundFormElementTemplateDirectiveModel {
- protected static Map<String, String> createAttributeKeyNamePairsMap(String ... attrNames) {
- Map<String, String> map = new HashMap<>();
- for (String attrName : attrNames) {
- map.put(attrName.toUpperCase(), attrName);
- }
- return map;
- }
-
- private static final Map<String, String> REGISTERED_ATTRIBUTES = Collections.unmodifiableMap(
- createAttributeKeyNamePairsMap(
- "class",
- "style",
- "lang",
- "title",
- "dir",
- "tabindex",
- "onclick",
- "ondblclick",
- "onmousedown",
- "onmouseup",
- "onmouseover",
- "onmousemove",
- "onmouseout",
- "onkeypress",
- "onkeyup",
- "onkeydown")
- );
-
- private static final int PATH_PARAM_IDX = 0;
+ private static final int NAMED_ARGS_OFFSET = AbstractDataBoundFormElementTemplateDirectiveModel.NAMED_ARGS_ENTRY_LIST
+ .size() + 1;
+
+ private static final int CSS_CLASS_PARAM_IDX = NAMED_ARGS_OFFSET;
+ private static final String CSS_CLASS_PARAM_NAME = "cssClass";
+
+ private static final int CSS_STYLE_PARAM_IDX = NAMED_ARGS_OFFSET + 1;
+ private static final String CSS_STYLE_PARAM_NAME = "cssStyle";
+
+ private static final int LANG_PARAM_IDX = NAMED_ARGS_OFFSET + 2;
+ private static final String LANG_PARAM_NAME = "lang";
+
+ private static final int TITLE_PARAM_IDX = NAMED_ARGS_OFFSET + 3;
+ private static final String TITLE_PARAM_NAME = "title";
+
+ private static final int DIR_PARAM_IDX = NAMED_ARGS_OFFSET + 4;
+ private static final String DIR_PARAM_NAME = "dir";
+
+ private static final int TABINDEX_PARAM_IDX = NAMED_ARGS_OFFSET + 5;
+ private static final String TABINDEX_PARAM_NAME = "tabindex";
+
+ private static final int ONCLICK_PARAM_IDX = NAMED_ARGS_OFFSET + 6;
+ private static final String ONCLICK_PARAM_NAME = "onclick";
+
+ private static final int ONDBLCLICK_PARAM_IDX = NAMED_ARGS_OFFSET + 7;
+ private static final String ONDBLCLICK_PARAM_NAME = "ondblclick";
+
+ private static final int ONMOUSEDOWN_PARAM_IDX = NAMED_ARGS_OFFSET + 8;
+ private static final String ONMOUSEDOWN_PARAM_NAME = "onmousedown";
+
+ private static final int ONMOUSEUP_PARAM_IDX = NAMED_ARGS_OFFSET + 9;
+ private static final String ONMOUSEUP_PARAM_NAME = "onmouseup";
+
+ private static final int ONMOUSEOVER_PARAM_IDX = NAMED_ARGS_OFFSET + 10;
+ private static final String ONMOUSEOVER_PARAM_NAME = "onmouseover";
+
+ private static final int ONMOUSEMOVE_PARAM_IDX = NAMED_ARGS_OFFSET + 11;
+ private static final String ONMOUSEMOVE_PARAM_NAME = "onmousemove";
+
+ private static final int ONMOUSEOUT_PARAM_IDX = NAMED_ARGS_OFFSET + 12;
+ private static final String ONMOUSEOUT_PARAM_NAME = "onmouseout";
+
+ private static final int ONKEYPRESS_PARAM_IDX = NAMED_ARGS_OFFSET + 13;
+ private static final String ONKEYPRESS_PARAM_NAME = "onkeypress";
+
+ private static final int ONKEYUP_PARAM_IDX = NAMED_ARGS_OFFSET + 14;
+ private static final String ONKEYUP_PARAM_NAME = "onkeyup";
+
+ private static final int ONKEYDOWN_PARAM_IDX = NAMED_ARGS_OFFSET + 15;
+ private static final String ONKEYDOWN_PARAM_NAME = "onkeydown";
+
+ private static final int CSSERRORCLASS_PARAM_IDX = NAMED_ARGS_OFFSET + 16;
+ private static final String CSSERRORCLASS_PARAM_NAME = "cssErrorClass";
+
+ protected static List<StringToIndexMap.Entry> NAMED_ARGS_ENTRY_LIST =
+ _CollectionUtils.mergeImmutableLists(false,
+ AbstractDataBoundFormElementTemplateDirectiveModel.NAMED_ARGS_ENTRY_LIST,
+ Arrays.asList(
+ new StringToIndexMap.Entry(CSS_CLASS_PARAM_NAME, CSS_CLASS_PARAM_IDX),
+ new StringToIndexMap.Entry(CSS_STYLE_PARAM_NAME, CSS_STYLE_PARAM_IDX),
+ new StringToIndexMap.Entry(LANG_PARAM_NAME, LANG_PARAM_IDX),
+ new StringToIndexMap.Entry(TITLE_PARAM_NAME, TITLE_PARAM_IDX),
+ new StringToIndexMap.Entry(DIR_PARAM_NAME, DIR_PARAM_IDX),
+ new StringToIndexMap.Entry(TABINDEX_PARAM_NAME, TABINDEX_PARAM_IDX),
+ new StringToIndexMap.Entry(ONCLICK_PARAM_NAME, ONCLICK_PARAM_IDX),
+ new StringToIndexMap.Entry(ONDBLCLICK_PARAM_NAME, ONDBLCLICK_PARAM_IDX),
+ new StringToIndexMap.Entry(ONMOUSEDOWN_PARAM_NAME, ONMOUSEDOWN_PARAM_IDX),
+ new StringToIndexMap.Entry(ONMOUSEUP_PARAM_NAME, ONMOUSEUP_PARAM_IDX),
+ new StringToIndexMap.Entry(ONMOUSEOVER_PARAM_NAME, ONMOUSEOVER_PARAM_IDX),
+ new StringToIndexMap.Entry(ONMOUSEMOVE_PARAM_NAME, ONMOUSEMOVE_PARAM_IDX),
+ new StringToIndexMap.Entry(ONMOUSEOUT_PARAM_NAME, ONMOUSEOUT_PARAM_IDX),
+ new StringToIndexMap.Entry(ONKEYPRESS_PARAM_NAME, ONKEYPRESS_PARAM_IDX),
+ new StringToIndexMap.Entry(ONKEYUP_PARAM_NAME, ONKEYUP_PARAM_IDX),
+ new StringToIndexMap.Entry(ONKEYDOWN_PARAM_NAME, ONKEYDOWN_PARAM_IDX),
+ new StringToIndexMap.Entry(CSSERRORCLASS_PARAM_NAME, CSSERRORCLASS_PARAM_IDX)
+ )
+ );
private static final ArgumentArrayLayout ARGS_LAYOUT =
ArgumentArrayLayout.create(
1,
false,
- null,
+ StringToIndexMap.of(NAMED_ARGS_ENTRY_LIST.toArray(new StringToIndexMap.Entry[NAMED_ARGS_ENTRY_LIST.size()])),
true
);
- private Map<String, Object> registeredAttributes;
- private Map<String, Object> unmodifiableRegisteredAttributes = Collections.emptyMap();
+ private String cssClass;
+ private String cssStyle;
+ private String lang;
+ private String title;
+ private String dir;
+ private String tabindex;
+ private String onclick;
+ private String ondblclick;
+ private String onmousedown;
+ private String onmouseup;
+ private String onmouseover;
+ private String onmousemove;
+ private String onmouseout;
+ private String onkeypress;
+ private String onkeyup;
+ private String onkeydown;
+ private String cssErrorClass;
+
private Map<String, Object> dynamicAttributes;
private Map<String, Object> unmodifiableDynamicAttributes = Collections.emptyMap();
@@ -94,32 +167,131 @@ public abstract class AbstractHtmlElementTemplateDirectiveModel
return ARGS_LAYOUT;
}
- public Map<String, Object> getRegisteredAttributes() {
- return unmodifiableRegisteredAttributes;
+ @Override
+ protected void executeInternal(TemplateModel[] args, CallPlace callPlace, Writer out, Environment env,
+ ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, RequestContext requestContext)
+ throws TemplateException, IOException {
+
+ super.executeInternal(args, callPlace, out, env, objectWrapperAndUnwrapper, requestContext);
+
+ cssClass = CallableUtils.getOptionalStringArgument(args, CSS_CLASS_PARAM_IDX, this);
+ cssStyle = CallableUtils.getOptionalStringArgument(args, CSS_STYLE_PARAM_IDX, this);
+ lang = CallableUtils.getOptionalStringArgument(args, LANG_PARAM_IDX, this);
+ title = CallableUtils.getOptionalStringArgument(args, TITLE_PARAM_IDX, this);
+ dir = CallableUtils.getOptionalStringArgument(args, DIR_PARAM_IDX, this);
+ tabindex = CallableUtils.getOptionalStringArgument(args, TABINDEX_PARAM_IDX, this);
+ onclick = CallableUtils.getOptionalStringArgument(args, ONCLICK_PARAM_IDX, this);
+ ondblclick = CallableUtils.getOptionalStringArgument(args, ONDBLCLICK_PARAM_IDX, this);
+ onmousedown = CallableUtils.getOptionalStringArgument(args, ONMOUSEDOWN_PARAM_IDX, this);
+ onmouseup = CallableUtils.getOptionalStringArgument(args, ONMOUSEUP_PARAM_IDX, this);
+ onmouseover = CallableUtils.getOptionalStringArgument(args, ONMOUSEOVER_PARAM_IDX, this);
+ onmousemove = CallableUtils.getOptionalStringArgument(args, ONMOUSEMOVE_PARAM_IDX, this);
+ onmouseout = CallableUtils.getOptionalStringArgument(args, ONMOUSEOUT_PARAM_IDX, this);
+ onkeypress = CallableUtils.getOptionalStringArgument(args, ONKEYPRESS_PARAM_IDX, this);
+ onkeyup = CallableUtils.getOptionalStringArgument(args, ONKEYUP_PARAM_IDX, this);
+ onkeydown = CallableUtils.getOptionalStringArgument(args, ONKEYDOWN_PARAM_IDX, this);
+ cssErrorClass = CallableUtils.getOptionalStringArgument(args, CSSERRORCLASS_PARAM_IDX, this);
+
+ final int attrsVarargsIndex = ARGS_LAYOUT.getNamedVarargsArgumentIndex();
+ final TemplateHashModelEx attrsHashModel = (TemplateHashModelEx) args[attrsVarargsIndex];
+
+ if (attrsHashModel != null && !attrsHashModel.isEmptyHash()) {
+ for (TemplateHashModelEx.KeyValuePairIterator attrIt = attrsHashModel.keyValuePairIterator(); attrIt.hasNext();) {
+ TemplateHashModelEx.KeyValuePair pair = attrIt.next();
+ TemplateModel attrNameModel = pair.getKey();
+ TemplateModel attrValueModel = pair.getValue();
+
+ if (!(attrNameModel instanceof TemplateStringModel)) {
+ throw CallableUtils.newArgumentValueException(attrsVarargsIndex,
+ "Attribute name must be a string.", this);
+ }
+
+ String attrName = ((TemplateStringModel) attrNameModel).getAsString();
+
+ if (attrName.isEmpty()) {
+ throw CallableUtils.newArgumentValueException(attrsVarargsIndex,
+ "Attribute name must be a non-blank string.", this);
+ }
+
+ final Object attrValue = objectWrapperAndUnwrapper.unwrap(attrValueModel);
+ setDynamicAttribute(attrName, attrValue);
+ }
+ }
}
- public Map<String, Object> getDynamicAttributes() {
- return unmodifiableDynamicAttributes;
+ public String getCssClass() {
+ return cssClass;
}
- public void setRegisteredAttribute(String localName, Object value) {
- if (localName == null) {
- throw new IllegalArgumentException("Attribute name must not be null.");
- }
+ public String getCssStyle() {
+ return cssStyle;
+ }
- if (!isRegisteredAttribute(localName, value)) {
- throw new IllegalArgumentException("Invalid attribute: " + localName + "=" + value);
- }
+ public String getLang() {
+ return lang;
+ }
- if (registeredAttributes == null) {
- registeredAttributes = new LinkedHashMap<String, Object>();
- unmodifiableRegisteredAttributes = Collections.unmodifiableMap(registeredAttributes);
- }
+ public String getTitle() {
+ return title;
+ }
- registeredAttributes.put(localName, value);
+ public String getDir() {
+ return dir;
}
- public void setDynamicAttribute(String localName, Object value) {
+ public String getTabindex() {
+ return tabindex;
+ }
+
+ public String getOnclick() {
+ return onclick;
+ }
+
+ public String getOndblclick() {
+ return ondblclick;
+ }
+
+ public String getOnmousedown() {
+ return onmousedown;
+ }
+
+ public String getOnmouseup() {
+ return onmouseup;
+ }
+
+ public String getOnmouseover() {
+ return onmouseover;
+ }
+
+ public String getOnmousemove() {
+ return onmousemove;
+ }
+
+ public String getOnmouseout() {
+ return onmouseout;
+ }
+
+ public String getOnkeypress() {
+ return onkeypress;
+ }
+
+ public String getOnkeyup() {
+ return onkeyup;
+ }
+
+ public String getOnkeydown() {
+ return onkeydown;
+ }
+
+ public String getCssErrorClass() {
+ return cssErrorClass;
+ }
+
+ public Map<String, Object> getDynamicAttributes() {
+ return unmodifiableDynamicAttributes;
+ }
+
+ private void setDynamicAttribute(String localName, Object value) {
if (localName == null) {
throw new IllegalArgumentException("Attribute name must not be null.");
}
@@ -136,62 +308,45 @@ public abstract class AbstractHtmlElementTemplateDirectiveModel
dynamicAttributes.put(localName, value);
}
- protected String getPathArgument(TemplateModel[] args) throws TemplateException {
- final String path = CallableUtils.getStringArgument(args, PATH_PARAM_IDX, this);
- return path;
- }
-
- protected boolean isRegisteredAttribute(String localName, Object value) {
- return REGISTERED_ATTRIBUTES.containsKey(localName.toUpperCase());
- }
-
protected boolean isValidDynamicAttribute(String localName, Object value) {
return true;
}
- protected void readRegisteredAndDynamicAttributes(TemplateModel[] args, ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper) throws TemplateException {
- final int attrsVarargsIndex = getDirectiveArgumentArrayLayout().getNamedVarargsArgumentIndex();
- final TemplateHashModelEx attrsHashModel = (TemplateHashModelEx) args[attrsVarargsIndex];
-
- if (!attrsHashModel.isEmptyHash()) {
- for (TemplateHashModelEx.KeyValuePairIterator attrIt = attrsHashModel.keyValuePairIterator(); attrIt.hasNext();) {
- TemplateHashModelEx.KeyValuePair pair = attrIt.next();
- TemplateModel attrNameModel = pair.getKey();
- TemplateModel attrValueModel = pair.getValue();
-
- if (!(attrNameModel instanceof TemplateStringModel)) {
- throw CallableUtils.newArgumentValueException(attrsVarargsIndex,
- "Parameter name must be a string.", this);
- }
-
- String attrName = ((TemplateStringModel) attrNameModel).getAsString();
-
- if (attrName.isEmpty()) {
- throw CallableUtils.newArgumentValueException(attrsVarargsIndex,
- "Attribute name must be a non-blank string.", this);
- }
-
- final Object attrValue = objectWrapperAndUnwrapper.unwrap(attrValueModel);
+ protected void writeDefaultAttributes(TagOutputter tagOut) throws TemplateException, IOException {
+ super.writeDefaultAttributes(tagOut);
+ writeOptionalAttributes(tagOut);
+ }
- if (isRegisteredAttribute(attrName, attrValue)) {
- setRegisteredAttribute(attrName.toUpperCase(), attrValue);
- } else {
- setDynamicAttribute(attrName, attrValue);
- }
+ protected void writeOptionalAttributes(TagOutputter tagOut) throws TemplateException, IOException {
+ tagOut.writeOptionalAttributeValue("class", resolveCssClass());
+ tagOut.writeOptionalAttributeValue("style", ObjectUtils.getDisplayString(evaluate("cssStyle", getCssStyle())));
+ writeOptionalAttribute(tagOut, LANG_PARAM_NAME, getLang());
+ writeOptionalAttribute(tagOut, TITLE_PARAM_NAME, getTitle());
+ writeOptionalAttribute(tagOut, DIR_PARAM_NAME, getDir());
+ writeOptionalAttribute(tagOut, TABINDEX_PARAM_NAME, getTabindex());
+ writeOptionalAttribute(tagOut, ONCLICK_PARAM_NAME, getOnclick());
+ writeOptionalAttribute(tagOut, ONDBLCLICK_PARAM_NAME, getOndblclick());
+ writeOptionalAttribute(tagOut, ONMOUSEDOWN_PARAM_NAME, getOnmousedown());
+ writeOptionalAttribute(tagOut, ONMOUSEUP_PARAM_NAME, getOnmouseup());
+ writeOptionalAttribute(tagOut, ONMOUSEOVER_PARAM_NAME, getOnmouseover());
+ writeOptionalAttribute(tagOut, ONMOUSEMOVE_PARAM_NAME, getOnmousemove());
+ writeOptionalAttribute(tagOut, ONMOUSEOUT_PARAM_NAME, getOnmouseout());
+ writeOptionalAttribute(tagOut, ONKEYPRESS_PARAM_NAME, getOnkeypress());
+ writeOptionalAttribute(tagOut, ONKEYUP_PARAM_NAME, getOnkeyup());
+ writeOptionalAttribute(tagOut, ONKEYDOWN_PARAM_NAME, getOnkeydown());
+
+ if (!this.unmodifiableDynamicAttributes.isEmpty()) {
+ for (String attr : this.dynamicAttributes.keySet()) {
+ tagOut.writeOptionalAttributeValue(attr, getDisplayString(this.dynamicAttributes.get(attr), false));
}
}
-
- System.out.println("$$$$$ dynamicAttributes: " + this.getDynamicAttributes());
}
- protected void writeDefaultHtmlElementAttributes(TagOutputter tagOut) throws TemplateException, IOException {
- super.writeDefaultHtmlElementAttributes(tagOut);
-
- for (Map.Entry<String, String> entry : REGISTERED_ATTRIBUTES.entrySet()) {
- String attrKey = entry.getKey();
- String attrName = entry.getValue();
- Object attrValue = getRegisteredAttributes().get(attrKey);
- writeOptionalAttribute(tagOut, attrName, attrValue);
+ protected String resolveCssClass() throws TemplateException {
+ if (getBindStatus().isError() && StringUtils.hasText(getCssErrorClass())) {
+ return ObjectUtils.getDisplayString(evaluate("cssErrorClass", getCssErrorClass()));
+ } else {
+ return ObjectUtils.getDisplayString(evaluate("cssClass", getCssClass()));
}
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2b5e9b7c/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractHtmlInputElementTemplateDirectiveModel.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractHtmlInputElementTemplateDirectiveModel.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractHtmlInputElementTemplateDirectiveModel.java
index e5ebf93..b77bc9d 100644
--- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractHtmlInputElementTemplateDirectiveModel.java
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/AbstractHtmlInputElementTemplateDirectiveModel.java
@@ -19,14 +19,140 @@
package org.apache.freemarker.spring.model.form;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.List;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.freemarker.core.CallPlace;
+import org.apache.freemarker.core.Environment;
+import org.apache.freemarker.core.TemplateException;
+import org.apache.freemarker.core.model.ArgumentArrayLayout;
+import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
+import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.util.CallableUtils;
+import org.apache.freemarker.core.util.StringToIndexMap;
+import org.apache.freemarker.core.util._CollectionUtils;
+import org.springframework.web.servlet.support.RequestContext;
+
public abstract class AbstractHtmlInputElementTemplateDirectiveModel extends AbstractHtmlElementTemplateDirectiveModel {
+ private static final int NAMED_ARGS_OFFSET = AbstractHtmlElementTemplateDirectiveModel.NAMED_ARGS_ENTRY_LIST.size()
+ + 1;
+
+ private static final int ONFOCUS_PARAM_IDX = NAMED_ARGS_OFFSET;
+ private static final String ONFOCUS_PARAM_NAME = "onfocus";
+
+ private static final int ONBLUR_PARAM_IDX = NAMED_ARGS_OFFSET + 1;
+ private static final String ONBLUR_PARAM_NAME = "onblur";
+
+ private static final int ONCHANGE_PARAM_IDX = NAMED_ARGS_OFFSET + 2;
+ private static final String ONCHANGE_PARAM_NAME = "onchange";
+
+ private static final int ACCESSKEY_PARAM_IDX = NAMED_ARGS_OFFSET + 3;
+ private static final String ACCESSKEY_PARAM_NAME = "accesskey";
+
+ private static final int DISABLED_PARAM_IDX = NAMED_ARGS_OFFSET + 4;
+ private static final String DISABLED_PARAM_NAME = "disabled";
+
+ private static final int READONLY_PARAM_IDX = NAMED_ARGS_OFFSET + 5;
+ private static final String READONLY_PARAM_NAME = "readonly";
+
+ protected static List<StringToIndexMap.Entry> NAMED_ARGS_ENTRY_LIST =
+ _CollectionUtils.mergeImmutableLists(false,
+ AbstractHtmlElementTemplateDirectiveModel.NAMED_ARGS_ENTRY_LIST,
+ Arrays.asList(
+ new StringToIndexMap.Entry(ONFOCUS_PARAM_NAME, ONFOCUS_PARAM_IDX),
+ new StringToIndexMap.Entry(ONBLUR_PARAM_NAME, ONBLUR_PARAM_IDX),
+ new StringToIndexMap.Entry(ONCHANGE_PARAM_NAME, ONCHANGE_PARAM_IDX),
+ new StringToIndexMap.Entry(ACCESSKEY_PARAM_NAME, ACCESSKEY_PARAM_IDX),
+ new StringToIndexMap.Entry(DISABLED_PARAM_NAME, DISABLED_PARAM_IDX),
+ new StringToIndexMap.Entry(READONLY_PARAM_NAME, READONLY_PARAM_IDX)
+ )
+ );
+
+ private static final ArgumentArrayLayout ARGS_LAYOUT =
+ ArgumentArrayLayout.create(
+ 1,
+ false,
+ StringToIndexMap.of(NAMED_ARGS_ENTRY_LIST.toArray(new StringToIndexMap.Entry[NAMED_ARGS_ENTRY_LIST.size()])),
+ true
+ );
+
+ private String onfocus;
+ private String onblur;
+ private String onchange;
+ private String accesskey;
+ private boolean disabled;
+ private boolean readonly;
+
protected AbstractHtmlInputElementTemplateDirectiveModel(HttpServletRequest request,
HttpServletResponse response) {
super(request, response);
}
+ @Override
+ public ArgumentArrayLayout getDirectiveArgumentArrayLayout() {
+ return ARGS_LAYOUT;
+ }
+
+ @Override
+ protected void executeInternal(TemplateModel[] args, CallPlace callPlace, Writer out, Environment env,
+ ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, RequestContext requestContext)
+ throws TemplateException, IOException {
+
+ super.executeInternal(args, callPlace, out, env, objectWrapperAndUnwrapper, requestContext);
+
+ onfocus = CallableUtils.getOptionalStringArgument(args, ONFOCUS_PARAM_IDX, this);
+ onblur = CallableUtils.getOptionalStringArgument(args, ONBLUR_PARAM_IDX, this);
+ onchange = CallableUtils.getOptionalStringArgument(args, ONCHANGE_PARAM_IDX, this);
+ accesskey = CallableUtils.getOptionalStringArgument(args, ACCESSKEY_PARAM_IDX, this);
+ disabled = CallableUtils.getOptionalBooleanArgument(args, DISABLED_PARAM_IDX, this, false);
+ readonly = CallableUtils.getOptionalBooleanArgument(args, READONLY_PARAM_IDX, this, false);
+ }
+
+ @Override
+ protected void writeOptionalAttributes(TagOutputter tagOut) throws TemplateException, IOException {
+ super.writeOptionalAttributes(tagOut);
+
+ writeOptionalAttribute(tagOut, ONFOCUS_PARAM_NAME, getOnfocus());
+ writeOptionalAttribute(tagOut, ONBLUR_PARAM_NAME, getOnblur());
+ writeOptionalAttribute(tagOut, ONCHANGE_PARAM_NAME, getOnchange());
+ writeOptionalAttribute(tagOut, ACCESSKEY_PARAM_NAME, getAccesskey());
+
+ if (isDisabled()) {
+ tagOut.writeAttribute(DISABLED_PARAM_NAME, "disabled");
+ }
+ if (isReadonly()) {
+ writeOptionalAttribute(tagOut, READONLY_PARAM_NAME, "readonly");
+ }
+ }
+
+ public String getOnfocus() {
+ return onfocus;
+ }
+
+ public String getOnblur() {
+ return onblur;
+ }
+
+ public String getOnchange() {
+ return onchange;
+ }
+
+ public String getAccesskey() {
+ return accesskey;
+ }
+
+ public boolean isDisabled() {
+ return disabled;
+ }
+
+ public boolean isReadonly() {
+ return readonly;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2b5e9b7c/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/InputTemplateDirectiveModel.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/InputTemplateDirectiveModel.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/InputTemplateDirectiveModel.java
index 4540006..e53eb0c 100644
--- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/InputTemplateDirectiveModel.java
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/InputTemplateDirectiveModel.java
@@ -20,8 +20,9 @@
package org.apache.freemarker.spring.model.form;
import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -29,22 +30,61 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.freemarker.core.CallPlace;
import org.apache.freemarker.core.Environment;
import org.apache.freemarker.core.TemplateException;
+import org.apache.freemarker.core.model.ArgumentArrayLayout;
import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.util.CallableUtils;
+import org.apache.freemarker.core.util.StringToIndexMap;
+import org.apache.freemarker.core.util._CollectionUtils;
import org.springframework.web.servlet.support.RequestContext;
-public class InputTemplateDirectiveModel extends AbstractHtmlElementTemplateDirectiveModel {
+public class InputTemplateDirectiveModel extends AbstractHtmlInputElementTemplateDirectiveModel {
public static final String NAME = "input";
- private static final Map<String, String> REGISTERED_ATTRIBUTES = Collections.unmodifiableMap(
- createAttributeKeyNamePairsMap(
- "size",
- "maxlength",
- "alt",
- "onselect",
- "readonly",
- "autocomplete"));
+ private static final int NAMED_ARGS_OFFSET = AbstractHtmlInputElementTemplateDirectiveModel.NAMED_ARGS_ENTRY_LIST
+ .size() + 1;
+
+ private static final int SIZE_PARAM_IDX = NAMED_ARGS_OFFSET;
+ private static final String SIZE_PARAM_NAME = "size";
+
+ private static final int MAXLENGTH_PARAM_IDX = NAMED_ARGS_OFFSET + 1;
+ private static final String MAXLENGTH_PARAM_NAME = "maxlength";
+
+ private static final int ALT_PARAM_IDX = NAMED_ARGS_OFFSET + 2;
+ private static final String ALT_PARAM_NAME = "alt";
+
+ private static final int ONSELECT_PARAM_IDX = NAMED_ARGS_OFFSET + 3;
+ private static final String ONSELECT_PARAM_NAME = "onselect";
+
+ private static final int AUTOCOMPLETE_PARAM_IDX = NAMED_ARGS_OFFSET + 4;
+ private static final String AUTOCOMPLETE_PARAM_NAME = "autocomplete";
+
+ protected static List<StringToIndexMap.Entry> NAMED_ARGS_ENTRY_LIST =
+ _CollectionUtils.mergeImmutableLists(false,
+ AbstractHtmlInputElementTemplateDirectiveModel.NAMED_ARGS_ENTRY_LIST,
+ Arrays.asList(
+ new StringToIndexMap.Entry(SIZE_PARAM_NAME, SIZE_PARAM_IDX),
+ new StringToIndexMap.Entry(MAXLENGTH_PARAM_NAME, MAXLENGTH_PARAM_IDX),
+ new StringToIndexMap.Entry(ALT_PARAM_NAME, ALT_PARAM_IDX),
+ new StringToIndexMap.Entry(ONSELECT_PARAM_NAME, ONSELECT_PARAM_IDX),
+ new StringToIndexMap.Entry(AUTOCOMPLETE_PARAM_NAME, AUTOCOMPLETE_PARAM_IDX)
+ )
+ );
+
+ private static final ArgumentArrayLayout ARGS_LAYOUT =
+ ArgumentArrayLayout.create(
+ 1,
+ false,
+ StringToIndexMap.of(NAMED_ARGS_ENTRY_LIST.toArray(new StringToIndexMap.Entry[NAMED_ARGS_ENTRY_LIST.size()])),
+ true
+ );
+
+ private String size;
+ private String maxlength;
+ private String alt;
+ private String onselect;
+ private String autocomplete;
protected InputTemplateDirectiveModel(HttpServletRequest request, HttpServletResponse response) {
super(request, response);
@@ -56,59 +96,77 @@ public class InputTemplateDirectiveModel extends AbstractHtmlElementTemplateDire
}
@Override
- protected void writeDirectiveContent(TemplateModel[] args, CallPlace callPlace, TagOutputter tagOut,
- Environment env, ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, RequestContext requestContext)
- throws TemplateException {
-
- final String path = getPathArgument(args);
+ public ArgumentArrayLayout getDirectiveArgumentArrayLayout() {
+ return ARGS_LAYOUT;
+ }
- try {
- readRegisteredAndDynamicAttributes(args, objectWrapperAndUnwrapper);
+ @Override
+ protected void executeInternal(TemplateModel[] args, CallPlace callPlace, Writer out, Environment env,
+ ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, RequestContext requestContext)
+ throws TemplateException, IOException {
- tagOut.beginTag(NAME);
+ super.executeInternal(args, callPlace, out, env, objectWrapperAndUnwrapper, requestContext);
- writeDefaultHtmlElementAttributes(tagOut);
+ size = CallableUtils.getOptionalStringArgument(args, SIZE_PARAM_IDX, this);
+ maxlength = CallableUtils.getOptionalStringArgument(args, MAXLENGTH_PARAM_IDX, this);
+ alt = CallableUtils.getOptionalStringArgument(args, ALT_PARAM_IDX, this);
+ onselect = CallableUtils.getOptionalStringArgument(args, ONSELECT_PARAM_IDX, this);
+ autocomplete = CallableUtils.getOptionalStringArgument(args, AUTOCOMPLETE_PARAM_IDX, this);
- if (!hasDynamicTypeAttribute()) {
- tagOut.writeAttribute("type", (String) getRegisteredAttributes().get("type"));
- }
+ TagOutputter tagOut = new TagOutputter(out);
- writeValue(tagOut);
+ tagOut.beginTag(NAME);
- // custom optional attributes
- for (Map.Entry<String, String> entry : REGISTERED_ATTRIBUTES.entrySet()) {
- String attrKey = entry.getKey();
- String attrName = entry.getValue();
- Object attrValue = getRegisteredAttributes().get(attrKey);
- writeOptionalAttribute(tagOut, attrName, attrValue);
- }
+ writeDefaultAttributes(tagOut);
- tagOut.endTag();
- } catch (IOException e) {
- throw new TemplateException(e);
+ if (!hasDynamicTypeAttribute()) {
+ tagOut.writeAttribute("type", getType());
}
+
+ writeValue(env, tagOut);
+
+ // more optional attributes by this tag
+ writeOptionalAttribute(tagOut, SIZE_PARAM_NAME, getSize());
+ writeOptionalAttribute(tagOut, MAXLENGTH_PARAM_NAME, getMaxlength());
+ writeOptionalAttribute(tagOut, ALT_PARAM_NAME, getAlt());
+ writeOptionalAttribute(tagOut, ONSELECT_PARAM_NAME, getOnselect());
+ writeOptionalAttribute(tagOut, AUTOCOMPLETE_PARAM_NAME, getAutocomplete());
+
+ tagOut.endTag();
}
- @Override
- protected boolean isRegisteredAttribute(String localName, Object value) {
- return super.isRegisteredAttribute(localName, value) && REGISTERED_ATTRIBUTES.containsKey(localName);
+ public String getSize() {
+ return size;
+ }
+
+ public String getMaxlength() {
+ return maxlength;
+ }
+
+ public String getAlt() {
+ return alt;
+ }
+
+ public String getOnselect() {
+ return onselect;
+ }
+
+ public String getAutocomplete() {
+ return autocomplete;
}
private boolean hasDynamicTypeAttribute() {
return getDynamicAttributes().containsKey("type");
}
- protected void writeValue(TagOutputter tagOut) throws TemplateException {
-// String value = getDisplayString(getBoundValue(), getPropertyEditor());
-// String type = hasDynamicTypeAttribute() ? (String) getDynamicAttributes().get("type") : getType();
-// tagWriter.writeAttribute("value", processFieldValue(getName(), value, type));
+ protected void writeValue(Environment env, TagOutputter tagOut) throws TemplateException, IOException {
+ String value = getDisplayString(getBindStatus().getValue(), getBindStatus().getEditor(), false);
+ String type = hasDynamicTypeAttribute() ? (String) getDynamicAttributes().get("type") : getType();
+ tagOut.writeAttribute("value", processFieldValue(env, getName(), value, type));
+ }
- //FIXME
- try {
- tagOut.writeAttribute("value", "value");
- } catch (IOException e) {
- throw new TemplateException(e);
- }
+ protected String getType() {
+ return "text";
}
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2b5e9b7c/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/TagOutputter.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/TagOutputter.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/TagOutputter.java
index dd20fe2..8569ad1 100644
--- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/TagOutputter.java
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/form/TagOutputter.java
@@ -77,7 +77,7 @@ class TagOutputter {
out.write(value);
}
- public void forceBlock() throws TemplateException, IOException {
+ public void forceBlock() throws TemplateException {
TagEntry current = tagStack.peek();
if (current.isBlockTag()) {
@@ -117,12 +117,17 @@ class TagOutputter {
tagStack.pop();
}
- private void closeAndMarkAsBlockTag() throws TemplateException, IOException {
+ private void closeAndMarkAsBlockTag() throws TemplateException {
TagEntry current = tagStack.peek();
if (!current.isBlockTag()) {
current.markAsBlockTag();
- out.write(">");
+
+ try {
+ out.write(">");
+ } catch (IOException e) {
+ throw new TemplateException("Failed to write output.", e);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2b5e9b7c/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/form/input-directive-usages.ftlh
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/form/input-directive-usages.ftlh b/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/form/input-directive-usages.ftlh
index 801b234..40beea0 100644
--- a/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/form/input-directive-usages.ftlh
+++ b/freemarker-spring/src/test/resources/META-INF/web-resources/views/test/model/form/input-directive-usages.ftlh
@@ -20,7 +20,7 @@
<body>
<div id="userEmail">
- <@spring.form.input 'user.email' type='text' value='${user.email!}' />
+ <@spring.form.input 'user.email' value='${user.email!}' />
</div>
</body>