Author: sebb Date: Fri Jul 31 02:24:07 2009 New Revision: 799492 URL: http://svn.apache.org/viewvc?rev=799492&view=rev Log: Initial implementation of Jexl Script engine and simple unit test
Added: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/scripting/JexlScriptEngine.java (with props) commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/scripting/JexlScriptEngineTest.java (with props) Added: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/scripting/JexlScriptEngine.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/scripting/JexlScriptEngine.java?rev=799492&view=auto ============================================================================== --- commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/scripting/JexlScriptEngine.java (added) +++ commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/scripting/JexlScriptEngine.java Fri Jul 31 02:24:07 2009 @@ -0,0 +1,202 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.commons.jexl.scripting; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import javax.script.AbstractScriptEngine; +import javax.script.Bindings; +import javax.script.ScriptContext; +import javax.script.ScriptEngineFactory; +import javax.script.ScriptException; +import javax.script.SimpleBindings; + +import org.apache.commons.jexl.JexlContext; +import org.apache.commons.jexl.JexlEngine; +import org.apache.commons.jexl.Script; + +// Note: this is a generated class, so won't be present until JavaCC has been run +import org.apache.commons.jexl.parser.ParseException; + +/** + * Implements the Jexl ScriptEngine for JSF-223. + * <p> + * See + * <a href="http://java.sun.com/javase/6/docs/api/javax/script/package-summary.html">Java Scripting API</a> + * Javadoc. + */ +public class JexlScriptEngine extends AbstractScriptEngine { + + private final ScriptEngineFactory factory; + + private final JexlEngine engine; + + public JexlScriptEngine() { + this(null); + } + + public JexlScriptEngine(final ScriptEngineFactory _factory) { + factory = _factory; + engine = new JexlEngine(); + } + + /** {...@inheritdoc} */ + public Bindings createBindings() { + return new SimpleBindings(); + } + + /** {...@inheritdoc} */ + public Object eval(Reader script, ScriptContext context) throws ScriptException { + BufferedReader reader = new BufferedReader(script); + StringBuilder buffer = new StringBuilder(); + try { + String line; + try { + while ((line = reader.readLine()) != null) { + buffer.append(line).append('\n'); + } + } catch (IOException e) { + throw new ScriptException(e); + } + } finally { + try { + reader.close(); + } catch (IOException e) { + } + } + return eval(buffer.toString(), context); + } + + /** {...@inheritdoc} */ + @SuppressWarnings("unchecked") + public Object eval(String scriptText, final ScriptContext context) throws ScriptException { + if (scriptText == null) { + return null; + } + context.setAttribute("context", context, ScriptContext.ENGINE_SCOPE); + try { + Script script = engine.createScript(scriptText); + JexlContext ctxt = new JexlContext(){ + public void setVars(Map vars) { + context.setBindings(new SimpleBindings(vars), ScriptContext.ENGINE_SCOPE); + } + + public Map getVars() { + return new JexlContextWrapper(context); + } + }; + + ctxt.getVars().put("context", "value"); + + return script.execute(ctxt); + } catch (ParseException e) { + e.printStackTrace(); + throw new ScriptException(e); + } catch (Exception e) { + e.printStackTrace(); + throw new ScriptException(e.toString()); + } + } + + /** {...@inheritdoc} */ + public ScriptEngineFactory getFactory() { + return factory == null ? new JexlScriptEngineFactory() : factory; + } + + /** + * Wrapper to convert a JSR-223 ScriptContext into a JexlContext. + * + * Current implementation only gives access to ENGINE_SCOPE binding. + */ + @SuppressWarnings("unchecked") + private static class JexlContextWrapper implements Map { + + private final ScriptContext context; + + private JexlContextWrapper (final ScriptContext _context){ + context = _context; + } + + public void clear() { + Bindings bnd = context.getBindings(ScriptContext.ENGINE_SCOPE); + bnd.clear(); + } + + public boolean containsKey(final Object key) { + Bindings bnd = context.getBindings(ScriptContext.ENGINE_SCOPE); + return bnd.containsKey(key); + } + + public boolean containsValue(final Object value) { + Bindings bnd = context.getBindings(ScriptContext.ENGINE_SCOPE); + return bnd.containsValue(value); + } + + public Set entrySet() { + Bindings bnd = context.getBindings(ScriptContext.ENGINE_SCOPE); + return bnd.entrySet(); + } + + public Object get(final Object key) { + Bindings bnd = context.getBindings(ScriptContext.ENGINE_SCOPE); + return bnd.get(key); + } + + public boolean isEmpty() { + Bindings bnd = context.getBindings(ScriptContext.ENGINE_SCOPE); + return bnd.isEmpty(); + } + + public Set keySet() { + Bindings bnd = context.getBindings(ScriptContext.ENGINE_SCOPE); + return bnd.keySet(); + } + + public Object put(final Object key, final Object value) { + Bindings bnd = context.getBindings(ScriptContext.ENGINE_SCOPE); + return bnd.put(key, value); + } + + public void putAll(Map t) { + Bindings bnd = context.getBindings(ScriptContext.ENGINE_SCOPE); + bnd.putAll(t); // N.B. SimpleBindings checks for valid keys + } + + public Object remove(Object key) { + Bindings bnd = context.getBindings(ScriptContext.ENGINE_SCOPE); + return bnd.remove(key); + } + + public int size() { + Bindings bnd = context.getBindings(ScriptContext.ENGINE_SCOPE); + return bnd.size(); + } + + public Collection values() { + Bindings bnd = context.getBindings(ScriptContext.ENGINE_SCOPE); + return bnd.values(); + } + + } +} Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/scripting/JexlScriptEngine.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/jexl/branches/2.0/src/java/org/apache/commons/jexl/scripting/JexlScriptEngine.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Added: commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/scripting/JexlScriptEngineTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/scripting/JexlScriptEngineTest.java?rev=799492&view=auto ============================================================================== --- commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/scripting/JexlScriptEngineTest.java (added) +++ commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/scripting/JexlScriptEngineTest.java Fri Jul 31 02:24:07 2009 @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.commons.jexl.scripting; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; + +import junit.framework.TestCase; + +public class JexlScriptEngineTest extends TestCase { + + public void testScripting() throws Exception { + ScriptEngineManager manager = new ScriptEngineManager(); + assertNotNull("Manager should not be null", manager); + ScriptEngine engine = manager.getEngineByName("jexl"); + assertNotNull("Engine should not be null (name)", engine); + engine = manager.getEngineByExtension("jexl"); + assertNotNull("Engine should not be null (ext)", engine); + final Integer initialValue = Integer.valueOf(123); + assertEquals(initialValue,engine.eval("123")); + assertEquals(initialValue,engine.eval("0;123"));// multiple statements + long time1 = System.currentTimeMillis(); + Long time2 = (Long) engine.eval("" + + "sys=context.class.forName(\"java.lang.System\");" + +"now=sys.currentTimeMillis();" + ); + assertTrue("Must take some time to process this",time1 <= time2.longValue()); + engine.put("value", initialValue); + assertEquals(initialValue,engine.get("value")); + final Long newValue = Long.valueOf(124); + assertEquals(newValue,engine.eval("old=value;value=value+1")); + assertEquals(initialValue,engine.get("old")); + assertEquals(newValue,engine.get("value")); + } + +} Propchange: commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/scripting/JexlScriptEngineTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/jexl/branches/2.0/src/test/org/apache/commons/jexl/scripting/JexlScriptEngineTest.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision