/** * This file is part of PaxmlCore. * * PaxmlCore is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * PaxmlCore 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with PaxmlCore. If not, see <http://www.gnu.org/licenses/>. */ package org.paxml.el; import org.apache.commons.jexl2.Expression; import org.apache.commons.jexl2.JexlContext; import org.apache.commons.jexl2.JexlEngine; import org.paxml.core.Context; import org.paxml.core.PaxmlRuntimeException; import org.paxml.tag.ITagLibrary; import org.paxml.util.ReflectUtils; /** * Apache Jexl expression impl. * * @author Xuetao Niu * */ public class JexlExpression extends AbstractExpression { private static final JexlEngine JEXL_ENGINE_STRICT = new JexlEngine(); private static final JexlEngine JEXL_ENGINE_NON_STRICT = new JexlEngine(); static { JEXL_ENGINE_STRICT.setLenient(false); JEXL_ENGINE_NON_STRICT.setLenient(true); } private final Expression exp; private final boolean strict; /** * Construct from string. * * @param exp * the string expression * @param strict true to disallow unknown const, false to allow. */ public JexlExpression(final String exp, boolean strict) { this.exp = (strict?JEXL_ENGINE_STRICT:JEXL_ENGINE_NON_STRICT).createExpression(exp); this.strict=strict; } /** * {@inheritDoc} */ public Object evaluate(Context context) { return exp.evaluate(convertContext(context)); } /** * {@inheritDoc} */ public String getString() { return exp.getExpression(); } private JexlContext convertContext(final Context context) { return new JexlContext() { public Object get(String name) { Object obj = context.getConst(name, true); if (obj == null) { // check if it is a util function reference obj = getUtilFunctions(name, context); if (obj != null) { context.getRootContext().addConst(name, null, obj, true); } } return obj; } public boolean has(String name) { if (!context.hasConstId(name, true)) { if(strict){ throw new PaxmlRuntimeException("Unknown const name: " + name); } return true; } return true; } public void set(String name, Object value) { throw new UnsupportedOperationException("Cannot change the reference of constant: " + name); } }; } private Object getUtilFunctions(String name, Context context) { for (ITagLibrary tagLib : context.getPaxml().getParser().getTagLibraries()) { Class<? extends IUtilFunctionsFactory> clazz = tagLib.getUtilFunctionsFactory(name); if (clazz != null) { return ReflectUtils.createObject(clazz).getUtilFunctions(context); } } return null; } }