< prev index next >
src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
Print this page
rev 1309 : 8085885: address Javadoc warnings in Nashorn source code
*** 1,7 ****
/*
! * 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
--- 1,7 ----
/*
! * Copyright (c) 2010, 2015, 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
*** 52,78 ****
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
/**
! * <p>A factory class that generates adapter classes. Adapter classes allow implementation of Java interfaces and
! * extending of Java classes from JavaScript. For every combination of a superclass to extend and interfaces to
! * implement (collectively: "original types"), exactly one adapter class is generated that extends the specified
! * superclass and implements the specified interfaces. (But see the discussion of class-based overrides for exceptions.)
! * </p><p>
! * The adapter class is generated in a new secure class loader that inherits Nashorn's protection domain, and has either
! * one of the original types' class loader or the Nashorn's class loader as its parent - the parent class loader
! * is chosen so that all the original types and the Nashorn core classes are visible from it (as the adapter will have
! * constant pool references to ScriptObject and ScriptFunction classes). In case none of the candidate class loaders has
! * visibility of all the required types, an error is thrown. The class uses {@link JavaAdapterBytecodeGenerator} to
! * generate the adapter class itself; see its documentation for details about the generated class.
! * </p><p>
! * You normally don't use this class directly, but rather either create adapters from script using
! * {@link jdk.nashorn.internal.objects.NativeJava#extend(Object, Object...)}, using the {@code new} operator on abstract classes and interfaces (see
! * {@link jdk.nashorn.internal.objects.NativeJava#type(Object, Object)}), or implicitly when passing script functions to Java methods expecting SAM
! * types.
! * </p>
*/
@SuppressWarnings("javadoc")
public final class JavaAdapterFactory {
private static final ProtectionDomain MINIMAL_PERMISSION_DOMAIN = createMinimalPermissionDomain();
--- 52,83 ----
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
/**
! * A factory class that generates adapter classes. Adapter classes allow
! * implementation of Java interfaces and extending of Java classes from
! * JavaScript. For every combination of a superclass to extend and interfaces to
! * implement (collectively: "original types"), exactly one adapter class is
! * generated that extends the specified superclass and implements the specified
! * interfaces. (But see the discussion of class-based overrides for exceptions.)
! * <p>
! * The adapter class is generated in a new secure class loader that inherits
! * Nashorn's protection domain, and has either one of the original types' class
! * loader or the Nashorn's class loader as its parent - the parent class loader
! * is chosen so that all the original types and the Nashorn core classes are
! * visible from it (as the adapter will have constant pool references to
! * ScriptObject and ScriptFunction classes). In case none of the candidate class
! * loaders has visibility of all the required types, an error is thrown. The
! * class uses {@link JavaAdapterBytecodeGenerator} to generate the adapter class
! * itself; see its documentation for details about the generated class.
! * <p>
! * You normally don't use this class directly, but rather either create adapters
! * from script using {@link jdk.nashorn.internal.objects.NativeJava#extend(Object, Object...)},
! * using the {@code new} operator on abstract classes and interfaces (see
! * {@link jdk.nashorn.internal.objects.NativeJava#type(Object, Object)}), or
! * implicitly when passing script functions to Java methods expecting SAM types.
*/
@SuppressWarnings("javadoc")
public final class JavaAdapterFactory {
private static final ProtectionDomain MINIMAL_PERMISSION_DOMAIN = createMinimalPermissionDomain();
*** 91,119 ****
return new HashMap<>();
}
};
/**
! * Returns an adapter class for the specified original types. The adapter class extends/implements the original
! * class/interfaces.
! * @param types the original types. The caller must pass at least one Java type representing either a public
! * interface or a non-final public class with at least one public or protected constructor. If more than one type is
! * specified, at most one can be a class and the rest have to be interfaces. The class can be in any position in the
! * array. Invoking the method twice with exactly the same types in the same order will return the same adapter
! * class, any reordering of types or even addition or removal of redundant types (i.e. interfaces that other types
! * in the list already implement/extend, or {@code java.lang.Object} in a list of types consisting purely of
! * interfaces) will result in a different adapter class, even though those adapter classes are functionally
! * identical; we deliberately don't want to incur the additional processing cost of canonicalizing type lists.
! * @param classOverrides a JavaScript object with functions serving as the class-level overrides and
! * implementations. These overrides are defined for all instances of the class, and can be further overridden on a
! * per-instance basis by passing additional objects in the constructor.
! * @param lookup the lookup object identifying the caller class. The generated adapter class will have the
! * protection domain of the caller class iff the lookup object is full-strength, otherwise it will be completely
! * unprivileged.
! * @return an adapter class. See this class' documentation for details on the generated adapter class.
! * @throws ECMAException with a TypeError if the adapter class can not be generated because the original class is
! * final, non-public, or has no public or protected constructors.
*/
public static StaticClass getAdapterClassFor(final Class<?>[] types, final ScriptObject classOverrides, final MethodHandles.Lookup lookup) {
return getAdapterClassFor(types, classOverrides, getProtectionDomain(lookup));
}
--- 96,138 ----
return new HashMap<>();
}
};
/**
! * Returns an adapter class for the specified original types. The adapter
! * class extends/implements the original class/interfaces.
! *
! * @param types the original types. The caller must pass at least one Java
! * type representing either a public interface or a non-final public
! * class with at least one public or protected constructor. If more
! * than one type is specified, at most one can be a class and the
! * rest have to be interfaces. The class can be in any position in
! * the array. Invoking the method twice with exactly the same types
! * in the same order will return the same adapter class, any
! * reordering of types or even addition or removal of redundant types
! * (i.e., interfaces that other types in the list already
! * implement/extend, or {@code java.lang.Object} in a list of types
! * consisting purely of interfaces) will result in a different
! * adapter class, even though those adapter classes are functionally
! * identical; we deliberately don't want to incur the additional
! * processing cost of canonicalizing type lists.
! * @param classOverrides a JavaScript object with functions serving as the
! * class-level overrides and implementations. These overrides are
! * defined for all instances of the class, and can be further
! * overridden on a per-instance basis by passing additional objects
! * in the constructor.
! * @param lookup the lookup object identifying the caller class. The
! * generated adapter class will have the protection domain of the
! * caller class iff the lookup object is full-strength, otherwise it
! * will be completely unprivileged.
! *
! * @return an adapter class. See this class' documentation for details on
! * the generated adapter class.
! *
! * @throws ECMAException with a TypeError if the adapter class can not be
! * generated because the original class is final, non-public, or has
! * no public or protected constructors.
*/
public static StaticClass getAdapterClassFor(final Class<?>[] types, final ScriptObject classOverrides, final MethodHandles.Lookup lookup) {
return getAdapterClassFor(types, classOverrides, getProtectionDomain(lookup));
}
*** 146,164 ****
}
});
}
/**
! * Returns a method handle representing a constructor that takes a single argument of the source type (which,
! * really, should be one of {@link ScriptObject}, {@link ScriptFunction}, or {@link Object}, and returns an instance
! * of the adapter for the target type. Used to implement the function autoconverters as well as the Nashorn's
! * JSR-223 script engine's {@code getInterface()} method.
! * @param sourceType the source type; should be either {@link ScriptObject}, {@link ScriptFunction}, or
! * {@link Object}. In case of {@code Object}, it will return a method handle that dispatches to either the script
! * object or function constructor at invocation based on the actual argument.
* @param targetType the target type, for which adapter instances will be created
* @return the constructor method handle.
* @throws Exception if anything goes wrong
*/
public static MethodHandle getConstructor(final Class<?> sourceType, final Class<?> targetType, final MethodHandles.Lookup lookup) throws Exception {
final StaticClass adapterClass = getAdapterClassFor(new Class<?>[] { targetType }, null, lookup);
return MH.bindTo(Bootstrap.getLinkerServices().getGuardedInvocation(new LinkRequestImpl(
--- 165,191 ----
}
});
}
/**
! * Returns a method handle representing a constructor that takes a single
! * argument of the source type (which, really, should be one of {@link ScriptObject},
! * {@link ScriptFunction}, or {@link Object}, and returns an instance of the
! * adapter for the target type. Used to implement the function autoconverters
! * as well as the Nashorn JSR-223 script engine's {@code getInterface()}
! * method.
! *
! * @param sourceType the source type; should be either {@link ScriptObject},
! * {@link ScriptFunction}, or {@link Object}. In case of {@code Object},
! * it will return a method handle that dispatches to either the script
! * object or function constructor at invocation based on the actual
! * argument.
* @param targetType the target type, for which adapter instances will be created
+ * @param lookup method handle lookup to use
+ *
* @return the constructor method handle.
+ *
* @throws Exception if anything goes wrong
*/
public static MethodHandle getConstructor(final Class<?> sourceType, final Class<?> targetType, final MethodHandles.Lookup lookup) throws Exception {
final StaticClass adapterClass = getAdapterClassFor(new Class<?>[] { targetType }, null, lookup);
return MH.bindTo(Bootstrap.getLinkerServices().getGuardedInvocation(new LinkRequestImpl(
*** 166,182 ****
MethodType.methodType(targetType, StaticClass.class, sourceType), 0), null, 0, false,
adapterClass, null)).getInvocation(), adapterClass);
}
/**
! * Returns whether an instance of the specified class/interface can be generated from a ScriptFunction. Returns true
! * iff: the adapter for the class/interface can be created, it is abstract (this includes interfaces), it has at
! * least one abstract method, all the abstract methods share the same name, and it has a public or protected default
! * constructor. Note that invoking this class will most likely result in the adapter class being defined in the JVM
! * if it hasn't been already.
* @param clazz the inspected class
! * @return true iff an instance of the specified class/interface can be generated from a ScriptFunction.
*/
static boolean isAutoConvertibleFromFunction(final Class<?> clazz) {
return getAdapterInfo(new Class<?>[] { clazz }).autoConvertibleFromFunction;
}
--- 193,214 ----
MethodType.methodType(targetType, StaticClass.class, sourceType), 0), null, 0, false,
adapterClass, null)).getInvocation(), adapterClass);
}
/**
! * Returns whether an instance of the specified class/interface can be
! * generated from a ScriptFunction. Returns {@code true} iff: the adapter
! * for the class/interface can be created, it is abstract (this includes
! * interfaces), it has at least one abstract method, all the abstract
! * methods share the same name, and it has a public or protected default
! * constructor. Note that invoking this class will most likely result in the
! * adapter class being defined in the JVM if it hasn't been already.
! *
* @param clazz the inspected class
! *
! * @return {@code true} iff an instance of the specified class/interface can
! * be generated from a ScriptFunction.
*/
static boolean isAutoConvertibleFromFunction(final Class<?> clazz) {
return getAdapterInfo(new Class<?>[] { clazz }).autoConvertibleFromFunction;
}
*** 196,206 ****
--- 228,240 ----
return adapterInfo;
}
/**
* For a given class, create its adapter class and associated info.
+ *
* @param type the class for which the adapter is created
+ *
* @return the adapter info for the class.
*/
private static AdapterInfo createAdapterInfo(final Class<?>[] types, final ClassAndLoader definingClassAndLoader) {
Class<?> superClass = null;
final List<Class<?>> interfaces = new ArrayList<>(types.length);
*** 309,323 ****
JavaAdapterServices.setClassOverrides(null);
}
}
/**
! * Choose between the passed class loader and the class loader that defines the ScriptObject class, based on which
! * of the two can see the classes in both.
! * @param classAndLoader the loader and a representative class from it that will be used to add the generated
! * adapter to its ADAPTER_INFO_MAPS.
* @return the class loader that sees both the specified class and Nashorn classes.
* @throws IllegalStateException if no such class loader is found.
*/
private static ClassLoader findCommonLoader(final ClassAndLoader classAndLoader) throws AdaptationException {
if(classAndLoader.canSee(SCRIPT_OBJECT_LOADER)) {
return classAndLoader.getLoader();
--- 343,360 ----
JavaAdapterServices.setClassOverrides(null);
}
}
/**
! * Choose between the passed class loader and the class loader that defines the
! * ScriptObject class, based on which of the two can see the classes in both.
! *
! * @param classAndLoader the loader and a representative class from it that will
! * be used to add the generated adapter to its ADAPTER_INFO_MAPS.
! *
* @return the class loader that sees both the specified class and Nashorn classes.
+ *
* @throws IllegalStateException if no such class loader is found.
*/
private static ClassLoader findCommonLoader(final ClassAndLoader classAndLoader) throws AdaptationException {
if(classAndLoader.canSee(SCRIPT_OBJECT_LOADER)) {
return classAndLoader.getLoader();
< prev index next >