001 /******************************************************************************* 002 * Portions created by Sebastian Thomschke are copyright (c) 2005-2013 Sebastian 003 * Thomschke. 004 * 005 * All Rights Reserved. This program and the accompanying materials 006 * are made available under the terms of the Eclipse Public License v1.0 007 * which accompanies this distribution, and is available at 008 * http://www.eclipse.org/legal/epl-v10.html 009 * 010 * Contributors: 011 * Sebastian Thomschke - initial implementation. 012 *******************************************************************************/ 013 package net.sf.oval.expression; 014 015 import java.util.ArrayList; 016 import java.util.Map; 017 import java.util.Map.Entry; 018 019 import net.sf.oval.exception.ExpressionEvaluationException; 020 import net.sf.oval.internal.Log; 021 022 import org.jruby.CompatVersion; 023 import org.jruby.Ruby; 024 import org.jruby.RubyInstanceConfig; 025 import org.jruby.javasupport.JavaEmbedUtils; 026 import org.jruby.runtime.builtin.IRubyObject; 027 028 /** 029 * @author Sebastian Thomschke 030 * 031 */ 032 public class ExpressionLanguageJRubyImpl implements ExpressionLanguage 033 { 034 private static final Log LOG = Log.getLog(ExpressionLanguageJRubyImpl.class); 035 036 /** 037 * {@inheritDoc} 038 */ 039 public Object evaluate(final String expression, final Map<String, ? > values) throws ExpressionEvaluationException 040 { 041 LOG.debug("Evaluating JRuby expression: {1}", expression); 042 try 043 { 044 final RubyInstanceConfig config = new RubyInstanceConfig(); 045 config.setCompatVersion(CompatVersion.RUBY1_9); 046 final Ruby runtime = JavaEmbedUtils.initialize(new ArrayList<String>(), config); 047 048 final StringBuilder localVars = new StringBuilder(); 049 for (final Entry<String, ? > entry : values.entrySet()) 050 { 051 runtime.getGlobalVariables().set("$" + entry.getKey(), JavaEmbedUtils.javaToRuby(runtime, entry.getValue())); 052 localVars.append(entry.getKey()) // 053 .append("=$") // 054 .append(entry.getKey()) // 055 .append("\n"); 056 } 057 final IRubyObject result = runtime.evalScriptlet(localVars + expression); 058 return JavaEmbedUtils.rubyToJava(runtime, result, Object.class); 059 } 060 catch (final RuntimeException ex) 061 { 062 throw new ExpressionEvaluationException("Evaluating JRuby expression failed: " + expression, ex); 063 } 064 } 065 066 /** 067 * {@inheritDoc} 068 */ 069 public boolean evaluateAsBoolean(final String expression, final Map<String, ? > values) throws ExpressionEvaluationException 070 { 071 final Object result = evaluate(expression, values); 072 if (!(result instanceof Boolean)) throw new ExpressionEvaluationException("The script must return a boolean value."); 073 return (Boolean) result; 074 } 075 }