nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AbstractJavaLinker.java
changeset 34456 84eaea8d0574
parent 34096 5ac6287ec71a
parent 34455 cc9f05d3caf0
child 34457 81a65a2faef3
equal deleted inserted replaced
34096:5ac6287ec71a 34456:84eaea8d0574
     1 /*
       
     2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 /*
       
    27  * This file is available under and governed by the GNU General Public
       
    28  * License version 2 only, as published by the Free Software Foundation.
       
    29  * However, the following notice accompanied the original version of this
       
    30  * file, and Oracle licenses the original version of this file under the BSD
       
    31  * license:
       
    32  */
       
    33 /*
       
    34    Copyright 2009-2013 Attila Szegedi
       
    35 
       
    36    Licensed under both the Apache License, Version 2.0 (the "Apache License")
       
    37    and the BSD License (the "BSD License"), with licensee being free to
       
    38    choose either of the two at their discretion.
       
    39 
       
    40    You may not use this file except in compliance with either the Apache
       
    41    License or the BSD License.
       
    42 
       
    43    If you choose to use this file in compliance with the Apache License, the
       
    44    following notice applies to you:
       
    45 
       
    46        You may obtain a copy of the Apache License at
       
    47 
       
    48            http://www.apache.org/licenses/LICENSE-2.0
       
    49 
       
    50        Unless required by applicable law or agreed to in writing, software
       
    51        distributed under the License is distributed on an "AS IS" BASIS,
       
    52        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
       
    53        implied. See the License for the specific language governing
       
    54        permissions and limitations under the License.
       
    55 
       
    56    If you choose to use this file in compliance with the BSD License, the
       
    57    following notice applies to you:
       
    58 
       
    59        Redistribution and use in source and binary forms, with or without
       
    60        modification, are permitted provided that the following conditions are
       
    61        met:
       
    62        * Redistributions of source code must retain the above copyright
       
    63          notice, this list of conditions and the following disclaimer.
       
    64        * Redistributions in binary form must reproduce the above copyright
       
    65          notice, this list of conditions and the following disclaimer in the
       
    66          documentation and/or other materials provided with the distribution.
       
    67        * Neither the name of the copyright holder nor the names of
       
    68          contributors may be used to endorse or promote products derived from
       
    69          this software without specific prior written permission.
       
    70 
       
    71        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
       
    72        IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
       
    73        TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
       
    74        PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
       
    75        BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
       
    76        CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
       
    77        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
       
    78        BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
       
    79        WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
       
    80        OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
       
    81        ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    82 */
       
    83 
       
    84 package jdk.internal.dynalink.beans;
       
    85 
       
    86 import java.lang.invoke.MethodHandle;
       
    87 import java.lang.invoke.MethodHandles;
       
    88 import java.lang.invoke.MethodType;
       
    89 import java.lang.reflect.AccessibleObject;
       
    90 import java.lang.reflect.Constructor;
       
    91 import java.lang.reflect.Field;
       
    92 import java.lang.reflect.Member;
       
    93 import java.lang.reflect.Method;
       
    94 import java.lang.reflect.Modifier;
       
    95 import java.util.Arrays;
       
    96 import java.util.Collections;
       
    97 import java.util.HashMap;
       
    98 import java.util.List;
       
    99 import java.util.Map;
       
   100 import java.util.Set;
       
   101 import jdk.internal.dynalink.CallSiteDescriptor;
       
   102 import jdk.internal.dynalink.CompositeOperation;
       
   103 import jdk.internal.dynalink.NamedOperation;
       
   104 import jdk.internal.dynalink.Operation;
       
   105 import jdk.internal.dynalink.StandardOperation;
       
   106 import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType;
       
   107 import jdk.internal.dynalink.internal.InternalTypeUtilities;
       
   108 import jdk.internal.dynalink.linker.GuardedInvocation;
       
   109 import jdk.internal.dynalink.linker.GuardingDynamicLinker;
       
   110 import jdk.internal.dynalink.linker.LinkRequest;
       
   111 import jdk.internal.dynalink.linker.LinkerServices;
       
   112 import jdk.internal.dynalink.linker.support.Guards;
       
   113 import jdk.internal.dynalink.linker.support.Lookup;
       
   114 import sun.reflect.CallerSensitive;
       
   115 
       
   116 /**
       
   117  * A base class for both {@link StaticClassLinker} and {@link BeanLinker}. Deals with common aspects of property
       
   118  * exposure and method calls for both static and instance facets of a class.
       
   119  */
       
   120 abstract class AbstractJavaLinker implements GuardingDynamicLinker {
       
   121 
       
   122     final Class<?> clazz;
       
   123     private final MethodHandle classGuard;
       
   124     private final MethodHandle assignableGuard;
       
   125     private final Map<String, AnnotatedDynamicMethod> propertyGetters = new HashMap<>();
       
   126     private final Map<String, DynamicMethod> propertySetters = new HashMap<>();
       
   127     private final Map<String, DynamicMethod> methods = new HashMap<>();
       
   128 
       
   129     AbstractJavaLinker(final Class<?> clazz, final MethodHandle classGuard) {
       
   130         this(clazz, classGuard, classGuard);
       
   131     }
       
   132 
       
   133     AbstractJavaLinker(final Class<?> clazz, final MethodHandle classGuard, final MethodHandle assignableGuard) {
       
   134         this.clazz = clazz;
       
   135         this.classGuard = classGuard;
       
   136         this.assignableGuard = assignableGuard;
       
   137 
       
   138         final FacetIntrospector introspector = createFacetIntrospector();
       
   139         // Add methods and properties
       
   140         for(final Method method: introspector.getMethods()) {
       
   141             final String name = method.getName();
       
   142             // Add method
       
   143             addMember(name, method, methods);
       
   144             // Add the method as a property getter and/or setter
       
   145             if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) {
       
   146                 // Property getter
       
   147                 setPropertyGetter(method, 3);
       
   148             } else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 &&
       
   149                     method.getReturnType() == boolean.class) {
       
   150                 // Boolean property getter
       
   151                 setPropertyGetter(method, 2);
       
   152             } else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) {
       
   153                 // Property setter
       
   154                 addMember(decapitalize(name.substring(3)), method, propertySetters);
       
   155             }
       
   156         }
       
   157 
       
   158         // Add field getter/setters as property getters/setters.
       
   159         for(final Field field: introspector.getFields()) {
       
   160             final String name = field.getName();
       
   161             // Only add a property getter when one is not defined already as a getXxx()/isXxx() method.
       
   162             if(!propertyGetters.containsKey(name)) {
       
   163                 setPropertyGetter(name, introspector.unreflectGetter(field), ValidationType.EXACT_CLASS);
       
   164             }
       
   165             if(!(Modifier.isFinal(field.getModifiers()) || propertySetters.containsKey(name))) {
       
   166                 addMember(name, new SimpleDynamicMethod(introspector.unreflectSetter(field), clazz, name),
       
   167                         propertySetters);
       
   168             }
       
   169         }
       
   170 
       
   171         // Add inner classes, but only those for which we don't hide a property with it
       
   172         for(final Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) {
       
   173             final String name = innerClassSpec.getKey();
       
   174             if(!propertyGetters.containsKey(name)) {
       
   175                 setPropertyGetter(name, innerClassSpec.getValue(), ValidationType.EXACT_CLASS);
       
   176             }
       
   177         }
       
   178     }
       
   179 
       
   180     private static String decapitalize(final String str) {
       
   181         assert str != null;
       
   182         if(str.isEmpty()) {
       
   183             return str;
       
   184         }
       
   185 
       
   186         final char c0 = str.charAt(0);
       
   187         if(Character.isLowerCase(c0)) {
       
   188             return str;
       
   189         }
       
   190 
       
   191         // If it has two consecutive upper-case characters, i.e. "URL", don't decapitalize
       
   192         if(str.length() > 1 && Character.isUpperCase(str.charAt(1))) {
       
   193             return str;
       
   194         }
       
   195 
       
   196         final char c[] = str.toCharArray();
       
   197         c[0] = Character.toLowerCase(c0);
       
   198         return new String(c);
       
   199     }
       
   200 
       
   201     abstract FacetIntrospector createFacetIntrospector();
       
   202 
       
   203     Set<String> getReadablePropertyNames() {
       
   204         return getUnmodifiableKeys(propertyGetters);
       
   205     }
       
   206 
       
   207     Set<String> getWritablePropertyNames() {
       
   208         return getUnmodifiableKeys(propertySetters);
       
   209     }
       
   210 
       
   211     Set<String> getMethodNames() {
       
   212         return getUnmodifiableKeys(methods);
       
   213     }
       
   214 
       
   215     private static Set<String> getUnmodifiableKeys(final Map<String, ?> m) {
       
   216         return Collections.unmodifiableSet(m.keySet());
       
   217     }
       
   218 
       
   219     /**
       
   220      * Sets the specified dynamic method to be the property getter for the specified property. Note that you can only
       
   221      * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties
       
   222      * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)}
       
   223      * instead.
       
   224      * @param name name of the property
       
   225      * @param handle the method handle that implements the property getter
       
   226      * @param validationType the validation type for the property
       
   227      */
       
   228     private void setPropertyGetter(final String name, final SingleDynamicMethod handle, final ValidationType validationType) {
       
   229         propertyGetters.put(name, new AnnotatedDynamicMethod(handle, validationType));
       
   230     }
       
   231 
       
   232     /**
       
   233      * Sets the specified reflective method to be the property getter for the specified property.
       
   234      * @param getter the getter method
       
   235      * @param prefixLen the getter prefix in the method name; should be 3 for getter names starting with "get" and 2 for
       
   236      * names starting with "is".
       
   237      */
       
   238     private void setPropertyGetter(final Method getter, final int prefixLen) {
       
   239         setPropertyGetter(decapitalize(getter.getName().substring(prefixLen)), createDynamicMethod(
       
   240                 getMostGenericGetter(getter)), ValidationType.INSTANCE_OF);
       
   241     }
       
   242 
       
   243     /**
       
   244      * Sets the specified method handle to be the property getter for the specified property. Note that you can only
       
   245      * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties
       
   246      * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)}
       
   247      * instead.
       
   248      * @param name name of the property
       
   249      * @param handle the method handle that implements the property getter
       
   250      * @param validationType the validation type for the property
       
   251      */
       
   252     void setPropertyGetter(final String name, final MethodHandle handle, final ValidationType validationType) {
       
   253         setPropertyGetter(name, new SimpleDynamicMethod(handle, clazz, name), validationType);
       
   254     }
       
   255 
       
   256     private void addMember(final String name, final AccessibleObject ao, final Map<String, DynamicMethod> methodMap) {
       
   257         addMember(name, createDynamicMethod(ao), methodMap);
       
   258     }
       
   259 
       
   260     private void addMember(final String name, final SingleDynamicMethod method, final Map<String, DynamicMethod> methodMap) {
       
   261         final DynamicMethod existingMethod = methodMap.get(name);
       
   262         final DynamicMethod newMethod = mergeMethods(method, existingMethod, clazz, name);
       
   263         if(newMethod != existingMethod) {
       
   264             methodMap.put(name, newMethod);
       
   265         }
       
   266     }
       
   267 
       
   268     /**
       
   269      * Given one or more reflective methods or constructors, creates a dynamic method that represents them all. The
       
   270      * methods should represent all overloads of the same name (or all constructors of the class).
       
   271      * @param members the reflective members
       
   272      * @param clazz the class declaring the reflective members
       
   273      * @param name the common name of the reflective members.
       
   274      * @return a dynamic method representing all the specified reflective members.
       
   275      */
       
   276     static DynamicMethod createDynamicMethod(final Iterable<? extends AccessibleObject> members, final Class<?> clazz, final String name) {
       
   277         DynamicMethod dynMethod = null;
       
   278         for(final AccessibleObject method: members) {
       
   279             dynMethod = mergeMethods(createDynamicMethod(method), dynMethod, clazz, name);
       
   280         }
       
   281         return dynMethod;
       
   282     }
       
   283 
       
   284     /**
       
   285      * Given a reflective method or a constructor, creates a dynamic method that represents it. This method will
       
   286      * distinguish between caller sensitive and ordinary methods/constructors, and create appropriate caller sensitive
       
   287      * dynamic method when needed.
       
   288      * @param m the reflective member
       
   289      * @return the single dynamic method representing the reflective member
       
   290      */
       
   291     private static SingleDynamicMethod createDynamicMethod(final AccessibleObject m) {
       
   292         if (m.isAnnotationPresent(CallerSensitive.class)) {
       
   293             // Method has @CallerSensitive annotation
       
   294             return new CallerSensitiveDynamicMethod(m);
       
   295         }
       
   296         // Method has no @CallerSensitive annotation
       
   297         final MethodHandle mh;
       
   298         try {
       
   299             mh = unreflectSafely(m);
       
   300         } catch (final IllegalAccessError e) {
       
   301             // java.lang.invoke can in some case conservatively treat as caller sensitive methods that aren't
       
   302             // marked with the annotation. In this case, we'll fall back to treating it as caller sensitive.
       
   303             return new CallerSensitiveDynamicMethod(m);
       
   304         }
       
   305         // Proceed with non-caller sensitive
       
   306         final Member member = (Member)m;
       
   307         return new SimpleDynamicMethod(mh, member.getDeclaringClass(), member.getName(), m instanceof Constructor);
       
   308     }
       
   309 
       
   310     /**
       
   311      * Unreflects a method handle from a Method or a Constructor using safe (zero-privilege) unreflection. Should be
       
   312      * only used for methods and constructors that are not caller sensitive. If a caller sensitive method were
       
   313      * unreflected through this mechanism, it would not be a security issue, but would be bound to the zero-privilege
       
   314      * unreflector as its caller, and thus completely useless.
       
   315      * @param m the method or constructor
       
   316      * @return the method handle
       
   317      */
       
   318     private static MethodHandle unreflectSafely(final AccessibleObject m) {
       
   319         if(m instanceof Method) {
       
   320             final Method reflMethod = (Method)m;
       
   321             final MethodHandle handle = Lookup.PUBLIC.unreflect(reflMethod);
       
   322             if(Modifier.isStatic(reflMethod.getModifiers())) {
       
   323                 return StaticClassIntrospector.editStaticMethodHandle(handle);
       
   324             }
       
   325             return handle;
       
   326         }
       
   327         return StaticClassIntrospector.editConstructorMethodHandle(Lookup.PUBLIC.unreflectConstructor((Constructor<?>)m));
       
   328     }
       
   329 
       
   330     private static DynamicMethod mergeMethods(final SingleDynamicMethod method, final DynamicMethod existing, final Class<?> clazz, final String name) {
       
   331         if(existing == null) {
       
   332             return method;
       
   333         } else if(existing.contains(method)) {
       
   334             return existing;
       
   335         } else if(existing instanceof SingleDynamicMethod) {
       
   336             final OverloadedDynamicMethod odm = new OverloadedDynamicMethod(clazz, name);
       
   337             odm.addMethod(((SingleDynamicMethod)existing));
       
   338             odm.addMethod(method);
       
   339             return odm;
       
   340         } else if(existing instanceof OverloadedDynamicMethod) {
       
   341             ((OverloadedDynamicMethod)existing).addMethod(method);
       
   342             return existing;
       
   343         }
       
   344         throw new AssertionError();
       
   345     }
       
   346 
       
   347     @Override
       
   348     public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices)
       
   349             throws Exception {
       
   350         final CallSiteDescriptor callSiteDescriptor = request.getCallSiteDescriptor();
       
   351 
       
   352         // Handle NamedOperation(CALL_METHOD, name) separately
       
   353         final Operation operation = callSiteDescriptor.getOperation();
       
   354         if (operation instanceof NamedOperation) {
       
   355             final NamedOperation namedOperation = (NamedOperation)operation;
       
   356             if (namedOperation.getBaseOperation() == StandardOperation.CALL_METHOD) {
       
   357                 return createGuardedDynamicMethodInvocation(callSiteDescriptor,
       
   358                         linkerServices, namedOperation.getName().toString(), methods);
       
   359             }
       
   360         }
       
   361 
       
   362         List<Operation> operations = Arrays.asList(
       
   363                 CompositeOperation.getOperations(
       
   364                         NamedOperation.getBaseOperation(operation)));
       
   365         final Object name = NamedOperation.getName(operation);
       
   366 
       
   367         while(!operations.isEmpty()) {
       
   368             final GuardedInvocationComponent gic =
       
   369                     getGuardedInvocationComponent(callSiteDescriptor,
       
   370                             linkerServices, operations, name);
       
   371             if(gic != null) {
       
   372                 return gic.getGuardedInvocation();
       
   373             }
       
   374             operations = pop(operations);
       
   375         }
       
   376         return null;
       
   377     }
       
   378 
       
   379     protected GuardedInvocationComponent getGuardedInvocationComponent(
       
   380             final CallSiteDescriptor callSiteDescriptor,
       
   381             final LinkerServices linkerServices,
       
   382             final List<Operation> operations, final Object name)
       
   383     throws Exception {
       
   384         if(operations.isEmpty()) {
       
   385             return null;
       
   386         }
       
   387         final Operation op = operations.get(0);
       
   388         // Either GET_PROPERTY:name(this) or GET_PROPERTY(this, name)
       
   389         if(op == StandardOperation.GET_PROPERTY) {
       
   390             return getPropertyGetter(callSiteDescriptor, linkerServices, pop(operations), name);
       
   391         }
       
   392         // Either SET_PROPERTY:name(this, value) or SET_PROPERTY(this, name, value)
       
   393         if(op == StandardOperation.SET_PROPERTY) {
       
   394             return getPropertySetter(callSiteDescriptor, linkerServices, pop(operations), name);
       
   395         }
       
   396         // Either GET_METHOD:name(this), or GET_METHOD(this, name)
       
   397         if(op == StandardOperation.GET_METHOD) {
       
   398             return getMethodGetter(callSiteDescriptor, linkerServices, pop(operations), name);
       
   399         }
       
   400         return null;
       
   401     }
       
   402 
       
   403     static final <T> List<T> pop(final List<T> l) {
       
   404         return l.subList(1, l.size());
       
   405     }
       
   406 
       
   407     MethodHandle getClassGuard(final CallSiteDescriptor desc) {
       
   408         return getClassGuard(desc.getMethodType());
       
   409     }
       
   410 
       
   411     MethodHandle getClassGuard(final MethodType type) {
       
   412         return Guards.asType(classGuard, type);
       
   413     }
       
   414 
       
   415     GuardedInvocationComponent getClassGuardedInvocationComponent(final MethodHandle invocation, final MethodType type) {
       
   416         return new GuardedInvocationComponent(invocation, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
       
   417     }
       
   418 
       
   419     abstract SingleDynamicMethod getConstructorMethod(final String signature);
       
   420 
       
   421     private MethodHandle getAssignableGuard(final MethodType type) {
       
   422         return Guards.asType(assignableGuard, type);
       
   423     }
       
   424 
       
   425     private GuardedInvocation createGuardedDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor,
       
   426             final LinkerServices linkerServices, final String methodName, final Map<String, DynamicMethod> methodMap){
       
   427         final MethodHandle inv = getDynamicMethodInvocation(callSiteDescriptor, linkerServices, methodName, methodMap);
       
   428         return inv == null ? null : new GuardedInvocation(inv, getClassGuard(callSiteDescriptor.getMethodType()));
       
   429     }
       
   430 
       
   431     private MethodHandle getDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor,
       
   432             final LinkerServices linkerServices, final String methodName, final Map<String, DynamicMethod> methodMap) {
       
   433         final DynamicMethod dynaMethod = getDynamicMethod(methodName, methodMap);
       
   434         return dynaMethod != null ? dynaMethod.getInvocation(callSiteDescriptor, linkerServices) : null;
       
   435     }
       
   436 
       
   437     private DynamicMethod getDynamicMethod(final String methodName, final Map<String, DynamicMethod> methodMap) {
       
   438         final DynamicMethod dynaMethod = methodMap.get(methodName);
       
   439         return dynaMethod != null ? dynaMethod : getExplicitSignatureDynamicMethod(methodName, methodMap);
       
   440     }
       
   441 
       
   442     private SingleDynamicMethod getExplicitSignatureDynamicMethod(final String fullName,
       
   443             final Map<String, DynamicMethod> methodsMap) {
       
   444         // What's below is meant to support the "name(type, type, ...)" syntax that programmers can use in a method name
       
   445         // to manually pin down an exact overloaded variant. This is not usually required, as the overloaded method
       
   446         // resolution works correctly in almost every situation. However, in presence of many language-specific
       
   447         // conversions with a radically dynamic language, most overloaded methods will end up being constantly selected
       
   448         // at invocation time, so a programmer knowledgeable of the situation might choose to pin down an exact overload
       
   449         // for performance reasons.
       
   450 
       
   451         // Is the method name lexically of the form "name(types)"?
       
   452         final int lastChar = fullName.length() - 1;
       
   453         if(fullName.charAt(lastChar) != ')') {
       
   454             return null;
       
   455         }
       
   456         final int openBrace = fullName.indexOf('(');
       
   457         if(openBrace == -1) {
       
   458             return null;
       
   459         }
       
   460 
       
   461         final String name = fullName.substring(0, openBrace);
       
   462         final String signature = fullName.substring(openBrace + 1, lastChar);
       
   463 
       
   464         // Find an existing method for the "name" part
       
   465         final DynamicMethod simpleNamedMethod = methodsMap.get(name);
       
   466         if(simpleNamedMethod == null) {
       
   467             // explicit signature constructor access
       
   468             // Java.type("java.awt.Color")["(int,int,int)"]
       
   469             // will get Color(int,int,int) constructor of Color class.
       
   470             if (name.isEmpty()) {
       
   471                 return getConstructorMethod(signature);
       
   472             }
       
   473 
       
   474             return null;
       
   475         }
       
   476 
       
   477         // Try to get a narrowed dynamic method for the explicit parameter types.
       
   478         return simpleNamedMethod.getMethodForExactParamTypes(signature);
       
   479     }
       
   480 
       
   481     private static final MethodHandle IS_METHOD_HANDLE_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType(
       
   482             boolean.class, MethodHandle.class));
       
   483     private static final MethodHandle CONSTANT_NULL_DROP_METHOD_HANDLE = MethodHandles.dropArguments(
       
   484             MethodHandles.constant(Object.class, null), 0, MethodHandle.class);
       
   485 
       
   486     private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor,
       
   487             final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception {
       
   488         if (name == null) {
       
   489             return getUnnamedPropertySetter(callSiteDescriptor, linkerServices, operations);
       
   490         }
       
   491         return getNamedPropertySetter(callSiteDescriptor, linkerServices, operations, name);
       
   492     }
       
   493 
       
   494     private GuardedInvocationComponent getUnnamedPropertySetter(final CallSiteDescriptor callSiteDescriptor,
       
   495             final LinkerServices linkerServices, final List<Operation> operations) throws Exception {
       
   496         // Must have three arguments: target object, property name, and property value.
       
   497         assertParameterCount(callSiteDescriptor, 3);
       
   498 
       
   499         // We want setters that conform to "Object(O, V)". Note, we aren't doing "R(O, V)" as it might not be
       
   500         // valid for us to convert return values proactively. Also, since we don't know what setters will be
       
   501         // invoked, we'll conservatively presume Object return type. The one exception is void return.
       
   502         final MethodType origType = callSiteDescriptor.getMethodType();
       
   503         final MethodType type = origType.returnType() == void.class ? origType : origType.changeReturnType(Object.class);
       
   504 
       
   505         // What's below is basically:
       
   506         //   foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation),
       
   507         //     get_setter_handle(type, linkerServices))
       
   508         // only with a bunch of method signature adjustments. Basically, retrieve method setter
       
   509         // MethodHandle; if it is non-null, invoke it, otherwise either return null, or delegate to next
       
   510         // component's invocation.
       
   511 
       
   512         // Call site type is "ret_type(object_type,property_name_type,property_value_type)", which we'll
       
   513         // abbreviate to R(O, N, V) going forward, although we don't really use R here (see above about using
       
   514         // Object return type).
       
   515         final MethodType setterType = type.dropParameterTypes(1, 2);
       
   516         // Bind property setter handle to the expected setter type and linker services. Type is
       
   517         // MethodHandle(Object, String, Object)
       
   518         final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0,
       
   519                 callSiteDescriptor.changeMethodType(setterType), linkerServices);
       
   520 
       
   521         // Cast getter to MethodHandle(O, N, V)
       
   522         final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType(
       
   523                 MethodHandle.class));
       
   524 
       
   525         // Handle to invoke the setter R(MethodHandle, O, V)
       
   526         final MethodHandle invokeHandle = MethodHandles.exactInvoker(setterType);
       
   527         // Handle to invoke the setter, dropping unnecessary fold arguments R(MethodHandle, O, N, V)
       
   528         final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandle, 2, type.parameterType(
       
   529                 1));
       
   530         final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
       
   531                 linkerServices, operations, null);
       
   532 
       
   533         final MethodHandle fallbackFolded;
       
   534         if(nextComponent == null) {
       
   535             // Object(MethodHandle)->Object(MethodHandle, O, N, V); returns constant null
       
   536             fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1,
       
   537                     type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class));
       
   538         } else {
       
   539             // Object(O, N, V)->Object(MethodHandle, O, N, V); adapts the next component's invocation to drop the
       
   540             // extra argument resulting from fold
       
   541             fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(),
       
   542                     0, MethodHandle.class);
       
   543         }
       
   544 
       
   545         // fold(R(MethodHandle, O, N, V), MethodHandle(O, N, V))
       
   546         final MethodHandle compositeSetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
       
   547                     IS_METHOD_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
       
   548         if(nextComponent == null) {
       
   549             return getClassGuardedInvocationComponent(compositeSetter, type);
       
   550         }
       
   551         return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
       
   552     }
       
   553 
       
   554     private GuardedInvocationComponent getNamedPropertySetter(final CallSiteDescriptor callSiteDescriptor,
       
   555             final LinkerServices linkerServices, final List<Operation> operations, final Object name) throws Exception {
       
   556         // Must have two arguments: target object and property value
       
   557         assertParameterCount(callSiteDescriptor, 2);
       
   558         final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices,
       
   559                 name.toString(), propertySetters);
       
   560         // If we have a property setter with this name, this composite operation will always stop here
       
   561         if(gi != null) {
       
   562             return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS);
       
   563         }
       
   564         // If we don't have a property setter with this name, always fall back to the next operation in the
       
   565         // composite (if any)
       
   566         return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations, name);
       
   567     }
       
   568 
       
   569     private static final Lookup privateLookup = new Lookup(MethodHandles.lookup());
       
   570 
       
   571     private static final MethodHandle IS_ANNOTATED_METHOD_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType(
       
   572             boolean.class, AnnotatedDynamicMethod.class));
       
   573     private static final MethodHandle CONSTANT_NULL_DROP_ANNOTATED_METHOD = MethodHandles.dropArguments(
       
   574             MethodHandles.constant(Object.class, null), 0, AnnotatedDynamicMethod.class);
       
   575     private static final MethodHandle GET_ANNOTATED_METHOD = privateLookup.findVirtual(AnnotatedDynamicMethod.class,
       
   576             "getTarget", MethodType.methodType(MethodHandle.class, CallSiteDescriptor.class, LinkerServices.class));
       
   577     private static final MethodHandle GETTER_INVOKER = MethodHandles.invoker(MethodType.methodType(Object.class, Object.class));
       
   578 
       
   579     private GuardedInvocationComponent getPropertyGetter(final CallSiteDescriptor callSiteDescriptor,
       
   580             final LinkerServices linkerServices, final List<Operation> ops, final Object name) throws Exception {
       
   581         if (name == null) {
       
   582             return getUnnamedPropertyGetter(callSiteDescriptor, linkerServices, ops);
       
   583         }
       
   584 
       
   585         return getNamedPropertyGetter(callSiteDescriptor, linkerServices, ops, name);
       
   586     }
       
   587 
       
   588     private GuardedInvocationComponent getUnnamedPropertyGetter(final CallSiteDescriptor callSiteDescriptor,
       
   589             final LinkerServices linkerServices, final List<Operation> ops) throws Exception {
       
   590         // Since we can't know what kind of a getter we'll get back on different invocations, we'll just
       
   591         // conservatively presume Object. Note we can't just coerce to a narrower call site type as the linking
       
   592         // runtime might not allow coercing at that call site.
       
   593         final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class);
       
   594         // Must have exactly two arguments: receiver and name
       
   595         assertParameterCount(callSiteDescriptor, 2);
       
   596 
       
   597         // What's below is basically:
       
   598         //   foldArguments(guardWithTest(isNotNull, invoke(get_handle), null|nextComponent.invocation), get_getter_handle)
       
   599         // only with a bunch of method signature adjustments. Basically, retrieve method getter
       
   600         // AnnotatedDynamicMethod; if it is non-null, invoke its "handle" field, otherwise either return null,
       
   601         // or delegate to next component's invocation.
       
   602 
       
   603         final MethodHandle typedGetter = linkerServices.asType(getPropertyGetterHandle, type.changeReturnType(
       
   604                 AnnotatedDynamicMethod.class));
       
   605         final MethodHandle callSiteBoundMethodGetter = MethodHandles.insertArguments(
       
   606                 GET_ANNOTATED_METHOD, 1, callSiteDescriptor, linkerServices);
       
   607         final MethodHandle callSiteBoundInvoker = MethodHandles.filterArguments(GETTER_INVOKER, 0,
       
   608                 callSiteBoundMethodGetter);
       
   609         // Object(AnnotatedDynamicMethod, Object)->Object(AnnotatedDynamicMethod, T0)
       
   610         final MethodHandle invokeHandleTyped = linkerServices.asType(callSiteBoundInvoker,
       
   611                 MethodType.methodType(type.returnType(), AnnotatedDynamicMethod.class, type.parameterType(0)));
       
   612         // Since it's in the target of a fold, drop the unnecessary second argument
       
   613         // Object(AnnotatedDynamicMethod, T0)->Object(AnnotatedDynamicMethod, T0, T1)
       
   614         final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2,
       
   615                 type.parameterType(1));
       
   616         final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
       
   617                 linkerServices, ops, null);
       
   618 
       
   619         final MethodHandle fallbackFolded;
       
   620         if(nextComponent == null) {
       
   621             // Object(AnnotatedDynamicMethod)->Object(AnnotatedDynamicMethod, T0, T1); returns constant null
       
   622             fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_ANNOTATED_METHOD, 1,
       
   623                     type.parameterList()).asType(type.insertParameterTypes(0, AnnotatedDynamicMethod.class));
       
   624         } else {
       
   625             // Object(T0, T1)->Object(AnnotatedDynamicMethod, T0, T1); adapts the next component's invocation to
       
   626             // drop the extra argument resulting from fold and to change its return type to Object.
       
   627             final MethodHandle nextInvocation = nextComponent.getGuardedInvocation().getInvocation();
       
   628             final MethodType nextType = nextInvocation.type();
       
   629             fallbackFolded = MethodHandles.dropArguments(nextInvocation.asType(
       
   630                     nextType.changeReturnType(Object.class)), 0, AnnotatedDynamicMethod.class);
       
   631         }
       
   632 
       
   633         // fold(Object(AnnotatedDynamicMethod, T0, T1), AnnotatedDynamicMethod(T0, T1))
       
   634         final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
       
   635                     IS_ANNOTATED_METHOD_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
       
   636         if(nextComponent == null) {
       
   637             return getClassGuardedInvocationComponent(compositeGetter, type);
       
   638         }
       
   639         return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
       
   640     }
       
   641 
       
   642     private GuardedInvocationComponent getNamedPropertyGetter(final CallSiteDescriptor callSiteDescriptor,
       
   643             final LinkerServices linkerServices, final List<Operation> ops, final Object name) throws Exception {
       
   644         // Must have exactly one argument: receiver
       
   645         assertParameterCount(callSiteDescriptor, 1);
       
   646         // Fixed name
       
   647         final AnnotatedDynamicMethod annGetter = propertyGetters.get(name.toString());
       
   648         if(annGetter == null) {
       
   649             // We have no such property, always delegate to the next component operation
       
   650             return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops, name);
       
   651         }
       
   652         final MethodHandle getter = annGetter.getInvocation(callSiteDescriptor, linkerServices);
       
   653         // NOTE: since property getters (not field getters!) are no-arg, we don't have to worry about them being
       
   654         // overloaded in a subclass. Therefore, we can discover the most abstract superclass that has the
       
   655         // method, and use that as the guard with Guards.isInstance() for a more stably linked call site. If
       
   656         // we're linking against a field getter, don't make the assumption.
       
   657         // NOTE: No delegation to the next component operation if we have a property with this name, even if its
       
   658         // value is null.
       
   659         final ValidationType validationType = annGetter.validationType;
       
   660         // TODO: we aren't using the type that declares the most generic getter here!
       
   661         return new GuardedInvocationComponent(getter, getGuard(validationType,
       
   662                 callSiteDescriptor.getMethodType()), clazz, validationType);
       
   663     }
       
   664 
       
   665     private MethodHandle getGuard(final ValidationType validationType, final MethodType methodType) {
       
   666         switch(validationType) {
       
   667             case EXACT_CLASS: {
       
   668                 return getClassGuard(methodType);
       
   669             }
       
   670             case INSTANCE_OF: {
       
   671                 return getAssignableGuard(methodType);
       
   672             }
       
   673             case IS_ARRAY: {
       
   674                 return Guards.isArray(0, methodType);
       
   675             }
       
   676             case NONE: {
       
   677                 return null;
       
   678             }
       
   679             default: {
       
   680                 throw new AssertionError();
       
   681             }
       
   682         }
       
   683     }
       
   684 
       
   685     private static final MethodHandle IS_DYNAMIC_METHOD = Guards.isInstance(DynamicMethod.class,
       
   686             MethodType.methodType(boolean.class, Object.class));
       
   687     private static final MethodHandle OBJECT_IDENTITY = MethodHandles.identity(Object.class);
       
   688 
       
   689     private GuardedInvocationComponent getMethodGetter(final CallSiteDescriptor callSiteDescriptor,
       
   690             final LinkerServices linkerServices, final List<Operation> ops, final Object name) throws Exception {
       
   691         // The created method handle will always return a DynamicMethod (or null), but since we don't want that type to
       
   692         // be visible outside of this linker, declare it to return Object.
       
   693         final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class);
       
   694         if (name == null) {
       
   695             return getUnnamedMethodGetter(callSiteDescriptor, linkerServices, ops, type);
       
   696         }
       
   697 
       
   698         return getNamedMethodGetter(callSiteDescriptor, linkerServices, ops, name, type);
       
   699     }
       
   700 
       
   701     private GuardedInvocationComponent getUnnamedMethodGetter(final CallSiteDescriptor callSiteDescriptor,
       
   702             final LinkerServices linkerServices, final List<Operation> ops, final MethodType type) throws Exception {
       
   703         // Must have exactly two arguments: receiver and name
       
   704         assertParameterCount(callSiteDescriptor, 2);
       
   705         final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
       
   706                 linkerServices, ops, null);
       
   707         if(nextComponent == null || !InternalTypeUtilities.areAssignable(DynamicMethod.class,
       
   708                 nextComponent.getGuardedInvocation().getInvocation().type().returnType())) {
       
   709             // No next component operation, or it can never produce a dynamic method; just return a component
       
   710             // for this operation.
       
   711             return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type);
       
   712         }
       
   713 
       
   714         // What's below is basically:
       
   715         // foldArguments(guardWithTest(isNotNull, identity, nextComponent.invocation), getter) only with a
       
   716         // bunch of method signature adjustments. Basically, execute method getter; if it returns a non-null
       
   717         // DynamicMethod, use identity to return it, otherwise delegate to nextComponent's invocation.
       
   718 
       
   719         final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type);
       
   720         // Since it is part of the foldArgument() target, it will have extra args that we need to drop.
       
   721         final MethodHandle returnMethodHandle = linkerServices.asType(MethodHandles.dropArguments(
       
   722                 OBJECT_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0, Object.class));
       
   723         final MethodHandle nextComponentInvocation = nextComponent.getGuardedInvocation().getInvocation();
       
   724         // The assumption is that getGuardedInvocationComponent() already asType()'d it correctly modulo the
       
   725         // return type.
       
   726         assert nextComponentInvocation.type().changeReturnType(type.returnType()).equals(type);
       
   727         // Since it is part of the foldArgument() target, we have to drop an extra arg it receives.
       
   728         final MethodHandle nextCombinedInvocation = MethodHandles.dropArguments(nextComponentInvocation, 0,
       
   729                 Object.class);
       
   730         // Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get)
       
   731         final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
       
   732                 IS_DYNAMIC_METHOD, returnMethodHandle, nextCombinedInvocation), typedGetter);
       
   733 
       
   734         return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
       
   735     }
       
   736 
       
   737     private GuardedInvocationComponent getNamedMethodGetter(final CallSiteDescriptor callSiteDescriptor,
       
   738             final LinkerServices linkerServices, final List<Operation> ops, final Object name, final MethodType type)
       
   739             throws Exception {
       
   740         // Must have exactly one argument: receiver
       
   741         assertParameterCount(callSiteDescriptor, 1);
       
   742         final DynamicMethod method = getDynamicMethod(name.toString());
       
   743         if(method == null) {
       
   744             // We have no such method, always delegate to the next component
       
   745             return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops, name);
       
   746         }
       
   747         // No delegation to the next component of the composite operation; if we have a method with that name,
       
   748         // we'll always return it at this point.
       
   749         return getClassGuardedInvocationComponent(linkerServices.asType(MethodHandles.dropArguments(
       
   750                 MethodHandles.constant(Object.class, method), 0, type.parameterType(0)), type), type);
       
   751     }
       
   752 
       
   753     static class MethodPair {
       
   754         final MethodHandle method1;
       
   755         final MethodHandle method2;
       
   756 
       
   757         MethodPair(final MethodHandle method1, final MethodHandle method2) {
       
   758             this.method1 = method1;
       
   759             this.method2 = method2;
       
   760         }
       
   761 
       
   762         MethodHandle guardWithTest(final MethodHandle test) {
       
   763             return MethodHandles.guardWithTest(test, method1, method2);
       
   764         }
       
   765     }
       
   766 
       
   767     static MethodPair matchReturnTypes(final MethodHandle m1, final MethodHandle m2) {
       
   768         final MethodType type1 = m1.type();
       
   769         final MethodType type2 = m2.type();
       
   770         final Class<?> commonRetType = InternalTypeUtilities.getCommonLosslessConversionType(type1.returnType(),
       
   771                 type2.returnType());
       
   772         return new MethodPair(
       
   773                 m1.asType(type1.changeReturnType(commonRetType)),
       
   774                 m2.asType(type2.changeReturnType(commonRetType)));
       
   775     }
       
   776 
       
   777     private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) {
       
   778         if(descriptor.getMethodType().parameterCount() != paramCount) {
       
   779             throw new BootstrapMethodError(descriptor.getOperation() + " must have exactly " + paramCount + " parameters.");
       
   780         }
       
   781     }
       
   782 
       
   783     private static MethodHandle GET_PROPERTY_GETTER_HANDLE = MethodHandles.dropArguments(privateLookup.findOwnSpecial(
       
   784             "getPropertyGetterHandle", Object.class, Object.class), 1, Object.class);
       
   785     private final MethodHandle getPropertyGetterHandle = GET_PROPERTY_GETTER_HANDLE.bindTo(this);
       
   786 
       
   787     /**
       
   788      * @param id the property ID
       
   789      * @return the method handle for retrieving the property, or null if the property does not exist
       
   790      */
       
   791     @SuppressWarnings("unused")
       
   792     private Object getPropertyGetterHandle(final Object id) {
       
   793         return propertyGetters.get(id);
       
   794     }
       
   795 
       
   796     // Type is MethodHandle(BeanLinker, MethodType, LinkerServices, Object, String, Object), of which the two "Object"
       
   797     // args are dropped; this makes handles with first three args conform to "Object, String, Object" though, which is
       
   798     // a typical property setter with variable name signature (target, name, value).
       
   799     private static final MethodHandle GET_PROPERTY_SETTER_HANDLE = MethodHandles.dropArguments(MethodHandles.dropArguments(
       
   800             privateLookup.findOwnSpecial("getPropertySetterHandle", MethodHandle.class, CallSiteDescriptor.class,
       
   801                     LinkerServices.class, Object.class), 3, Object.class), 5, Object.class);
       
   802     // Type is MethodHandle(MethodType, LinkerServices, Object, String, Object)
       
   803     private final MethodHandle getPropertySetterHandle = GET_PROPERTY_SETTER_HANDLE.bindTo(this);
       
   804 
       
   805     @SuppressWarnings("unused")
       
   806     private MethodHandle getPropertySetterHandle(final CallSiteDescriptor setterDescriptor, final LinkerServices linkerServices,
       
   807             final Object id) {
       
   808         return getDynamicMethodInvocation(setterDescriptor, linkerServices, String.valueOf(id), propertySetters);
       
   809     }
       
   810 
       
   811     private static MethodHandle GET_DYNAMIC_METHOD = MethodHandles.dropArguments(privateLookup.findOwnSpecial(
       
   812             "getDynamicMethod", Object.class, Object.class), 1, Object.class);
       
   813     private final MethodHandle getDynamicMethod = GET_DYNAMIC_METHOD.bindTo(this);
       
   814 
       
   815     @SuppressWarnings("unused")
       
   816     // This method is marked to return Object instead of DynamicMethod as it's used as a linking component and we don't
       
   817     // want to make the DynamicMethod type observable externally (e.g. as the return type of a MethodHandle returned for
       
   818     // GET_METHOD linking).
       
   819     private Object getDynamicMethod(final Object name) {
       
   820         return getDynamicMethod(String.valueOf(name), methods);
       
   821     }
       
   822 
       
   823     /**
       
   824      * Returns a dynamic method of the specified name.
       
   825      *
       
   826      * @param name name of the method
       
   827      * @return the dynamic method (either {@link SimpleDynamicMethod} or {@link OverloadedDynamicMethod}, or null if the
       
   828      * method with the specified name does not exist.
       
   829      */
       
   830     DynamicMethod getDynamicMethod(final String name) {
       
   831         return getDynamicMethod(name, methods);
       
   832     }
       
   833 
       
   834     /**
       
   835      * Find the most generic superclass that declares this getter. Since getters have zero args (aside from the
       
   836      * receiver), they can't be overloaded, so we're free to link with an instanceof guard for the most generic one,
       
   837      * creating more stable call sites.
       
   838      * @param getter the getter
       
   839      * @return getter with same name, declared on the most generic superclass/interface of the declaring class
       
   840      */
       
   841     private static Method getMostGenericGetter(final Method getter) {
       
   842         return getMostGenericGetter(getter.getName(), getter.getReturnType(), getter.getDeclaringClass());
       
   843     }
       
   844 
       
   845     private static Method getMostGenericGetter(final String name, final Class<?> returnType, final Class<?> declaringClass) {
       
   846         if(declaringClass == null) {
       
   847             return null;
       
   848         }
       
   849         // Prefer interfaces
       
   850         for(final Class<?> itf: declaringClass.getInterfaces()) {
       
   851             final Method itfGetter = getMostGenericGetter(name, returnType, itf);
       
   852             if(itfGetter != null) {
       
   853                 return itfGetter;
       
   854             }
       
   855         }
       
   856         final Method superGetter = getMostGenericGetter(name, returnType, declaringClass.getSuperclass());
       
   857         if(superGetter != null) {
       
   858             return superGetter;
       
   859         }
       
   860         if(!CheckRestrictedPackage.isRestrictedClass(declaringClass)) {
       
   861             try {
       
   862                 return declaringClass.getMethod(name);
       
   863             } catch(final NoSuchMethodException e) {
       
   864                 // Intentionally ignored, meant to fall through
       
   865             }
       
   866         }
       
   867         return null;
       
   868     }
       
   869 
       
   870     private static final class AnnotatedDynamicMethod {
       
   871         private final SingleDynamicMethod method;
       
   872         /*private*/ final ValidationType validationType;
       
   873 
       
   874         AnnotatedDynamicMethod(final SingleDynamicMethod method, final ValidationType validationType) {
       
   875             this.method = method;
       
   876             this.validationType = validationType;
       
   877         }
       
   878 
       
   879         MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) {
       
   880             return method.getInvocation(callSiteDescriptor, linkerServices);
       
   881         }
       
   882 
       
   883         @SuppressWarnings("unused")
       
   884         MethodHandle getTarget(final CallSiteDescriptor desc, final LinkerServices linkerServices) {
       
   885             final MethodHandle inv = linkerServices.filterInternalObjects(method.getTarget(desc));
       
   886             assert inv != null;
       
   887             return inv;
       
   888         }
       
   889     }
       
   890 }