revised EvalTag implementation

This commit is contained in:
Juergen Hoeller 2010-02-16 18:16:47 +00:00
parent 4ae1709313
commit 64fc4c23ea
6 changed files with 81 additions and 79 deletions

View File

@ -38,7 +38,7 @@ import org.springframework.util.ClassUtils;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.servlet.handler.ConversionServiceHandlerInterceptor;
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
import org.springframework.web.servlet.handler.MappedInterceptor;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
import org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping;
@ -112,7 +112,7 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
annAdapterDef.getPropertyValues().add("messageConverters", getMessageConverters(source));
String annAdapterName = parserContext.getReaderContext().registerWithGeneratedName(annAdapterDef);
RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceHandlerInterceptor.class);
RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class);
csInterceptorDef.setSource(source);
csInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, conversionService);
RootBeanDefinition mappedCsInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 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 @@
package org.springframework.web.servlet.handler;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -26,28 +25,35 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.util.Assert;
/**
* Interceptor that places the configured {@link ConversionService} in request scope so it's available during request processing.
* Mainly for use within JSP tags such as the spring:eval tag.
* The request attribute name is "org.springframework.core.convert.ConversionService", the value of ConversionService.class.getName();
* Interceptor that places the configured {@link ConversionService} in request scope
* so it's available during request processing. The request attribute name is
* "org.springframework.core.convert.ConversionService", the value of
* <code>ConversionService.class.getName()</code>.
*
* <p>Mainly for use within JSP tags such as the spring:eval tag.
*
* @author Keith Donald
* @since 3.0.1
*/
public class ConversionServiceHandlerInterceptor extends HandlerInterceptorAdapter {
public class ConversionServiceExposingInterceptor extends HandlerInterceptorAdapter {
private final ConversionService conversionService;
/**
* Creates a new {@link ConversionServiceHandlerInterceptor}.
* @param conversionService the conversion service to export to request scope when this interceptor is invoked.
* Creates a new {@link ConversionServiceExposingInterceptor}.
* @param conversionService the conversion service to export to request scope when this interceptor is invoked
*/
public ConversionServiceHandlerInterceptor(ConversionService conversionService) {
public ConversionServiceExposingInterceptor(ConversionService conversionService) {
Assert.notNull(conversionService, "The ConversionService may not be null");
this.conversionService = conversionService;
}
@Override
public final boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws ServletException, IOException {
request.setAttribute(ConversionService.class.getName(), this.conversionService);
return true;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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,12 +17,9 @@
package org.springframework.web.servlet.tags;
import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.el.ELException;
import org.springframework.beans.BeansException;
import org.springframework.core.convert.ConversionService;
import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext;
@ -47,9 +44,11 @@ import org.springframework.web.util.TagUtils;
*/
public class EvalTag extends HtmlEscapingAwareTag {
private ExpressionParser expressionParser;
private final ExpressionParser expressionParser = new SpelExpressionParser();
private String expression;
private EvaluationContext evaluationContext;
private Expression expression;
private String var;
@ -57,11 +56,18 @@ public class EvalTag extends HtmlEscapingAwareTag {
private boolean javaScriptEscape = false;
@Override
public void setPageContext(PageContext pageContext) {
super.setPageContext(pageContext);
this.evaluationContext = createEvaluationContext(pageContext);
}
/**
* Set the expression to evaluate.
*/
public void setExpression(String expression) {
this.expression = expression;
this.expression = this.expressionParser.parseExpression(expression);
}
/**
@ -89,55 +95,51 @@ public class EvalTag extends HtmlEscapingAwareTag {
ExpressionEvaluationUtils.evaluateBoolean("javaScriptEscape", javaScriptEscape, this.pageContext);
}
@Override
public int doStartTagInternal() throws JspException {
this.expressionParser = new SpelExpressionParser();
return EVAL_BODY_INCLUDE;
}
@Override
public int doEndTag() throws JspException {
Expression expression = this.expressionParser.parseExpression(this.expression);
EvaluationContext context = createEvaluationContext();
if (this.var == null) {
try {
String result = expression.getValue(context, String.class);
String result = this.expression.getValue(this.evaluationContext, String.class);
result = isHtmlEscape() ? HtmlUtils.htmlEscape(result) : result;
result = this.javaScriptEscape ? JavaScriptUtils.javaScriptEscape(result) : result;
pageContext.getOut().print(result);
}
catch (IOException e) {
throw new JspException(e);
catch (IOException ex) {
throw new JspException(ex);
}
}
else {
Object result = expression.getValue(context);
pageContext.setAttribute(var, result, scope);
Object result = this.expression.getValue(this.evaluationContext);
pageContext.setAttribute(this.var, result, this.scope);
}
return EVAL_PAGE;
}
private EvaluationContext createEvaluationContext() {
private EvaluationContext createEvaluationContext(PageContext pageContext) {
StandardEvaluationContext context = new StandardEvaluationContext();
context.addPropertyAccessor(new JspPropertyAccessor(this.pageContext));
ConversionService conversionService = getConversionService();
context.addPropertyAccessor(new JspPropertyAccessor(pageContext));
ConversionService conversionService = getConversionService(pageContext);
if (conversionService != null) {
context.setTypeConverter(new StandardTypeConverter(conversionService));
}
return context;
}
private ConversionService getConversionService() {
try {
return (ConversionService) this.pageContext.getRequest().getAttribute(ConversionService.class.getName());
} catch (BeansException e) {
return null;
}
private ConversionService getConversionService(PageContext pageContext) {
return (ConversionService) pageContext.getRequest().getAttribute(ConversionService.class.getName());
}
private static class JspPropertyAccessor implements PropertyAccessor {
private PageContext pageContext;
private final PageContext pageContext;
public JspPropertyAccessor(PageContext pageContext) {
this.pageContext = pageContext;
@ -147,17 +149,11 @@ public class EvalTag extends HtmlEscapingAwareTag {
return null;
}
public boolean canRead(EvaluationContext context, Object target,
String name) throws AccessException {
Object implicitVar = resolveImplicitVariable(name);
if (implicitVar != null) {
return true;
}
return this.pageContext.findAttribute(name) != null;
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
return (resolveImplicitVariable(name) != null || this.pageContext.findAttribute(name) != null);
}
public TypedValue read(EvaluationContext context, Object target,
String name) throws AccessException {
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
Object implicitVar = resolveImplicitVariable(name);
if (implicitVar != null) {
return new TypedValue(implicitVar);
@ -165,24 +161,23 @@ public class EvalTag extends HtmlEscapingAwareTag {
return new TypedValue(this.pageContext.findAttribute(name));
}
public boolean canWrite(EvaluationContext context, Object target,
String name) throws AccessException {
public boolean canWrite(EvaluationContext context, Object target, String name) {
return false;
}
public void write(EvaluationContext context, Object target,
String name, Object newValue) throws AccessException {
public void write(EvaluationContext context, Object target, String name, Object newValue) {
throw new UnsupportedOperationException();
}
private Object resolveImplicitVariable(String name) throws AccessException {
try {
return this.pageContext.getVariableResolver().resolveVariable(name);
} catch (ELException e) {
throw new AccessException("Unexpected exception occurred accessing '" + name + "' as an implicit variable", e);
}
catch (Exception ex) {
throw new AccessException(
"Unexpected exception occurred accessing '" + name + "' as an implicit variable", ex);
}
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2006 the original author or authors.
* Copyright 2002-2010 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.
@ -47,9 +47,10 @@ import org.springframework.web.servlet.support.RequestContext;
*/
public abstract class RequestContextAwareTag extends TagSupport implements TryCatchFinally {
/** {@link javax.servlet.jsp.PageContext} attribute for page-level
/**
* {@link javax.servlet.jsp.PageContext} attribute for page-level
* {@link RequestContext} instance.
* */
*/
public static final String REQUEST_CONTEXT_PAGE_ATTRIBUTE =
"org.springframework.web.servlet.tags.REQUEST_CONTEXT";

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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.
@ -53,7 +53,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.ConversionServiceHandlerInterceptor;
import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
@ -115,8 +115,8 @@ public class MvcNamespaceTests {
HandlerExecutionChain chain = mapping.getHandler(request);
assertEquals(2, chain.getInterceptors().length);
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceHandlerInterceptor);
ConversionServiceHandlerInterceptor interceptor = (ConversionServiceHandlerInterceptor) chain.getInterceptors()[1];
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor);
ConversionServiceExposingInterceptor interceptor = (ConversionServiceExposingInterceptor) chain.getInterceptors()[1];
interceptor.preHandle(request, response, handler);
assertSame(appContext.getBean(ConversionService.class), request.getAttribute(ConversionService.class.getName()));
@ -144,8 +144,8 @@ public class MvcNamespaceTests {
HandlerExecutionChain chain = mapping.getHandler(request);
assertEquals(2, chain.getInterceptors().length);
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceHandlerInterceptor);
ConversionServiceHandlerInterceptor interceptor = (ConversionServiceHandlerInterceptor) chain.getInterceptors()[1];
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor);
ConversionServiceExposingInterceptor interceptor = (ConversionServiceExposingInterceptor) chain.getInterceptors()[1];
interceptor.preHandle(request, response, handler);
assertSame(appContext.getBean("conversionService"), request.getAttribute(ConversionService.class.getName()));
@ -194,7 +194,7 @@ public class MvcNamespaceTests {
HandlerExecutionChain chain = mapping.getHandler(request);
assertEquals(4, chain.getInterceptors().length);
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceHandlerInterceptor);
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor);
assertTrue(chain.getInterceptors()[2] instanceof LocaleChangeInterceptor);
assertTrue(chain.getInterceptors()[3] instanceof ThemeChangeInterceptor);
@ -225,7 +225,7 @@ public class MvcNamespaceTests {
HandlerExecutionChain chain = mapping.getHandler(request);
assertEquals(4, chain.getInterceptors().length);
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceHandlerInterceptor);
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor);
assertTrue(chain.getInterceptors()[2] instanceof LocaleChangeInterceptor);
assertTrue(chain.getInterceptors()[3] instanceof ThemeChangeInterceptor);
LocaleChangeInterceptor interceptor = (LocaleChangeInterceptor) chain.getInterceptors()[2];
@ -249,7 +249,7 @@ public class MvcNamespaceTests {
HandlerExecutionChain chain = mapping.getHandler(request);
assertEquals(4, chain.getInterceptors().length);
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceHandlerInterceptor);
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor);
assertTrue(chain.getInterceptors()[2] instanceof LocaleChangeInterceptor);
assertTrue(chain.getInterceptors()[3] instanceof ThemeChangeInterceptor);
@ -263,7 +263,7 @@ public class MvcNamespaceTests {
request.setMethod("GET");
chain = mapping2.getHandler(request);
assertEquals(4, chain.getInterceptors().length);
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceHandlerInterceptor);
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor);
assertTrue(chain.getInterceptors()[2] instanceof LocaleChangeInterceptor);
assertTrue(chain.getInterceptors()[3] instanceof ThemeChangeInterceptor);
ModelAndView mv = adapter.handle(request, new MockHttpServletResponse(), chain.getHandler());
@ -272,7 +272,7 @@ public class MvcNamespaceTests {
request.setRequestURI("/bar");
chain = mapping2.getHandler(request);
assertEquals(4, chain.getInterceptors().length);
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceHandlerInterceptor);
assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor);
assertTrue(chain.getInterceptors()[2] instanceof LocaleChangeInterceptor);
assertTrue(chain.getInterceptors()[3] instanceof ThemeChangeInterceptor);
ModelAndView mv2 = adapter.handle(request, new MockHttpServletResponse(), chain.getHandler());

View File

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