SharedContextEvaluator.java revision 6:5a1b0714df0e
1/*
2 * Copyright (c) 2010, 2013, 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.internal.test.framework;
27
28import static jdk.nashorn.tools.Shell.COMPILATION_ERROR;
29import static jdk.nashorn.tools.Shell.RUNTIME_ERROR;
30import static jdk.nashorn.tools.Shell.SUCCESS;
31
32import java.io.File;
33import java.io.IOException;
34import java.io.OutputStream;
35import java.io.PrintWriter;
36import jdk.nashorn.api.scripting.NashornException;
37import jdk.nashorn.internal.runtime.Context;
38import jdk.nashorn.internal.runtime.ErrorManager;
39import jdk.nashorn.internal.runtime.ScriptFunction;
40import jdk.nashorn.internal.runtime.ScriptObject;
41import jdk.nashorn.internal.runtime.ScriptRuntime;
42import jdk.nashorn.internal.runtime.options.Options;
43
44/**
45 * A script evaluator that shares a single Nashorn Context instance to run
46 * scripts many times on it.
47 */
48public final class SharedContextEvaluator implements ScriptEvaluator {
49    // The shared Nashorn Context
50    private final Context context;
51
52    // We can't replace output and error streams after Context is created
53    // So, we create these delegating streams - so that we can replace underlying
54    // delegate streams for each script run call
55    private final DelegatingOutputStream ctxOut;
56    private final DelegatingOutputStream ctxErr;
57
58    private static class DelegatingOutputStream extends OutputStream {
59        private OutputStream underlying;
60
61        public DelegatingOutputStream(final OutputStream out) {
62            this.underlying = out;
63        }
64
65        @Override
66        public void close() throws IOException {
67            underlying.close();
68        }
69
70        @Override
71        public void flush() throws IOException {
72            underlying.flush();
73        }
74
75        @Override
76        public void write(byte[] b) throws IOException {
77            underlying.write(b);
78        }
79
80        @Override
81        public void write(byte[] b, int off, int len) throws IOException {
82            underlying.write(b, off, len);
83        }
84
85        @Override
86        public void write(int b) throws IOException {
87            underlying.write(b);
88        }
89
90        void setDelegatee(OutputStream stream) {
91            this.underlying = stream;
92        }
93    }
94
95    /**
96     * SharedContextEvaluator constructor
97     * @param args initial script arguments to create shared context
98     */
99    public SharedContextEvaluator(final String[] args) {
100        this.ctxOut = new DelegatingOutputStream(System.out);
101        this.ctxErr = new DelegatingOutputStream(System.err);
102        PrintWriter wout = new PrintWriter(ctxOut, true);
103        PrintWriter werr = new PrintWriter(ctxErr, true);
104        Options options = new Options("nashorn", werr);
105        options.process(args);
106        ErrorManager errors = new ErrorManager(werr);
107        this.context = new Context(options, errors, wout, werr);
108    }
109
110    @Override
111    public int run(final OutputStream out, final OutputStream err, final String[] args) throws IOException {
112        final ScriptObject oldGlobal = Context.getGlobal();
113        try {
114            ctxOut.setDelegatee(out);
115            ctxErr.setDelegatee(err);
116            final ErrorManager errors = context.getErrors();
117            final ScriptObject global = context.createGlobal();
118            Context.setGlobal(global);
119
120            // For each file on the command line.
121            for (final String fileName : args) {
122                if (fileName.startsWith("-")) {
123                    // ignore options in shared context mode (which was initialized upfront!)
124                    continue;
125                }
126                final File file = new File(fileName);
127                ScriptFunction script = context.compileScript(fileName, file.toURI().toURL(), global, context._strict);
128                if (script == null || errors.getNumberOfErrors() != 0) {
129                    return COMPILATION_ERROR;
130                }
131
132                try {
133                    ScriptRuntime.apply(script, global);
134                } catch (final NashornException e) {
135                    errors.error(e.toString());
136                    if (context._dump_on_error) {
137                        e.printStackTrace(context.getErr());
138                    }
139
140                    return RUNTIME_ERROR;
141                }
142            }
143        } finally {
144            context.getOut().flush();
145            context.getErr().flush();
146            Context.setGlobal(oldGlobal);
147        }
148
149        return SUCCESS;
150    }
151}
152