1 /*
2  * Copyright (c) 2005, 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 
26 package javax.script;
27 import java.io.Reader;
28 import java.util.Map;
29 import java.util.Iterator;
30 
31 /**
32  * Provides a standard implementation for several of the variants of the <code>eval</code>
33  * method.
34  * <br><br>
35  * <code><b>eval(Reader)</b></code><p><code><b>eval(String)</b></code><p>
36  * <code><b>eval(String, Bindings)</b></code><p><code><b>eval(Reader, Bindings)</b></code>
37  * <br><br> are implemented using the abstract methods
38  * <br><br>
39  * <code><b>eval(Reader,ScriptContext)</b></code> or
40  * <code><b>eval(String, ScriptContext)</b></code>
41  * <br><br>
42  * with a <code>SimpleScriptContext</code>.
43  * <br><br>
44  * A <code>SimpleScriptContext</code> is used as the default <code>ScriptContext</code>
45  * of the <code>AbstractScriptEngine</code>..
46  *
47  * @author Mike Grogan
48  * @since 1.6
49  */
50 public abstract class AbstractScriptEngine  implements ScriptEngine {
51 
52     /**
53      * The default <code>ScriptContext</code> of this <code>AbstractScriptEngine</code>.
54      */
55 
56     protected ScriptContext context;
57 
58     /**
59      * Creates a new instance of AbstractScriptEngine using a <code>SimpleScriptContext</code>
60      * as its default <code>ScriptContext</code>.
61      */
AbstractScriptEngine()62     public AbstractScriptEngine() {
63 
64         context = new SimpleScriptContext();
65 
66     }
67 
68     /**
69      * Creates a new instance using the specified <code>Bindings</code> as the
70      * <code>ENGINE_SCOPE</code> <code>Bindings</code> in the protected <code>context</code> field.
71      *
72      * @param n The specified <code>Bindings</code>.
73      * @throws NullPointerException if n is null.
74      */
AbstractScriptEngine(Bindings n)75     public AbstractScriptEngine(Bindings n) {
76 
77         this();
78         if (n == null) {
79             throw new NullPointerException("n is null");
80         }
81         context.setBindings(n, ScriptContext.ENGINE_SCOPE);
82     }
83 
84     /**
85      * Sets the value of the protected <code>context</code> field to the specified
86      * <code>ScriptContext</code>.
87      *
88      * @param ctxt The specified <code>ScriptContext</code>.
89      * @throws NullPointerException if ctxt is null.
90      */
setContext(ScriptContext ctxt)91     public void setContext(ScriptContext ctxt) {
92         if (ctxt == null) {
93             throw new NullPointerException("null context");
94         }
95         context = ctxt;
96     }
97 
98     /**
99      * Returns the value of the protected <code>context</code> field.
100      *
101      * @return The value of the protected <code>context</code> field.
102      */
getContext()103     public ScriptContext getContext() {
104         return context;
105     }
106 
107     /**
108      * Returns the <code>Bindings</code> with the specified scope value in
109      * the protected <code>context</code> field.
110      *
111      * @param scope The specified scope
112      *
113      * @return The corresponding <code>Bindings</code>.
114      *
115      * @throws IllegalArgumentException if the value of scope is
116      * invalid for the type the protected <code>context</code> field.
117      */
getBindings(int scope)118     public Bindings getBindings(int scope) {
119 
120         if (scope == ScriptContext.GLOBAL_SCOPE) {
121             return context.getBindings(ScriptContext.GLOBAL_SCOPE);
122         } else if (scope == ScriptContext.ENGINE_SCOPE) {
123             return context.getBindings(ScriptContext.ENGINE_SCOPE);
124         } else {
125             throw new IllegalArgumentException("Invalid scope value.");
126         }
127     }
128 
129     /**
130      * Sets the <code>Bindings</code> with the corresponding scope value in the
131      * <code>context</code> field.
132      *
133      * @param bindings The specified <code>Bindings</code>.
134      * @param scope The specified scope.
135      *
136      * @throws IllegalArgumentException if the value of scope is
137      * invalid for the type the <code>context</code> field.
138      * @throws NullPointerException if the bindings is null and the scope is
139      * <code>ScriptContext.ENGINE_SCOPE</code>
140      */
setBindings(Bindings bindings, int scope)141     public void setBindings(Bindings bindings, int scope) {
142 
143         if (scope == ScriptContext.GLOBAL_SCOPE) {
144             context.setBindings(bindings, ScriptContext.GLOBAL_SCOPE);;
145         } else if (scope == ScriptContext.ENGINE_SCOPE) {
146             context.setBindings(bindings, ScriptContext.ENGINE_SCOPE);;
147         } else {
148             throw new IllegalArgumentException("Invalid scope value.");
149         }
150     }
151 
152     /**
153      * Sets the specified value with the specified key in the <code>ENGINE_SCOPE</code>
154      * <code>Bindings</code> of the protected <code>context</code> field.
155      *
156      * @param key The specified key.
157      * @param value The specified value.
158      *
159      * @throws NullPointerException if key is null.
160      * @throws IllegalArgumentException if key is empty.
161      */
put(String key, Object value)162     public void put(String key, Object value) {
163 
164         Bindings nn = getBindings(ScriptContext.ENGINE_SCOPE);
165         if (nn != null) {
166             nn.put(key, value);
167         }
168 
169     }
170 
171     /**
172      * Gets the value for the specified key in the <code>ENGINE_SCOPE</code> of the
173      * protected <code>context</code> field.
174      *
175      * @return The value for the specified key.
176      *
177      * @throws NullPointerException if key is null.
178      * @throws IllegalArgumentException if key is empty.
179      */
get(String key)180     public Object get(String key) {
181 
182         Bindings nn = getBindings(ScriptContext.ENGINE_SCOPE);
183         if (nn != null) {
184             return nn.get(key);
185         }
186 
187         return null;
188     }
189 
190 
191     /**
192      * <code>eval(Reader, Bindings)</code> calls the abstract
193      * <code>eval(Reader, ScriptContext)</code> method, passing it a <code>ScriptContext</code>
194      * whose Reader, Writers and Bindings for scopes other that <code>ENGINE_SCOPE</code>
195      * are identical to those members of the protected <code>context</code> field.  The specified
196      * <code>Bindings</code> is used instead of the <code>ENGINE_SCOPE</code>
197      *
198      * <code>Bindings</code> of the <code>context</code> field.
199      *
200      * @param reader A <code>Reader</code> containing the source of the script.
201      * @param bindings A <code>Bindings</code> to use for the <code>ENGINE_SCOPE</code>
202      * while the script executes.
203      *
204      * @return The return value from <code>eval(Reader, ScriptContext)</code>
205      * @throws ScriptException if an error occurs in script.
206      * @throws NullPointerException if any of the parameters is null.
207      */
eval(Reader reader, Bindings bindings )208     public Object eval(Reader reader, Bindings bindings ) throws ScriptException {
209 
210         ScriptContext ctxt = getScriptContext(bindings);
211 
212         return eval(reader, ctxt);
213     }
214 
215 
216     /**
217      * Same as <code>eval(Reader, Bindings)</code> except that the abstract
218      * <code>eval(String, ScriptContext)</code> is used.
219      *
220      * @param script A <code>String</code> containing the source of the script.
221      *
222      * @param bindings A <code>Bindings</code> to use as the <code>ENGINE_SCOPE</code>
223      * while the script executes.
224      *
225      * @return The return value from <code>eval(String, ScriptContext)</code>
226      * @throws ScriptException if an error occurs in script.
227      * @throws NullPointerException if any of the parameters is null.
228      */
eval(String script, Bindings bindings)229     public Object eval(String script, Bindings bindings) throws ScriptException {
230 
231         ScriptContext ctxt = getScriptContext(bindings);
232 
233         return eval(script , ctxt);
234     }
235 
236     /**
237      * <code>eval(Reader)</code> calls the abstract
238      * <code>eval(Reader, ScriptContext)</code> passing the value of the <code>context</code>
239      * field.
240      *
241      * @param reader A <code>Reader</code> containing the source of the script.
242      * @return The return value from <code>eval(Reader, ScriptContext)</code>
243      * @throws ScriptException if an error occurs in script.
244      * @throws NullPointerException if any of the parameters is null.
245      */
eval(Reader reader)246     public Object eval(Reader reader) throws ScriptException {
247 
248 
249         return eval(reader, context);
250     }
251 
252     /**
253      * Same as <code>eval(Reader)</code> except that the abstract
254      * <code>eval(String, ScriptContext)</code> is used.
255      *
256      * @param script A <code>String</code> containing the source of the script.
257      * @return The return value from <code>eval(String, ScriptContext)</code>
258      * @throws ScriptException if an error occurs in script.
259      * @throws NullPointerException if any of the parameters is null.
260      */
eval(String script)261     public Object eval(String script) throws ScriptException {
262 
263 
264         return eval(script, context);
265     }
266 
267     /**
268      * Returns a <code>SimpleScriptContext</code>.  The <code>SimpleScriptContext</code>:
269      *<br><br>
270      * <ul>
271      * <li>Uses the specified <code>Bindings</code> for its <code>ENGINE_SCOPE</code>
272      * </li>
273      * <li>Uses the <code>Bindings</code> returned by the abstract <code>getGlobalScope</code>
274      * method as its <code>GLOBAL_SCOPE</code>
275      * </li>
276      * <li>Uses the Reader and Writer in the default <code>ScriptContext</code> of this
277      * <code>ScriptEngine</code>
278      * </li>
279      * </ul>
280      * <br><br>
281      * A <code>SimpleScriptContext</code> returned by this method is used to implement eval methods
282      * using the abstract <code>eval(Reader,Bindings)</code> and <code>eval(String,Bindings)</code>
283      * versions.
284      *
285      * @param nn Bindings to use for the <code>ENGINE_SCOPE</code>
286      * @return The <code>SimpleScriptContext</code>
287      */
getScriptContext(Bindings nn)288     protected ScriptContext getScriptContext(Bindings nn) {
289 
290         SimpleScriptContext ctxt = new SimpleScriptContext(context.getReader(), context.getWriter(), context.getErrorWriter());
291         Bindings gs = getBindings(ScriptContext.GLOBAL_SCOPE);
292 
293         if (gs != null) {
294             ctxt.setBindings(gs, ScriptContext.GLOBAL_SCOPE);
295         }
296 
297         if (nn != null) {
298             ctxt.setBindings(nn,
299                     ScriptContext.ENGINE_SCOPE);
300         } else {
301             throw new NullPointerException("Engine scope Bindings may not be null.");
302         }
303 
304         return ctxt;
305 
306     }
307 }
308