001package com.killcoding.jsplus;
002
003import com.killcoding.jsplus.JsPlusContext;
004import java.io.File;
005import com.killcoding.tool.FileTools;
006import com.killcoding.log.LoggerFactory;
007import com.killcoding.log.Logger;
008import com.killcoding.tool.CommonTools;
009import java.util.Set;
010import java.util.Iterator;
011import com.killcoding.tool.ConfigProperties;
012import java.util.Map;
013
014import org.graalvm.polyglot.Context;
015import org.graalvm.polyglot.HostAccess;
016import org.graalvm.polyglot.PolyglotAccess;
017import org.graalvm.polyglot.Value;
018import org.graalvm.polyglot.Engine;
019import org.graalvm.options.OptionDescriptors;
020import com.killcoding.tool.CipherTools;
021import com.killcoding.file.DiskFile;
022import com.killcoding.file.BaseFile;
023
024public class GraalVmContext extends JsPlusContext {
025
026        private Engine engine = null;
027        private Context context = null;
028        private Value value = null;
029        
030        public GraalVmContext(String engineName) {
031                super(engineName);
032                String[] parseJsParams = engineName.split("\\.",2);
033        String useEngineName = "js";
034        if(parseJsParams.length >= 2) {
035            useEngineName = parseJsParams[1];
036        }
037        this.engineName = useEngineName;
038        }
039        
040        @Override
041        public String getEngineName(){
042            return engineName;
043        }
044
045        @Override
046        public void initScriptEngineManager() throws Exception {
047                Engine.Builder builder = Engine.newBuilder();
048                ConfigProperties appenvCp = ScriptConsole.getAppenv();
049                if(appenvCp != null){
050                   String engineNameMapKey = String.format("GraalVM.%s",engineName);
051                   Map appenvMap = appenvCp.getMap(engineNameMapKey,null);
052                   if(appenvMap != null){
053                       System.out.println("GraalVM options: " + appenvMap);
054                       builder.options(appenvMap);
055                   }
056                }
057                engine = builder.build();
058                Set<String> languages = engine.getLanguages().keySet();
059                System.out.println("GraalVM supported Languages: " + languages);
060                
061                Context.Builder contextBuiilder = Context.newBuilder();
062                if(allowAllAccess){
063            contextBuiilder
064                    .allowAllAccess(true)
065                    .allowHostAccess(HostAccess.ALL)
066                            .allowCreateThread(true);
067                }                   
068            context = contextBuiilder.engine(engine).build();   
069            
070                value = context.getBindings(engineName);
071                value.putMember("ScriptClassLoader", context.getClass().getClassLoader());
072        }
073
074        @Override
075        public Object getBindings() {
076                return value;
077        }
078
079        @Override
080        public Engine getEngine() {
081                return engine;
082        }
083
084        @Override
085        public Context getContext() {
086                return context;
087        }
088
089        @Override
090        public void remove(String name) {
091                value.removeMember(name);
092        }
093
094        @Override
095        public Object get(String name) {
096                return value.getMember(name);
097        }
098
099        @Override
100        public void put(String name, Object obj) {
101                value.putMember(name, obj);
102        }
103
104        @Override
105        public Object eval(String scriptPath) throws Exception {
106                return eval(new File(scriptPath));
107        }
108
109        @Override
110        public Object eval(File scriptPath) throws Exception {
111            String script = null;
112            if(CommonTools.isBlank(scriptCipherAesKey)){
113                script = FileTools.text(scriptPath);
114            }else{
115                DiskFile df = new DiskFile(scriptPath);
116                byte[] encryptBytes = df.readAllBytes();
117                byte[] decryptBytes = CipherTools.AESDecrypt(scriptCipherAesKey,encryptBytes);
118                script = new String(decryptBytes,BaseFile.CHARSET);
119            }
120            return evalScript(script);
121        }
122
123        @Override
124        public Object evalScript(String script) throws Exception {
125                synchronized (context) {
126                        try {
127                                context.enter();
128                                return context.eval(engineName, script);
129                        } finally {
130                                context.leave();
131                        }
132                }
133        }
134
135        @Override
136        public void close() {
137                context.close(true);
138        }
139
140}