package org.develnext.jphp.scripting;
import org.develnext.jphp.scripting.util.ReaderInputStream;
import php.runtime.Information;
import php.runtime.env.Context;
import php.runtime.env.Environment;
import php.runtime.launcher.Launcher;
import php.runtime.memory.ArrayMemory;
import php.runtime.memory.support.MemoryUtils;
import php.runtime.reflection.ModuleEntity;
import javax.script.*;
import java.io.*;
import java.util.*;
public class JPHPScriptEngine extends AbstractScriptEngine implements Compilable {
private static final String __ENGINE_VERSION__ = Information.CORE_VERSION;
private static final String __NAME__ = Information.NAME;
private static final String __SHORT_NAME__ = "jphp";
private static final String __LANGUAGE__ = "php";
private static final String __LANGUAGE_VERSION__ = Information.LIKE_PHP_VERSION;
private ScriptEngineFactory factory = null;
private Environment environment;
public JPHPScriptEngine() {
super();
Launcher launcher = new Launcher();
try {
launcher.run(false);
} catch (Throwable e) {
//pass
}
environment = new Environment(launcher.getCompileScope(), System.out);
environment.getDefaultBuffer().setImplicitFlush(true);
JPHPContext ctx = new JPHPContext();
ctx.setBindings(createBindings(), ScriptContext.ENGINE_SCOPE);
setContext(ctx);
put(LANGUAGE_VERSION, __LANGUAGE_VERSION__);
put(LANGUAGE, __LANGUAGE__);
put(ENGINE, __NAME__);
put(ENGINE_VERSION, __ENGINE_VERSION__);
put(NAME, __SHORT_NAME__);
}
@Override
public Object eval(String script, ScriptContext context) throws ScriptException {
return eval(new StringReader(script), context);
}
@Override
public Object eval(Reader reader, ScriptContext _ctx) throws ScriptException {
return compile(reader).eval(_ctx);
}
@Override
public CompiledScript compile(String script) throws ScriptException {
return compile(new StringReader(script));
}
@Override
public CompiledScript compile(Reader reader) throws ScriptException {
try {
InputStream is = new ReaderInputStream(reader);
Context context = new Context(is);
ModuleEntity module = environment.importModule(context);
return new JPHPCompiledScript(module, environment);
} catch (IOException e) {
throw new ScriptException(e);
} catch (Throwable e) {
throw new ScriptException(new Exception(e));
}
}
@Override
public Bindings createBindings() {
return new JPHPBindings(environment.getGlobals());
}
@Override
public synchronized ScriptEngineFactory getFactory() {
if (factory == null) {
factory = new JPHPScriptEngineFactory();
}
return factory;
}
public void setFactory(JPHPScriptEngineFactory f) {
factory = f;
}
public class JPHPBindings implements Bindings {
private ArrayMemory globals;
public JPHPBindings(ArrayMemory globals) {
this.globals = globals;
}
@Override
public Object put(String name, Object value) {
return globals.putAsKeyString(name, MemoryUtils.valueOf(value));
}
@Override
public void putAll(Map<? extends String, ? extends Object> toMerge) {
for (String key : toMerge.keySet()) {
put(key, toMerge.get(key));
}
}
@Override
public void clear() {
globals.clear();
}
@Override
public Set<String> keySet() {
Set<String> set = new HashSet<String>(size());
for (Object k : globals.keySet()) {
set.add(k.toString());
}
return set;
}
@Override
public Collection<Object> values() {
return new ArrayList<Object>(Arrays.asList(globals.values()));
}
@Override
public Set<Entry<String, Object>> entrySet() {
Set<Entry<String, Object>> set = new HashSet<Entry<String, Object>>(size());
for (Object k : globals.keySet()) {
set.add(new AbstractMap.SimpleEntry<String, Object>(k.toString(), get(k)));
}
return set;
}
@Override
public int size() {
return globals.size();
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public boolean containsKey(Object key) {
return globals.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return false;
}
@Override
public Object get(Object key) {
return globals.getByScalar(key);
}
@Override
public Object remove(Object key) {
return globals.removeByScalar(key);
}
}
public class JPHPCompiledScript extends CompiledScript {
private ModuleEntity module;
private Environment environment;
public JPHPCompiledScript(ModuleEntity m, Environment env) {
module = m;
environment = env;
}
@Override
public Object eval(ScriptContext context) throws ScriptException {
try {
try {
return module.include(environment);
} catch (Exception e) {
environment.catchUncaught(e);
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
} finally {
try {
environment.doFinal();
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}
} catch (Throwable e) {
throw new ScriptException(new Exception(e));
}
return null;
}
@Override
public ScriptEngine getEngine() {
return JPHPScriptEngine.this;
}
}
}