Skip to content

Commit

Permalink
Simplify instrumenter and tests
Browse files Browse the repository at this point in the history
This commit simplifies the entitlements instrumentation service and
instrumenter a bit. It especially removes some repetition in the
instrumenter tests.
  • Loading branch information
rjernst committed Dec 11, 2024
1 parent 9837e78 commit 0a2c86e
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 326 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
module org.elasticsearch.entitlement.instrumentation {
requires org.objectweb.asm;
requires org.elasticsearch.entitlement;
requires java.logging;

provides InstrumentationService with InstrumentationServiceImpl;
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,13 @@
public class InstrumentationServiceImpl implements InstrumentationService {

@Override
public Instrumenter newInstrumenter(Map<MethodKey, CheckMethod> checkMethods) {
return InstrumenterImpl.create(checkMethods);
public Instrumenter newInstrumenter(Class<?> clazz, Map<MethodKey, CheckMethod> methods) {
return InstrumenterImpl.create(clazz, methods);
}

@Override
public Map<MethodKey, CheckMethod> lookupMethodsToInstrument(String entitlementCheckerClassName) throws ClassNotFoundException,
IOException {
public Map<MethodKey, CheckMethod> lookupMethods(Class<?> checkerClass) throws IOException {
var methodsToInstrument = new HashMap<MethodKey, CheckMethod>();
var checkerClass = Class.forName(entitlementCheckerClassName);
var classFileInfo = InstrumenterImpl.getClassFileInfo(checkerClass);
ClassReader reader = new ClassReader(classFileInfo.bytecodes());
ClassVisitor visitor = new ClassVisitor(Opcodes.ASM9) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.logging.LogManager;
import java.util.stream.Stream;

import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES;
Expand Down Expand Up @@ -58,30 +59,14 @@ public class InstrumenterImpl implements Instrumenter {
this.checkMethods = checkMethods;
}

static String getCheckerClassName() {
int javaVersion = Runtime.version().feature();
final String classNamePrefix;
if (javaVersion >= 23) {
classNamePrefix = "Java23";
} else {
classNamePrefix = "";
}
return "org/elasticsearch/entitlement/bridge/" + classNamePrefix + "EntitlementChecker";
}

public static InstrumenterImpl create(Map<MethodKey, CheckMethod> checkMethods) {
String checkerClass = getCheckerClassName();
public static InstrumenterImpl create(Class<?> checkerClass, Map<MethodKey, CheckMethod> checkMethods) {
Type checkerClassType = Type.getType(checkerClass);
String handleClass = checkerClass + "Handle";
String getCheckerClassMethodDescriptor = Type.getMethodDescriptor(Type.getObjectType(checkerClass));
String getCheckerClassMethodDescriptor = Type.getMethodDescriptor(checkerClassType);
return new InstrumenterImpl(handleClass, getCheckerClassMethodDescriptor, "", checkMethods);
}

public ClassFileInfo instrumentClassFile(Class<?> clazz) throws IOException {
ClassFileInfo initial = getClassFileInfo(clazz);
return new ClassFileInfo(initial.fileName(), instrumentClass(Type.getInternalName(clazz), initial.bytecodes()));
}

public static ClassFileInfo getClassFileInfo(Class<?> clazz) throws IOException {
static ClassFileInfo getClassFileInfo(Class<?> clazz) throws IOException {
String internalName = Type.getInternalName(clazz);
String fileName = "/" + internalName + ".class";
byte[] originalBytecodes;
Expand Down Expand Up @@ -171,7 +156,7 @@ public MethodVisitor visitMethod(int access, String name, String descriptor, Str
var key = new MethodKey(className, name, Stream.of(Type.getArgumentTypes(descriptor)).map(Type::getInternalName).toList());
var instrumentationMethod = checkMethods.get(key);
if (instrumentationMethod != null) {
// LOGGER.debug("Will instrument method {}", key);
System.out.println("Will instrument method " + name);
return new EntitlementMethodVisitor(Opcodes.ASM9, mv, isStatic, isCtor, descriptor, instrumentationMethod);
} else {
// LOGGER.trace("Will not instrument method {}", key);
Expand Down Expand Up @@ -306,5 +291,5 @@ protected void pushEntitlementChecker(MethodVisitor mv) {
mv.visitMethodInsn(INVOKESTATIC, handleClass, "instance", getCheckerClassMethodDescriptor, false);
}

public record ClassFileInfo(String fileName, byte[] bytecodes) {}
record ClassFileInfo(String fileName, byte[] bytecodes) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ interface TestCheckerCtors {
void check$org_example_TestTargetClass$(Class<?> clazz, int x, String y);
}

public void testInstrumentationTargetLookup() throws IOException, ClassNotFoundException {
Map<MethodKey, CheckMethod> checkMethods = instrumentationService.lookupMethodsToInstrument(TestChecker.class.getName());
public void testInstrumentationTargetLookup() throws IOException {
Map<MethodKey, CheckMethod> checkMethods = instrumentationService.lookupMethods(TestChecker.class);

assertThat(checkMethods, aMapWithSize(3));
assertThat(
Expand Down Expand Up @@ -116,8 +116,8 @@ public void testInstrumentationTargetLookup() throws IOException, ClassNotFoundE
);
}

public void testInstrumentationTargetLookupWithOverloads() throws IOException, ClassNotFoundException {
Map<MethodKey, CheckMethod> checkMethods = instrumentationService.lookupMethodsToInstrument(TestCheckerOverloads.class.getName());
public void testInstrumentationTargetLookupWithOverloads() throws IOException {
Map<MethodKey, CheckMethod> checkMethods = instrumentationService.lookupMethods(TestCheckerOverloads.class);

assertThat(checkMethods, aMapWithSize(2));
assertThat(
Expand Down Expand Up @@ -148,8 +148,8 @@ public void testInstrumentationTargetLookupWithOverloads() throws IOException, C
);
}

public void testInstrumentationTargetLookupWithCtors() throws IOException, ClassNotFoundException {
Map<MethodKey, CheckMethod> checkMethods = instrumentationService.lookupMethodsToInstrument(TestCheckerCtors.class.getName());
public void testInstrumentationTargetLookupWithCtors() throws IOException {
Map<MethodKey, CheckMethod> checkMethods = instrumentationService.lookupMethods(TestCheckerCtors.class);

assertThat(checkMethods, aMapWithSize(2));
assertThat(
Expand Down
Loading

0 comments on commit 0a2c86e

Please sign in to comment.