Skip to content

Commit

Permalink
(feat) Impl script engine SPI and refactor AviatorScriptEngine etc., #…
Browse files Browse the repository at this point in the history
  • Loading branch information
killme2008 committed Apr 9, 2020
1 parent 1e7d8f8 commit ae675ab
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 52 deletions.
2 changes: 1 addition & 1 deletion src/main/java/com/googlecode/aviator/AviatorEvaluator.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public final class AviatorEvaluator {
/**
* Aviator version
*/
public static final String VERSION = "3.0.0";
public static final String VERSION = "5.0.0";

/**
* The global evaluator's functions map.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package com.googlecode.aviator;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
Expand Down Expand Up @@ -138,6 +137,7 @@
import com.googlecode.aviator.utils.Env;
import com.googlecode.aviator.utils.LRUMap;
import com.googlecode.aviator.utils.Reflector;
import com.googlecode.aviator.utils.Utils;


/**
Expand Down Expand Up @@ -210,14 +210,9 @@ public Expression compileScript(final String path, final boolean cached) throws
public Expression compileScript(final String cacheKey, final File file, final boolean cached)
throws IOException {
try (InputStream in = new FileInputStream(file);
Reader fr = new InputStreamReader(in, Charset.forName("utf-8"));
BufferedReader reader = new BufferedReader(fr)) {
StringBuilder script = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
script.append(line).append(Constants.NEWLINE);
}
return compile(cacheKey, script.toString(), cached);
Reader reader = new InputStreamReader(in, Charset.forName("utf-8"));) {

return compile(cacheKey, Utils.readFully(reader), cached);
}
}

Expand Down
26 changes: 21 additions & 5 deletions src/main/java/com/googlecode/aviator/BaseExpression.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,35 @@ public BaseExpression(final AviatorEvaluatorInstance instance, final List<String
this.varNames = new ArrayList<String>(tmp);
}

private class SymbolHashMap extends HashMap<String, Object> {

private static final long serialVersionUID = 5951510458689965590L;

public SymbolHashMap(final int initialCapacity) {
super(initialCapacity);
}

@Override
public Object put(String key, final Object value) {
Variable var = null;
if (BaseExpression.this.symbolTable != null
&& (var = BaseExpression.this.symbolTable.getVariable(key)) != null) {
key = var.getLexeme();
}
return super.put(key, value);
}

}

@Override
public Map<String, Object> newEnv(final Object... args) {
if (args != null && args.length % 2 != 0) {
throw new IllegalArgumentException("Expect arguments number is even.");
}
Map<String, Object> env = new HashMap<>(args != null ? args.length : 10);
Map<String, Object> env = new SymbolHashMap(args != null ? args.length : 10);
if (args != null) {
for (int i = 0; i < args.length; i += 2) {
String key = (String) args[i];
Variable var = null;
if (this.symbolTable != null && (var = this.symbolTable.getVariable(key)) != null) {
key = var.getLexeme();
}
env.put(key, args[i + 1]);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.googlecode.aviator.script;

import java.io.IOException;
import java.io.Reader;
import javax.script.AbstractScriptEngine;
import javax.script.Bindings;
Expand All @@ -11,38 +12,57 @@
import javax.script.SimpleBindings;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.AviatorEvaluatorInstance;
import com.googlecode.aviator.utils.Utils;


/**
* Aviator Expression engine
* Aviator script engine
*
* @author [email protected]
* @author dennis([email protected])
* @date 2011-1-18 上午11:03:34
* @version
*/
public class AviatorScriptEngine extends AbstractScriptEngine implements Compilable {

// 缓存编译结果
private boolean cached = true;
private final AviatorScriptEngineFactory factory;
private AviatorEvaluatorInstance evaluator;
private final AviatorEvaluatorInstance engine;


public AviatorScriptEngine(AviatorScriptEngineFactory factory) {
public AviatorScriptEngine() {
super();
this.factory = AviatorScriptEngineFactory.newInstance();
this.engine = AviatorEvaluator.newInstance();
}


public AviatorScriptEngine(final Bindings n) {
super(n);
this.factory = AviatorScriptEngineFactory.newInstance();
this.engine = AviatorEvaluator.newInstance();
}


public AviatorScriptEngine(final AviatorScriptEngineFactory factory) {
this.factory = factory;
this.evaluator = AviatorEvaluator.newInstance();
this.engine = AviatorEvaluator.newInstance();
}


@Override
public CompiledScript compile(String script) throws ScriptException {
return new CompiledAviatorScript(this, evaluator.compile(script, this.cached));
public CompiledScript compile(final String script) throws ScriptException {
return new CompiledAviatorScript(this, this.engine.compile(script, this.cached));
}


@Override
public CompiledScript compile(Reader script) throws ScriptException {
throw new UnsupportedOperationException();
public CompiledScript compile(final Reader script) throws ScriptException {
try {
return this.compile(Utils.readFully(script));
} catch (IOException e) {
throw new ScriptException(e);
}
}


Expand All @@ -51,16 +71,19 @@ public Bindings createBindings() {
return new SimpleBindings();
}


@Override
public Object eval(String script, ScriptContext context) throws ScriptException {
public Object eval(final String script, final ScriptContext context) throws ScriptException {
return this.compile(script).eval(context);
}


@Override
public Object eval(Reader reader, ScriptContext context) throws ScriptException {
throw new UnsupportedOperationException();
public Object eval(final Reader reader, final ScriptContext context) throws ScriptException {
try {
return eval(Utils.readFully(reader), context);
} catch (IOException e) {
throw new ScriptException(e);
}
}


Expand All @@ -75,7 +98,12 @@ public boolean isCached() {
}


public void setCached(boolean cached) {
/**
* Setting whether to cache the compiled exprssion, defualt is true(caching).
*
* @param cached true means enable caching.
*/
public void setCached(final boolean cached) {
this.cached = cached;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@


/**
* Aviator script engine factory.
*
* @author [email protected]
* @author dennis
Expand All @@ -19,22 +20,27 @@
*/
public class AviatorScriptEngineFactory implements ScriptEngineFactory {

private static final List<String> extensions =
Collections.unmodifiableList(Arrays.asList(new String[] {}));
private static final List<String> extensions = Collections.unmodifiableList(Arrays.asList(".av"));
private static final List<String> mimeTypes =
Collections.unmodifiableList(Arrays.asList(new String[] {"text/aviator"}));
private static final List<String> names =
Collections.unmodifiableList(Arrays.asList(new String[] {"Aviator", "aviator"}));
Collections.unmodifiableList(Arrays.asList("text/aviator"));
private static final List<String> names = Collections
.unmodifiableList(Arrays.asList("Aviator", "aviator", "aviatorscript", "AviatorScript"));

private static final Map<String, String> parameterMap = new HashMap<String, String>();
static {
parameterMap.put(ScriptEngine.ENGINE, "Aviator");
parameterMap.put(ScriptEngine.ENGINE_VERSION, AviatorEvaluator.VERSION);
parameterMap.put(ScriptEngine.LANGUAGE, "A high performance expression evaluator for java");
parameterMap.put(ScriptEngine.LANGUAGE,
"A high performance scripting language hosted on the JVM");
parameterMap.put(ScriptEngine.LANGUAGE_VERSION, AviatorEvaluator.VERSION);
}


public static final AviatorScriptEngineFactory newInstance() {
return new AviatorScriptEngineFactory();
}


@Override
public String getEngineName() {
return parameterMap.get(ScriptEngine.ENGINE);
Expand Down Expand Up @@ -66,7 +72,7 @@ public String getLanguageVersion() {


@Override
public String getMethodCallSyntax(String obj, String m, String... args) {
public String getMethodCallSyntax(final String obj, final String m, final String... args) {
StringBuilder sb = new StringBuilder(m);
sb.append("(").append(obj);
if (args != null) {
Expand All @@ -93,20 +99,24 @@ public List<String> getNames() {


@Override
public String getOutputStatement(String toDisplay) {
public String getOutputStatement(final String toDisplay) {
return "print(+" + toDisplay + ")";
}


@Override
public Object getParameter(String key) {
public Object getParameter(final String key) {
return parameterMap.get(key);
}


@Override
public String getProgram(String... statements) {
return null;
public String getProgram(final String... statements) {
StringBuilder sb = new StringBuilder();
for (String stmt : statements) {
sb.append(stmt).append(";");
}
return sb.toString();
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.googlecode.aviator.script;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
Expand All @@ -13,8 +12,10 @@


/**
*
* A compiled aviator script.
*
* @author [email protected]
* @author dennis([email protected])
* @date 2011-1-18 上午11:03:34
* @version
*/
Expand All @@ -24,27 +25,26 @@ public class CompiledAviatorScript extends CompiledScript {
private final Expression expression;


CompiledAviatorScript(AviatorScriptEngine engine, Expression expression) {
CompiledAviatorScript(final AviatorScriptEngine engine, final Expression expression) {
this.engine = engine;
this.expression = expression;
}


@Override
@SuppressWarnings("unchecked")
public Object eval(ScriptContext context) throws ScriptException {
public Object eval(final ScriptContext context) throws ScriptException {
try {
Map<String, Object> map = new HashMap<String, Object>();
for (Iterator it = context.getScopes().iterator(); it.hasNext();) {
int scope = ((Integer) it.next()).intValue();
Map<String, Object> env = this.expression.newEnv();
for (Iterator<Integer> it = context.getScopes().iterator(); it.hasNext();) {
int scope = it.next().intValue();
Bindings bindings = context.getBindings(scope);
Set keys = bindings.keySet();
Set<String> keys = bindings.keySet();

for (Object key : keys) {
map.put((String) key, bindings.get(key));
for (String key : keys) {
env.put(key, bindings.get(key));
}
}
return this.expression.execute(map);
return this.expression.execute(env);
} catch (Exception e) {
throw new ScriptException(e);
}
Expand Down
28 changes: 28 additions & 0 deletions src/main/java/com/googlecode/aviator/utils/Utils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.googlecode.aviator.utils;

import java.io.IOException;
import java.io.Reader;

/**
* Some helper methods.
*
* @author dennis([email protected])
*
*/
public class Utils {
private Utils() {

}

public static String readFully(final Reader reader) throws IOException {
final char[] arr = new char[16 * 1024];
final StringBuilder buf = new StringBuilder();
int numChars;

while ((numChars = reader.read(arr, 0, arr.length)) > 0) {
buf.append(arr, 0, numChars);
}

return buf.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.googlecode.aviator.script.AviatorScriptEngineFactory
20 changes: 20 additions & 0 deletions src/test/java/com/googlecode/aviator/ScriptEngineTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.googlecode.aviator;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import org.junit.Test;

public class ScriptEngineTest {

@Test
public void testScriptEngine() throws Exception {
final ScriptEngineManager m = new ScriptEngineManager();
final ScriptEngine engine = m.getEngineByName("aviator");
assertNotNull(engine);

assertEquals(3, engine.eval("1+2"));
assertEquals(6, engine.eval("square = lambda(x) -> x*2 end; square(3)"));
}
}

0 comments on commit ae675ab

Please sign in to comment.