001/*
002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Anahide Tchertchian
016 */
017package org.nuxeo.ecm.platform.actions.jsf;
018
019import javax.el.ELContext;
020import javax.el.ELException;
021import javax.el.ExpressionFactory;
022import javax.el.ValueExpression;
023import javax.el.VariableMapper;
024import javax.faces.context.FacesContext;
025
026import org.apache.commons.lang.StringUtils;
027import org.nuxeo.ecm.core.api.DocumentModel;
028import org.nuxeo.ecm.core.api.NuxeoPrincipal;
029import org.nuxeo.ecm.platform.actions.AbstractActionContext;
030import org.nuxeo.ecm.platform.actions.ActionContext;
031import org.nuxeo.ecm.platform.ui.web.util.SeamContextHelper;
032
033/**
034 * @since 5.7.3
035 */
036public class JSFActionContext extends AbstractActionContext implements ActionContext {
037
038    private static final long serialVersionUID = 1L;
039
040    protected final ELContext originalContext;
041
042    protected final ExpressionFactory expressionFactory;
043
044    public JSFActionContext(FacesContext faces) {
045        super();
046        this.originalContext = faces.getELContext();
047        this.expressionFactory = faces.getApplication().getExpressionFactory();
048    }
049
050    public JSFActionContext(ELContext originalContext, ExpressionFactory expressionFactory) {
051        super();
052        this.originalContext = originalContext;
053        this.expressionFactory = expressionFactory;
054    }
055
056    @Override
057    public boolean checkCondition(String expression) throws ELException {
058        if (StringUtils.isBlank(expression) || (expression != null && StringUtils.isBlank(expression.trim()))) {
059            return false;
060        }
061        String expr = expression.trim();
062        // compatibility code, as JEXL could resolve that kind of expression:
063        // detect if expression is in brackets #{}, otherwise add it
064        if (!expr.startsWith("#{") && !expr.startsWith("${")
065        // don't confuse error messages in case of simple mistakes in the
066        // expression
067                && !expr.endsWith("}")) {
068            expr = "#{" + expr + "}";
069        }
070        ELContext finalContext = new JSFELContext(originalContext);
071        VariableMapper vm = finalContext.getVariableMapper();
072        // init default variables
073        ValueExpression documentExpr = expressionFactory.createValueExpression(getCurrentDocument(),
074                DocumentModel.class);
075        ValueExpression userExpr = expressionFactory.createValueExpression(getCurrentPrincipal(), NuxeoPrincipal.class);
076        // add variables originally exposed by the action framework,
077        // do not add aliases currentDocument and currentUser here as they
078        // should already be available in this JSF context
079        vm.setVariable("document", documentExpr);
080        vm.setVariable("principal", userExpr);
081        // get custom context from ActionContext
082        for (String key : localVariables.keySet()) {
083            vm.setVariable(key, expressionFactory.createValueExpression(getLocalVariable(key), Object.class));
084        }
085        // expose Seam context for compatibility, although available its
086        // components should be natively exposed in this JSF context
087        putLocalVariable("SeamContext", new SeamContextHelper());
088
089        // evaluate expression
090        ValueExpression ve = expressionFactory.createValueExpression(finalContext, expr, Boolean.class);
091        return Boolean.TRUE.equals(ve.getValue(finalContext));
092    }
093
094}