|
Java example source code file (JavaAdapterServices.java)
The JavaAdapterServices.java Java example source code/* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package jdk.nashorn.internal.runtime.linker; import static jdk.internal.org.objectweb.asm.Opcodes.ACC_FINAL; import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC; import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC; import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER; import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD; import static jdk.internal.org.objectweb.asm.Opcodes.RETURN; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.security.AccessController; import java.security.CodeSigner; import java.security.CodeSource; import java.security.Permissions; import java.security.PrivilegedAction; import java.security.ProtectionDomain; import java.security.SecureClassLoader; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Type; import jdk.internal.org.objectweb.asm.commons.InstructionAdapter; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.Undefined; /** * Provides static utility services to generated Java adapter classes. */ public final class JavaAdapterServices { private static final ThreadLocal<ScriptObject> classOverrides = new ThreadLocal<>(); private static final MethodHandle NO_PERMISSIONS_INVOKER = createNoPermissionsInvoker(); private JavaAdapterServices() { } /** * Given a JS script function, binds it to null JS "this", and adapts its parameter types, return types, and arity * to the specified type and arity. This method is public mainly for implementation reasons, so the adapter classes * can invoke it from their constructors that take a ScriptFunction in its first argument to obtain the method * handles for their abstract method implementations. * @param fn the script function * @param type the method type it has to conform to * @return the appropriately adapted method handle for invoking the script function. */ public static MethodHandle getHandle(final ScriptFunction fn, final MethodType type) { // JS "this" will be global object or undefined depending on if 'fn' is strict or not return bindAndAdaptHandle(fn, fn.isStrict()? ScriptRuntime.UNDEFINED : Context.getGlobal(), type); } /** * Given a JS script object, retrieves a function from it by name, binds it to the script object as its "this", and * adapts its parameter types, return types, and arity to the specified type and arity. This method is public mainly * for implementation reasons, so the adapter classes can invoke it from their constructors that take a Object * in its first argument to obtain the method handles for their method implementations. * @param obj the script obj * @param name the name of the property that contains the function * @param type the method type it has to conform to * @return the appropriately adapted method handle for invoking the script function, or null if the value of the * property is either null or undefined, or "toString" was requested as the name, but the object doesn't directly * define it but just inherits it through prototype. */ public static MethodHandle getHandle(final Object obj, final String name, final MethodType type) { if (! (obj instanceof ScriptObject)) { throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); } final ScriptObject sobj = (ScriptObject)obj; // Since every JS Object has a toString, we only override "String toString()" it if it's explicitly specified if ("toString".equals(name) && !sobj.hasOwnProperty("toString")) { return null; } final Object fnObj = sobj.get(name); if (fnObj instanceof ScriptFunction) { return bindAndAdaptHandle((ScriptFunction)fnObj, sobj, type); } else if(fnObj == null || fnObj instanceof Undefined) { return null; } else { throw typeError("not.a.function", name); } } /** * Returns a thread-local JS object used to define methods for the adapter class being initialized on the current * thread. This method is public solely for implementation reasons, so the adapter classes can invoke it from their * static initializers. * @return the thread-local JS object used to define methods for the class being initialized. */ public static ScriptObject getClassOverrides() { final ScriptObject overrides = classOverrides.get(); assert overrides != null; return overrides; } /** * Takes a method handle and an argument to it, and invokes the method handle passing it the argument. Basically * equivalent to {@code method.invokeExact(arg)}, except that the method handle will be invoked in a protection * domain with absolutely no permissions. * @param method the method handle to invoke. The handle must have the exact type of {@code void(Object)}. * @param arg the argument to pass to the handle. * @throws Throwable if anything goes wrong. */ public static void invokeNoPermissions(final MethodHandle method, final Object arg) throws Throwable { NO_PERMISSIONS_INVOKER.invokeExact(method, arg); } static void setClassOverrides(ScriptObject overrides) { classOverrides.set(overrides); } private static MethodHandle bindAndAdaptHandle(final ScriptFunction fn, final Object self, final MethodType type) { return Bootstrap.getLinkerServices().asType(ScriptObject.pairArguments(fn.getBoundInvokeHandle(self), type, false), type); } private static MethodHandle createNoPermissionsInvoker() { final String className = "NoPermissionsInvoker"; final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); cw.visit(Opcodes.V1_7, ACC_PUBLIC | ACC_SUPER | ACC_FINAL, className, null, "java/lang/Object", null); final Type objectType = Type.getType(Object.class); final Type methodHandleType = Type.getType(MethodHandle.class); final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "invoke", Type.getMethodDescriptor(Type.VOID_TYPE, methodHandleType, objectType), null, null)); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.invokevirtual(methodHandleType.getInternalName(), "invokeExact", Type.getMethodDescriptor( Type.VOID_TYPE, objectType), false); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); cw.visitEnd(); final byte[] bytes = cw.toByteArray(); final ClassLoader loader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { @Override public ClassLoader run() { return new SecureClassLoader(null) { @Override protected Class<?> findClass(String name) throws ClassNotFoundException { if(name.equals(className)) { return defineClass(name, bytes, 0, bytes.length, new ProtectionDomain( new CodeSource(null, (CodeSigner[])null), new Permissions())); } throw new ClassNotFoundException(name); } }; } }); try { return MethodHandles.lookup().findStatic(Class.forName(className, true, loader), "invoke", MethodType.methodType(void.class, MethodHandle.class, Object.class)); } catch(ReflectiveOperationException e) { throw new AssertionError(e.getMessage(), e); } } } Other Java examples (source code examples)Here is a short list of links related to this Java JavaAdapterServices.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.