src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java

Print this page




  31 import java.lang.invoke.MethodHandles;
  32 import java.lang.invoke.MethodHandles.Lookup;
  33 import java.lang.invoke.MethodType;
  34 import java.lang.reflect.Modifier;
  35 import java.security.AccessControlContext;
  36 import java.security.AccessController;
  37 import java.security.CodeSigner;
  38 import java.security.CodeSource;
  39 import java.security.Permissions;
  40 import java.security.PrivilegedAction;
  41 import java.security.ProtectionDomain;
  42 import java.util.ArrayList;
  43 import java.util.Arrays;
  44 import java.util.Collections;
  45 import java.util.HashMap;
  46 import java.util.List;
  47 import java.util.Map;
  48 import java.util.concurrent.ConcurrentHashMap;
  49 import jdk.internal.dynalink.beans.StaticClass;
  50 import jdk.internal.dynalink.support.LinkRequestImpl;
  51 import jdk.nashorn.internal.objects.NativeJava;
  52 import jdk.nashorn.internal.runtime.Context;
  53 import jdk.nashorn.internal.runtime.ECMAException;
  54 import jdk.nashorn.internal.runtime.ScriptFunction;
  55 import jdk.nashorn.internal.runtime.ScriptObject;
  56 
  57 /**
  58  * <p>A factory class that generates adapter classes. Adapter classes allow implementation of Java interfaces and
  59  * extending of Java classes from JavaScript. For every combination of a superclass to extend and interfaces to
  60  * implement (collectively: "original types"), exactly one adapter class is generated that extends the specified
  61  * superclass and implements the specified interfaces. (But see the discussion of class-based overrides for exceptions.)
  62  * </p><p>
  63  * The adapter class is generated in a new secure class loader that inherits Nashorn's protection domain, and has either
  64  * one of the original types' class loader or the Nashorn's class loader as its parent - the parent class loader
  65  * is chosen so that all the original types and the Nashorn core classes are visible from it (as the adapter will have
  66  * constant pool references to ScriptObject and ScriptFunction classes). In case none of the candidate class loaders has
  67  * visibility of all the required types, an error is thrown. The class uses {@link JavaAdapterBytecodeGenerator} to
  68  * generate the adapter class itself; see its documentation for details about the generated class.
  69  * </p><p>
  70  * You normally don't use this class directly, but rather either create adapters from script using
  71  * {@link NativeJava#extend(Object, Object...)}, using the {@code new} operator on abstract classes and interfaces (see
  72  * {@link NativeJava#type(Object, Object)}), or implicitly when passing script functions to Java methods expecting SAM
  73  * types.
  74  * </p>
  75  */
  76 
  77 @SuppressWarnings("javadoc")
  78 public final class JavaAdapterFactory {
  79     private static final ProtectionDomain MINIMAL_PERMISSION_DOMAIN = createMinimalPermissionDomain();
  80 
  81     // context with permissions needs for AdapterInfo creation
  82     private static final AccessControlContext CREATE_ADAPTER_INFO_ACC_CTXT =
  83         ClassAndLoader.createPermAccCtxt("createClassLoader", "getClassLoader",
  84             "accessDeclaredMembers", "accessClassInPackage.jdk.nashorn.internal.runtime");
  85 
  86     /**
  87      * A mapping from an original Class object to AdapterInfo representing the adapter for the class it represents.
  88      */
  89     private static final ClassValue<Map<List<Class<?>>, AdapterInfo>> ADAPTER_INFO_MAPS = new ClassValue<Map<List<Class<?>>, AdapterInfo>>() {
  90         @Override
  91         protected Map<List<Class<?>>, AdapterInfo> computeValue(final Class<?> type) {
  92             return new HashMap<>();


 320          * @param classAndLoader the loader and a representative class from it that will be used to add the generated
 321          * adapter to its ADAPTER_INFO_MAPS.
 322          * @return the class loader that sees both the specified class and Nashorn classes.
 323          * @throws IllegalStateException if no such class loader is found.
 324          */
 325         private static ClassLoader findCommonLoader(final ClassAndLoader classAndLoader) throws AdaptationException {
 326             if(classAndLoader.canSee(SCRIPT_OBJECT_LOADER)) {
 327                 return classAndLoader.getLoader();
 328             }
 329             if (SCRIPT_OBJECT_LOADER.canSee(classAndLoader)) {
 330                 return SCRIPT_OBJECT_LOADER.getLoader();
 331             }
 332 
 333             throw new AdaptationException(AdaptationResult.Outcome.ERROR_NO_COMMON_LOADER, classAndLoader.getRepresentativeClass().getCanonicalName());
 334         }
 335     }
 336 
 337     private static ProtectionDomain createMinimalPermissionDomain() {
 338         // Generated classes need to have at least the permission to access Nashorn runtime and runtime.linker packages.
 339         final Permissions permissions = new Permissions();

 340         permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime"));
 341         permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime.linker"));
 342         return new ProtectionDomain(new CodeSource(null, (CodeSigner[])null), permissions);
 343     }
 344 }


  31 import java.lang.invoke.MethodHandles;
  32 import java.lang.invoke.MethodHandles.Lookup;
  33 import java.lang.invoke.MethodType;
  34 import java.lang.reflect.Modifier;
  35 import java.security.AccessControlContext;
  36 import java.security.AccessController;
  37 import java.security.CodeSigner;
  38 import java.security.CodeSource;
  39 import java.security.Permissions;
  40 import java.security.PrivilegedAction;
  41 import java.security.ProtectionDomain;
  42 import java.util.ArrayList;
  43 import java.util.Arrays;
  44 import java.util.Collections;
  45 import java.util.HashMap;
  46 import java.util.List;
  47 import java.util.Map;
  48 import java.util.concurrent.ConcurrentHashMap;
  49 import jdk.internal.dynalink.beans.StaticClass;
  50 import jdk.internal.dynalink.support.LinkRequestImpl;

  51 import jdk.nashorn.internal.runtime.Context;
  52 import jdk.nashorn.internal.runtime.ECMAException;
  53 import jdk.nashorn.internal.runtime.ScriptFunction;
  54 import jdk.nashorn.internal.runtime.ScriptObject;
  55 
  56 /**
  57  * <p>A factory class that generates adapter classes. Adapter classes allow implementation of Java interfaces and
  58  * extending of Java classes from JavaScript. For every combination of a superclass to extend and interfaces to
  59  * implement (collectively: "original types"), exactly one adapter class is generated that extends the specified
  60  * superclass and implements the specified interfaces. (But see the discussion of class-based overrides for exceptions.)
  61  * </p><p>
  62  * The adapter class is generated in a new secure class loader that inherits Nashorn's protection domain, and has either
  63  * one of the original types' class loader or the Nashorn's class loader as its parent - the parent class loader
  64  * is chosen so that all the original types and the Nashorn core classes are visible from it (as the adapter will have
  65  * constant pool references to ScriptObject and ScriptFunction classes). In case none of the candidate class loaders has
  66  * visibility of all the required types, an error is thrown. The class uses {@link JavaAdapterBytecodeGenerator} to
  67  * generate the adapter class itself; see its documentation for details about the generated class.
  68  * </p><p>
  69  * You normally don't use this class directly, but rather either create adapters from script using
  70  * {@link jdk.nashorn.internal.objects.NativeJava#extend(Object, Object...)}, using the {@code new} operator on abstract classes and interfaces (see
  71  * {@link jdk.nashorn.internal.objects.NativeJava#type(Object, Object)}), or implicitly when passing script functions to Java methods expecting SAM
  72  * types.
  73  * </p>
  74  */
  75 
  76 @SuppressWarnings("javadoc")
  77 public final class JavaAdapterFactory {
  78     private static final ProtectionDomain MINIMAL_PERMISSION_DOMAIN = createMinimalPermissionDomain();
  79 
  80     // context with permissions needs for AdapterInfo creation
  81     private static final AccessControlContext CREATE_ADAPTER_INFO_ACC_CTXT =
  82         ClassAndLoader.createPermAccCtxt("createClassLoader", "getClassLoader",
  83             "accessDeclaredMembers", "accessClassInPackage.jdk.nashorn.internal.runtime");
  84 
  85     /**
  86      * A mapping from an original Class object to AdapterInfo representing the adapter for the class it represents.
  87      */
  88     private static final ClassValue<Map<List<Class<?>>, AdapterInfo>> ADAPTER_INFO_MAPS = new ClassValue<Map<List<Class<?>>, AdapterInfo>>() {
  89         @Override
  90         protected Map<List<Class<?>>, AdapterInfo> computeValue(final Class<?> type) {
  91             return new HashMap<>();


 319          * @param classAndLoader the loader and a representative class from it that will be used to add the generated
 320          * adapter to its ADAPTER_INFO_MAPS.
 321          * @return the class loader that sees both the specified class and Nashorn classes.
 322          * @throws IllegalStateException if no such class loader is found.
 323          */
 324         private static ClassLoader findCommonLoader(final ClassAndLoader classAndLoader) throws AdaptationException {
 325             if(classAndLoader.canSee(SCRIPT_OBJECT_LOADER)) {
 326                 return classAndLoader.getLoader();
 327             }
 328             if (SCRIPT_OBJECT_LOADER.canSee(classAndLoader)) {
 329                 return SCRIPT_OBJECT_LOADER.getLoader();
 330             }
 331 
 332             throw new AdaptationException(AdaptationResult.Outcome.ERROR_NO_COMMON_LOADER, classAndLoader.getRepresentativeClass().getCanonicalName());
 333         }
 334     }
 335 
 336     private static ProtectionDomain createMinimalPermissionDomain() {
 337         // Generated classes need to have at least the permission to access Nashorn runtime and runtime.linker packages.
 338         final Permissions permissions = new Permissions();
 339         permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.objects"));
 340         permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime"));
 341         permissions.add(new RuntimePermission("accessClassInPackage.jdk.nashorn.internal.runtime.linker"));
 342         return new ProtectionDomain(new CodeSource(null, (CodeSigner[])null), permissions);
 343     }
 344 }