1 /*
2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package jdk.nashorn.tools;
27 
28 import static jdk.nashorn.internal.lookup.Lookup.MH;
29 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
30 
31 import java.io.BufferedReader;
32 import java.io.File;
33 import java.io.IOException;
34 import java.io.InputStreamReader;
35 import java.io.OutputStreamWriter;
36 import java.lang.invoke.MethodHandle;
37 import java.lang.invoke.MethodHandles;
38 import jdk.nashorn.internal.runtime.JSType;
39 import jdk.nashorn.internal.objects.Global;
40 
41 /**
42  * Global functions supported only in shell interactive mode.
43  */
44 public final class ShellFunctions {
45 
46     /** Handle to implementation of {@link ShellFunctions#input} - Nashorn extension */
47     public static final MethodHandle INPUT = findOwnMH("input", Object.class, Object.class, Object.class, Object.class);
48 
49     /** Handle to implementation of {@link ShellFunctions#evalinput} - Nashorn extension */
50     public static final MethodHandle EVALINPUT = findOwnMH("evalinput",     Object.class, Object.class, Object.class, Object.class);
51 
ShellFunctions()52     private ShellFunctions() {
53     }
54 
55     /**
56      * Nashorn extension: global.input (shell-interactive-mode-only)
57      * Read one or more lines of input from the standard input till the
58      * given end marker is seen in standard input.
59      *
60      * @param self   self reference
61      * @param endMarker String used as end marker for input
62      * @param prompt String used as input prompt
63      *
64      * @return line that was read
65      *
66      * @throws IOException if an exception occurs
67      */
input(final Object self, final Object endMarker, final Object prompt)68     public static Object input(final Object self, final Object endMarker, final Object prompt) throws IOException {
69         final String endMarkerStr = (endMarker != UNDEFINED)? JSType.toString(endMarker) : "";
70         final String promptStr = (prompt != UNDEFINED)? JSType.toString(prompt)  : ">> ";
71         final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
72         final StringBuilder buf = new StringBuilder();
73         while (true) {
74             System.out.print(promptStr);
75             final String line = reader.readLine();
76             if (line == null || line.equals(endMarkerStr)) {
77                 break;
78             }
79             buf.append(line);
80             buf.append('\n');
81         }
82         return buf.toString();
83     }
84 
85     /**
86      * Nashorn extension: Reads zero or more lines from standard input and
87      * evaluates the concatenated string as code
88      *
89      * @param self self reference
90      * @param endMarker String used as end marker for input
91      * @param prompt String used as input prompt
92      *
93      * @return output from evaluating the script
94      *
95      * @throws IOException if an exception occurs
96      */
evalinput(final Object self, final Object endMarker, final Object prompt)97     public static Object evalinput(final Object self, final Object endMarker, final Object prompt) throws IOException {
98         return Global.eval(self, input(self, endMarker, prompt));
99     }
100 
findOwnMH(final String name, final Class<?> rtype, final Class<?>... types)101     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
102         return MH.findStatic(MethodHandles.lookup(), ShellFunctions.class, name, MH.type(rtype, types));
103     }
104 }
105