src/jdk/nashorn/internal/runtime/ScriptingFunctions.java

Wed, 06 Feb 2013 11:57:51 -0400

author
jlaskey
date
Wed, 06 Feb 2013 11:57:51 -0400
changeset 75
2ca25bf25d0c
parent 69
c48e8a28da90
child 82
abea4ba28901
permissions
-rw-r--r--

8007629: Remove extraneous quit from shell.js
Reviewed-by: sundar, hannesw
Contributed-by: james.laskey@oracle.com

jlaskey@3 1 /*
jlaskey@7 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
jlaskey@3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jlaskey@3 4 *
jlaskey@3 5 * This code is free software; you can redistribute it and/or modify it
jlaskey@3 6 * under the terms of the GNU General Public License version 2 only, as
jlaskey@3 7 * published by the Free Software Foundation. Oracle designates this
jlaskey@3 8 * particular file as subject to the "Classpath" exception as provided
jlaskey@3 9 * by Oracle in the LICENSE file that accompanied this code.
jlaskey@3 10 *
jlaskey@3 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jlaskey@3 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jlaskey@3 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jlaskey@3 14 * version 2 for more details (a copy is included in the LICENSE file that
jlaskey@3 15 * accompanied this code).
jlaskey@3 16 *
jlaskey@3 17 * You should have received a copy of the GNU General Public License version
jlaskey@3 18 * 2 along with this work; if not, write to the Free Software Foundation,
jlaskey@3 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jlaskey@3 20 *
jlaskey@3 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jlaskey@3 22 * or visit www.oracle.com if you need additional information or have any
jlaskey@3 23 * questions.
jlaskey@3 24 */
jlaskey@3 25
jlaskey@3 26 package jdk.nashorn.internal.runtime;
jlaskey@3 27
jlaskey@3 28 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
jlaskey@3 29 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
jlaskey@3 30 import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
jlaskey@3 31
jlaskey@3 32 import java.io.BufferedReader;
jlaskey@3 33 import java.io.File;
jlaskey@3 34 import java.io.IOException;
jlaskey@67 35 import java.io.InputStream;
jlaskey@3 36 import java.io.InputStreamReader;
jlaskey@67 37 import java.io.OutputStream;
jlaskey@3 38 import java.lang.invoke.MethodHandle;
jlaskey@3 39 import java.lang.invoke.MethodHandles;
jlaskey@67 40 import java.util.HashMap;
jlaskey@67 41 import java.util.Map;
jlaskey@67 42 import java.util.Set;
jlaskey@67 43 import java.util.StringTokenizer;
jlaskey@3 44
jlaskey@3 45 /**
jlaskey@3 46 * Global functions supported only in scripting mode.
jlaskey@3 47 */
jlaskey@3 48 public class ScriptingFunctions {
jlaskey@3 49
lagergren@57 50 /** Handle to implementation of {@link ScriptingFunctions#readLine} - Nashorn extension */
jlaskey@3 51 public static final MethodHandle READLINE = findOwnMH("readLine", Object.class, Object.class);
jlaskey@3 52
sundar@52 53 /** Handle to implementation of {@link ScriptingFunctions#readFully} - Nashorn extension */
sundar@52 54 public static final MethodHandle READFULLY = findOwnMH("readFully", Object.class, Object.class, Object.class);
jlaskey@3 55
jlaskey@75 56 /** Handle to implementation of {@link ScriptingFunctions#exec} - Nashorn extension */
jlaskey@67 57 public static final MethodHandle EXEC = findOwnMH("exec", Object.class, Object.class, Object.class, Object.class);
jlaskey@67 58
jlaskey@67 59 /** Names of special properties used by $EXEC API. */
jlaskey@67 60 public static final String EXEC_NAME = "$EXEC";
sundar@69 61 public static final String OUT_NAME = "$OUT";
sundar@69 62 public static final String ERR_NAME = "$ERR";
sundar@69 63 public static final String EXIT_NAME = "$EXIT";
jlaskey@67 64
jlaskey@67 65 /** Names of special properties used by $ENV API. */
jlaskey@67 66 public static final String ENV_NAME = "$ENV";
jlaskey@67 67 private static final String PWD_NAME = "PWD";
jlaskey@67 68
jlaskey@3 69 private ScriptingFunctions() {
jlaskey@3 70 }
jlaskey@3 71
jlaskey@3 72 /**
jlaskey@3 73 * Nashorn extension: global.readLine (scripting-mode-only)
jlaskey@3 74 * Read one line of input from the standard input.
jlaskey@3 75 *
jlaskey@3 76 * @param self self reference
jlaskey@3 77 *
jlaskey@3 78 * @return line that was read
jlaskey@3 79 *
jlaskey@3 80 * @throws IOException if an exception occurs
jlaskey@3 81 */
jlaskey@3 82 public static Object readLine(final Object self) throws IOException {
jlaskey@3 83 final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
jlaskey@3 84 return reader.readLine();
jlaskey@3 85 }
jlaskey@3 86
jlaskey@3 87 /**
jlaskey@3 88 * Nashorn extension: Read the entire contents of a text file and return as String.
jlaskey@3 89 *
jlaskey@3 90 * @param self self reference
jlaskey@3 91 * @param file The input file whose content is read.
jlaskey@3 92 *
jlaskey@3 93 * @return String content of the input file.
jlaskey@3 94 *
jlaskey@3 95 * @throws IOException if an exception occurs
jlaskey@3 96 */
sundar@52 97 public static Object readFully(final Object self, final Object file) throws IOException {
jlaskey@3 98 File f = null;
jlaskey@3 99
jlaskey@3 100 if (file instanceof File) {
jlaskey@3 101 f = (File)file;
jlaskey@3 102 } else if (file instanceof String) {
jlaskey@3 103 f = new java.io.File((String)file);
jlaskey@3 104 }
jlaskey@3 105
jlaskey@3 106 if (f == null || !f.isFile()) {
sundar@44 107 typeError("not.a.file", ScriptRuntime.safeToString(file));
jlaskey@3 108 return UNDEFINED;
jlaskey@3 109 }
jlaskey@3 110
jlaskey@3 111 return new String(Source.readFully(f));
jlaskey@3 112 }
jlaskey@3 113
jlaskey@3 114 /**
jlaskey@67 115 * Nashorn extension: exec a string in a separate process.
jlaskey@67 116 *
jlaskey@67 117 * @param self self reference
jlaskey@67 118 * @param string string to execute
jlaskey@67 119 *
jlaskey@67 120 * @return output string from the request
jlaskey@67 121 */
jlaskey@67 122 public static Object exec(final Object self, final Object string, final Object input) throws IOException, InterruptedException {
jlaskey@67 123 // Current global is need to fetch additional inputs and for additional results.
jlaskey@67 124 final ScriptObject global = Context.getGlobal();
jlaskey@67 125
jlaskey@67 126 // Break exec string into tokens.
jlaskey@67 127 final StringTokenizer tokenizer = new StringTokenizer(JSType.toString(string));
jlaskey@67 128 final String[] cmdArray = new String[tokenizer.countTokens()];
jlaskey@67 129 for (int i = 0; tokenizer.hasMoreTokens(); i++) {
jlaskey@67 130 cmdArray[i] = tokenizer.nextToken();
jlaskey@67 131 }
jlaskey@67 132
jlaskey@67 133 // Set up initial process.
jlaskey@67 134 final ProcessBuilder processBuilder = new ProcessBuilder(cmdArray);
jlaskey@67 135
sundar@69 136 // Current ENV property state.
sundar@69 137 final Object env = global.get(ENV_NAME);
sundar@69 138 if (env instanceof ScriptObject) {
sundar@69 139 final ScriptObject envProperties = (ScriptObject)env;
jlaskey@67 140
sundar@69 141 // If a working directory is present, use it.
sundar@69 142 final Object pwd = envProperties.get(PWD_NAME);
sundar@69 143 if (pwd != UNDEFINED) {
sundar@69 144 processBuilder.directory(new File(JSType.toString(pwd)));
sundar@69 145 }
jlaskey@67 146
sundar@69 147 // Set up ENV variables.
sundar@69 148 final Map<String, String> environment = processBuilder.environment();
sundar@69 149 environment.clear();
sundar@69 150 for (Map.Entry<Object, Object> entry : envProperties.entrySet()) {
sundar@69 151 environment.put(JSType.toString(entry.getKey()), JSType.toString(entry.getValue()));
sundar@69 152 }
jlaskey@67 153 }
jlaskey@67 154
jlaskey@67 155 // Start the process.
jlaskey@67 156 final Process process = processBuilder.start();
jlaskey@67 157
jlaskey@67 158 // If input is present, pass on to process.
jlaskey@67 159 try (OutputStream outputStream = process.getOutputStream()) {
jlaskey@67 160 if (input != UNDEFINED) {
jlaskey@67 161 outputStream.write(JSType.toString(input).getBytes());
jlaskey@67 162 }
jlaskey@67 163 }
jlaskey@67 164
jlaskey@67 165 // Wait for the process to complete.
jlaskey@67 166 final int exit = process.waitFor();
jlaskey@67 167
jlaskey@67 168 // Collect output.
jlaskey@67 169 String out;
jlaskey@67 170 try (InputStream inputStream = process.getInputStream()) {
jlaskey@67 171 final StringBuilder outBuffer = new StringBuilder();
jlaskey@67 172 for (int ch; (ch = inputStream.read()) != -1; ) {
jlaskey@67 173 outBuffer.append((char)ch);
jlaskey@67 174 }
jlaskey@67 175 out = outBuffer.toString();
jlaskey@67 176 }
jlaskey@67 177
jlaskey@67 178 // Collect errors.
jlaskey@67 179 String err;
jlaskey@67 180 try (InputStream errorStream = process.getErrorStream()) {
jlaskey@67 181 final StringBuilder errBuffer = new StringBuilder();
jlaskey@67 182 for (int ch; (ch = errorStream.read()) != -1; ) {
jlaskey@67 183 errBuffer.append((char)ch);
jlaskey@67 184 }
jlaskey@67 185 err = errBuffer.toString();
jlaskey@67 186 }
jlaskey@67 187
jlaskey@67 188 // Set globals for secondary results.
jlaskey@67 189 final boolean isStrict = global.isStrictContext();
jlaskey@67 190 global.set(OUT_NAME, out, isStrict);
jlaskey@67 191 global.set(ERR_NAME, err, isStrict);
jlaskey@67 192 global.set(EXIT_NAME, exit, isStrict);
jlaskey@67 193
jlaskey@67 194 // Return the result from stdout.
jlaskey@67 195 return out;
jlaskey@67 196 }
jlaskey@67 197
jlaskey@3 198 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
jlaskey@3 199 return MH.findStatic(MethodHandles.lookup(), ScriptingFunctions.class, name, MH.type(rtype, types));
jlaskey@3 200 }
jlaskey@3 201 }

mercurial