View Javadoc
1   /*******************************************************************************
2    * Portions created by Sebastian Thomschke are copyright (c) 2005-2015 Sebastian
3    * Thomschke.
4    *
5    * All Rights Reserved. This program and the accompanying materials
6    * are made available under the terms of the Eclipse Public License v1.0
7    * which accompanies this distribution, and is available at
8    * http://www.eclipse.org/legal/epl-v10.html
9    *
10   * Contributors:
11   *     Sebastian Thomschke - initial implementation.
12   *******************************************************************************/
13  package net.sf.oval.expression;
14  
15  import java.util.Map;
16  import java.util.Map.Entry;
17  
18  import net.sf.oval.exception.ExpressionEvaluationException;
19  import net.sf.oval.internal.Log;
20  import net.sf.oval.internal.util.ObjectCache;
21  
22  import org.mozilla.javascript.Context;
23  import org.mozilla.javascript.ContextFactory;
24  import org.mozilla.javascript.EvaluatorException;
25  import org.mozilla.javascript.Script;
26  import org.mozilla.javascript.Scriptable;
27  
28  /**
29   * @author Sebastian Thomschke
30   */
31  public class ExpressionLanguageJavaScriptImpl extends AbstractExpressionLanguage
32  {
33  	private static final Log LOG = Log.getLog(ExpressionLanguageJavaScriptImpl.class);
34  
35  	private final Scriptable parentScope;
36  
37  	private final ObjectCache<String, Script> scriptCache = new ObjectCache<String, Script>();
38  
39  	public ExpressionLanguageJavaScriptImpl()
40  	{
41  		final Context ctx = ContextFactory.getGlobal().enterContext();
42  		try
43  		{
44  			parentScope = ctx.initStandardObjects();
45  		}
46  		finally
47  		{
48  			Context.exit();
49  		}
50  	}
51  
52  	public Object evaluate(final String expression, final Map<String, ? > values) throws ExpressionEvaluationException
53  	{
54  		LOG.debug("Evaluating JavaScript expression: {1}", expression);
55  		try
56  		{
57  			final Context ctx = ContextFactory.getGlobal().enterContext();
58  			Script script = scriptCache.get(expression);
59  			if (script == null)
60  			{
61  				ctx.setOptimizationLevel(9);
62  				script = ctx.compileString(expression, "<cmd>", 1, null);
63  				scriptCache.put(expression, script);
64  			}
65  			final Scriptable scope = ctx.newObject(parentScope);
66  			scope.setPrototype(parentScope);
67  			scope.setParentScope(null);
68  			for (final Entry<String, ? > entry : values.entrySet())
69  			{
70  				scope.put(entry.getKey(), scope, Context.javaToJS(entry.getValue(), scope));
71  			}
72  			return script.exec(ctx, scope);
73  		}
74  		catch (final EvaluatorException ex)
75  		{
76  			throw new ExpressionEvaluationException("Evaluating JavaScript expression failed: " + expression, ex);
77  		}
78  		finally
79  		{
80  			Context.exit();
81  		}
82  	}
83  }