You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2017/09/13 09:49:16 UTC
[15/36] incubator-freemarker git commit: FREEMARKER-55: Adding more
functions.
FREEMARKER-55: Adding more functions.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/234f96ec
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/234f96ec
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/234f96ec
Branch: refs/heads/3
Commit: 234f96ec2c2868c72f797bda42a8d0c854e63b87
Parents: d0bd43c
Author: Woonsan Ko <wo...@apache.org>
Authored: Fri Sep 8 12:21:53 2017 -0400
Committer: Woonsan Ko <wo...@apache.org>
Committed: Fri Sep 8 12:21:53 2017 -0400
----------------------------------------------------------------------
.../AbstractSpringTemplateCallableModel.java | 11 +-
.../spring/model/BindErrorsDirective.java | 5 +-
.../freemarker/spring/model/EvalFunction.java | 153 +++++++++++++++++++
.../spring/model/MessageFunction.java | 14 +-
.../freemarker/spring/model/MvcUrlFunction.java | 74 +++++++++
.../model/SpringTemplateCallableHashModel.java | 7 +-
.../spring/model/TransformFunction.java | 101 ++++++++++++
.../freemarker/spring/model/UrlFunction.java | 86 +++++++++++
8 files changed, 437 insertions(+), 14 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/234f96ec/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/AbstractSpringTemplateCallableModel.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/AbstractSpringTemplateCallableModel.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/AbstractSpringTemplateCallableModel.java
index de95df5..0d5d6ed 100644
--- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/AbstractSpringTemplateCallableModel.java
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/AbstractSpringTemplateCallableModel.java
@@ -73,14 +73,21 @@ public abstract class AbstractSpringTemplateCallableModel implements TemplateCal
RequestContext requestContext, String path, boolean ignoreNestedPath) throws TemplateException {
final String resolvedPath = (ignoreNestedPath) ? path : resolveNestedPath(env, objectWrapperAndUnwrapper, path);
BindStatus status = requestContext.getBindStatus(resolvedPath, false);
+ return wrapObject(objectWrapperAndUnwrapper, status);
+ }
+
+ protected final Object unwrapObject(ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, TemplateModel model) throws TemplateException {
+ return (model != null) ? objectWrapperAndUnwrapper.unwrap(model) : null;
+ }
- if (status != null) {
+ protected final TemplateModel wrapObject(ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, Object object) throws TemplateException {
+ if (object != null) {
if (!(objectWrapperAndUnwrapper instanceof DefaultObjectWrapper)) {
CallableUtils.newGenericExecuteException("objectWrapperAndUnwrapper is not a DefaultObjectWrapper.",
this, isFunction());
}
- return ((DefaultObjectWrapper) objectWrapperAndUnwrapper).wrap(status);
+ return ((DefaultObjectWrapper) objectWrapperAndUnwrapper).wrap(object);
}
return null;
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/234f96ec/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/BindErrorsDirective.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/BindErrorsDirective.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/BindErrorsDirective.java
index c98db67..e35b6ee 100644
--- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/BindErrorsDirective.java
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/BindErrorsDirective.java
@@ -30,7 +30,6 @@ 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.ObjectWrappingException;
import org.apache.freemarker.core.model.TemplateModel;
import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
import org.apache.freemarker.core.util.CallableUtils;
@@ -104,7 +103,7 @@ public class BindErrorsDirective extends AbstractSpringTemplateDirectiveModel {
}
private final TemplateModel getBindErrorsTemplateModel(Environment env, ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper,
- RequestContext requestContext, String name) throws ObjectWrappingException {
+ RequestContext requestContext, String name) throws TemplateException {
final Errors errors = requestContext.getErrors(name, false);
if (errors != null && errors.hasErrors()) {
@@ -113,7 +112,7 @@ public class BindErrorsDirective extends AbstractSpringTemplateDirectiveModel {
this, isFunction());
}
- return ((DefaultObjectWrapper) objectWrapperAndUnwrapper).wrap(errors);
+ return wrapObject(objectWrapperAndUnwrapper, errors);
}
return null;
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/234f96ec/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/EvalFunction.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/EvalFunction.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/EvalFunction.java
new file mode 100644
index 0000000..a380f19
--- /dev/null
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/EvalFunction.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.spring.model;
+
+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.springframework.context.expression.BeanFactoryResolver;
+import org.springframework.context.expression.EnvironmentAccessor;
+import org.springframework.context.expression.MapAccessor;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.expression.AccessException;
+import org.springframework.expression.EvaluationContext;
+import org.springframework.expression.Expression;
+import org.springframework.expression.ExpressionParser;
+import org.springframework.expression.PropertyAccessor;
+import org.springframework.expression.TypedValue;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
+import org.springframework.expression.spel.support.StandardTypeConverter;
+import org.springframework.web.servlet.support.RequestContext;
+
+/**
+ * A <code>TemplateFunctionModel</code> providing functionality equivalent to the Spring Framework's
+ * <code><spring:eval /></code> JSP Tag Library.
+ * <P>
+ * Some valid example(s):
+ * </P>
+ * <PRE>
+ * </PRE>
+ * <P>
+ * <EM>Note:</EM> Unlike Spring Framework's <code><spring:message /></code> JSP Tag Library, this function
+ * does not support <code>htmlEscape</code> parameter. It always returns the message not to escape HTML's
+ * because it is much easier to control escaping in FreeMarker Template expressions.
+ * </P>
+ */
+public class EvalFunction extends AbstractSpringTemplateFunctionModel {
+
+ public static final String NAME = "eval";
+
+ private static final int EXPRESSION_PARAM_IDX = 0;
+
+ private static final ArgumentArrayLayout ARGS_LAYOUT = ArgumentArrayLayout.create(1, false, null, false);
+
+ private final ExpressionParser expressionParser = new SpelExpressionParser();
+
+ public EvalFunction(HttpServletRequest request, HttpServletResponse response) {
+ super(request, response);
+ }
+
+ @Override
+ public TemplateModel executeInternal(TemplateModel[] args, CallPlace callPlace, Environment env,
+ ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, RequestContext requestContext)
+ throws TemplateException {
+ final String expressionString = CallableUtils.getStringArgument(args, EXPRESSION_PARAM_IDX, this);
+ final Expression expression = expressionParser.parseExpression(expressionString);
+
+ // TODO: cache evaluationContext somewhere in request level....
+ EvaluationContext evaluationContext = createEvaluationContext(env, requestContext);
+
+ final Object result = expression.getValue(evaluationContext);
+ return wrapObject(objectWrapperAndUnwrapper, result);
+ }
+
+ @Override
+ public ArgumentArrayLayout getFunctionArgumentArrayLayout() {
+ return ARGS_LAYOUT;
+ }
+
+ private EvaluationContext createEvaluationContext(final Environment env, final RequestContext requestContext) {
+ StandardEvaluationContext context = new StandardEvaluationContext();
+
+ context.addPropertyAccessor(new EnvironmentVariablesPropertyAccessor(env));
+ context.addPropertyAccessor(new MapAccessor());
+ context.addPropertyAccessor(new EnvironmentAccessor());
+ context.setBeanResolver(new BeanFactoryResolver(requestContext.getWebApplicationContext()));
+
+ ConversionService conversionService = getConversionService();
+
+ if (conversionService != null) {
+ context.setTypeConverter(new StandardTypeConverter(conversionService));
+ }
+
+ return context;
+ }
+
+ private ConversionService getConversionService() {
+ return (ConversionService) getRequest().getAttribute(ConversionService.class.getName());
+ }
+
+ private static class EnvironmentVariablesPropertyAccessor implements PropertyAccessor {
+
+ private final Environment env;
+
+ public EnvironmentVariablesPropertyAccessor(final Environment env) {
+ this.env = env;
+ }
+
+ @Override
+ public Class<?>[] getSpecificTargetClasses() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public void write(EvaluationContext context, Object target, String name, Object newValue)
+ throws AccessException {
+ // TODO Auto-generated method stub
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/234f96ec/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MessageFunction.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MessageFunction.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MessageFunction.java
index 46547a6..94a1e0f 100644
--- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MessageFunction.java
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MessageFunction.java
@@ -33,7 +33,6 @@ import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
import org.apache.freemarker.core.model.TemplateCollectionModel;
import org.apache.freemarker.core.model.TemplateModel;
import org.apache.freemarker.core.model.TemplateModelIterator;
-import org.apache.freemarker.core.model.impl.SimpleString;
import org.apache.freemarker.core.util.CallableUtils;
import org.apache.freemarker.core.util.StringToIndexMap;
import org.apache.freemarker.core.util._StringUtils;
@@ -111,10 +110,10 @@ public class MessageFunction extends AbstractSpringTemplateFunctionModel {
final TemplateModel messageResolvableModel = CallableUtils.getOptionalArgument(args, MESSAGE_RESOLVABLE_PARAM_IDX,
TemplateModel.class, this);
+ final MessageSourceResolvable messageResolvable = (MessageSourceResolvable) unwrapObject(
+ objectWrapperAndUnwrapper, messageResolvableModel);
- if (messageResolvableModel != null) {
- MessageSourceResolvable messageResolvable = (MessageSourceResolvable) objectWrapperAndUnwrapper
- .unwrap(messageResolvableModel);
+ if (messageResolvable != null) {
message = messageSource.getMessage(messageResolvable, requestContext.getLocale());
} else {
final String code = _StringUtils
@@ -127,10 +126,9 @@ public class MessageFunction extends AbstractSpringTemplateFunctionModel {
if (!messageArgsModel.isEmptyCollection()) {
msgArgumentList = new ArrayList<>();
TemplateModel msgArgModel;
- int i = 0;
- for (TemplateModelIterator tit = messageArgsModel.iterator(); tit.hasNext(); i++) {
+ for (TemplateModelIterator tit = messageArgsModel.iterator(); tit.hasNext(); ) {
msgArgModel = tit.next();
- msgArgumentList.add(objectWrapperAndUnwrapper.unwrap(msgArgModel));
+ msgArgumentList.add(unwrapObject(objectWrapperAndUnwrapper, msgArgModel));
}
}
@@ -143,7 +141,7 @@ public class MessageFunction extends AbstractSpringTemplateFunctionModel {
}
}
- return (message != null) ? new SimpleString(message) : null;
+ return wrapObject(objectWrapperAndUnwrapper, message);
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/234f96ec/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MvcUrlFunction.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MvcUrlFunction.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MvcUrlFunction.java
new file mode 100644
index 0000000..047d5c2
--- /dev/null
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/MvcUrlFunction.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.spring.model;
+
+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.StringToIndexMap;
+import org.springframework.web.servlet.support.RequestContext;
+
+/**
+ * A <code>TemplateFunctionModel</code> providing functionality equivalent to the Spring Framework's
+ * <code>spring:mvcUrl</code> JSP Tag Library Function.
+ * <P>
+ * Some valid example(s):
+ * </P>
+ * <PRE>
+ * </PRE>
+ */
+public class MvcUrlFunction extends AbstractSpringTemplateFunctionModel {
+
+ public static final String NAME = "mvcUrl";
+
+ private static final int MAPPING_NAME_PARAM_IDX = 0;
+
+ private static final ArgumentArrayLayout ARGS_LAYOUT =
+ ArgumentArrayLayout.create(
+ 1,
+ false,
+ null,
+ false
+ );
+
+ public MvcUrlFunction(HttpServletRequest request, HttpServletResponse response) {
+ super(request, response);
+ }
+
+ @Override
+ public TemplateModel executeInternal(TemplateModel[] args, CallPlace callPlace, Environment env,
+ ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, RequestContext requestContext)
+ throws TemplateException {
+ // TODO
+ return null;
+ }
+
+ @Override
+ public ArgumentArrayLayout getFunctionArgumentArrayLayout() {
+ return ARGS_LAYOUT;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/234f96ec/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/SpringTemplateCallableHashModel.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/SpringTemplateCallableHashModel.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/SpringTemplateCallableHashModel.java
index dd2f71c..e090cd9 100644
--- a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/SpringTemplateCallableHashModel.java
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/SpringTemplateCallableHashModel.java
@@ -47,11 +47,16 @@ public final class SpringTemplateCallableHashModel implements TemplateHashModel,
private String nestedPath;
public SpringTemplateCallableHashModel(final HttpServletRequest request, final HttpServletResponse response) {
- callablesMap.put(BindDirective.NAME, new BindDirective(request, response));
callablesMap.put(MessageFunction.NAME, new MessageFunction(request, response));
callablesMap.put(ThemeFunction.NAME, new ThemeFunction(request, response));
callablesMap.put(BindErrorsDirective.NAME, new BindErrorsDirective(request, response));
callablesMap.put(NestedPathDirective.NAME, new NestedPathDirective(request, response));
+ callablesMap.put(BindDirective.NAME, new BindDirective(request, response));
+
+ callablesMap.put(TransformFunction.NAME, new TransformFunction(request, response));
+ callablesMap.put(UrlFunction.NAME, new UrlFunction(request, response));
+ callablesMap.put(EvalFunction.NAME, new EvalFunction(request, response));
+ callablesMap.put(MvcUrlFunction.NAME, new MvcUrlFunction(request, response));
}
public TemplateModel get(String key) throws TemplateException {
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/234f96ec/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/TransformFunction.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/TransformFunction.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/TransformFunction.java
new file mode 100644
index 0000000..ee3cc1c
--- /dev/null
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/TransformFunction.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.spring.model;
+
+import java.beans.PropertyEditor;
+
+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.springframework.web.servlet.support.RequestContext;
+
+/**
+ * A <code>TemplateFunctionModel</code> providing functionality equivalent to the Spring Framework's
+ * <code><spring:transform /></code> JSP Tag Library.
+ * <P>
+ * Some valid example(s):
+ * </P>
+ * <PRE>
+ * </PRE>
+ * <P>
+ * Some valid example(s):
+ * </P>
+ * <PRE>
+ * <@spring.bind "user"; status>
+ * ${spring.transform(status, user.birthDate)}
+ * </@spring.bind>
+ * </PRE>
+ * <P>
+ * <EM>Note:</EM> Unlike Spring Framework's <code><spring:bind /></code> JSP Tag Library, this directive
+ * does not support <code>htmlEscape</code> parameter. It always has <code>BindStatus</code> not to escape HTML's
+ * because it is much easier to control escaping in FreeMarker Template expressions.
+ * </P>
+ */
+public class TransformFunction extends AbstractSpringTemplateFunctionModel {
+
+ public static final String NAME = "transform";
+
+ private static final int PROPERTY_EDITOR_PARAM_IDX = 0;
+ private static final int VALUE_PARAM_IDX = 1;
+
+ private static final ArgumentArrayLayout ARGS_LAYOUT = ArgumentArrayLayout.create(2, false, null, false);
+
+ public TransformFunction(HttpServletRequest request, HttpServletResponse response) {
+ super(request, response);
+ }
+
+ @Override
+ public TemplateModel executeInternal(TemplateModel[] args, CallPlace callPlace, Environment env,
+ ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, RequestContext requestContext)
+ throws TemplateException {
+ final TemplateModel editorModel = CallableUtils.getOptionalArgument(args, PROPERTY_EDITOR_PARAM_IDX,
+ TemplateModel.class, this);
+ final PropertyEditor editor = (PropertyEditor) unwrapObject(objectWrapperAndUnwrapper, editorModel);
+
+ final TemplateModel valueModel = CallableUtils.getOptionalArgument(args, VALUE_PARAM_IDX, TemplateModel.class, this);
+ final Object value = unwrapObject(objectWrapperAndUnwrapper, valueModel);
+
+ String valueAsString = null;
+
+ if (value != null) {
+ if (editor != null) {
+ editor.setValue(value);
+ valueAsString = editor.getAsText();
+ } else {
+ valueAsString = value.toString();
+ }
+ }
+
+ return wrapObject(objectWrapperAndUnwrapper, valueAsString);
+ }
+
+ @Override
+ public ArgumentArrayLayout getFunctionArgumentArrayLayout() {
+ return ARGS_LAYOUT;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/234f96ec/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/UrlFunction.java
----------------------------------------------------------------------
diff --git a/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/UrlFunction.java b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/UrlFunction.java
new file mode 100644
index 0000000..402e74d
--- /dev/null
+++ b/freemarker-spring/src/main/java/org/apache/freemarker/spring/model/UrlFunction.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.spring.model;
+
+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.StringToIndexMap;
+import org.springframework.web.servlet.support.RequestContext;
+
+/**
+ * A <code>TemplateFunctionModel</code> providing functionality equivalent to the Spring Framework's
+ * <code><spring:url /></code> JSP Tag Library.
+ * <P>
+ * Some valid example(s):
+ * </P>
+ * <PRE>
+ * </PRE>
+ * <P>
+ * <EM>Note:</EM> Unlike Spring Framework's <code><spring:message /></code> JSP Tag Library, this function
+ * does not support <code>htmlEscape</code> parameter. It always returns the message not to escape HTML's
+ * because it is much easier to control escaping in FreeMarker Template expressions.
+ * </P>
+ */
+public class UrlFunction extends AbstractSpringTemplateFunctionModel {
+
+ public static final String NAME = "url";
+
+ private static final int VALUE_PARAM_IDX = 0;
+ private static final int CONTEXT_PARAM_IDX = 1;
+
+ private static final String CONTEXT_PARAM_NAME = "context";
+
+
+ // TODO: How to deal with parameters (spring:param tags)??
+
+
+ private static final ArgumentArrayLayout ARGS_LAYOUT =
+ ArgumentArrayLayout.create(
+ 1,
+ false,
+ StringToIndexMap.of(CONTEXT_PARAM_NAME, CONTEXT_PARAM_IDX),
+ false
+ );
+
+ public UrlFunction(HttpServletRequest request, HttpServletResponse response) {
+ super(request, response);
+ }
+
+ @Override
+ public TemplateModel executeInternal(TemplateModel[] args, CallPlace callPlace, Environment env,
+ ObjectWrapperAndUnwrapper objectWrapperAndUnwrapper, RequestContext requestContext)
+ throws TemplateException {
+ // TODO
+ return null;
+ }
+
+ @Override
+ public ArgumentArrayLayout getFunctionArgumentArrayLayout() {
+ return ARGS_LAYOUT;
+ }
+
+}