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}