From 60fcba39c5e449c865851e000f7c47e4ce83b080 Mon Sep 17 00:00:00 2001 From: Jeremy Grelle Date: Tue, 19 Feb 2008 19:06:06 +0000 Subject: [PATCH] SWF-301 - Make JSF managed beans accessible inside a flow definition using EL expressions --- .../expression/LegacyJSFBeanResolver.java | 93 +++++++++++++++++++ .../LegacyJSFELExpressionParser.java | 73 +++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 spring-faces/src/main/java/org/springframework/faces/expression/LegacyJSFBeanResolver.java create mode 100644 spring-faces/src/main/java/org/springframework/faces/expression/LegacyJSFELExpressionParser.java diff --git a/spring-faces/src/main/java/org/springframework/faces/expression/LegacyJSFBeanResolver.java b/spring-faces/src/main/java/org/springframework/faces/expression/LegacyJSFBeanResolver.java new file mode 100644 index 00000000..ceadc25c --- /dev/null +++ b/spring-faces/src/main/java/org/springframework/faces/expression/LegacyJSFBeanResolver.java @@ -0,0 +1,93 @@ +package org.springframework.faces.expression; + +import java.util.Iterator; + +import javax.el.ELContext; +import javax.el.ELResolver; + +import org.springframework.webflow.execution.RequestContext; +import org.springframework.webflow.execution.RequestContextHolder; + +/** + * ELResolver that checks request, session, and application scopes for existing JSF-managed beans. This allows + * traditional JSF-managed beans (defined in faces-config.xml) to be resolved through expressions in a flow definition. + * The preferred approach is to instead use Spring to configure such beans, but this is meant to ease migration for + * users with existing JSF artifacts. Note that this resolver does not have access to the JSF managed bean definitions + * and will not trigger the bean's instantiation if it has not already been initialized by JSF. + * + * @author Jeremy Grelle + */ +public class LegacyJSFBeanResolver extends ELResolver { + + public Class getCommonPropertyType(ELContext context, Object base) { + return Object.class; + } + + public Iterator getFeatureDescriptors(ELContext context, Object base) { + return null; + } + + public Class getType(ELContext context, Object base, Object property) { + if (base == null) { + RequestContext requestContext = RequestContextHolder.getRequestContext(); + if (requestContext.getExternalContext().getRequestMap().contains(property.toString())) { + context.setPropertyResolved(true); + return requestContext.getExternalContext().getRequestMap().get(property.toString()).getClass(); + } else if (requestContext.getExternalContext().getSessionMap().contains(property.toString())) { + context.setPropertyResolved(true); + return requestContext.getExternalContext().getSessionMap().get(property.toString()).getClass(); + } else if (requestContext.getExternalContext().getApplicationMap().contains(property.toString())) { + context.setPropertyResolved(true); + return requestContext.getExternalContext().getApplicationMap().get(property.toString()).getClass(); + } + } + return null; + } + + public Object getValue(ELContext context, Object base, Object property) { + if (base == null) { + RequestContext requestContext = RequestContextHolder.getRequestContext(); + if (requestContext.getExternalContext().getRequestMap().contains(property.toString())) { + context.setPropertyResolved(true); + return requestContext.getExternalContext().getRequestMap().get(property.toString()); + } else if (requestContext.getExternalContext().getSessionMap().contains(property.toString())) { + context.setPropertyResolved(true); + return requestContext.getExternalContext().getSessionMap().get(property.toString()); + } else if (requestContext.getExternalContext().getApplicationMap().contains(property.toString())) { + context.setPropertyResolved(true); + return requestContext.getExternalContext().getApplicationMap().get(property.toString()); + } + } + return null; + } + + public boolean isReadOnly(ELContext context, Object base, Object property) { + if (base == null) { + RequestContext requestContext = RequestContextHolder.getRequestContext(); + if (requestContext.getExternalContext().getRequestMap().contains(property.toString()) + || requestContext.getExternalContext().getSessionMap().contains(property.toString()) + || requestContext.getExternalContext().getApplicationMap().contains(property.toString())) { + context.setPropertyResolved(true); + return true; + } + } + return false; + } + + public void setValue(ELContext context, Object base, Object property, Object value) { + if (base == null) { + RequestContext requestContext = RequestContextHolder.getRequestContext(); + if (requestContext.getExternalContext().getRequestMap().contains(property.toString())) { + context.setPropertyResolved(true); + requestContext.getExternalContext().getRequestMap().put(property.toString(), value); + } else if (requestContext.getExternalContext().getSessionMap().contains(property.toString())) { + context.setPropertyResolved(true); + requestContext.getExternalContext().getSessionMap().put(property.toString(), value); + } else if (requestContext.getExternalContext().getApplicationMap().contains(property.toString())) { + context.setPropertyResolved(true); + requestContext.getExternalContext().getApplicationMap().put(property.toString(), value); + } + } + } + +} diff --git a/spring-faces/src/main/java/org/springframework/faces/expression/LegacyJSFELExpressionParser.java b/spring-faces/src/main/java/org/springframework/faces/expression/LegacyJSFELExpressionParser.java new file mode 100644 index 00000000..ed89d0e6 --- /dev/null +++ b/spring-faces/src/main/java/org/springframework/faces/expression/LegacyJSFELExpressionParser.java @@ -0,0 +1,73 @@ +package org.springframework.faces.expression; + +import java.util.ArrayList; +import java.util.List; + +import javax.el.ELContext; +import javax.el.ELResolver; +import javax.el.ExpressionFactory; +import javax.el.FunctionMapper; +import javax.el.VariableMapper; + +import org.springframework.binding.expression.el.DefaultELResolver; +import org.springframework.binding.expression.el.ELContextFactory; +import org.springframework.binding.expression.el.ELExpressionParser; +import org.springframework.webflow.core.collection.MutableAttributeMap; +import org.springframework.webflow.core.expression.el.RequestContextELResolver; +import org.springframework.webflow.core.expression.el.ScopeSearchingELResolver; +import org.springframework.webflow.execution.RequestContext; + +/** + * A JSF-specific ExpressionParser that allows beans managed by either JSF, Spring, or Web Flow referenced in + * expressions in the FlowDefinition. + * + * @author Jeremy Grelle + */ +public class LegacyJSFELExpressionParser extends ELExpressionParser { + + public LegacyJSFELExpressionParser(ExpressionFactory expressionFactory) { + super(expressionFactory); + putContextFactory(RequestContext.class, new RequestContextELContextFactory()); + putContextFactory(MutableAttributeMap.class, new AttributeMapELContextFactory()); + } + + private static class RequestContextELContextFactory implements ELContextFactory { + public ELContext getELContext(Object target) { + List customResolvers = new ArrayList(); + customResolvers.add(new RequestContextELResolver()); + customResolvers.add(new ScopeSearchingELResolver()); + customResolvers.add(new LegacyJSFBeanResolver()); + ELResolver resolver = new DefaultELResolver(target, customResolvers); + return new WebFlowELContext(resolver); + } + } + + private static class AttributeMapELContextFactory implements ELContextFactory { + public ELContext getELContext(Object target) { + ELResolver resolver = new DefaultELResolver(target, null); + return new WebFlowELContext(resolver); + } + } + + private static class WebFlowELContext extends ELContext { + + private ELResolver resolver; + + public WebFlowELContext(ELResolver resolver) { + this.resolver = resolver; + } + + public ELResolver getELResolver() { + return resolver; + } + + public FunctionMapper getFunctionMapper() { + return null; + } + + public VariableMapper getVariableMapper() { + return null; + } + } + +}