nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeansLinker.java
changeset 33333 0bad500ce4e0
parent 33007 03119bfefbbf
child 33339 334cd3ebfa5e
equal deleted inserted replaced
33332:f180be6368d8 33333:0bad500ce4e0
    81        ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    81        ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    82 */
    82 */
    83 
    83 
    84 package jdk.internal.dynalink.beans;
    84 package jdk.internal.dynalink.beans;
    85 
    85 
    86 import java.lang.invoke.MethodHandles;
    86 import java.lang.invoke.MethodHandles.Lookup;
    87 import java.util.Collection;
    87 import java.util.Collection;
    88 import java.util.Collections;
    88 import java.util.Collections;
    89 import jdk.internal.dynalink.CallSiteDescriptor;
    89 import jdk.internal.dynalink.CallSiteDescriptor;
    90 import jdk.internal.dynalink.DynamicLinkerFactory;
    90 import jdk.internal.dynalink.DynamicLinkerFactory;
    91 import jdk.internal.dynalink.linker.GuardedInvocation;
    91 import jdk.internal.dynalink.linker.GuardedInvocation;
    93 import jdk.internal.dynalink.linker.LinkRequest;
    93 import jdk.internal.dynalink.linker.LinkRequest;
    94 import jdk.internal.dynalink.linker.LinkerServices;
    94 import jdk.internal.dynalink.linker.LinkerServices;
    95 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
    95 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
    96 
    96 
    97 /**
    97 /**
    98  * A linker for POJOs. Normally used as the ultimate fallback linker by the {@link DynamicLinkerFactory} so it is given
    98  * A linker for ordinary Java objects. Normally used as the ultimate fallback
    99  * the chance to link calls to all objects that no other language runtime recognizes. Specifically, this linker will:
    99  * linker by the {@link DynamicLinkerFactory} so it is given the chance to link
       
   100  * calls to all objects that no other linker recognized. Specifically, this
       
   101  * linker will:
   100  * <ul>
   102  * <ul>
   101  * <li>expose all public methods of form {@code setXxx()}, {@code getXxx()}, and {@code isXxx()} as property setters and
   103  * <li>expose all public methods of form {@code setXxx()}, {@code getXxx()},
   102  * getters for {@code dyn:setProp} and {@code dyn:getProp} operations;</li>
   104  * and {@code isXxx()} as property setters and getters for {@code dyn:setProp}
   103  * <li>expose all public methods for invocation through {@code dyn:callMethod} operation;</li>
   105  * and {@code dyn:getProp} operations;</li>
   104  * <li>expose all public methods for retrieval for {@code dyn:getMethod} operation; the methods thus retrieved can then
   106  * <li>expose all public methods for invocation through {@code dyn:callMethod}
   105  * be invoked using {@code dyn:call};</li>
   107  * operation;</li>
   106  * <li>expose all public fields as properties, unless there are getters or setters for the properties of the same name;</li>
   108  * <li>expose all public methods for retrieval for {@code dyn:getMethod}
   107  * <li>expose {@code dyn:getLength}, {@code dyn:getElem} and {@code dyn:setElem} on native Java arrays, as well as
   109  * operation; the methods thus retrieved can then be invoked using
   108  * {@link java.util.List} and {@link java.util.Map} objects; ({@code dyn:getLength} works on any
   110  * {@code dyn:call};</li>
       
   111  * <li>expose all public fields as properties, unless there are getters or
       
   112  * setters for the properties of the same name;</li>
       
   113  * <li>expose {@code dyn:getLength}, {@code dyn:getElem} and
       
   114  * {@code dyn:setElem} on native Java arrays, as well as {@link java.util.List}
       
   115  * and {@link java.util.Map} objects; ({@code dyn:getLength} works on any
   109  * {@link java.util.Collection});</li>
   116  * {@link java.util.Collection});</li>
   110  * <li>expose a virtual property named {@code length} on Java arrays;</li>
   117  * <li>expose a virtual property named {@code length} on Java arrays;</li>
   111  * <li>expose {@code dyn:new} on instances of {@link StaticClass} as calls to constructors, including those static class
   118  * <li>expose {@code dyn:new} on instances of {@link StaticClass} as calls to
   112  * objects that represent Java arrays (their constructors take a single {@code int} parameter representing the length of
   119  * constructors, including those static class objects that represent Java arrays
   113  * the array to create);</li>
   120  * (their constructors take a single {@code int} parameter representing the
   114  * <li>expose static methods, fields, and properties of classes in a similar manner to how instance method, fields, and
   121  * length of the array to create);</li>
   115  * properties are exposed, on {@link StaticClass} objects.</li>
   122  * <li>expose static methods, fields, and properties of classes in a similar
   116  * <li>expose a virtual property named {@code static} on instances of {@link java.lang.Class} to access their
   123  * manner to how instance method, fields, and properties are exposed, on
   117  * {@link StaticClass}.</li>
   124  * {@link StaticClass} objects.</li>
       
   125  * <li>expose a virtual property named {@code static} on instances of
       
   126  * {@link java.lang.Class} to access their {@link StaticClass}.</li>
   118  * </ul>
   127  * </ul>
   119  * <p><strong>Overloaded method resolution</strong> is performed automatically for property setters, methods, and
   128  * <p><strong>Overloaded method resolution</strong> is performed automatically
   120  * constructors. Additionally, manual overloaded method selection is supported by having a call site specify a name for
   129  * for property setters, methods, and constructors. Additionally, manual
   121  * a method that contains an explicit signature, i.e. {@code dyn:getMethod:parseInt(String,int)}. You can use
   130  * overloaded method selection is supported by having a call site specify a name
   122  * non-qualified class names in such signatures regardless of those classes' packages, they will match any class with
   131  * for a method that contains an explicit signature, i.e.
   123  * the same non-qualified name. You only have to use a fully qualified class name in case non-qualified class names
   132  * {@code dyn:getMethod:parseInt(String,int)}. You can use non-qualified class
   124  * would cause selection ambiguity (that is extremely rare).</p>
   133  * names in such signatures regardless of those classes' packages, they will
   125  * <p><strong>Variable argument invocation</strong> is handled for both methods and constructors.</p>
   134  * match any class with the same non-qualified name. You only have to use a
   126  * <p>Currently, only public fields and methods are supported. Any Lookup objects passed in the
   135  * fully qualified class name in case non-qualified class names would cause
   127  * {@link LinkRequest}s are ignored and {@link MethodHandles#publicLookup()} is used instead.</p>
   136  * selection ambiguity (that is extremely rare). Overloaded resolution for
       
   137  * constructors is not automatic as there is no logical place to attach that
       
   138  * functionality to but if a language wishes to provide this functionality, it
       
   139  * can use {@link #getConstructorMethod(Class, String)} as a useful building
       
   140  * block for it.</p>
       
   141  * <p><strong>Variable argument invocation</strong> is handled for both methods
       
   142  * and constructors.</p>
       
   143  * <p><strong>Caller sensitive methods</strong> can be linked as long as they
       
   144  * are otherwise public and link requests have call site descriptors carrying
       
   145  * full-strength {@link Lookup} objects and not weakened lookups or the public
       
   146  * lookup.</p>
       
   147  * <p>The class also exposes various static methods for discovery of available
       
   148  * property and method names on classes and class instances, as well as access
       
   149  * to per-class linkers using the {@link #getLinkerForClass(Class)}
       
   150  * method.</p>
   128  */
   151  */
   129 public class BeansLinker implements GuardingDynamicLinker {
   152 public class BeansLinker implements GuardingDynamicLinker {
   130     private static final ClassValue<TypeBasedGuardingDynamicLinker> linkers = new ClassValue<TypeBasedGuardingDynamicLinker>() {
   153     private static final ClassValue<TypeBasedGuardingDynamicLinker> linkers = new ClassValue<TypeBasedGuardingDynamicLinker>() {
   131         @Override
   154         @Override
   132         protected TypeBasedGuardingDynamicLinker computeValue(final Class<?> clazz) {
   155         protected TypeBasedGuardingDynamicLinker computeValue(final Class<?> clazz) {
   138                 new BeanLinker(clazz);
   161                 new BeanLinker(clazz);
   139         }
   162         }
   140     };
   163     };
   141 
   164 
   142     /**
   165     /**
   143      * Creates a new POJO linker.
   166      * Creates a new beans linker.
   144      */
   167      */
   145     public BeansLinker() {
   168     public BeansLinker() {
   146     }
   169     }
   147 
   170 
   148     /**
   171     /**
   149      * Returns a bean linker for a particular single class. Useful when you need to override or extend the behavior of
   172      * Returns a bean linker for a particular single class. Useful when you need
   150      * linking for some classes in your language runtime's linker, but still want to delegate to the default behavior in
   173      * to override or extend the behavior of linking for some classes in your
   151      * some cases.
   174      * language runtime's linker, but still want to delegate to the default
       
   175      * behavior in some cases.
   152      * @param clazz the class
   176      * @param clazz the class
   153      * @return a bean linker for that class
   177      * @return a bean linker for that class
   154      */
   178      */
   155     public static TypeBasedGuardingDynamicLinker getLinkerForClass(final Class<?> clazz) {
   179     public static TypeBasedGuardingDynamicLinker getLinkerForClass(final Class<?> clazz) {
   156         return linkers.get(clazz);
   180         return linkers.get(clazz);
   157     }
   181     }
   158 
   182 
   159     /**
   183     /**
   160      * Returns true if the object is a Dynalink Java dynamic method.
   184      * Returns true if the object is a Java dynamic method (e.g., one
       
   185      * obtained through a {@code dyn:getMethod} call on a Java object or
       
   186      * {@link StaticClass} or through
       
   187      * {@link #getConstructorMethod(Class, String)}.
   161      *
   188      *
   162      * @param obj the object we want to test for being a dynamic method
   189      * @param obj the object we want to test for being a Java dynamic method.
   163      * @return true if it is a dynamic method, false otherwise.
   190      * @return true if it is a dynamic method, false otherwise.
   164      */
   191      */
   165     public static boolean isDynamicMethod(final Object obj) {
   192     public static boolean isDynamicMethod(final Object obj) {
   166         return obj instanceof DynamicMethod;
   193         return obj instanceof DynamicMethod;
   167     }
   194     }
   168 
   195 
   169     /**
   196     /**
   170      * Returns true if the object is a Dynalink Java constructor.
   197      * Returns true if the object is a Java constructor (obtained through
       
   198      * {@link #getConstructorMethod(Class, String)}}.
   171      *
   199      *
   172      * @param obj the object we want to test for being a constructor
   200      * @param obj the object we want to test for being a Java constructor.
   173      * @return true if it is a constructor, false otherwise.
   201      * @return true if it is a constructor, false otherwise.
   174      */
   202      */
   175     public static boolean isDynamicConstructor(final Object obj) {
   203     public static boolean isDynamicConstructor(final Object obj) {
   176         return obj instanceof DynamicMethod && ((DynamicMethod)obj).isConstructor();
   204         return obj instanceof DynamicMethod && ((DynamicMethod)obj).isConstructor();
   177     }
   205     }
   178 
   206 
   179     /**
   207     /**
   180      * Return the dynamic method of constructor of the given class and the given signature.
   208      * Return the dynamic method of constructor of the given class and the given
       
   209      * signature. This method is useful for exposing a functionality for
       
   210      * selecting an overloaded constructor based on an explicit signature, as
       
   211      * this functionality is not otherwise exposed by Dynalink as
       
   212      * {@link StaticClass} objects act as overloaded constructors without
       
   213      * explicit signature selection.
   181      * @param clazz the class
   214      * @param clazz the class
   182      * @param signature full signature of the constructor
   215      * @param signature full signature of the constructor
   183      * @return DynamicMethod for the constructor
   216      * @return dynamic method for the constructor
   184      */
   217      */
   185     public static Object getConstructorMethod(final Class<?> clazz, final String signature) {
   218     public static Object getConstructorMethod(final Class<?> clazz, final String signature) {
   186         return StaticClassLinker.getConstructorMethod(clazz, signature);
   219         return StaticClassLinker.getConstructorMethod(clazz, signature);
   187     }
   220     }
   188 
   221