Add class validation utilities
This commit is contained in:
parent
7a737ad335
commit
15f6897c14
@ -17,6 +17,12 @@
|
||||
<artifactId>annotations-java5</artifactId>
|
||||
<version>RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.16.10</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
@ -0,0 +1,97 @@
|
||||
package eu.mikroskeem.utils.reflect;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Validate {
|
||||
/* Code got from Google Guava */
|
||||
private static <T> T checkNotNull(T reference, @Nullable Object errorMessage) {
|
||||
if(reference == null) {
|
||||
throw new NullPointerException(String.valueOf(errorMessage));
|
||||
} else {
|
||||
return reference;
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkMethods(ClassDescriptor classDescriptor, Validate.MethodDescriptor... methods) {
|
||||
checkClass(classDescriptor);
|
||||
Stream.of(methods).forEach(methodDescriptor ->
|
||||
checkNotNull(Reflect.getMethod(classDescriptor.getClazz(),
|
||||
methodDescriptor.getMethodName(),
|
||||
methodDescriptor.getArguments()),
|
||||
String.format("Method %s(%s) not found",
|
||||
methodDescriptor.getMethodName(),
|
||||
Arrays.toString(methodDescriptor.getArguments())
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
public static void checkConstructors(ClassDescriptor classDescriptor,
|
||||
Validate.ConstructorDescriptor... constructors) {
|
||||
checkClass(classDescriptor);
|
||||
Stream.of(constructors).forEach(constructorDescriptor -> {
|
||||
try {
|
||||
checkNotNull(classDescriptor.getClazz().getConstructor(constructorDescriptor.getArguments()),
|
||||
String.format("Constructor (%s) not found",
|
||||
Arrays.toString(constructorDescriptor.getArguments())
|
||||
));
|
||||
} catch (Exception e){
|
||||
throw new NullPointerException(e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void checkClass(ClassDescriptor classDescriptor){
|
||||
checkNotNull(classDescriptor.getClazz(), "Class is null");
|
||||
Stream.of(classDescriptor.getExtendingClasses()).forEach(clazz->{
|
||||
if(!clazz.isAssignableFrom(classDescriptor.getClazz())){
|
||||
throw new NullPointerException(String.format("Class doesn't extend %s", clazz.getSimpleName()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static @Getter class ClassDescriptor {
|
||||
private final Class<?> clazz;
|
||||
private final Class<?>[] extendingClasses;
|
||||
private ClassDescriptor(Class<?> clazz, Class<?>... arguments){
|
||||
this.clazz = clazz;
|
||||
this.extendingClasses = arguments;
|
||||
}
|
||||
|
||||
public static ClassDescriptor newClassDescriptor(Class<?> clazz, Class<?>... classes){
|
||||
return new ClassDescriptor(clazz, classes);
|
||||
}
|
||||
|
||||
public static ClassDescriptor newClassDescriptor(String clazzName, Class<?>... classes){
|
||||
Class<?> clazz = Reflect.getClass(clazzName);
|
||||
return new ClassDescriptor(clazz, classes);
|
||||
}
|
||||
}
|
||||
|
||||
public static @Getter class ConstructorDescriptor {
|
||||
private final Class[] arguments;
|
||||
private ConstructorDescriptor(Class... arguments){
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public static ConstructorDescriptor newConstructorDescriptor(Class... arguments){
|
||||
return new ConstructorDescriptor(arguments);
|
||||
}
|
||||
}
|
||||
|
||||
public static @Getter class MethodDescriptor {
|
||||
private final String methodName;
|
||||
private final Class[] arguments;
|
||||
private MethodDescriptor(String methodName, Class... arguments){
|
||||
this.methodName = methodName;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
public static MethodDescriptor newMethodDescriptor(String methodName, Class... arguments){
|
||||
return new MethodDescriptor(methodName, arguments);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package eu.mikroskeem.utils.test.reflect;
|
||||
|
||||
import eu.mikroskeem.utils.reflect.Reflect;
|
||||
import eu.mikroskeem.utils.reflect.Validate;
|
||||
import org.junit.Test;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import static eu.mikroskeem.utils.reflect.Validate.ClassDescriptor.newClassDescriptor;
|
||||
import static eu.mikroskeem.utils.reflect.Validate.MethodDescriptor.newMethodDescriptor;
|
||||
import static eu.mikroskeem.utils.reflect.Validate.checkClass;
|
||||
import static eu.mikroskeem.utils.reflect.Validate.checkMethods;
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class TestValidate {
|
||||
@Test
|
||||
public void testMethodNoArguments() throws Exception {
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
|
||||
cw.visit(V1_8, ACC_PUBLIC+ACC_SUPER, "eu/mikroskeem/utils/test/reflect/TestClass1",
|
||||
null, Type.getInternalName(Object.class), null);
|
||||
String desc = String.format("(%s)%s", "", "V");
|
||||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", desc, null, null);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", desc, false);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
desc = String.format("(%s)%s", "", Type.getDescriptor(String.class));
|
||||
mv = cw.visitMethod(ACC_PUBLIC, "toString", desc, null, null);
|
||||
mv.visitLdcInsn("TestClass1 instance");
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
cw.visitEnd();
|
||||
Class<?> clazz = Reflect.defineClass(
|
||||
ClassLoader.getSystemClassLoader(),
|
||||
"eu.mikroskeem.utils.test.reflect.TestClass1",
|
||||
cw.toByteArray());
|
||||
Validate.ClassDescriptor cd = newClassDescriptor(clazz, Object.class);
|
||||
|
||||
checkClass(cd);
|
||||
checkMethods(cd, newMethodDescriptor("toString"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user