001package org.jszip.rhino; 002 003import org.apache.commons.lang3.StringUtils; 004import org.apache.maven.plugin.logging.Log; 005import org.codehaus.plexus.util.IOUtil; 006import org.jszip.pseudo.io.ProxyPseudoFile; 007import org.jszip.pseudo.io.PseudoFile; 008import org.jszip.pseudo.io.PseudoFileInputStream; 009import org.jszip.pseudo.io.PseudoFileOutputStream; 010import org.jszip.pseudo.io.PseudoFileReader; 011import org.jszip.pseudo.io.PseudoFileSystem; 012import org.jszip.pseudo.io.PseudoFileWriter; 013import org.mozilla.javascript.Context; 014import org.mozilla.javascript.Function; 015import org.mozilla.javascript.NativeJavaPackage; 016import org.mozilla.javascript.NativeJavaTopPackage; 017import org.mozilla.javascript.ScriptRuntime; 018import org.mozilla.javascript.Scriptable; 019import org.mozilla.javascript.ScriptableObject; 020import org.mozilla.javascript.tools.shell.Global; 021 022import java.io.IOException; 023import java.io.InputStream; 024 025/** 026 * @author stephenc 027 * @since 29/01/2013 22:51 028 */ 029public class GlobalFunctions { 030 /** 031 * Print the string values of its arguments. 032 * <p/> 033 * This method is defined as a JavaScript function. Note that its arguments 034 * are of the "varargs" form, which allows it to handle an arbitrary number 035 * of arguments supplied to the JavaScript function. 036 */ 037 public static void print(Context cx, Scriptable thisObj, Object[] args, Function funObj) { 038 StringBuilder builder = new StringBuilder(); 039 for (int i = 0; i < args.length; i++) { 040 if (i > 0) { 041 builder.append(" "); 042 } 043 044 // Convert the arbitrary JavaScript value into a string form. 045 String s = Context.toString(args[i]); 046 047 builder.append(s); 048 } 049 Log log = (Log) cx.getThreadLocal(Log.class); 050 if (log != null) { 051 for (String line : builder.toString().split("(\\r\\n?)|(\\n\\r?)")) { 052 log.info(line); 053 } 054 } 055 } 056 057 /** 058 * Print the string values of its arguments. 059 * <p/> 060 * This method is defined as a JavaScript function. Note that its arguments 061 * are of the "varargs" form, which allows it to handle an arbitrary number 062 * of arguments supplied to the JavaScript function. 063 */ 064 public static void debug(Context cx, Scriptable thisObj, Object[] args, Function funObj) { 065 StringBuilder builder = new StringBuilder(); 066 for (int i = 0; i < args.length; i++) { 067 if (i > 0) { 068 builder.append(" "); 069 } 070 071 // Convert the arbitrary JavaScript value into a string form. 072 String s = Context.toString(args[i]); 073 074 builder.append(s); 075 } 076 Log log = (Log) cx.getThreadLocal(Log.class); 077 if (log != null) { 078 for (String line : builder.toString().split("(\\r\\n?)|(\\n\\r?)")) { 079 log.debug(line); 080 } 081 } 082 } 083 084 /** 085 * Print the string values of its arguments. 086 * <p/> 087 * This method is defined as a JavaScript function. Note that its arguments 088 * are of the "varargs" form, which allows it to handle an arbitrary number 089 * of arguments supplied to the JavaScript function. 090 */ 091 public static void warn(Context cx, Scriptable thisObj, Object[] args, Function funObj) { 092 StringBuilder builder = new StringBuilder(); 093 for (int i = 0; i < args.length; i++) { 094 if (i > 0) { 095 builder.append(" "); 096 } 097 098 // Convert the arbitrary JavaScript value into a string form. 099 String s = Context.toString(args[i]); 100 101 builder.append(s); 102 } 103 Log log = (Log) cx.getThreadLocal(Log.class); 104 if (log != null) { 105 for (String line : builder.toString().split("(\\r\\n?)|(\\n\\r?)")) { 106 log.warn(line); 107 } 108 } 109 } 110 111 /** 112 * Print the string values of its arguments. 113 * <p/> 114 * This method is defined as a JavaScript function. Note that its arguments 115 * are of the "varargs" form, which allows it to handle an arbitrary number 116 * of arguments supplied to the JavaScript function. 117 */ 118 public static void quit(Context cx, Scriptable thisObj, Object[] args, Function funObj) { 119 final int exitCode = args.length == 0 ? 0 : ScriptRuntime.toInt32(args[0]); 120 final Log log = (Log) cx.getThreadLocal(Log.class); 121 cx.putThreadLocal(ExitCodeHolder.class, new ExitCodeHolder(exitCode)); 122 if (exitCode > 0) { 123 if (log != null) { 124 log.debug("Script exit code = " + exitCode); 125 } 126 } else { 127 if (log != null) { 128 log.debug("Script exit code = " + exitCode); 129 } 130 } 131 132 } 133 134 /** 135 * The readFile reads the given file content and convert it to a string 136 * using the specified character coding or default character coding if 137 * explicit coding argument is not given. 138 * <p> 139 * Usage: 140 * <pre> 141 * readFile(filePath) 142 * readFile(filePath, charCoding) 143 * </pre> 144 * The first form converts file's context to string using the default 145 * character coding. 146 */ 147 public static Object readFile(Context cx, Scriptable thisObj, Object[] args, 148 Function funObj) 149 throws IOException 150 { 151 if (args.length == 0) { 152 throw Context.reportRuntimeError("Bad arguments supplied to readFile()"); 153 } 154 String path = ScriptRuntime.toString(args[0]); 155 String charCoding = null; 156 if (args.length >= 2) { 157 charCoding = ScriptRuntime.toString(args[1]); 158 } 159 160 final PseudoFile file = PseudoFileSystem.current().getPseudoFile(path); 161 InputStream inputStream = null; 162 try { 163 inputStream = new PseudoFileInputStream(file); 164 return charCoding == null ? IOUtil.toString(inputStream) : IOUtil.toString(inputStream, charCoding); 165 } finally { 166 IOUtil.close(inputStream); 167 } 168 } 169 170 171 public static void setExitCode(int exitCode) { 172 Context.getCurrentContext().putThreadLocal(ExitCodeHolder.class, new ExitCodeHolder(exitCode)); 173 } 174 175 public static Integer getExitCode() { 176 final Context context = Context.getCurrentContext(); 177 if (context != null) { 178 ExitCodeHolder result = (ExitCodeHolder) context.getThreadLocal(ExitCodeHolder.class); 179 context.putThreadLocal(GlobalFunctions.ExitCodeHolder.class, null); 180 return result == null ? null : result.getExitCode(); 181 } 182 return null; 183 } 184 185 public static Scriptable createPseudoFileSystemScope(Global global, Context context) { 186 Scriptable scope = context.newObject(global); 187 scope.setPrototype(global); 188 scope.setParentScope(null); 189 190 NativeJavaTopPackage $packages = (NativeJavaTopPackage) global.get("Packages"); 191 NativeJavaPackage $java = (NativeJavaPackage) $packages.get("java"); 192 NativeJavaPackage $java_io = (NativeJavaPackage) $java.get("io"); 193 194 ProxyNativeJavaPackage proxy$java = new ProxyNativeJavaPackage($java); 195 ProxyNativeJavaPackage proxy$java_io = new ProxyNativeJavaPackage($java_io); 196 proxy$java_io.put("File", global, get(global, "Packages." + ProxyPseudoFile.class.getName())); 197 proxy$java_io.put("FileInputStream", global, 198 get(global, "Packages." + PseudoFileInputStream.class.getName())); 199 proxy$java_io.put("FileOutputStream", global, 200 get(global, "Packages." + PseudoFileOutputStream.class.getName())); 201 proxy$java_io.put("FileReader", global, 202 get(global, "Packages." + PseudoFileReader.class.getName())); 203 proxy$java_io.put("FileWriter", global, 204 get(global, "Packages." + PseudoFileWriter.class.getName())); 205 proxy$java.put("io", global, proxy$java_io); 206 global.defineProperty("java", proxy$java, ScriptableObject.DONTENUM); 207 return scope; 208 } 209 210 public static Object get(Scriptable scope, String name) { 211 Scriptable cur = scope; 212 for (String part : StringUtils.split(name, ".")) { 213 Object next = cur.get(part, scope); 214 if (next instanceof Scriptable) { 215 cur = (Scriptable) next; 216 } else { 217 return null; 218 } 219 } 220 return cur; 221 } 222 223 private static class ExitCodeHolder { 224 private final int exitCode; 225 226 private ExitCodeHolder(int exitCode) { 227 this.exitCode = exitCode; 228 } 229 230 public int getExitCode() { 231 return exitCode; 232 } 233 234 } 235 236 237}