added getter support in precidates

This commit is contained in:
wea_ondara
2022-07-14 20:12:05 +02:00
parent 4bee1e28e4
commit da574b52cf
2 changed files with 47 additions and 7 deletions

View File

@@ -18,11 +18,14 @@ import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.Stack;
import java.util.function.Consumer;
@@ -80,7 +83,7 @@ class FilterMethodVisitor extends MethodVisitor {
@Override
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
System.out.println("method insn: " + ops.getOrDefault(opcode, "" + opcode) + ", " + owner + ", " + name + ", " + descriptor);
if (opcode == Opcodes.INVOKESTATIC) {
if (opcode == Opcodes.INVOKESTATIC && name.equals("valueOf")) {
//ignore boxed primitive types
var boxedPrimitiveClasses = Set.of("java/lang/Boolean", "java/lang/Integer", "java/lang/Long", "java/lang/Float", "java/lang/Double");
if (boxedPrimitiveClasses.contains(owner)) {
@@ -89,18 +92,34 @@ class FilterMethodVisitor extends MethodVisitor {
//do something
throw new RuntimeException("method insn: unsupported opcode " + ops.getOrDefault(opcode, "" + opcode));
}
} else if (opcode == Opcodes.INVOKEINTERFACE) {
} else if (opcode == Opcodes.INVOKEINTERFACE || opcode == Opcodes.INVOKEVIRTUAL) {
try {
if (name.equals("contains")
&& owner.startsWith("java/util/")
&& Collection.class.isAssignableFrom(Class.forName(owner.replace("/", ".")))) {
var element = varStack.pop();
var collection = varStack.pop();
// System.out.println("element: " + element);
// System.out.println("collection: " + collection);
varStack.push(new BinaryExpression(element, collection, BinaryExpression.Operator.IN));
} else if (name.startsWith("get") && name.length() > 3 && descriptor.startsWith("()")) { //hacky getter support, TODO replace this with proper getter eval later
var field = findField(owner, name);
if (field.isPresent()) {
var v = varStack.pop();
if (v instanceof ParameterExpression p) {
if (p.isInput()) {
varStack.push(new FieldExpression(field.get().getName(), descriptor.substring(2)));
} else {
throw new RuntimeException("method insn: getter support only to predicate parameter");
}
} catch (ClassNotFoundException e) {
} else {
throw new RuntimeException("method insn: getter support expected ParameterExpression but found" + v.getClass().getSimpleName());
}
} else {
throw new RuntimeException("method insn: could not find field for getter " + name + " in " + owner);
}
} else {
throw new RuntimeException("method insn: unsupported function " + name + " in " + owner);
}
} catch (Exception e) {
throw new RuntimeException("method insn: ", e);
}
} else {
@@ -447,4 +466,19 @@ class FilterMethodVisitor extends MethodVisitor {
System.out.println("-------------------> " + new WhereExpression(new SelectExpression(List.of("*"), new TableExpression("dummy"), ""), varStack.peek()));
}
}
private static Optional<Field> findField(String owner, String name) throws Exception {
var cls = Class.forName(owner.replace("/", "."));
String fieldname = name.substring(3, 4).toLowerCase(Locale.ROOT) + name.substring(4);
var field = cls.getDeclaredField(fieldname);
if (field != null) {
return Optional.of(field);
}
for (Field declaredField : cls.getDeclaredFields()) {
if (declaredField.getName().equalsIgnoreCase(fieldname)) {
return Optional.of(declaredField);
}
}
return Optional.empty();
}
}

View File

@@ -1,6 +1,7 @@
package jef.operations;
import jef.DBSet;
import lombok.Getter;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -207,10 +208,15 @@ public class FilterOpTest {
}
@Test
public void test() {
public void testMemberViaGetter() {
String act;
act = new DBSet<TestClass>("table1")
.filter(e -> e.getI() == 1337)
.toString();
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE a.i = 1337", act);
}
@Getter
public static class TestClass implements Serializable {
public int i = 1;
public Object o = new Object();