package com.oracle.svm.jni.access;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import com.oracle.svm.core.util.VMError;
import jdk.vm.ci.meta.JavaMethod;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.meta.MetaUtil;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public final class JNIAccessibleMethodDescriptor {
private static final String CONSTRUCTOR_NAME = "<init>";
private static final String INITIALIZER_NAME = "<clinit>";
public static JNIAccessibleMethodDescriptor of(JavaMethod method) {
return new JNIAccessibleMethodDescriptor(method.getName(), method.getSignature().toMethodDescriptor());
}
public static JNIAccessibleMethodDescriptor of(Executable method) {
StringBuilder sb = new StringBuilder("(");
for (Class<?> type : method.getParameterTypes()) {
sb.append(MetaUtil.toInternalName(type.getName()));
}
String name = method.getName();
Class<?> returnType;
if (method instanceof Constructor) {
name = CONSTRUCTOR_NAME;
returnType = Void.TYPE;
} else if (method instanceof Method) {
returnType = ((Method) method).getReturnType();
} else {
throw VMError.shouldNotReachHere();
}
sb.append(')').append(MetaUtil.toInternalName(returnType.getName()));
return new JNIAccessibleMethodDescriptor(name, sb.toString());
}
private final String name;
private final String signature;
JNIAccessibleMethodDescriptor(String name, String signature) {
assert !signature.contains(".") : "Malformed signature (needs to use '/' as package separator)";
this.name = name;
this.signature = signature;
}
public boolean isConstructor() {
return name.equals(CONSTRUCTOR_NAME);
}
public boolean isClassInitializer() {
return name.equals(INITIALIZER_NAME);
}
public String getName() {
return name;
}
public String getSignature() {
return signature;
}
public String getNameAndSignature() {
return name + signature;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof JNIAccessibleMethodDescriptor) {
JNIAccessibleMethodDescriptor other = (JNIAccessibleMethodDescriptor) obj;
return (other == this) || (name.equals(other.name) && signature.equals(other.signature));
}
return false;
}
boolean matchesIgnoreReturnType(ResolvedJavaMethod method) {
if (!name.equals(method.getName())) {
return false;
}
int position = 1;
for (JavaType parameterType : method.getSignature().toParameterTypes(null)) {
String paramInternal = parameterType.getName();
if (!signature.startsWith(paramInternal, position)) {
return false;
}
position += paramInternal.length();
}
return signature.startsWith(")", position);
}
@Override
public int hashCode() {
return name.hashCode() * 31 + signature.hashCode();
}
}