001package com.killcoding.jsplus;
002
003import javax.script.ScriptEngine;
004import javax.script.ScriptEngineManager;
005import javax.script.ScriptEngineFactory;
006import javax.script.Invocable;
007import javax.script.Bindings;
008import javax.script.ScriptContext;
009import javax.script.SimpleScriptContext;
010import com.killcoding.jsplus.JsPlusContext;
011import com.killcoding.tool.CommonTools;
012import java.nio.file.Files;
013import java.util.List;
014import java.nio.file.Paths;
015import com.killcoding.tool.FileTools;
016import java.io.File;
017import com.killcoding.file.DiskFile;
018import com.killcoding.tool.CipherTools;
019import com.killcoding.file.BaseFile;
020import com.killcoding.jsplus.ScriptConsole;
021
022public class JsContext extends JsPlusContext {
023
024    private ScriptEngineManager scriptEngineManager = null;
025        private Invocable invocable = null;
026        private ScriptEngine scriptEngine = null;
027        private ScriptContext context = null;
028        private Bindings bindings = null;
029        
030    public JsContext(String engineName){
031        super(engineName);
032    }
033    
034        @Override
035        public Object getBindings(){
036            return bindings;
037        }    
038    
039        @Override
040    public ScriptEngineManager getEngine(){
041        return scriptEngineManager;
042    }
043    
044        @Override
045    public ScriptContext getContext(){
046        return context;
047    }    
048    
049    @Override
050        public void remove(String name){
051            bindings.remove(name);
052        }        
053    
054    @Override
055        public void put(String name,Object value){
056            bindings.put(name,value);
057        }  
058        
059        @Override
060        public Object get(String name){
061            return bindings.get(name);
062        }       
063
064    @Override
065        public void initScriptEngineManager() throws Exception {
066                ClassLoader classLoader = null;
067                classLoader = ClassLoader.getSystemClassLoader();
068                scriptEngineManager = new ScriptEngineManager();
069                List<ScriptEngineFactory> factories = scriptEngineManager.getEngineFactories();
070                for (ScriptEngineFactory factory : factories) {
071                        System.out.println(
072                                        String.format("%s %s %s", factory.getEngineName(), factory.getEngineVersion(), factory.getNames()));
073                }
074                if (factories.isEmpty()) {
075                        System.out.println("No script engines found");
076                } else {
077                        scriptEngine = scriptEngineManager.getEngineByName(engineName);
078                        if(scriptEngine == null){
079                            throw new Exception(String.format("Missing engine '%s'.",engineName));
080                        }
081                        context = new SimpleScriptContext();
082                        context.setBindings(scriptEngine.createBindings(), ScriptContext.ENGINE_SCOPE);
083                        bindings = context.getBindings(ScriptContext.ENGINE_SCOPE);
084                        bindings.put("ScriptClassLoader", classLoader);
085                        disableAllowAllAccess();
086                        invocable = (Invocable) scriptEngine;
087                }
088        }
089        
090        @Override
091        public void setAllowAllAccess(boolean allowAllAccess){
092            this.allowAllAccess = allowAllAccess;
093            disableAllowAllAccess();
094        }
095
096    @Override
097        public Object eval(String scriptPath) throws Exception {
098                return eval(new File(scriptPath));
099        }
100
101    @Override
102        public Object eval(File scriptPath) throws Exception {
103            String script = null;
104            if(CommonTools.isBlank(scriptCipherAesKey)){
105                script = FileTools.text(scriptPath);
106            }else{
107                DiskFile df = new DiskFile(scriptPath);
108                byte[] encryptBytes = df.readAllBytes();
109                byte[] decryptBytes = CipherTools.AESDecrypt(scriptCipherAesKey,encryptBytes);
110                script = new String(decryptBytes,BaseFile.CHARSET);
111            }
112                Object result = scriptEngine.eval(script, context);
113                scriptEngine.setContext(context);
114                invocable = (Invocable) scriptEngine;
115                return result;      
116        }
117        
118        @Override
119        public Object evalScript(String script) throws Exception {
120                Object result = scriptEngine.eval(script, context);
121                scriptEngine.setContext(context);
122                invocable = (Invocable) scriptEngine;
123                return result;
124        }       
125        
126    @Override
127    public void close(){
128        bindings.clear();
129        bindings = null;
130        context = null;
131    }   
132    
133        @Override
134        public String getEngineName(){
135            return engineName;
136        } 
137        
138        protected void disableAllowAllAccess(){
139            if(!this.allowAllAccess && bindings != null){
140            bindings.put("Java", null);
141            bindings.put("JavaImporter", null);                     
142            bindings.put("java", null);
143            bindings.put("javax", null);
144            bindings.put("app", null);
145            bindings.put("com", null);
146            bindings.put("org", null);
147            bindings.put("net", null);
148            bindings.put("sun", null);
149            bindings.put("android", null);
150            bindings.put("oracle", null);
151            bindings.put("ibm", null);
152            bindings.put("io", null);
153            bindings.put("jdk", null);
154            bindings.put("jakarta", null);
155            }
156        }
157        
158}