298 }
299
300 // perform security access check as early as possible
301 final SecurityManager sm = System.getSecurityManager();
302 if (sm != null) {
303 if (! Modifier.isPublic(clazz.getModifiers())) {
304 throw new SecurityException(getMessage("implementing.non.public.interface", clazz.getName()));
305 }
306 Context.checkPackageAccess(clazz.getName());
307 }
308
309 ScriptObject realSelf = null;
310 ScriptObject realGlobal = null;
311 if(thiz == null) {
312 // making interface out of global functions
313 realSelf = realGlobal = getNashornGlobalFrom(context);
314 } else if (thiz instanceof ScriptObjectMirror) {
315 final ScriptObjectMirror mirror = (ScriptObjectMirror)thiz;
316 realSelf = mirror.getScriptObject();
317 realGlobal = mirror.getHomeGlobal();
318 if (! realGlobal.isOfContext(nashornContext)) {
319 throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
320 }
321 } else if (thiz instanceof ScriptObject) {
322 // called from script code.
323 realSelf = (ScriptObject)thiz;
324 realGlobal = Context.getGlobal();
325 if (realGlobal == null) {
326 throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
327 }
328
329 if (! realGlobal.isOfContext(nashornContext)) {
330 throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
331 }
332 }
333
334 if (realSelf == null) {
335 throw new IllegalArgumentException(getMessage("interface.on.non.script.object"));
336 }
337
338 try {
339 final ScriptObject oldGlobal = Context.getGlobal();
340 final boolean globalChanged = (oldGlobal != realGlobal);
341 try {
342 if (globalChanged) {
343 Context.setGlobal(realGlobal);
344 }
345
346 if (! isInterfaceImplemented(clazz, realSelf)) {
347 return null;
348 }
349 return clazz.cast(JavaAdapterFactory.getConstructor(realSelf.getClass(), clazz).invoke(realSelf));
377
378 // Arbitrary user Bindings implementation. Look for NASHORN_GLOBAL in it!
379 Object scope = bindings.get(NASHORN_GLOBAL);
380 if (scope instanceof ScriptObjectMirror) {
381 final ScriptObject sobj = globalFromMirror((ScriptObjectMirror)scope);
382 if (sobj != null) {
383 return sobj;
384 }
385 }
386
387 // We didn't find associated nashorn global mirror in the Bindings given!
388 // Create new global instance mirror and associate with the Bindings.
389 final ScriptObjectMirror mirror = createGlobalMirror(ctxt);
390 bindings.put(NASHORN_GLOBAL, mirror);
391 return mirror.getScriptObject();
392 }
393
394 // Retrieve nashorn Global object from a given ScriptObjectMirror
395 private ScriptObject globalFromMirror(final ScriptObjectMirror mirror) {
396 ScriptObject sobj = mirror.getScriptObject();
397 if (sobj instanceof GlobalObject && sobj.isOfContext(nashornContext)) {
398 return sobj;
399 }
400
401 return null;
402 }
403
404 // Create a new ScriptObjectMirror wrapping a newly created Nashorn Global object
405 private ScriptObjectMirror createGlobalMirror(final ScriptContext ctxt) {
406 final ScriptObject newGlobal = createNashornGlobal(ctxt);
407 return new ScriptObjectMirror(newGlobal, newGlobal);
408 }
409
410 // Create a new Nashorn Global object
411 private ScriptObject createNashornGlobal(final ScriptContext ctxt) {
412 final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() {
413 @Override
414 public ScriptObject run() {
415 try {
416 return nashornContext.newGlobal();
417 } catch (final RuntimeException e) {
453 // set "context" global variable via contextProperty - because this
454 // property is non-writable
455 contextProperty.setObjectValue(ctxtGlobal, ctxtGlobal, ctxt, false);
456 Object args = ScriptObjectMirror.unwrap(ctxt.getAttribute("arguments"), ctxtGlobal);
457 if (args == null || args == UNDEFINED) {
458 args = ScriptRuntime.EMPTY_ARRAY;
459 }
460 // if no arguments passed, expose it
461 if (! (args instanceof ScriptObject)) {
462 args = ((GlobalObject)ctxtGlobal).wrapAsObject(args);
463 ctxtGlobal.set("arguments", args, false);
464 }
465 }
466
467 private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
468 name.getClass(); // null check
469
470 ScriptObjectMirror selfMirror = null;
471 if (selfObject instanceof ScriptObjectMirror) {
472 selfMirror = (ScriptObjectMirror)selfObject;
473 if (! selfMirror.getHomeGlobal().isOfContext(nashornContext)) {
474 throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
475 }
476 } else if (selfObject instanceof ScriptObject) {
477 // invokeMethod called from script code - in which case we may get 'naked' ScriptObject
478 // Wrap it with oldGlobal to make a ScriptObjectMirror for the same.
479 final ScriptObject oldGlobal = Context.getGlobal();
480 if (oldGlobal == null) {
481 throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
482 }
483
484 if (! oldGlobal.isOfContext(nashornContext)) {
485 throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
486 }
487
488 selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(selfObject, oldGlobal);
489 } else if (selfObject == null) {
490 // selfObject is null => global function call
491 final ScriptObject ctxtGlobal = getNashornGlobalFrom(context);
492 selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(ctxtGlobal, ctxtGlobal);
493 }
494
495 if (selfMirror != null) {
496 try {
497 return ScriptObjectMirror.translateUndefined(selfMirror.call(name, args));
498 } catch (final Exception e) {
499 final Throwable cause = e.getCause();
500 if (cause instanceof NoSuchMethodException) {
501 throw (NoSuchMethodException)cause;
502 }
503 throwAsScriptException(e);
504 throw new AssertionError("should not reach here");
599 } finally {
600 if (globalChanged) {
601 Context.setGlobal(oldGlobal);
602 }
603 }
604 }
605
606 private static boolean isInterfaceImplemented(final Class<?> iface, final ScriptObject sobj) {
607 for (final Method method : iface.getMethods()) {
608 // ignore methods of java.lang.Object class
609 if (method.getDeclaringClass() == Object.class) {
610 continue;
611 }
612
613 Object obj = sobj.get(method.getName());
614 if (! (obj instanceof ScriptFunction)) {
615 return false;
616 }
617 }
618 return true;
619 }
620 }
|
298 }
299
300 // perform security access check as early as possible
301 final SecurityManager sm = System.getSecurityManager();
302 if (sm != null) {
303 if (! Modifier.isPublic(clazz.getModifiers())) {
304 throw new SecurityException(getMessage("implementing.non.public.interface", clazz.getName()));
305 }
306 Context.checkPackageAccess(clazz.getName());
307 }
308
309 ScriptObject realSelf = null;
310 ScriptObject realGlobal = null;
311 if(thiz == null) {
312 // making interface out of global functions
313 realSelf = realGlobal = getNashornGlobalFrom(context);
314 } else if (thiz instanceof ScriptObjectMirror) {
315 final ScriptObjectMirror mirror = (ScriptObjectMirror)thiz;
316 realSelf = mirror.getScriptObject();
317 realGlobal = mirror.getHomeGlobal();
318 if (! isOfContext(realGlobal, nashornContext)) {
319 throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
320 }
321 } else if (thiz instanceof ScriptObject) {
322 // called from script code.
323 realSelf = (ScriptObject)thiz;
324 realGlobal = Context.getGlobal();
325 if (realGlobal == null) {
326 throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
327 }
328
329 if (! isOfContext(realGlobal, nashornContext)) {
330 throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
331 }
332 }
333
334 if (realSelf == null) {
335 throw new IllegalArgumentException(getMessage("interface.on.non.script.object"));
336 }
337
338 try {
339 final ScriptObject oldGlobal = Context.getGlobal();
340 final boolean globalChanged = (oldGlobal != realGlobal);
341 try {
342 if (globalChanged) {
343 Context.setGlobal(realGlobal);
344 }
345
346 if (! isInterfaceImplemented(clazz, realSelf)) {
347 return null;
348 }
349 return clazz.cast(JavaAdapterFactory.getConstructor(realSelf.getClass(), clazz).invoke(realSelf));
377
378 // Arbitrary user Bindings implementation. Look for NASHORN_GLOBAL in it!
379 Object scope = bindings.get(NASHORN_GLOBAL);
380 if (scope instanceof ScriptObjectMirror) {
381 final ScriptObject sobj = globalFromMirror((ScriptObjectMirror)scope);
382 if (sobj != null) {
383 return sobj;
384 }
385 }
386
387 // We didn't find associated nashorn global mirror in the Bindings given!
388 // Create new global instance mirror and associate with the Bindings.
389 final ScriptObjectMirror mirror = createGlobalMirror(ctxt);
390 bindings.put(NASHORN_GLOBAL, mirror);
391 return mirror.getScriptObject();
392 }
393
394 // Retrieve nashorn Global object from a given ScriptObjectMirror
395 private ScriptObject globalFromMirror(final ScriptObjectMirror mirror) {
396 ScriptObject sobj = mirror.getScriptObject();
397 if (sobj instanceof GlobalObject && isOfContext(sobj, nashornContext)) {
398 return sobj;
399 }
400
401 return null;
402 }
403
404 // Create a new ScriptObjectMirror wrapping a newly created Nashorn Global object
405 private ScriptObjectMirror createGlobalMirror(final ScriptContext ctxt) {
406 final ScriptObject newGlobal = createNashornGlobal(ctxt);
407 return new ScriptObjectMirror(newGlobal, newGlobal);
408 }
409
410 // Create a new Nashorn Global object
411 private ScriptObject createNashornGlobal(final ScriptContext ctxt) {
412 final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() {
413 @Override
414 public ScriptObject run() {
415 try {
416 return nashornContext.newGlobal();
417 } catch (final RuntimeException e) {
453 // set "context" global variable via contextProperty - because this
454 // property is non-writable
455 contextProperty.setObjectValue(ctxtGlobal, ctxtGlobal, ctxt, false);
456 Object args = ScriptObjectMirror.unwrap(ctxt.getAttribute("arguments"), ctxtGlobal);
457 if (args == null || args == UNDEFINED) {
458 args = ScriptRuntime.EMPTY_ARRAY;
459 }
460 // if no arguments passed, expose it
461 if (! (args instanceof ScriptObject)) {
462 args = ((GlobalObject)ctxtGlobal).wrapAsObject(args);
463 ctxtGlobal.set("arguments", args, false);
464 }
465 }
466
467 private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
468 name.getClass(); // null check
469
470 ScriptObjectMirror selfMirror = null;
471 if (selfObject instanceof ScriptObjectMirror) {
472 selfMirror = (ScriptObjectMirror)selfObject;
473 if (! isOfContext(selfMirror.getHomeGlobal(), nashornContext)) {
474 throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
475 }
476 } else if (selfObject instanceof ScriptObject) {
477 // invokeMethod called from script code - in which case we may get 'naked' ScriptObject
478 // Wrap it with oldGlobal to make a ScriptObjectMirror for the same.
479 final ScriptObject oldGlobal = Context.getGlobal();
480 if (oldGlobal == null) {
481 throw new IllegalArgumentException(getMessage("no.current.nashorn.global"));
482 }
483
484 if (! isOfContext(oldGlobal, nashornContext)) {
485 throw new IllegalArgumentException(getMessage("script.object.from.another.engine"));
486 }
487
488 selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(selfObject, oldGlobal);
489 } else if (selfObject == null) {
490 // selfObject is null => global function call
491 final ScriptObject ctxtGlobal = getNashornGlobalFrom(context);
492 selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(ctxtGlobal, ctxtGlobal);
493 }
494
495 if (selfMirror != null) {
496 try {
497 return ScriptObjectMirror.translateUndefined(selfMirror.call(name, args));
498 } catch (final Exception e) {
499 final Throwable cause = e.getCause();
500 if (cause instanceof NoSuchMethodException) {
501 throw (NoSuchMethodException)cause;
502 }
503 throwAsScriptException(e);
504 throw new AssertionError("should not reach here");
599 } finally {
600 if (globalChanged) {
601 Context.setGlobal(oldGlobal);
602 }
603 }
604 }
605
606 private static boolean isInterfaceImplemented(final Class<?> iface, final ScriptObject sobj) {
607 for (final Method method : iface.getMethods()) {
608 // ignore methods of java.lang.Object class
609 if (method.getDeclaringClass() == Object.class) {
610 continue;
611 }
612
613 Object obj = sobj.get(method.getName());
614 if (! (obj instanceof ScriptFunction)) {
615 return false;
616 }
617 }
618 return true;
619 }
620
621 private static boolean isOfContext(final ScriptObject global, final Context context) {
622 assert global instanceof GlobalObject: "Not a Global object";
623 return ((GlobalObject)global).isOfContext(context);
624 }
625 }
|