diff --git a/spring-webflow/pom.xml b/spring-webflow/pom.xml index 76e80ac2..6b3358f9 100644 --- a/spring-webflow/pom.xml +++ b/spring-webflow/pom.xml @@ -5,7 +5,7 @@ spring-webflow jar Spring Web Flow - 2.0-m4-SNAPSHOT + 2.0-m4 Spring Web Flow http://www.springframework.org @@ -107,7 +107,7 @@ true - org.springframework + org.springframework.security spring-security-core 2.0-M2 true diff --git a/spring-webflow/src/main/java/org/springframework/webflow/expression/WebFlowOgnlExpressionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/expression/WebFlowOgnlExpressionParser.java index adefc92b..021e7d01 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/expression/WebFlowOgnlExpressionParser.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/expression/WebFlowOgnlExpressionParser.java @@ -21,9 +21,15 @@ import ognl.ObjectPropertyAccessor; import ognl.OgnlException; import ognl.PropertyAccessor; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.binding.collection.MapAdaptable; import org.springframework.binding.expression.ognl.OgnlExpressionParser; +import org.springframework.security.context.SecurityContextHolder; +import org.springframework.util.ClassUtils; import org.springframework.webflow.core.collection.MutableAttributeMap; +import org.springframework.webflow.engine.AnnotatedAction; +import org.springframework.webflow.execution.Action; import org.springframework.webflow.execution.RequestContext; /** @@ -37,16 +43,12 @@ public class WebFlowOgnlExpressionParser extends OgnlExpressionParser { * Creates a webflow-specific ognl expression parser. */ public WebFlowOgnlExpressionParser() { - addPropertyAccessor(RequestContext.class, new RequestContextPropertyAccessor(new ObjectPropertyAccessor())); addPropertyAccessor(MapAdaptable.class, new MapAdaptablePropertyAccessor()); addPropertyAccessor(MutableAttributeMap.class, new MutableAttributeMapPropertyAccessor()); + addPropertyAccessor(RequestContext.class, new RequestContextPropertyAccessor(new ObjectPropertyAccessor())); + addPropertyAccessor(Action.class, new ActionPropertyAccessor()); } - /** - * The {@link MapAdaptable} property accessor. - * - * @author Keith Donald - */ private static class MapAdaptablePropertyAccessor implements PropertyAccessor { public Object getProperty(Map context, Object target, Object name) throws OgnlException { return ((MapAdaptable) target).asMap().get(name); @@ -58,11 +60,6 @@ public class WebFlowOgnlExpressionParser extends OgnlExpressionParser { } } - /** - * The {@link MutableAttributeMap} property accessor. - * - * @author Keith Donald - */ private static class MutableAttributeMapPropertyAccessor extends MapAdaptablePropertyAccessor { public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { ((MutableAttributeMap) target).put((String) name, value); @@ -70,6 +67,12 @@ public class WebFlowOgnlExpressionParser extends OgnlExpressionParser { } private static class RequestContextPropertyAccessor implements PropertyAccessor { + + private static boolean securityPresent = ClassUtils + .isPresent("org.springframework.security.context.SecurityContextHolder"); + + private static final BeanFactory EMPTY_BEAN_FACTORY = new StaticListableBeanFactory(); + private PropertyAccessor delegate; public RequestContextPropertyAccessor(PropertyAccessor delegate) { @@ -79,6 +82,16 @@ public class WebFlowOgnlExpressionParser extends OgnlExpressionParser { public Object getProperty(Map context, Object target, Object name) throws OgnlException { String property = name.toString(); RequestContext requestContext = (RequestContext) target; + if (property.equals("flowRequestContext")) { + return requestContext; + } + if (securityPresent && property.equals("currentUser")) { + if (SecurityContextHolder.getContext() != null) { + return SecurityContextHolder.getContext().getAuthentication(); + } else { + return null; + } + } if (requestContext.getRequestScope().contains(property)) { return requestContext.getRequestScope().get(property); } else if (requestContext.getFlashScope().contains(property)) { @@ -87,14 +100,39 @@ public class WebFlowOgnlExpressionParser extends OgnlExpressionParser { return requestContext.getFlowScope().get(property); } else if (requestContext.getConversationScope().contains(property)) { return requestContext.getConversationScope().get(property); - } else { - return delegate.getProperty(context, target, name); } + BeanFactory bf = getBeanFactory(requestContext); + if (bf.containsBean(property)) { + return bf.getBean(property); + } + return delegate.getProperty(context, target, name); } public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { delegate.setProperty(context, target, name, value); } + private BeanFactory getBeanFactory(RequestContext requestContext) { + if (requestContext.getActiveFlow().getBeanFactory() != null) { + BeanFactory factory = requestContext.getActiveFlow().getBeanFactory(); + return factory; + } else { + return EMPTY_BEAN_FACTORY; + } + } } + + private static class ActionPropertyAccessor implements PropertyAccessor { + public Object getProperty(Map context, Object target, Object name) throws OgnlException { + Action action = (Action) target; + AnnotatedAction annotated = new AnnotatedAction(action); + annotated.setMethod(name.toString()); + return annotated; + } + + public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { + throw new OgnlException("Cannot set properties on a Action instance - operation not allowed"); + } + } + } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/expression/el/WebFlowELExpressionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/expression/el/WebFlowELExpressionParser.java index ba5b8fb3..0428ea97 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/expression/el/WebFlowELExpressionParser.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/expression/el/WebFlowELExpressionParser.java @@ -25,6 +25,9 @@ import org.springframework.webflow.execution.RequestContext; */ public class WebFlowELExpressionParser extends ELExpressionParser { + private static boolean securityPresent = ClassUtils + .isPresent("org.springframework.security.context.SecurityContextHolder"); + public WebFlowELExpressionParser(ExpressionFactory expressionFactory) { super(expressionFactory); putContextFactory(RequestContext.class, new RequestContextELContextFactory()); @@ -36,13 +39,13 @@ public class WebFlowELExpressionParser extends ELExpressionParser { RequestContext context = (RequestContext) target; List customResolvers = new ArrayList(); customResolvers.add(new RequestContextELResolver(context)); - customResolvers.add(new ImplicitFlowVariableELResolver(context)); - customResolvers.add(new ScopeSearchingELResolver(context)); - customResolvers.add(new ActionMethodELResolver()); - if (ClassUtils.isPresent("org.springframework.security.context.SecurityContextHolder")) { + if (securityPresent) { customResolvers.add(new SpringSecurityELResolver()); } + customResolvers.add(new ImplicitFlowVariableELResolver(context)); + customResolvers.add(new ScopeSearchingELResolver(context)); customResolvers.add(new SpringBeanWebFlowELResolver(context)); + customResolvers.add(new ActionMethodELResolver()); ELResolver resolver = new DefaultELResolver(null, customResolvers); return new WebFlowELContext(resolver); } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/support/TextToTargetStateResolverTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/support/TextToTargetStateResolverTests.java index 87ff4aa2..a8834121 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/support/TextToTargetStateResolverTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/support/TextToTargetStateResolverTests.java @@ -39,7 +39,7 @@ public class TextToTargetStateResolverTests extends TestCase { } public void testDynamic() { - String expression = "#{flowScope.lastState}"; + String expression = "${flowScope.lastState}"; TargetStateResolver resolver = (TargetStateResolver) converter.convert(expression); MockRequestContext context = new MockRequestContext(); context.getFlowScope().put("lastState", "mockState");