History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/script/javascript (13 of 18352 files). Show all

Unified · Split

13 files
  1. java/pkg/com/sun/script/javascript/ExternalScriptable.java +467 −0
  2. java/pkg/com/sun/script/javascript/JSAdapter.java +338 −0
  3. java/pkg/com/sun/script/javascript/JavaAdapter.java +106 −0
  4. java/pkg/com/sun/script/javascript/META-INF/mkfile +6 −0
  5. java/pkg/com/sun/script/javascript/META-INF/services/javax.script.ScriptEngineFactory +5 −0
  6. java/pkg/com/sun/script/javascript/META-INF/services/mkfile +2 −0
  7. java/pkg/com/sun/script/javascript/RhinoClassShutter.java +75 −0
  8. java/pkg/com/sun/script/javascript/RhinoCompiledScript.java +78 −0
  9. java/pkg/com/sun/script/javascript/RhinoScriptEngine.java +398 −0
  10. java/pkg/com/sun/script/javascript/RhinoScriptEngineFactory.java +163 −0
  11. java/pkg/com/sun/script/javascript/RhinoTopLevel.java +156 −0
  12. java/pkg/com/sun/script/javascript/RhinoWrapFactory.java +148 −0
  13. java/pkg/com/sun/script/javascript/mkfile +20 −0
