Main.java revision 1378:54af83b4a714
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
26package jdk.nashorn.tools.jjs;
27
28import java.io.BufferedReader;
29import java.io.File;
30import java.io.InputStream;
31import java.io.InputStreamReader;
32import java.io.IOException;
33import java.io.OutputStream;
34import java.io.PrintWriter;
35import jdk.internal.jline.console.completer.Completer;
36import jdk.internal.jline.console.UserInterruptException;
37import jdk.nashorn.api.scripting.NashornException;
38import jdk.nashorn.internal.objects.Global;
39import jdk.nashorn.internal.runtime.Context;
40import jdk.nashorn.internal.runtime.JSType;
41import jdk.nashorn.internal.runtime.ScriptEnvironment;
42import jdk.nashorn.internal.runtime.ScriptRuntime;
43import jdk.nashorn.tools.Shell;
44
45/**
46 * Interactive command line Shell for Nashorn.
47 */
48public final class Main extends Shell {
49    private Main() {}
50
51    // file where history is persisted.
52    private static final File HIST_FILE = new File(new File(System.getProperty("user.home")), ".jjs.history");
53
54    /**
55     * Main entry point with the default input, output and error streams.
56     *
57     * @param args The command line arguments
58     */
59    public static void main(final String[] args) {
60        try {
61            final int exitCode = main(System.in, System.out, System.err, args);
62            if (exitCode != SUCCESS) {
63                System.exit(exitCode);
64            }
65        } catch (final IOException e) {
66            System.err.println(e); //bootstrapping, Context.err may not exist
67            System.exit(IO_ERROR);
68        }
69    }
70
71    /**
72     * Starting point for executing a {@code Shell}. Starts a shell with the
73     * given arguments and streams and lets it run until exit.
74     *
75     * @param in input stream for Shell
76     * @param out output stream for Shell
77     * @param err error stream for Shell
78     * @param args arguments to Shell
79     *
80     * @return exit code
81     *
82     * @throws IOException if there's a problem setting up the streams
83     */
84    public static int main(final InputStream in, final OutputStream out, final OutputStream err, final String[] args) throws IOException {
85        return new Main().run(in, out, err, args);
86    }
87
88    /**
89     * read-eval-print loop for Nashorn shell.
90     *
91     * @param context the nashorn context
92     * @param global  global scope object to use
93     * @return return code
94     */
95    protected int readEvalPrint(final Context context, final Global global) {
96        final ScriptEnvironment env = context.getEnv();
97        final String prompt = bundle.getString("shell.prompt");
98        final PrintWriter err = context.getErr();
99        final Global oldGlobal = Context.getGlobal();
100        final boolean globalChanged = (oldGlobal != global);
101        final Completer completer = new NashornCompleter(context, global);
102
103        try (final Console in = new Console(System.in, System.out, HIST_FILE, completer)) {
104            if (globalChanged) {
105                Context.setGlobal(global);
106            }
107
108            global.addShellBuiltins();
109            // expose history object for reflecting on command line history
110            global.put("history", new HistoryObject(in.getHistory()), false);
111
112            while (true) {
113                String source = "";
114                try {
115                    source = in.readLine(prompt);
116                } catch (final IOException ioe) {
117                    err.println(ioe.toString());
118                    if (env._dump_on_error) {
119                        ioe.printStackTrace(err);
120                    }
121                    return IO_ERROR;
122                } catch (final UserInterruptException ex) {
123                    break;
124                }
125
126                if (source.isEmpty()) {
127                    continue;
128                }
129
130                try {
131                    final Object res = context.eval(global, source, global, "<shell>");
132                    if (res != ScriptRuntime.UNDEFINED) {
133                        err.println(JSType.toString(res));
134                    }
135                } catch (final Exception e) {
136                    err.println(e);
137                    if (env._dump_on_error) {
138                        e.printStackTrace(err);
139                    }
140                }
141            }
142        } catch (final Exception e) {
143            err.println(e);
144            if (env._dump_on_error) {
145                e.printStackTrace(err);
146            }
147        } finally {
148            if (globalChanged) {
149                Context.setGlobal(oldGlobal);
150            }
151        }
152
153        return SUCCESS;
154    }
155}
156