rt/emul/compact/src/main/java/java/lang/invoke/InfoFromMemberName.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 09 Aug 2014 11:11:13 +0200
branchjdk8-b132
changeset 1646 c880a8a8803b
permissions -rw-r--r--
Batch of classes necessary to implement invoke dynamic interfaces. Taken from JDK8 build 132
     1 /*
     2  * Copyright (c) 2012, 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 package java.lang.invoke;
    27 
    28 import java.security.*;
    29 import java.lang.reflect.*;
    30 import java.lang.invoke.MethodHandleNatives.Constants;
    31 import java.lang.invoke.MethodHandles.Lookup;
    32 import static java.lang.invoke.MethodHandleStatics.*;
    33 
    34 /*
    35  * Auxiliary to MethodHandleInfo, wants to nest in MethodHandleInfo but must be non-public.
    36  */
    37 /*non-public*/
    38 final
    39 class InfoFromMemberName implements MethodHandleInfo {
    40     private final MemberName member;
    41     private final int referenceKind;
    42 
    43     InfoFromMemberName(Lookup lookup, MemberName member, byte referenceKind) {
    44         assert(member.isResolved() || member.isMethodHandleInvoke());
    45         assert(member.referenceKindIsConsistentWith(referenceKind));
    46         this.member = member;
    47         this.referenceKind = referenceKind;
    48     }
    49 
    50     @Override
    51     public Class<?> getDeclaringClass() {
    52         return member.getDeclaringClass();
    53     }
    54 
    55     @Override
    56     public String getName() {
    57         return member.getName();
    58     }
    59 
    60     @Override
    61     public MethodType getMethodType() {
    62         return member.getMethodOrFieldType();
    63     }
    64 
    65     @Override
    66     public int getModifiers() {
    67         return member.getModifiers();
    68     }
    69 
    70     @Override
    71     public int getReferenceKind() {
    72         return referenceKind;
    73     }
    74 
    75     @Override
    76     public String toString() {
    77         return MethodHandleInfo.toString(getReferenceKind(), getDeclaringClass(), getName(), getMethodType());
    78     }
    79 
    80     @Override
    81     public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup) {
    82         if (member.isMethodHandleInvoke() && !member.isVarargs()) {
    83             // This member is an instance of a signature-polymorphic method, which cannot be reflected
    84             // A method handle invoker can come in either of two forms:
    85             // A generic placeholder (present in the source code, and varargs)
    86             // and a signature-polymorphic instance (synthetic and not varargs).
    87             // For more information see comments on {@link MethodHandleNatives#linkMethod}.
    88             throw new IllegalArgumentException("cannot reflect signature polymorphic method");
    89         }
    90         Member mem = AccessController.doPrivileged(new PrivilegedAction<Member>() {
    91                 public Member run() {
    92                     try {
    93                         return reflectUnchecked();
    94                     } catch (ReflectiveOperationException ex) {
    95                         throw new IllegalArgumentException(ex);
    96                     }
    97                 }
    98             });
    99         try {
   100             Class<?> defc = getDeclaringClass();
   101             byte refKind = (byte) getReferenceKind();
   102             lookup.checkAccess(refKind, defc, convertToMemberName(refKind, mem));
   103         } catch (IllegalAccessException ex) {
   104             throw new IllegalArgumentException(ex);
   105         }
   106         return expected.cast(mem);
   107     }
   108 
   109     private Member reflectUnchecked() throws ReflectiveOperationException {
   110         byte refKind = (byte) getReferenceKind();
   111         Class<?> defc = getDeclaringClass();
   112         boolean isPublic = Modifier.isPublic(getModifiers());
   113         if (MethodHandleNatives.refKindIsMethod(refKind)) {
   114             if (isPublic)
   115                 return defc.getMethod(getName(), getMethodType().parameterArray());
   116             else
   117                 return defc.getDeclaredMethod(getName(), getMethodType().parameterArray());
   118         } else if (MethodHandleNatives.refKindIsConstructor(refKind)) {
   119             if (isPublic)
   120                 return defc.getConstructor(getMethodType().parameterArray());
   121             else
   122                 return defc.getDeclaredConstructor(getMethodType().parameterArray());
   123         } else if (MethodHandleNatives.refKindIsField(refKind)) {
   124             if (isPublic)
   125                 return defc.getField(getName());
   126             else
   127                 return defc.getDeclaredField(getName());
   128         } else {
   129             throw new IllegalArgumentException("referenceKind="+refKind);
   130         }
   131     }
   132 
   133     private static MemberName convertToMemberName(byte refKind, Member mem) throws IllegalAccessException {
   134         if (mem instanceof Method) {
   135             boolean wantSpecial = (refKind == REF_invokeSpecial);
   136             return new MemberName((Method) mem, wantSpecial);
   137         } else if (mem instanceof Constructor) {
   138             return new MemberName((Constructor) mem);
   139         } else if (mem instanceof Field) {
   140             boolean isSetter = (refKind == REF_putField || refKind == REF_putStatic);
   141             return new MemberName((Field) mem, isSetter);
   142         }
   143         throw new InternalError(mem.getClass().getName());
   144     }
   145 }