001/*
002 * Stallion Core: A Modern Web Framework
003 *
004 * Copyright (C) 2015 - 2016 Stallion Software LLC.
005 *
006 * This program is free software: you can redistribute it and/or modify it under the terms of the
007 * GNU General Public License as published by the Free Software Foundation, either version 2 of
008 * the License, or (at your option) any later version. This program is distributed in the hope that
009 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
011 * License for more details. You should have received a copy of the GNU General Public License
012 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
013 *
014 *
015 *
016 */
017
018package io.stallion.plugins.javascript;
019
020import io.stallion.exceptions.*;
021import io.stallion.settings.Settings;
022import jdk.internal.dynalink.beans.StaticClass;
023import jdk.nashorn.api.scripting.ScriptObjectMirror;
024import jdk.nashorn.internal.runtime.ScriptObject;
025import jline.console.ConsoleReader;
026import jline.internal.Log;
027import org.apache.commons.io.FileUtils;
028
029import java.io.File;
030import java.io.IOException;
031import java.lang.reflect.Field;
032import java.lang.reflect.Method;
033import java.util.HashMap;
034import java.util.List;
035import java.util.Map;
036
037import static io.stallion.utils.Literals.*;
038import static io.stallion.Context.*;
039
040
041public class JavaToJsHelpers {
042    private boolean sandboxed = false;
043    private Sandbox box;
044
045    public JavaToJsHelpers(Sandbox box) {
046        if (box != null) {
047            sandboxed = true;
048            this.box = box;
049        }
050    }
051
052    public String readFileToString(String file) {
053        if (!sandboxed) {
054            try {
055                return FileUtils.readFileToString(new File(file), "UTF-8");
056            } catch (IOException e) {
057                throw new RuntimeException(e);
058            }
059        }
060        throw new UsageException("You cannot read a file from a sandboxed plugin.");
061    }
062
063
064    public Object toJava(Object obj) {
065        if (!(obj instanceof ScriptObjectMirror)) {
066            return obj;
067        }
068        ScriptObjectMirror so = (ScriptObjectMirror)obj;
069        if (so.isArray()) {
070            List items = list();
071            for (String key: so.getOwnKeys(false)) {
072                items.add(so.get(key));
073            }
074            return items;
075        } else {
076            Map<String, Object> o = map();
077            for(String key: so.getOwnKeys(false)) {
078                Object val = so.get(key);
079                if (val instanceof ScriptObjectMirror && ((ScriptObjectMirror) val).isArray()) {
080                    val = toJava((ScriptObjectMirror)val);
081                }
082                o.put(key, val);
083            }
084            return o;
085        }
086    }
087
088    public boolean isClass(Object cls) {
089        return cls instanceof Class;
090    }
091
092    public boolean isStatic(Object cls) {
093        if (cls == null) {
094            return false;
095        }
096        //jdk.internal.dynalink.beans.StaticClass
097        if (cls instanceof StaticClass) {
098            return true;
099        }
100        return false;
101    }
102
103    public void raiseRedirect(String msg, Integer status) {
104        status = or(status, 302);
105        throw new RedirectException(msg, status);
106
107    }
108
109    public void raiseNotFound(String msg) {
110        throw new NotFoundException(msg);
111    }
112
113
114
115    public void raiseClientException(String msg, Integer status) {
116        status = or(status, 400);
117        throw new ClientException(msg, status);
118    }
119
120    public void raiseServerException(String msg, Integer status) {
121        status = or(status, 500);
122        throw new WebException(msg, status);
123    }
124
125    public void raiseAssertionError(String msg) {
126        throw new AssertionError(msg);
127    }
128
129    public String getInput(String prompt) throws Exception {
130        if (!Settings.instance().getLocalMode()) {
131            Log.error("You can only call 'getInput' in local mode");
132            return "";
133        }
134
135        ConsoleReader reader = new ConsoleReader();
136        return reader.readLine(prompt);
137    }
138
139    public Object inspect(Object object) throws Exception {
140        if (!Settings.instance().getLocalMode()) {
141            Log.error("You can only call 'inspect' in local mode");
142            return "";
143        }
144        Class<?> c = Class.forName("jdk.nashorn.internal.runtime.DebuggerSupport");//full package name
145        //note: getConstructor() can return only public constructors,
146        //you need to use
147
148        Method method = c.getDeclaredMethod("valueInfos", Object.class, boolean.class);
149        //valueInfos(Object object, boolean all)
150        //Constructor<?> constructor = c.getDeclaredConstructor();
151        method.setAccessible(true);
152        Object[] objects = (Object[])method.invoke(null, object, true);
153        //List<Map> returnObjects = new ArrayList<>();
154        Map desc = new HashMap<>();
155        for(Object o: objects) {
156            Map map = new HashMap<>();
157
158            Field field = o.getClass().getDeclaredField("key");
159            field.setAccessible(true);
160            Object key = field.get(o);
161
162            Field field2 = o.getClass().getDeclaredField("valueAsString");
163            field2.setAccessible(true);
164            Object val = field2.get(o);
165            desc.put(key.toString(), val.toString());
166
167        }
168        return desc;
169    }
170
171    public Object eval(ScriptObject o, Object scope, String source, boolean returnStuff) {
172        if (!Settings.instance().getLocalMode()) {
173            Log.error("You can only call 'eval' in local mode");
174            return "";
175        }
176        try {
177            //new jdk.nashorn.internal.runtime.DebugLogger().
178            Class<?> c = Class.forName("jdk.nashorn.internal.runtime.DebuggerSupport");//full package name
179            //note: getConstructor() can return only public constructors,
180            //you need to use
181
182            Method method = c.getDeclaredMethod("eval", ScriptObject.class, Object.class, String.class, boolean.class);
183
184            //Constructor<?> constructor = c.getDeclaredConstructor();
185            method.setAccessible(true);
186            return method.invoke(null, o, scope, source, returnStuff);
187        } catch (Exception e) {
188            Log.error(e);
189            return null;
190        }
191    }
192
193    private Object getDebugSupport() {
194
195
196        //return new NashornDebugHelper();
197        try {
198            Class<?> c = Class.forName("jdk.nashorn.internal.runtime.DebuggerSupport");//full package name
199            //note: getConstructor() can return only public constructors,
200            //you need to use
201            Method method = c.getDeclaredMethod("eval", ScriptObject.class, Object.class, String.class, boolean.class);
202
203            //Constructor<?> constructor = c.getDeclaredConstructor();
204            method.setAccessible(true);
205            return method;
206            //constructor.setAccessible(true);
207            //Object o = constructor.newInstance(null);
208            //return o;
209        } catch (Exception e) {
210            Log.error(e);
211            return null;
212        }
213    }
214
215
216}