146 lines
4.7 KiB
146 lines
4.7 KiB
/*
|
|
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
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.
|
|
*/
|
|
/*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());
|
|
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.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).
|
|
// For more information see comments on {@link MethodHandleNatives#linkMethod}.
|
|
throw new IllegalArgumentException("cannot reflect signature polymorphic method");
|
|
}
|
|
Member mem = AccessController.doPrivileged(new PrivilegedAction<Member>() {
|
|
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());
|
|
}
|
|
}
|