package org.jboss.seam.test.unit; import static org.testng.Assert.assertEquals; import java.beans.FeatureDescriptor; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.el.ELContext; import javax.el.ELResolver; import javax.el.PropertyNotFoundException; import javax.faces.application.Application; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import javax.faces.event.PhaseId; import org.jboss.seam.contexts.FacesLifecycle; import org.jboss.seam.core.Expressions; import org.jboss.seam.faces.FacesExpressions; import org.jboss.seam.mock.MockApplication; import org.jboss.seam.mock.MockExternalContext; import org.jboss.seam.mock.MockFacesContext; import org.jboss.seam.mock.MockHttpServletRequest; import org.jboss.seam.mock.MockHttpSession; import org.testng.annotations.Test; public class ExpressionsTest { /** * Validate that FacesExpressions reports that the FacesContext is activate and * returns the Faces-aware EL context so that a Faces-specific expression can * be resolved through Seam's built-in expression resolver. * @jira JBSEAM-3674 */ @Test public void testExpressionResolvedInFacesELContext() { Map<String, String> params = new HashMap<String, String>(); params.put("foo", "bar"); FacesContext facesContext = setupFacesContextToAccessRequestParams(params); String expr = "#{param.foo}"; // the control assertEquals(facesContext.getApplication().evaluateExpressionGet(facesContext, expr, Object.class), "bar"); // the test FacesLifecycle.setPhaseId(PhaseId.INVOKE_APPLICATION); Expressions expressions = new FacesExpressions(); assert expressions.getELContext().getContext(FacesContext.class) != null; assertEquals(expressions.createValueExpression(expr).getValue(), "bar"); } protected FacesContext setupFacesContextToAccessRequestParams(Map<String, String> params) { MockHttpServletRequest request = new MockHttpServletRequest(new MockHttpSession()); if (params != null) { for (Map.Entry<String, String> param : params.entrySet()) { request.getParameterMap().put(param.getKey(), new String[] { param.getValue() }); } } ExternalContext extContext = new MockExternalContext(request); Application application = new MockApplication(); application.addELResolver(new ImplicitObjectELResolver()); FacesContext facesCtx = new MockFacesContext(extContext, application).setCurrent(); assert FacesContext.getCurrentInstance() != null; return facesCtx; } /** * This resolver resolves select implicit objects that are available to the EL during a Faces request. * It must be implemented here since it is part of the JSF RI, not the API. */ class ImplicitObjectELResolver extends ELResolver { private final String PARAM = "param"; private final String[] IMPLICIT_OBJECT_NAMES = new String[] { PARAM }; @Override public Class<?> getCommonPropertyType(ELContext ctx, Object base) { return null; } @Override public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext ctx, Object base) { return null; } @Override public Class<?> getType(ELContext ctx, Object base, Object prop) { return null; } @Override public Object getValue(ELContext elCtx, Object base, Object prop) { if (base != null) return null; if (prop == null) throw new PropertyNotFoundException("No such property " + prop); int idx = Arrays.binarySearch(IMPLICIT_OBJECT_NAMES, prop); if (idx < 0) return null; FacesContext facesCtx = (FacesContext) elCtx.getContext(FacesContext.class); ExternalContext extCtx = facesCtx.getExternalContext(); if (prop.equals(PARAM)) { elCtx.setPropertyResolved(true); return extCtx.getRequestParameterMap(); } throw new IllegalStateException("Programming error: list of possible conditions is incomplete"); } @Override public boolean isReadOnly(ELContext ctx, Object base, Object prop) { return true; } @Override public void setValue(ELContext ctx, Object base, Object prop, Object value) {} } }