/* * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and contributors. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser General Public License * (LGPL) version 2.1 which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl-2.1.html * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * Contributors: * Anahide Tchertchian */ package org.nuxeo.ecm.platform.ui.web.binding; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.el.ELException; import javax.el.ValueExpression; import javax.el.VariableMapper; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jboss.el.ValueExpressionLiteral; import org.nuxeo.ecm.platform.ui.web.binding.alias.AliasVariableMapper; /** * Alternative to {@link AliasVariableMapper} optimized behavior. * <p> * Keeps variables in the current context, but without aliasing variables for efficiency. Compared to the standard * variable mappers, adds blocking features, given patterns, to allow compartmenting variables contexts (inside layout * widget trees for instance). * * @since 8.2 */ public class BlockingVariableMapper extends VariableMapper { private static final Log log = LogFactory.getLog(BlockingVariableMapper.class); protected final VariableMapper orig; protected Map<String, ValueExpression> vars; protected List<String> blockedPatterns; public BlockingVariableMapper(VariableMapper orig) { super(); this.orig = orig; } @Override public ValueExpression resolveVariable(String variable) { ValueExpression ve = null; try { if (hasVariable(variable)) { ve = (ValueExpression) vars.get(variable); } else { // resolve to a value expression resolving to null if variable // is supposed to be blocked if (variable != null && blockedPatterns != null) { for (String blockedPattern : blockedPatterns) { if (StringUtils.isBlank(blockedPattern)) { continue; } boolean doBlock = false; if (blockedPattern.endsWith("*")) { String pattern = blockedPattern.substring(0, blockedPattern.length() - 1); if (variable.startsWith(pattern)) { doBlock = true; } } else if (blockedPattern.equals(variable)) { doBlock = true; } if (doBlock) { if (log.isDebugEnabled()) { log.debug(String.format("Blocked expression var='%s'", variable)); } return getNullValueExpression(); } } } return orig.resolveVariable(variable); } return ve; } catch (StackOverflowError e) { throw new ELException("Could not Resolve Variable [Overflow]: " + variable, e); } } @Override public ValueExpression setVariable(String variable, ValueExpression expression) { if (vars == null) { vars = new LinkedHashMap<String, ValueExpression>(); } return vars.put(variable, expression); } public boolean hasVariable(String variable) { return vars != null && vars.containsKey(variable); } protected ValueExpression getNullValueExpression() { return new ValueExpressionLiteral(null, Object.class); } public Map<String, ValueExpression> getVariables() { return vars; } public List<String> getBlockedPatterns() { return blockedPatterns; } public void setBlockedPatterns(List<String> blockedPatterns) { if (blockedPatterns != null) { this.blockedPatterns = new ArrayList<String>(); this.blockedPatterns.addAll(blockedPatterns); } else { this.blockedPatterns = null; } } public void addBlockedPattern(String blockedPattern) { if (StringUtils.isBlank(blockedPattern)) { return; } if (this.blockedPatterns == null) { this.blockedPatterns = new ArrayList<String>(); } this.blockedPatterns.add(blockedPattern); } @Override public String toString() { final StringBuilder buf = new StringBuilder(); buf.append(getClass().getSimpleName()); buf.append(" {"); buf.append("vars="); buf.append(vars); buf.append('}'); return buf.toString(); } }