| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package java.lang.invoke;  | 
 | 
 | 
 | 
import java.security.*;  | 
 | 
import java.lang.reflect.*;  | 
 | 
import java.lang.invoke.MethodHandleNatives.Constants;  | 
 | 
import java.lang.invoke.MethodHandles.Lookup;  | 
 | 
import static java.lang.invoke.MethodHandleStatics.*;  | 
 | 
 | 
 | 
/*  | 
 | 
 * Auxiliary to MethodHandleInfo, wants to nest in MethodHandleInfo but must be non-public.  | 
 | 
 */  | 
 | 
 | 
 | 
final  | 
 | 
class InfoFromMemberName implements MethodHandleInfo { | 
 | 
    private final MemberName member;  | 
 | 
    private final int referenceKind;  | 
 | 
 | 
 | 
    InfoFromMemberName(Lookup lookup, MemberName member, byte referenceKind) { | 
 | 
        assert(member.isResolved() || member.isMethodHandleInvoke() || member.isVarHandleMethodInvoke());  | 
 | 
        assert(member.referenceKindIsConsistentWith(referenceKind));  | 
 | 
        this.member = member;  | 
 | 
        this.referenceKind = referenceKind;  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public Class<?> getDeclaringClass() { | 
 | 
        return member.getDeclaringClass();  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public String getName() { | 
 | 
        return member.getName();  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public MethodType getMethodType() { | 
 | 
        return member.getMethodOrFieldType();  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public int getModifiers() { | 
 | 
        return member.getModifiers();  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public int getReferenceKind() { | 
 | 
        return referenceKind;  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public String toString() { | 
 | 
        return MethodHandleInfo.toString(getReferenceKind(), getDeclaringClass(), getName(), getMethodType());  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup) { | 
 | 
        if ((member.isMethodHandleInvoke() || member.isVarHandleMethodInvoke())  | 
 | 
            && !member.isVarargs()) { | 
 | 
            // This member is an instance of a signature-polymorphic method, which cannot be reflected  | 
 | 
            // A method handle invoker can come in either of two forms:  | 
 | 
            // A generic placeholder (present in the source code, and varargs)  | 
 | 
            // and a signature-polymorphic instance (synthetic and not varargs).  | 
 | 
              | 
 | 
            throw new IllegalArgumentException("cannot reflect signature polymorphic method"); | 
 | 
        }  | 
 | 
        Member mem = AccessController.doPrivileged(new PrivilegedAction<>() { | 
 | 
                public Member run() { | 
 | 
                    try { | 
 | 
                        return reflectUnchecked();  | 
 | 
                    } catch (ReflectiveOperationException ex) { | 
 | 
                        throw new IllegalArgumentException(ex);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            });  | 
 | 
        try { | 
 | 
            Class<?> defc = getDeclaringClass();  | 
 | 
            byte refKind = (byte) getReferenceKind();  | 
 | 
            lookup.checkAccess(refKind, defc, convertToMemberName(refKind, mem));  | 
 | 
        } catch (IllegalAccessException ex) { | 
 | 
            throw new IllegalArgumentException(ex);  | 
 | 
        }  | 
 | 
        return expected.cast(mem);  | 
 | 
    }  | 
 | 
 | 
 | 
    private Member reflectUnchecked() throws ReflectiveOperationException { | 
 | 
        byte refKind = (byte) getReferenceKind();  | 
 | 
        Class<?> defc = getDeclaringClass();  | 
 | 
        boolean isPublic = Modifier.isPublic(getModifiers());  | 
 | 
        if (MethodHandleNatives.refKindIsMethod(refKind)) { | 
 | 
            if (isPublic)  | 
 | 
                return defc.getMethod(getName(), getMethodType().parameterArray());  | 
 | 
            else  | 
 | 
                return defc.getDeclaredMethod(getName(), getMethodType().parameterArray());  | 
 | 
        } else if (MethodHandleNatives.refKindIsConstructor(refKind)) { | 
 | 
            if (isPublic)  | 
 | 
                return defc.getConstructor(getMethodType().parameterArray());  | 
 | 
            else  | 
 | 
                return defc.getDeclaredConstructor(getMethodType().parameterArray());  | 
 | 
        } else if (MethodHandleNatives.refKindIsField(refKind)) { | 
 | 
            if (isPublic)  | 
 | 
                return defc.getField(getName());  | 
 | 
            else  | 
 | 
                return defc.getDeclaredField(getName());  | 
 | 
        } else { | 
 | 
            throw new IllegalArgumentException("referenceKind="+refKind); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private static MemberName convertToMemberName(byte refKind, Member mem) throws IllegalAccessException { | 
 | 
        if (mem instanceof Method) { | 
 | 
            boolean wantSpecial = (refKind == REF_invokeSpecial);  | 
 | 
            return new MemberName((Method) mem, wantSpecial);  | 
 | 
        } else if (mem instanceof Constructor) { | 
 | 
            return new MemberName((Constructor) mem);  | 
 | 
        } else if (mem instanceof Field) { | 
 | 
            boolean isSetter = (refKind == REF_putField || refKind == REF_putStatic);  | 
 | 
            return new MemberName((Field) mem, isSetter);  | 
 | 
        }  | 
 | 
        throw new InternalError(mem.getClass().getName());  | 
 | 
    }  | 
 | 
}  |