java/pkg/com/sun/script/javascript/ExternalScriptable.java+467−0
@@ -0,0 +1,467 @@
1/*
2 * Copyright (c) 2005, 2006, 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 com.sun.script.javascript;
27import sun.org.mozilla.javascript.internal.*;
28import javax.script.*;
29import java.util.*;
30
31/**
32 * ExternalScriptable is an implementation of Scriptable
33 * backed by a JSR 223 ScriptContext instance.
34 *
35 * @author Mike Grogan
36 * @author A. Sundararajan
37 * @since 1.6
38 */
39
40final class ExternalScriptable implements Scriptable {
41 /* Underlying ScriptContext that we use to store
42 * named variables of this scope.
43 */
44 private ScriptContext context;
45
46 /* JavaScript allows variables to be named as numbers (indexed
47 * properties). This way arrays, objects (scopes) are treated uniformly.
48 * Note that JSR 223 API supports only String named variables and
49 * so we can't store these in Bindings. Also, JavaScript allows name
50 * of the property name to be even empty String! Again, JSR 223 API
51 * does not support empty name. So, we use the following fallback map
52 * to store such variables of this scope. This map is not exposed to
53 * JSR 223 API. We can just script objects "as is" and need not convert.
54 */
55 private Map<Object, Object> indexedProps;
56
57 // my prototype
58 private Scriptable prototype;
59 // my parent scope, if any
60 private Scriptable parent;
61
62 ExternalScriptable(ScriptContext context) {
63 this(context, new HashMap<Object, Object>());
64 }
65
66 ExternalScriptable(ScriptContext context, Map<Object, Object> indexedProps) {
67 if (context == null) {
68 throw new NullPointerException("context is null");
69 }
70 this.context = context;
71 this.indexedProps = indexedProps;
72 }
73
74 ScriptContext getContext() {
75 return context;
76 }
77
78 private boolean isEmpty(String name) {
79 return name.equals("");
80 }
81
82 /**
83 * Return the name of the class.
84 */
85 public String getClassName() {
86 return "Global";
87 }
88
89 /**
90 * Returns the value of the named property or NOT_FOUND.
91 *
92 * If the property was created using defineProperty, the
93 * appropriate getter method is called.
94 *
95 * @param name the name of the property
96 * @param start the object in which the lookup began
97 * @return the value of the property (may be null), or NOT_FOUND
98 */
99 public synchronized Object get(String name, Scriptable start) {
100 if (isEmpty(name)) {
101 if (indexedProps.containsKey(name)) {
102 return indexedProps.get(name);
103 } else {
104 return NOT_FOUND;
105 }
106 } else {
107 synchronized (context) {
108 int scope = context.getAttributesScope(name);
109 if (scope != -1) {
110 Object value = context.getAttribute(name, scope);
111 return Context.javaToJS(value, this);
112 } else {
113 return NOT_FOUND;
114 }
115 }
116 }
117 }
118
119 /**
120 * Returns the value of the indexed property or NOT_FOUND.
121 *
122 * @param index the numeric index for the property
123 * @param start the object in which the lookup began
124 * @return the value of the property (may be null), or NOT_FOUND
125 */
126 public synchronized Object get(int index, Scriptable start) {
127 Integer key = new Integer(index);
128 if (indexedProps.containsKey(index)) {
129 return indexedProps.get(key);
130 } else {
131 return NOT_FOUND;
132 }
133 }
134
135 /**
136 * Returns true if the named property is defined.
137 *
138 * @param name the name of the property
139 * @param start the object in which the lookup began
140 * @return true if and only if the property was found in the object
141 */
142 public synchronized boolean has(String name, Scriptable start) {
143 if (isEmpty(name)) {
144 return indexedProps.containsKey(name);
145 } else {
146 synchronized (context) {
147 return context.getAttributesScope(name) != -1;
148 }
149 }
150 }
151
152 /**
153 * Returns true if the property index is defined.
154 *
155 * @param index the numeric index for the property
156 * @param start the object in which the lookup began
157 * @return true if and only if the property was found in the object
158 */
159 public synchronized boolean has(int index, Scriptable start) {
160 Integer key = new Integer(index);
161 return indexedProps.containsKey(key);
162 }
163
164 /**
165 * Sets the value of the named property, creating it if need be.
166 *
167 * @param name the name of the property
168 * @param start the object whose property is being set
169 * @param value value to set the property to
170 */
171 public void put(String name, Scriptable start, Object value) {
172 if (start == this) {
173 synchronized (this) {
174 if (isEmpty(name)) {
175 indexedProps.put(name, value);
176 } else {
177 synchronized (context) {
178 int scope = context.getAttributesScope(name);
179 if (scope == -1) {
180 scope = ScriptContext.ENGINE_SCOPE;
181 }
182 context.setAttribute(name, jsToJava(value), scope);
183 }
184 }
185 }
186 } else {
187 start.put(name, start, value);
188 }
189 }
190
191 /**
192 * Sets the value of the indexed property, creating it if need be.
193 *
194 * @param index the numeric index for the property
195 * @param start the object whose property is being set
196 * @param value value to set the property to
197 */
198 public void put(int index, Scriptable start, Object value) {
199 if (start == this) {
200 synchronized (this) {
201 indexedProps.put(new Integer(index), value);
202 }
203 } else {
204 start.put(index, start, value);
205 }
206 }
207
208 /**
209 * Removes a named property from the object.
210 *
211 * If the property is not found, no action is taken.
212 *
213 * @param name the name of the property
214 */
215 public synchronized void delete(String name) {
216 if (isEmpty(name)) {
217 indexedProps.remove(name);
218 } else {
219 synchronized (context) {
220 int scope = context.getAttributesScope(name);
221 if (scope != -1) {
222 context.removeAttribute(name, scope);
223 }
224 }
225 }
226 }
227
228 /**
229 * Removes the indexed property from the object.
230 *
231 * If the property is not found, no action is taken.
232 *
233 * @param index the numeric index for the property
234 */
235 public void delete(int index) {
236 indexedProps.remove(new Integer(index));
237 }
238
239 /**
240 * Get the prototype of the object.
241 * @return the prototype
242 */
243 public Scriptable getPrototype() {
244 return prototype;
245 }
246
247 /**
248 * Set the prototype of the object.
249 * @param prototype the prototype to set
250 */
251 public void setPrototype(Scriptable prototype) {
252 this.prototype = prototype;
253 }
254
255 /**
256 * Get the parent scope of the object.
257 * @return the parent scope
258 */
259 public Scriptable getParentScope() {
260 return parent;
261 }
262
263 /**
264 * Set the parent scope of the object.
265 * @param parent the parent scope to set
266 */
267 public void setParentScope(Scriptable parent) {
268 this.parent = parent;
269 }
270
271 /**
272 * Get an array of property ids.
273 *
274 * Not all property ids need be returned. Those properties
275 * whose ids are not returned are considered non-enumerable.
276 *
277 * @return an array of Objects. Each entry in the array is either
278 * a java.lang.String or a java.lang.Number
279 */
280 public synchronized Object[] getIds() {
281 String[] keys = getAllKeys();
282 int size = keys.length + indexedProps.size();
283 Object[] res = new Object[size];
284 System.arraycopy(keys, 0, res, 0, keys.length);
285 int i = keys.length;
286 // now add all indexed properties
287 for (Object index : indexedProps.keySet()) {
288 res[i++] = index;
289 }
290 return res;
291 }
292
293 /**
294 * Get the default value of the object with a given hint.
295 * The hints are String.class for type String, Number.class for type
296 * Number, Scriptable.class for type Object, and Boolean.class for
297 * type Boolean. <p>
298 *
299 * A <code>hint</code> of null means "no hint".
300 *
301 * See ECMA 8.6.2.6.
302 *
303 * @param hint the type hint
304 * @return the default value
305 */
306 public Object getDefaultValue(Class typeHint) {
307 for (int i=0; i < 2; i++) {
308 boolean tryToString;
309 if (typeHint == ScriptRuntime.StringClass) {
310 tryToString = (i == 0);
311 } else {
312 tryToString = (i == 1);
313 }
314
315 String methodName;
316 Object[] args;
317 if (tryToString) {
318 methodName = "toString";
319 args = ScriptRuntime.emptyArgs;
320 } else {
321 methodName = "valueOf";
322 args = new Object[1];
323 String hint;
324 if (typeHint == null) {
325 hint = "undefined";
326 } else if (typeHint == ScriptRuntime.StringClass) {
327 hint = "string";
328 } else if (typeHint == ScriptRuntime.ScriptableClass) {
329 hint = "object";
330 } else if (typeHint == ScriptRuntime.FunctionClass) {
331 hint = "function";
332 } else if (typeHint == ScriptRuntime.BooleanClass
333 || typeHint == Boolean.TYPE)
334 {
335 hint = "boolean";
336 } else if (typeHint == ScriptRuntime.NumberClass ||
337 typeHint == ScriptRuntime.ByteClass ||
338 typeHint == Byte.TYPE ||
339 typeHint == ScriptRuntime.ShortClass ||
340 typeHint == Short.TYPE ||
341 typeHint == ScriptRuntime.IntegerClass ||
342 typeHint == Integer.TYPE ||
343 typeHint == ScriptRuntime.FloatClass ||
344 typeHint == Float.TYPE ||
345 typeHint == ScriptRuntime.DoubleClass ||
346 typeHint == Double.TYPE)
347 {
348 hint = "number";
349 } else {
350 throw Context.reportRuntimeError(
351 "Invalid JavaScript value of type " +
352 typeHint.toString());
353 }
354 args[0] = hint;
355 }
356 Object v = ScriptableObject.getProperty(this, methodName);
357 if (!(v instanceof Function))
358 continue;
359 Function fun = (Function) v;
360 Context cx = RhinoScriptEngine.enterContext();
361 try {
362 v = fun.call(cx, fun.getParentScope(), this, args);
363 } finally {
364 cx.exit();
365 }
366 if (v != null) {
367 if (!(v instanceof Scriptable)) {
368 return v;
369 }
370 if (typeHint == ScriptRuntime.ScriptableClass
371 || typeHint == ScriptRuntime.FunctionClass)
372 {
373 return v;
374 }
375 if (tryToString && v instanceof Wrapper) {
376 // Let a wrapped java.lang.String pass for a primitive
377 // string.
378 Object u = ((Wrapper)v).unwrap();
379 if (u instanceof String)
380 return u;
381 }
382 }
383 }
384 // fall through to error
385 String arg = (typeHint == null) ? "undefined" : typeHint.getName();
386 throw Context.reportRuntimeError(
387 "Cannot find default value for object " + arg);
388 }
389
390 /**
391 * Implements the instanceof operator.
392 *
393 * @param instance The value that appeared on the LHS of the instanceof
394 * operator
395 * @return true if "this" appears in value's prototype chain
396 *
397 */
398 public boolean hasInstance(Scriptable instance) {
399 // Default for JS objects (other than Function) is to do prototype
400 // chasing.
401 Scriptable proto = instance.getPrototype();
402 while (proto != null) {
403 if (proto.equals(this)) return true;
404 proto = proto.getPrototype();
405 }
406 return false;
407 }
408
409 private String[] getAllKeys() {
410 ArrayList<String> list = new ArrayList<String>();
411 synchronized (context) {
412 for (int scope : context.getScopes()) {
413 Bindings bindings = context.getBindings(scope);
414 if (bindings != null) {
415 list.ensureCapacity(bindings.size());
416 for (String key : bindings.keySet()) {
417 list.add(key);
418 }
419 }
420 }
421 }
422 String[] res = new String[list.size()];
423 list.toArray(res);
424 return res;
425 }
426
427 /**
428 * We convert script values to the nearest Java value.
429 * We unwrap wrapped Java objects so that access from
430 * Bindings.get() would return "workable" value for Java.
431 * But, at the same time, we need to make few special cases
432 * and hence the following function is used.
433 */
434 private Object jsToJava(Object jsObj) {
435 if (jsObj instanceof Wrapper) {
436 Wrapper njb = (Wrapper) jsObj;
437 /* importClass feature of ImporterTopLevel puts
438 * NativeJavaClass in global scope. If we unwrap
439 * it, importClass won't work.
440 */
441 if (njb instanceof NativeJavaClass) {
442 return njb;
443 }
444
445 /* script may use Java primitive wrapper type objects
446 * (such as java.lang.Integer, java.lang.Boolean etc)
447 * explicitly. If we unwrap, then these script objects
448 * will become script primitive types. For example,
449 *
450 * var x = new java.lang.Double(3.0); print(typeof x);
451 *
452 * will print 'number'. We don't want that to happen.
453 */
454 Object obj = njb.unwrap();
455 if (obj instanceof Number || obj instanceof String ||
456 obj instanceof Boolean || obj instanceof Character) {
457 // special type wrapped -- we just leave it as is.
458 return njb;
459 } else {
460 // return unwrapped object for any other object.
461 return obj;
462 }
463 } else { // not-a-Java-wrapper
464 return jsObj;
465 }
466 }
467}
java/pkg/com/sun/script/javascript/JSAdapter.java+338−0
@@ -0,0 +1,338 @@
1/*
2 * Copyright (c) 2005, 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 com.sun.script.javascript;
27
28import sun.org.mozilla.javascript.internal.*;
29import java.util.*;
30
31/**
32 * JSAdapter is java.lang.reflect.Proxy equivalent for JavaScript. JSAdapter
33 * calls specially named JavaScript methods on an adaptee object when property
34 * access is attempted on it.
35 *
36 * Example:
37 *
38 * var y = {
39 * __get__ : function (name) { ... }
40 * __has__ : function (name) { ... }
41 * __put__ : function (name, value) {...}
42 * __delete__ : function (name) { ... }
43 * __getIds__ : function () { ... }
44 * };
45 *
46 * var x = new JSAdapter(y);
47 *
48 * x.i; // calls y.__get__
49 * i in x; // calls y.__has__
50 * x.p = 10; // calls y.__put__
51 * delete x.p; // calls y.__delete__
52 * for (i in x) { print(i); } // calls y.__getIds__
53 *
54 * If a special JavaScript method is not found in the adaptee, then JSAdapter
55 * forwards the property access to the adaptee itself.
56 *
57 * JavaScript caller of adapter object is isolated from the fact that
58 * the property access/mutation/deletion are really calls to
59 * JavaScript methods on adaptee. Use cases include 'smart'
60 * properties, property access tracing/debugging, encaptulation with
61 * easy client access - in short JavaScript becomes more "Self" like.
62 *
63 * Note that Rhino already supports special properties like __proto__
64 * (to set, get prototype), __parent__ (to set, get parent scope). We
65 * follow the same double underscore nameing convention here. Similarly
66 * the name JSAdapter is derived from JavaAdapter -- which is a facility
67 * to extend, implement Java classes/interfaces by JavaScript.
68 *
69 * @author A. Sundararajan
70 * @since 1.6
71 */
72public final class JSAdapter implements Scriptable, Function {
73 private JSAdapter(Scriptable obj) {
74 setAdaptee(obj);
75 }
76
77 // initializer to setup JSAdapter prototype in the given scope
78 public static void init(Context cx, Scriptable scope, boolean sealed)
79 throws RhinoException {
80 JSAdapter obj = new JSAdapter(cx.newObject(scope));
81 obj.setParentScope(scope);
82 obj.setPrototype(getFunctionPrototype(scope));
83 obj.isPrototype = true;
84 ScriptableObject.defineProperty(scope, "JSAdapter", obj,
85 ScriptableObject.DONTENUM);
86 }
87
88 public String getClassName() {
89 return "JSAdapter";
90 }
91
92 public Object get(String name, Scriptable start) {
93 Function func = getAdapteeFunction(GET_PROP);
94 if (func != null) {
95 return call(func, new Object[] { name });
96 } else {
97 start = getAdaptee();
98 return start.get(name, start);
99 }
100 }
101
102 public Object get(int index, Scriptable start) {
103 Function func = getAdapteeFunction(GET_PROP);
104 if (func != null) {
105 return call(func, new Object[] { new Integer(index) });
106 } else {
107 start = getAdaptee();
108 return start.get(index, start);
109 }
110 }
111
112 public boolean has(String name, Scriptable start) {
113 Function func = getAdapteeFunction(HAS_PROP);
114 if (func != null) {
115 Object res = call(func, new Object[] { name });
116 return Context.toBoolean(res);
117 } else {
118 start = getAdaptee();
119 return start.has(name, start);
120 }
121 }
122
123 public boolean has(int index, Scriptable start) {
124 Function func = getAdapteeFunction(HAS_PROP);
125 if (func != null) {
126 Object res = call(func, new Object[] { new Integer(index) });
127 return Context.toBoolean(res);
128 } else {
129 start = getAdaptee();
130 return start.has(index, start);
131 }
132 }
133
134 public void put(String name, Scriptable start, Object value) {
135 if (start == this) {
136 Function func = getAdapteeFunction(PUT_PROP);
137 if (func != null) {
138 call(func, new Object[] { name, value });
139 } else {
140 start = getAdaptee();
141 start.put(name, start, value);
142 }
143 } else {
144 start.put(name, start, value);
145 }
146 }
147
148 public void put(int index, Scriptable start, Object value) {
149 if (start == this) {
150 Function func = getAdapteeFunction(PUT_PROP);
151 if( func != null) {
152 call(func, new Object[] { new Integer(index), value });
153 } else {
154 start = getAdaptee();
155 start.put(index, start, value);
156 }
157 } else {
158 start.put(index, start, value);
159 }
160 }
161
162 public void delete(String name) {
163 Function func = getAdapteeFunction(DEL_PROP);
164 if (func != null) {
165 call(func, new Object[] { name });
166 } else {
167 getAdaptee().delete(name);
168 }
169 }
170
171 public void delete(int index) {
172 Function func = getAdapteeFunction(DEL_PROP);
173 if (func != null) {
174 call(func, new Object[] { new Integer(index) });
175 } else {
176 getAdaptee().delete(index);
177 }
178 }
179
180 public Scriptable getPrototype() {
181 return prototype;
182 }
183
184 public void setPrototype(Scriptable prototype) {
185 this.prototype = prototype;
186 }
187
188 public Scriptable getParentScope() {
189 return parent;
190 }
191
192 public void setParentScope(Scriptable parent) {
193 this.parent = parent;
194 }
195
196 public Object[] getIds() {
197 Function func = getAdapteeFunction(GET_PROPIDS);
198 if (func != null) {
199 Object val = call(func, new Object[0]);
200 // in most cases, adaptee would return native JS array
201 if (val instanceof NativeArray) {
202 NativeArray array = (NativeArray) val;
203 Object[] res = new Object[(int)array.getLength()];
204 for (int index = 0; index < res.length; index++) {
205 res[index] = mapToId(array.get(index, array));
206 }
207 return res;
208 } else if (val instanceof NativeJavaArray) {
209 // may be attempt wrapped Java array
210 Object tmp = ((NativeJavaArray)val).unwrap();
211 Object[] res;
212 if (tmp.getClass() == Object[].class) {
213 Object[] array = (Object[]) tmp;
214 res = new Object[array.length];
215 for (int index = 0; index < array.length; index++) {
216 res[index] = mapToId(array[index]);
217 }
218 } else {
219 // just return an empty array
220 res = Context.emptyArgs;
221 }
222 return res;
223 } else {
224 // some other return type, just return empty array
225 return Context.emptyArgs;
226 }
227 } else {
228 return getAdaptee().getIds();
229 }
230 }
231
232 public boolean hasInstance(Scriptable scriptable) {
233 if (scriptable instanceof JSAdapter) {
234 return true;
235 } else {
236 Scriptable proto = scriptable.getPrototype();
237 while (proto != null) {
238 if (proto.equals(this)) return true;
239 proto = proto.getPrototype();
240 }
241 return false;
242 }
243 }
244
245 public Object getDefaultValue(Class hint) {
246 return getAdaptee().getDefaultValue(hint);
247 }
248
249 public Object call(Context cx, Scriptable scope, Scriptable thisObj,
250 Object[] args)
251 throws RhinoException {
252 if (isPrototype) {
253 return construct(cx, scope, args);
254 } else {
255 Scriptable tmp = getAdaptee();
256 if (tmp instanceof Function) {
257 return ((Function)tmp).call(cx, scope, tmp, args);
258 } else {
259 throw Context.reportRuntimeError("TypeError: not a function");
260 }
261 }
262 }
263
264 public Scriptable construct(Context cx, Scriptable scope, Object[] args)
265 throws RhinoException {
266 if (isPrototype) {
267 Scriptable topLevel = ScriptableObject.getTopLevelScope(scope);
268 JSAdapter newObj;
269 if (args.length > 0) {
270 newObj = new JSAdapter(Context.toObject(args[0], topLevel));
271 } else {
272 throw Context.reportRuntimeError("JSAdapter requires adaptee");
273 }
274 return newObj;
275 } else {
276 Scriptable tmp = getAdaptee();
277 if (tmp instanceof Function) {
278 return ((Function)tmp).construct(cx, scope, args);
279 } else {
280 throw Context.reportRuntimeError("TypeError: not a constructor");
281 }
282 }
283 }
284
285 public Scriptable getAdaptee() {
286 return adaptee;
287 }
288
289 public void setAdaptee(Scriptable adaptee) {
290 if (adaptee == null) {
291 throw new NullPointerException("adaptee can not be null");
292 }
293 this.adaptee = adaptee;
294 }
295
296 //-- internals only below this point
297
298 // map a property id. Property id can only be an Integer or String
299 private Object mapToId(Object tmp) {
300 if (tmp instanceof Double) {
301 return new Integer(((Double)tmp).intValue());
302 } else {
303 return Context.toString(tmp);
304 }
305 }
306
307 private static Scriptable getFunctionPrototype(Scriptable scope) {
308 return ScriptableObject.getFunctionPrototype(scope);
309 }
310
311 private Function getAdapteeFunction(String name) {
312 Object o = ScriptableObject.getProperty(getAdaptee(), name);
313 return (o instanceof Function)? (Function)o : null;
314 }
315
316 private Object call(Function func, Object[] args) {
317 Context cx = Context.getCurrentContext();
318 Scriptable thisObj = getAdaptee();
319 Scriptable scope = func.getParentScope();
320 try {
321 return func.call(cx, scope, thisObj, args);
322 } catch (RhinoException re) {
323 throw Context.reportRuntimeError(re.getMessage());
324 }
325 }
326
327 private Scriptable prototype;
328 private Scriptable parent;
329 private Scriptable adaptee;
330 private boolean isPrototype;
331
332 // names of adaptee JavaScript functions
333 private static final String GET_PROP = "__get__";
334 private static final String HAS_PROP = "__has__";
335 private static final String PUT_PROP = "__put__";
336 private static final String DEL_PROP = "__delete__";
337 private static final String GET_PROPIDS = "__getIds__";
338}
java/pkg/com/sun/script/javascript/JavaAdapter.java+106−0
@@ -0,0 +1,106 @@
1/*
2 * Copyright (c) 2005, 2006, 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 com.sun.script.javascript;
27
28import javax.script.Invocable;
29import sun.org.mozilla.javascript.internal.*;
30
31/**
32 * This class implements Rhino-like JavaAdapter to help implement a Java
33 * interface in JavaScript. We support this using Invocable.getInterface.
34 * Using this JavaAdapter, script author could write:
35 *
36 * var r = new java.lang.Runnable() {
37 * run: function() { script... }
38 * };
39 *
40 * r.run();
41 * new java.lang.Thread(r).start();
42 *
43 * Note that Rhino's JavaAdapter support allows extending a Java class and/or
44 * implementing one or more interfaces. This JavaAdapter implementation does
45 * not support these.
46 *
47 * @author A. Sundararajan
48 * @since 1.6
49 */
50final class JavaAdapter extends ScriptableObject implements Function {
51 private JavaAdapter(Invocable engine) {
52 this.engine = engine;
53 }
54
55 static void init(Context cx, Scriptable scope, boolean sealed)
56 throws RhinoException {
57 RhinoTopLevel topLevel = (RhinoTopLevel) scope;
58 Invocable engine = topLevel.getScriptEngine();
59 JavaAdapter obj = new JavaAdapter(engine);
60 obj.setParentScope(scope);
61 obj.setPrototype(getFunctionPrototype(scope));
62 /*
63 * Note that we can't use defineProperty. A property of this
64 * name is already defined in Context.initStandardObjects. We
65 * simply overwrite the property value!
66 */
67 ScriptableObject.putProperty(topLevel, "JavaAdapter", obj);
68 }
69
70 public String getClassName() {
71 return "JavaAdapter";
72 }
73
74 public Object call(Context cx, Scriptable scope, Scriptable thisObj,
75 Object[] args) throws RhinoException {
76 return construct(cx, scope, args);
77 }
78
79 public Scriptable construct(Context cx, Scriptable scope, Object[] args)
80 throws RhinoException {
81 if (args.length == 2) {
82 Class<?> clazz = null;
83 Object obj1 = args[0];
84 if (obj1 instanceof Wrapper) {
85 Object o = ((Wrapper)obj1).unwrap();
86 if (o instanceof Class && ((Class)o).isInterface()) {
87 clazz = (Class) o;
88 }
89 } else if (obj1 instanceof Class) {
90 if (((Class)obj1).isInterface()) {
91 clazz = (Class) obj1;
92 }
93 }
94 if (clazz == null) {
95 throw Context.reportRuntimeError("JavaAdapter: first arg should be interface Class");
96 }
97
98 Scriptable topLevel = ScriptableObject.getTopLevelScope(scope);
99 return cx.toObject(engine.getInterface(args[1], clazz), topLevel);
100 } else {
101 throw Context.reportRuntimeError("JavaAdapter requires two arguments");
102 }
103 }
104
105 private Invocable engine;
106}
java/pkg/com/sun/script/javascript/META-INF/mkfile+6−0
@@ -0,0 +1,6 @@
1<../../../../../../../mkconfig
2
3DIRS=\
4 services\
5
6<$ROOT/mkfiles/mksubdirs
java/pkg/com/sun/script/javascript/META-INF/services/javax.script.ScriptEngineFactory+5−0
@@ -0,0 +1,5 @@
1
2#script engines supported
3
4com.sun.script.javascript.RhinoScriptEngineFactory #javascript
5
java/pkg/com/sun/script/javascript/META-INF/services/mkfile+2−0
@@ -0,0 +1,2 @@
1<../../../../../../../../mkconfig
2
java/pkg/com/sun/script/javascript/RhinoClassShutter.java+75−0
@@ -0,0 +1,75 @@
1/*
2 * Copyright (c) 2005, 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 com.sun.script.javascript;
27
28import java.util.*;
29import sun.org.mozilla.javascript.internal.*;
30
31/**
32 * This class prevents script access to certain sensitive classes.
33 * Note that this class checks over and above SecurityManager. i.e., although
34 * a SecurityManager would pass, class shutter may still prevent access.
35 *
36 * @author A. Sundararajan
37 * @since 1.6
38 */
39final class RhinoClassShutter implements ClassShutter {
40 private static Map<String, Boolean> protectedClasses;
41 private static RhinoClassShutter theInstance;
42
43 private RhinoClassShutter() {
44 }
45
46 static synchronized ClassShutter getInstance() {
47 if (theInstance == null) {
48 theInstance = new RhinoClassShutter();
49 protectedClasses = new HashMap<String, Boolean>();
50
51 // For now, we just have AccessController. Allowing scripts
52 // to this class will allow it to execute doPrivileged in
53 // bootstrap context. We can add more classes for other reasons.
54 protectedClasses.put("java.security.AccessController", Boolean.TRUE);
55 }
56 return theInstance;
57 }
58
59 public boolean visibleToScripts(String fullClassName) {
60 // first do the security check.
61 SecurityManager sm = System.getSecurityManager();
62 if (sm != null) {
63 int i = fullClassName.lastIndexOf(".");
64 if (i != -1) {
65 try {
66 sm.checkPackageAccess(fullClassName.substring(0, i));
67 } catch (SecurityException se) {
68 return false;
69 }
70 }
71 }
72 // now, check is it a protected class.
73 return protectedClasses.get(fullClassName) == null;
74 }
75}
java/pkg/com/sun/script/javascript/RhinoCompiledScript.java+78−0
@@ -0,0 +1,78 @@
1/*
2 * Copyright (c) 2005, 2006, 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 com.sun.script.javascript;
27import javax.script.*;
28import sun.org.mozilla.javascript.internal.*;
29
30/**
31 * Represents compiled JavaScript code.
32 *
33 * @author Mike Grogan
34 * @since 1.6
35 */
36final class RhinoCompiledScript extends CompiledScript {
37
38 private RhinoScriptEngine engine;
39 private Script script;
40
41
42 RhinoCompiledScript(RhinoScriptEngine engine, Script script) {
43 this.engine = engine;
44 this.script = script;
45 }
46
47 public Object eval(ScriptContext context) throws ScriptException {
48
49 Object result = null;
50 Context cx = RhinoScriptEngine.enterContext();
51 try {
52
53 Scriptable scope = engine.getRuntimeScope(context);
54 Object ret = script.exec(cx, scope);
55 result = engine.unwrapReturnValue(ret);
56 } catch (RhinoException re) {
57 int line = (line = re.lineNumber()) == 0 ? -1 : line;
58 String msg;
59 if (re instanceof JavaScriptException) {
60 msg = String.valueOf(((JavaScriptException)re).getValue());
61 } else {
62 msg = re.toString();
63 }
64 ScriptException se = new ScriptException(msg, re.sourceName(), line);
65 se.initCause(re);
66 throw se;
67 } finally {
68 Context.exit();
69 }
70
71 return result;
72 }
73
74 public ScriptEngine getEngine() {
75 return engine;
76 }
77
78}
java/pkg/com/sun/script/javascript/RhinoScriptEngine.java+398−0
@@ -0,0 +1,398 @@
1/*
2 * Copyright (c) 2005, 2011, 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 com.sun.script.javascript;
27import com.sun.script.util.*;
28import javax.script.*;
29import sun.org.mozilla.javascript.internal.*;
30import java.lang.reflect.Method;
31import java.io.*;
32import java.util.*;
33
34
35/**
36 * Implementation of <code>ScriptEngine</code> using the Mozilla Rhino
37 * interpreter.
38 *
39 * @author Mike Grogan
40 * @author A. Sundararajan
41 * @since 1.6
42 */
43public final class RhinoScriptEngine extends AbstractScriptEngine
44 implements Invocable, Compilable {
45
46 private static final boolean DEBUG = false;
47
48 /* Scope where standard JavaScript objects and our
49 * extensions to it are stored. Note that these are not
50 * user defined engine level global variables. These are
51 * variables have to be there on all compliant ECMAScript
52 * scopes. We put these standard objects in this top level.
53 */
54 private RhinoTopLevel topLevel;
55
56 /* map used to store indexed properties in engine scope
57 * refer to comment on 'indexedProps' in ExternalScriptable.java.
58 */
59 private Map<Object, Object> indexedProps;
60
61 private ScriptEngineFactory factory;
62 private InterfaceImplementor implementor;
63
64 private static final int languageVersion = getLanguageVersion();
65 private static final int optimizationLevel = getOptimizationLevel();
66 static {
67 ContextFactory.initGlobal(new ContextFactory() {
68 protected Context makeContext() {
69 Context cx = super.makeContext();
70 cx.setLanguageVersion(languageVersion);
71 cx.setOptimizationLevel(optimizationLevel);
72 cx.setClassShutter(RhinoClassShutter.getInstance());
73 cx.setWrapFactory(RhinoWrapFactory.getInstance());
74 return cx;
75 }
76 });
77 }
78
79 private static final String RHINO_JS_VERSION = "rhino.js.version";
80 private static int getLanguageVersion() {
81 int version;
82 String tmp = java.security.AccessController.doPrivileged(
83 new sun.security.action.GetPropertyAction(RHINO_JS_VERSION));
84 if (tmp != null) {
85 version = Integer.parseInt((String)tmp);
86 } else {
87 version = Context.VERSION_1_8;
88 }
89 return version;
90 }
91
92 private static final String RHINO_OPT_LEVEL = "rhino.opt.level";
93 private static int getOptimizationLevel() {
94 int optLevel = -1;
95 // disable optimizer under security manager, for now.
96 if (System.getSecurityManager() == null) {
97 optLevel = Integer.getInteger(RHINO_OPT_LEVEL, -1);
98 }
99 return optLevel;
100 }
101
102 /**
103 * Creates a new instance of RhinoScriptEngine
104 */
105 public RhinoScriptEngine() {
106
107 Context cx = enterContext();
108 try {
109 topLevel = new RhinoTopLevel(cx, this);
110 } finally {
111 cx.exit();
112 }
113
114 indexedProps = new HashMap<Object, Object>();
115
116 //construct object used to implement getInterface
117 implementor = new InterfaceImplementor(this) {
118 protected boolean isImplemented(Object thiz, Class<?> iface) {
119 Context cx = enterContext();
120 try {
121 if (thiz != null && !(thiz instanceof Scriptable)) {
122 thiz = cx.toObject(thiz, topLevel);
123 }
124 Scriptable engineScope = getRuntimeScope(context);
125 Scriptable localScope = (thiz != null)? (Scriptable) thiz :
126 engineScope;
127 for (Method method : iface.getMethods()) {
128 // ignore methods of java.lang.Object class
129 if (method.getDeclaringClass() == Object.class) {
130 continue;
131 }
132 Object obj = ScriptableObject.getProperty(localScope, method.getName());
133 if (! (obj instanceof Function)) {
134 return false;
135 }
136 }
137 return true;
138 } finally {
139 cx.exit();
140 }
141 }
142
143 protected Object convertResult(Method method, Object res)
144 throws ScriptException {
145 Class desiredType = method.getReturnType();
146 if (desiredType == Void.TYPE) {
147 return null;
148 } else {
149 return Context.jsToJava(res, desiredType);
150 }
151 }
152 };
153 }
154
155 public Object eval(Reader reader, ScriptContext ctxt)
156 throws ScriptException {
157 Object ret;
158
159 Context cx = enterContext();
160 try {
161 Scriptable scope = getRuntimeScope(ctxt);
162 String filename = (String) get(ScriptEngine.FILENAME);
163 filename = filename == null ? "<Unknown source>" : filename;
164
165 ret = cx.evaluateReader(scope, reader, filename , 1, null);
166 } catch (RhinoException re) {
167 if (DEBUG) re.printStackTrace();
168 int line = (line = re.lineNumber()) == 0 ? -1 : line;
169 String msg;
170 if (re instanceof JavaScriptException) {
171 msg = String.valueOf(((JavaScriptException)re).getValue());
172 } else {
173 msg = re.toString();
174 }
175 ScriptException se = new ScriptException(msg, re.sourceName(), line);
176 se.initCause(re);
177 throw se;
178 } catch (IOException ee) {
179 throw new ScriptException(ee);
180 } finally {
181 cx.exit();
182 }
183
184 return unwrapReturnValue(ret);
185 }
186
187 public Object eval(String script, ScriptContext ctxt) throws ScriptException {
188 if (script == null) {
189 throw new NullPointerException("null script");
190 }
191 return eval(new StringReader(script) , ctxt);
192 }
193
194 public ScriptEngineFactory getFactory() {
195 if (factory != null) {
196 return factory;
197 } else {
198 return new RhinoScriptEngineFactory();
199 }
200 }
201
202 public Bindings createBindings() {
203 return new SimpleBindings();
204 }
205
206 //Invocable methods
207 public Object invokeFunction(String name, Object... args)
208 throws ScriptException, NoSuchMethodException {
209 return invoke(null, name, args);
210 }
211
212 public Object invokeMethod(Object thiz, String name, Object... args)
213 throws ScriptException, NoSuchMethodException {
214 if (thiz == null) {
215 throw new IllegalArgumentException("script object can not be null");
216 }
217 return invoke(thiz, name, args);
218 }
219
220 private Object invoke(Object thiz, String name, Object... args)
221 throws ScriptException, NoSuchMethodException {
222 Context cx = enterContext();
223 try {
224 if (name == null) {
225 throw new NullPointerException("method name is null");
226 }
227
228 if (thiz != null && !(thiz instanceof Scriptable)) {
229 thiz = cx.toObject(thiz, topLevel);
230 }
231
232 Scriptable engineScope = getRuntimeScope(context);
233 Scriptable localScope = (thiz != null)? (Scriptable) thiz :
234 engineScope;
235 Object obj = ScriptableObject.getProperty(localScope, name);
236 if (! (obj instanceof Function)) {
237 throw new NoSuchMethodException("no such method: " + name);
238 }
239
240 Function func = (Function) obj;
241 Scriptable scope = func.getParentScope();
242 if (scope == null) {
243 scope = engineScope;
244 }
245 Object result = func.call(cx, scope, localScope,
246 wrapArguments(args));
247 return unwrapReturnValue(result);
248 } catch (RhinoException re) {
249 if (DEBUG) re.printStackTrace();
250 int line = (line = re.lineNumber()) == 0 ? -1 : line;
251 ScriptException se = new ScriptException(re.toString(), re.sourceName(), line);
252 se.initCause(re);
253 throw se;
254 } finally {
255 cx.exit();
256 }
257 }
258
259 public <T> T getInterface(Class<T> clasz) {
260 try {
261 return implementor.getInterface(null, clasz);
262 } catch (ScriptException e) {
263 return null;
264 }
265 }
266
267 public <T> T getInterface(Object thiz, Class<T> clasz) {
268 if (thiz == null) {
269 throw new IllegalArgumentException("script object can not be null");
270 }
271
272 try {
273 return implementor.getInterface(thiz, clasz);
274 } catch (ScriptException e) {
275 return null;
276 }
277 }
278
279 private static final String printSource =
280 "function print(str, newline) { \n" +
281 " if (typeof(str) == 'undefined') { \n" +
282 " str = 'undefined'; \n" +
283 " } else if (str == null) { \n" +
284 " str = 'null'; \n" +
285 " } \n" +
286 " var out = context.getWriter(); \n" +
287 " if (!(out instanceof java.io.PrintWriter))\n" +
288 " out = new java.io.PrintWriter(out); \n" +
289 " out.print(String(str)); \n" +
290 " if (newline) out.print('\\n'); \n" +
291 " out.flush(); \n" +
292 "}\n" +
293 "function println(str) { \n" +
294 " print(str, true); \n" +
295 "}";
296
297 Scriptable getRuntimeScope(ScriptContext ctxt) {
298 if (ctxt == null) {
299 throw new NullPointerException("null script context");
300 }
301
302 // we create a scope for the given ScriptContext
303 Scriptable newScope = new ExternalScriptable(ctxt, indexedProps);
304
305 // Set the prototype of newScope to be 'topLevel' so that
306 // JavaScript standard objects are visible from the scope.
307 newScope.setPrototype(topLevel);
308
309 // define "context" variable in the new scope
310 newScope.put("context", newScope, ctxt);
311
312 // define "print", "println" functions in the new scope
313 Context cx = enterContext();
314 try {
315 cx.evaluateString(newScope, printSource, "print", 1, null);
316 } finally {
317 cx.exit();
318 }
319 return newScope;
320 }
321
322
323 //Compilable methods
324 public CompiledScript compile(String script) throws ScriptException {
325 return compile(new StringReader(script));
326 }
327
328 public CompiledScript compile(java.io.Reader script) throws ScriptException {
329 CompiledScript ret = null;
330 Context cx = enterContext();
331
332 try {
333 String fileName = (String) get(ScriptEngine.FILENAME);
334 if (fileName == null) {
335 fileName = "<Unknown Source>";
336 }
337
338 Scriptable scope = getRuntimeScope(context);
339 Script scr = cx.compileReader(scope, script, fileName, 1, null);
340 ret = new RhinoCompiledScript(this, scr);
341 } catch (Exception e) {
342 if (DEBUG) e.printStackTrace();
343 throw new ScriptException(e);
344 } finally {
345 cx.exit();
346 }
347 return ret;
348 }
349
350
351 //package-private helpers
352
353 static Context enterContext() {
354 // call this always so that initializer of this class runs
355 // and initializes custom wrap factory and class shutter.
356 return Context.enter();
357 }
358
359 void setEngineFactory(ScriptEngineFactory fac) {
360 factory = fac;
361 }
362
363 Object[] wrapArguments(Object[] args) {
364 if (args == null) {
365 return Context.emptyArgs;
366 }
367 Object[] res = new Object[args.length];
368 for (int i = 0; i < res.length; i++) {
369 res[i] = Context.javaToJS(args[i], topLevel);
370 }
371 return res;
372 }
373
374 Object unwrapReturnValue(Object result) {
375 if (result instanceof Wrapper) {
376 result = ( (Wrapper) result).unwrap();
377 }
378
379 return result instanceof Undefined ? null : result;
380 }
381
382 /*
383 public static void main(String[] args) throws Exception {
384 if (args.length == 0) {
385 System.out.println("No file specified");
386 return;
387 }
388
389 InputStreamReader r = new InputStreamReader(new FileInputStream(args[0]));
390 ScriptEngine engine = new RhinoScriptEngine();
391
392 engine.put("x", "y");
393 engine.put(ScriptEngine.FILENAME, args[0]);
394 engine.eval(r);
395 System.out.println(engine.get("x"));
396 }
397 */
398}
java/pkg/com/sun/script/javascript/RhinoScriptEngineFactory.java+163−0
@@ -0,0 +1,163 @@
1/*
2 * Copyright (c) 2005, 2010, 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 com.sun.script.javascript;
27import javax.script.*;
28import java.util.*;
29import sun.org.mozilla.javascript.internal.*;
30import com.sun.script.util.*;
31
32/**
33 * Factory to create RhinoScriptEngine
34 *
35 * @author Mike Grogan
36 * @since 1.6
37 */
38public class RhinoScriptEngineFactory extends ScriptEngineFactoryBase {
39
40 public RhinoScriptEngineFactory() {
41 }
42
43 public List<String> getExtensions() {
44 return extensions;
45 }
46
47 public List<String> getMimeTypes() {
48 return mimeTypes;
49 }
50
51 public List<String> getNames() {
52 return names;
53 }
54
55 public Object getParameter(String key) {
56 if (key.equals(ScriptEngine.NAME)) {
57 return "javascript";
58 } else if (key.equals(ScriptEngine.ENGINE)) {
59 return "Mozilla Rhino";
60 } else if (key.equals(ScriptEngine.ENGINE_VERSION)) {
61 return "1.7 release 3 PRERELEASE";
62 } else if (key.equals(ScriptEngine.LANGUAGE)) {
63 return "ECMAScript";
64 } else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) {
65 return "1.8";
66 } else if (key.equals("THREADING")) {
67 return "MULTITHREADED";
68 } else {
69 throw new IllegalArgumentException("Invalid key");
70 }
71 }
72
73 public ScriptEngine getScriptEngine() {
74 RhinoScriptEngine ret = new RhinoScriptEngine();
75 ret.setEngineFactory(this);
76 return ret;
77 }
78
79 public String getMethodCallSyntax(String obj, String method, String... args) {
80
81 String ret = obj + "." + method + "(";
82 int len = args.length;
83 if (len == 0) {
84 ret += ")";
85 return ret;
86 }
87
88 for (int i = 0; i < len; i++) {
89 ret += args[i];
90 if (i != len - 1) {
91 ret += ",";
92 } else {
93 ret += ")";
94 }
95 }
96 return ret;
97 }
98
99 public String getOutputStatement(String toDisplay) {
100 StringBuffer buf = new StringBuffer();
101 int len = toDisplay.length();
102 buf.append("print(\"");
103 for (int i = 0; i < len; i++) {
104 char ch = toDisplay.charAt(i);
105 switch (ch) {
106 case '"':
107 buf.append("\\\"");
108 break;
109 case '\\':
110 buf.append("\\\\");
111 break;
112 default:
113 buf.append(ch);
114 break;
115 }
116 }
117 buf.append("\")");
118 return buf.toString();
119 }
120
121 public String getProgram(String... statements) {
122 int len = statements.length;
123 String ret = "";
124 for (int i = 0; i < len; i++) {
125 ret += statements[i] + ";";
126 }
127
128 return ret;
129 }
130
131 /*
132 public static void main(String[] args) {
133 RhinoScriptEngineFactory fact = new RhinoScriptEngineFactory();
134 System.out.println(fact.getParameter(ScriptEngine.ENGINE_VERSION));
135 }
136 */
137
138 private static List<String> names;
139 private static List<String> mimeTypes;
140 private static List<String> extensions;
141
142 static {
143 names = new ArrayList<String>(6);
144 names.add("js");
145 names.add("rhino");
146 names.add("JavaScript");
147 names.add("javascript");
148 names.add("ECMAScript");
149 names.add("ecmascript");
150 names = Collections.unmodifiableList(names);
151
152 mimeTypes = new ArrayList<String>(4);
153 mimeTypes.add("application/javascript");
154 mimeTypes.add("application/ecmascript");
155 mimeTypes.add("text/javascript");
156 mimeTypes.add("text/ecmascript");
157 mimeTypes = Collections.unmodifiableList(mimeTypes);
158
159 extensions = new ArrayList<String>(1);
160 extensions.add("js");
161 extensions = Collections.unmodifiableList(extensions);
162 }
163}
java/pkg/com/sun/script/javascript/RhinoTopLevel.java+156−0
@@ -0,0 +1,156 @@
1/*
2 * Copyright (c) 2005, 2010, 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 com.sun.script.javascript;
27
28import sun.org.mozilla.javascript.internal.*;
29import javax.script.*;
30
31/**
32 * This class serves as top level scope for Rhino. This class adds
33 * 3 top level functions (bindings, scope, sync) and two constructors
34 * (JSAdapter, JavaAdapter).
35 *
36 * @author A. Sundararajan
37 * @since 1.6
38 */
39public final class RhinoTopLevel extends ImporterTopLevel {
40 RhinoTopLevel(Context cx, RhinoScriptEngine engine) {
41 super(cx);
42 this.engine = engine;
43
44
45 // initialize JSAdapter lazily. Reduces footprint & startup time.
46 new LazilyLoadedCtor(this, "JSAdapter",
47 "com.sun.script.javascript.JSAdapter",
48 false);
49
50 /*
51 * initialize JavaAdapter. We can't lazy initialize this because
52 * lazy initializer attempts to define a new property. But, JavaAdapter
53 * is an exisiting property that we overwrite.
54 */
55 JavaAdapter.init(cx, this, false);
56
57 // add top level functions
58 String names[] = { "bindings", "scope", "sync" };
59 defineFunctionProperties(names, RhinoTopLevel.class,
60 ScriptableObject.DONTENUM);
61 }
62
63 /**
64 * The bindings function takes a JavaScript scope object
65 * of type ExternalScriptable and returns the underlying Bindings
66 * instance.
67 *
68 * var page = scope(pageBindings);
69 * with (page) {
70 * // code that uses page scope
71 * }
72 * var b = bindings(page);
73 * // operate on bindings here.
74 */
75 public static Object bindings(Context cx, Scriptable thisObj, Object[] args,
76 Function funObj) {
77 if (args.length == 1) {
78 Object arg = args[0];
79 if (arg instanceof Wrapper) {
80 arg = ((Wrapper)arg).unwrap();
81 }
82 if (arg instanceof ExternalScriptable) {
83 ScriptContext ctx = ((ExternalScriptable)arg).getContext();
84 Bindings bind = ctx.getBindings(ScriptContext.ENGINE_SCOPE);
85 return Context.javaToJS(bind,
86 ScriptableObject.getTopLevelScope(thisObj));
87 }
88 }
89 return cx.getUndefinedValue();
90 }
91
92 /**
93 * The scope function creates a new JavaScript scope object
94 * with given Bindings object as backing store. This can be used
95 * to create a script scope based on arbitrary Bindings instance.
96 * For example, in webapp scenario, a 'page' level Bindings instance
97 * may be wrapped as a scope and code can be run in JavaScripe 'with'
98 * statement:
99 *
100 * var page = scope(pageBindings);
101 * with (page) {
102 * // code that uses page scope
103 * }
104 */
105 public static Object scope(Context cx, Scriptable thisObj, Object[] args,
106 Function funObj) {
107 if (args.length == 1) {
108 Object arg = args[0];
109 if (arg instanceof Wrapper) {
110 arg = ((Wrapper)arg).unwrap();
111 }
112 if (arg instanceof Bindings) {
113 ScriptContext ctx = new SimpleScriptContext();
114 ctx.setBindings((Bindings)arg, ScriptContext.ENGINE_SCOPE);
115 Scriptable res = new ExternalScriptable(ctx);
116 res.setPrototype(ScriptableObject.getObjectPrototype(thisObj));
117 res.setParentScope(ScriptableObject.getTopLevelScope(thisObj));
118 return res;
119 }
120 }
121 return cx.getUndefinedValue();
122 }
123
124 /**
125 * The sync function creates a synchronized function (in the sense
126 * of a Java synchronized method) from an existing function. The
127 * new function synchronizes on the <code>this</code> object of
128 * its invocation.
129 * js> var o = { f : sync(function(x) {
130 * print("entry");
131 * Packages.java.lang.Thread.sleep(x*1000);
132 * print("exit");
133 * })};
134 * js> thread(function() {o.f(5);});
135 * entry
136 * js> thread(function() {o.f(5);});
137 * js>
138 * exit
139 * entry
140 * exit
141 */
142 public static Object sync(Context cx, Scriptable thisObj, Object[] args,
143 Function funObj) {
144 if (args.length == 1 && args[0] instanceof Function) {
145 return new Synchronizer((Function)args[0]);
146 } else {
147 throw Context.reportRuntimeError("wrong argument(s) for sync");
148 }
149 }
150
151 RhinoScriptEngine getScriptEngine() {
152 return engine;
153 }
154
155 private RhinoScriptEngine engine;
156}
java/pkg/com/sun/script/javascript/RhinoWrapFactory.java+148−0
@@ -0,0 +1,148 @@
1/*
2 * Copyright (c) 2005, 2006, 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 com.sun.script.javascript;
27
28import java.lang.reflect.*;
29import static sun.security.util.SecurityConstants.*;
30import sun.org.mozilla.javascript.internal.*;
31
32/**
33 * This wrap factory is used for security reasons. JSR 223 script
34 * engine interface and JavaScript engine classes are run as bootstrap
35 * classes. For example, java.lang.Class.forName method (when called without
36 * class loader) uses caller's class loader. This may be exploited by script
37 * authors to access classes otherwise not accessible. For example,
38 * classes in sun.* namespace are normally not accessible to untrusted
39 * code and hence should not be accessible to JavaScript run from
40 * untrusted code.
41 *
42 * @author A. Sundararajan
43 * @since 1.6
44 */
45final class RhinoWrapFactory extends WrapFactory {
46 private RhinoWrapFactory() {}
47 private static RhinoWrapFactory theInstance;
48
49 static synchronized WrapFactory getInstance() {
50 if (theInstance == null) {
51 theInstance = new RhinoWrapFactory();
52 }
53 return theInstance;
54 }
55
56 // We use instance of this class to wrap security sensitive
57 // Java object. Please refer below.
58 private static class RhinoJavaObject extends NativeJavaObject {
59 RhinoJavaObject(Scriptable scope, Object obj, Class type) {
60 // we pass 'null' to object. NativeJavaObject uses
61 // passed 'type' to reflect fields and methods when
62 // object is null.
63 super(scope, null, type);
64
65 // Now, we set actual object. 'javaObject' is protected
66 // field of NativeJavaObject.
67 javaObject = obj;
68 }
69 }
70
71 public Scriptable wrapAsJavaObject(Context cx, Scriptable scope,
72 Object javaObject, Class staticType) {
73 SecurityManager sm = System.getSecurityManager();
74 ClassShutter classShutter = RhinoClassShutter.getInstance();
75 if (javaObject instanceof ClassLoader) {
76 // Check with Security Manager whether we can expose a
77 // ClassLoader...
78 if (sm != null) {
79 sm.checkPermission(GET_CLASSLOADER_PERMISSION);
80 }
81 // if we fall through here, check permission succeeded.
82 return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
83 } else {
84 String name = null;
85 if (javaObject instanceof Class) {
86 name = ((Class)javaObject).getName();
87 } else if (javaObject instanceof Member) {
88 Member member = (Member) javaObject;
89 // Check member access. Don't allow reflective access to
90 // non-public members. Note that we can't call checkMemberAccess
91 // because that expects exact stack depth!
92 if (sm != null && !Modifier.isPublic(member.getModifiers())) {
93 return null;
94 }
95 name = member.getDeclaringClass().getName();
96 }
97 // Now, make sure that no ClassShutter prevented Class or Member
98 // of it is accessed reflectively. Note that ClassShutter may
99 // prevent access to a class, even though SecurityManager permit.
100 if (name != null) {
101 if (!classShutter.visibleToScripts(name)) {
102 return null;
103 } else {
104 return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
105 }
106 }
107 }
108
109 // we have got some non-reflective object.
110 Class dynamicType = javaObject.getClass();
111 String name = dynamicType.getName();
112 if (!classShutter.visibleToScripts(name)) {
113 // Object of some sensitive class (such as sun.net.www.*
114 // objects returned from public method of java.net.URL class.
115 // We expose this object as though it is an object of some
116 // super class that is safe for access.
117
118 Class type = null;
119
120 // Whenever a Java Object is wrapped, we are passed with a
121 // staticType which is the type found from environment. For
122 // example, method return type known from signature. The dynamic
123 // type would be the actual Class of the actual returned object.
124 // If the staticType is an interface, we just use that type.
125 if (staticType != null && staticType.isInterface()) {
126 type = staticType;
127 } else {
128 // dynamicType is always a class type and never an interface.
129 // find an accessible super class of the dynamic type.
130 while (dynamicType != null) {
131 dynamicType = dynamicType.getSuperclass();
132 name = dynamicType.getName();
133 if (classShutter.visibleToScripts(name)) {
134 type = dynamicType; break;
135 }
136 }
137 // atleast java.lang.Object has to be accessible. So, when
138 // we reach here, type variable should not be null.
139 assert type != null:
140 "even java.lang.Object is not accessible?";
141 }
142 // create custom wrapper with the 'safe' type.
143 return new RhinoJavaObject(scope, javaObject, type);
144 } else {
145 return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
146 }
147 }
148}
java/pkg/com/sun/script/javascript/mkfile+20−0
@@ -0,0 +1,20 @@
1<../../../../../../mkconfig
2
3DIRS=\
4 META-INF\
5
6TARG=\
7 ExternalScriptable.dis\
8 JavaAdapter.dis\
9 JSAdapter.dis\
10 RhinoClassShutter.dis\
11 RhinoCompiledScript.dis\
12 RhinoScriptEngine.dis\
13 RhinoScriptEngineFactory.dis\
14 RhinoTopLevel.dis\
15 RhinoWrapFactory.dis\
16
17DISBIN=$ROOT/java/dis/java/java/com/sun/script/javascript
18
19<$ROOT/mkfiles/mkjava
20<$ROOT/mkfiles/mksubdirs