Skip to content

Commit

Permalink
Merge branch 'main' into api-redirects-2
Browse files Browse the repository at this point in the history
  • Loading branch information
lcawl authored Dec 31, 2024
2 parents fbab714 + 4012208 commit f34d5f7
Show file tree
Hide file tree
Showing 41 changed files with 297 additions and 208 deletions.
1 change: 1 addition & 0 deletions docs/reference/shutdown/apis/shutdown-get.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ including the status of shard migration, task migration, and plugin cleanup:
"nodes": [
{
"node_id": "USpTGYaBSIKbgSUJR2Z9lg",
"node_ephemeral_id": null,
"type": "RESTART",
"reason": "Demonstrating how the node shutdown API works",
"shutdown_startedmillis": 1624406108685,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,19 @@ public MethodVisitor visitMethod(
private static final Type CLASS_TYPE = Type.getType(Class.class);

static MethodKey parseCheckerMethodSignature(String checkerMethodName, Type[] checkerMethodArgumentTypes) {
var classNameStartIndex = checkerMethodName.indexOf('$');
var classNameEndIndex = checkerMethodName.lastIndexOf('$');
boolean targetMethodIsStatic;
int classNameEndIndex = checkerMethodName.lastIndexOf("$$");
int methodNameStartIndex;
if (classNameEndIndex == -1) {
targetMethodIsStatic = false;
classNameEndIndex = checkerMethodName.lastIndexOf('$');
methodNameStartIndex = classNameEndIndex + 1;
} else {
targetMethodIsStatic = true;
methodNameStartIndex = classNameEndIndex + 2;
}

var classNameStartIndex = checkerMethodName.indexOf('$');
if (classNameStartIndex == -1 || classNameStartIndex >= classNameEndIndex) {
throw new IllegalArgumentException(
String.format(
Expand All @@ -82,15 +92,17 @@ static MethodKey parseCheckerMethodSignature(String checkerMethodName, Type[] ch
);
}

// No "className" (check$$methodName) -> method is instance, and we'll get the class from the actual typed argument
final boolean targetMethodIsStatic = classNameStartIndex + 1 != classNameEndIndex;
// No "methodName" (check$package_ClassName$) -> method is ctor
final boolean targetMethodIsCtor = classNameEndIndex + 1 == checkerMethodName.length();
final String targetMethodName = targetMethodIsCtor ? "<init>" : checkerMethodName.substring(classNameEndIndex + 1);
final String targetMethodName = targetMethodIsCtor ? "<init>" : checkerMethodName.substring(methodNameStartIndex);

final String targetClassName = checkerMethodName.substring(classNameStartIndex + 1, classNameEndIndex).replace('_', '/');
if (targetClassName.isBlank()) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "Checker method %s has no class name", checkerMethodName));
}

final String targetClassName;
final List<String> targetParameterTypes;
if (targetMethodIsStatic) {
if (targetMethodIsStatic || targetMethodIsCtor) {
if (checkerMethodArgumentTypes.length < 1 || CLASS_TYPE.equals(checkerMethodArgumentTypes[0]) == false) {
throw new IllegalArgumentException(
String.format(
Expand All @@ -101,7 +113,6 @@ static MethodKey parseCheckerMethodSignature(String checkerMethodName, Type[] ch
);
}

targetClassName = checkerMethodName.substring(classNameStartIndex + 1, classNameEndIndex).replace('_', '/');
targetParameterTypes = Arrays.stream(checkerMethodArgumentTypes).skip(1).map(Type::getInternalName).toList();
} else {
if (checkerMethodArgumentTypes.length < 2
Expand All @@ -117,10 +128,9 @@ static MethodKey parseCheckerMethodSignature(String checkerMethodName, Type[] ch
)
);
}
var targetClassType = checkerMethodArgumentTypes[1];
targetClassName = targetClassType.getInternalName();
targetParameterTypes = Arrays.stream(checkerMethodArgumentTypes).skip(2).map(Type::getInternalName).toList();
}
boolean hasReceiver = (targetMethodIsStatic || targetMethodIsCtor) == false;
return new MethodKey(targetClassName, targetMethodName, targetParameterTypes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public MethodVisitor visitMethod(int access, String name, String descriptor, Str
if (isAnnotationPresent == false) {
boolean isStatic = (access & ACC_STATIC) != 0;
boolean isCtor = "<init>".equals(name);
boolean hasReceiver = (isStatic || isCtor) == false;
var key = new MethodKey(className, name, Stream.of(Type.getArgumentTypes(descriptor)).map(Type::getInternalName).toList());
var instrumentationMethod = checkMethods.get(key);
if (instrumentationMethod != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ public class InstrumentationServiceImplTests extends ESTestCase {
static class TestTargetClass {}

interface TestChecker {
void check$org_example_TestTargetClass$staticMethod(Class<?> clazz, int arg0, String arg1, Object arg2);
void check$org_example_TestTargetClass$$staticMethod(Class<?> clazz, int arg0, String arg1, Object arg2);

void check$$instanceMethodNoArgs(Class<?> clazz, TestTargetClass that);
void check$org_example_TestTargetClass$instanceMethodNoArgs(Class<?> clazz, TestTargetClass that);

void check$$instanceMethodWithArgs(Class<?> clazz, TestTargetClass that, int x, int y);
void check$org_example_TestTargetClass$instanceMethodWithArgs(Class<?> clazz, TestTargetClass that, int x, int y);
}

interface TestCheckerOverloads {
void check$org_example_TestTargetClass$staticMethodWithOverload(Class<?> clazz, int x, int y);
void check$org_example_TestTargetClass$$staticMethodWithOverload(Class<?> clazz, int x, int y);

void check$org_example_TestTargetClass$staticMethodWithOverload(Class<?> clazz, int x, String y);
void check$org_example_TestTargetClass$$staticMethodWithOverload(Class<?> clazz, int x, String y);
}

interface TestCheckerCtors {
Expand All @@ -62,7 +62,7 @@ public void testInstrumentationTargetLookup() throws IOException {
equalTo(
new CheckMethod(
"org/elasticsearch/entitlement/instrumentation/impl/InstrumentationServiceImplTests$TestChecker",
"check$org_example_TestTargetClass$staticMethod",
"check$org_example_TestTargetClass$$staticMethod",
List.of("Ljava/lang/Class;", "I", "Ljava/lang/String;", "Ljava/lang/Object;")
)
)
Expand All @@ -71,17 +71,11 @@ public void testInstrumentationTargetLookup() throws IOException {
assertThat(
checkMethods,
hasEntry(
equalTo(
new MethodKey(
"org/elasticsearch/entitlement/instrumentation/impl/InstrumentationServiceImplTests$TestTargetClass",
"instanceMethodNoArgs",
List.of()
)
),
equalTo(new MethodKey("org/example/TestTargetClass", "instanceMethodNoArgs", List.of())),
equalTo(
new CheckMethod(
"org/elasticsearch/entitlement/instrumentation/impl/InstrumentationServiceImplTests$TestChecker",
"check$$instanceMethodNoArgs",
"check$org_example_TestTargetClass$instanceMethodNoArgs",
List.of(
"Ljava/lang/Class;",
"Lorg/elasticsearch/entitlement/instrumentation/impl/InstrumentationServiceImplTests$TestTargetClass;"
Expand All @@ -93,17 +87,11 @@ public void testInstrumentationTargetLookup() throws IOException {
assertThat(
checkMethods,
hasEntry(
equalTo(
new MethodKey(
"org/elasticsearch/entitlement/instrumentation/impl/InstrumentationServiceImplTests$TestTargetClass",
"instanceMethodWithArgs",
List.of("I", "I")
)
),
equalTo(new MethodKey("org/example/TestTargetClass", "instanceMethodWithArgs", List.of("I", "I"))),
equalTo(
new CheckMethod(
"org/elasticsearch/entitlement/instrumentation/impl/InstrumentationServiceImplTests$TestChecker",
"check$$instanceMethodWithArgs",
"check$org_example_TestTargetClass$instanceMethodWithArgs",
List.of(
"Ljava/lang/Class;",
"Lorg/elasticsearch/entitlement/instrumentation/impl/InstrumentationServiceImplTests$TestTargetClass;",
Expand All @@ -127,7 +115,7 @@ public void testInstrumentationTargetLookupWithOverloads() throws IOException {
equalTo(
new CheckMethod(
"org/elasticsearch/entitlement/instrumentation/impl/InstrumentationServiceImplTests$TestCheckerOverloads",
"check$org_example_TestTargetClass$staticMethodWithOverload",
"check$org_example_TestTargetClass$$staticMethodWithOverload",
List.of("Ljava/lang/Class;", "I", "Ljava/lang/String;")
)
)
Expand All @@ -140,7 +128,7 @@ public void testInstrumentationTargetLookupWithOverloads() throws IOException {
equalTo(
new CheckMethod(
"org/elasticsearch/entitlement/instrumentation/impl/InstrumentationServiceImplTests$TestCheckerOverloads",
"check$org_example_TestTargetClass$staticMethodWithOverload",
"check$org_example_TestTargetClass$$staticMethodWithOverload",
List.of("Ljava/lang/Class;", "I", "I")
)
)
Expand Down Expand Up @@ -182,7 +170,7 @@ public void testInstrumentationTargetLookupWithCtors() throws IOException {

public void testParseCheckerMethodSignatureStaticMethod() {
var methodKey = InstrumentationServiceImpl.parseCheckerMethodSignature(
"check$org_example_TestClass$staticMethod",
"check$org_example_TestClass$$staticMethod",
new Type[] { Type.getType(Class.class) }
);

Expand All @@ -191,7 +179,7 @@ public void testParseCheckerMethodSignatureStaticMethod() {

public void testParseCheckerMethodSignatureStaticMethodWithArgs() {
var methodKey = InstrumentationServiceImpl.parseCheckerMethodSignature(
"check$org_example_TestClass$staticMethod",
"check$org_example_TestClass$$staticMethod",
new Type[] { Type.getType(Class.class), Type.getType("I"), Type.getType(String.class) }
);

Expand All @@ -200,7 +188,7 @@ public void testParseCheckerMethodSignatureStaticMethodWithArgs() {

public void testParseCheckerMethodSignatureStaticMethodInnerClass() {
var methodKey = InstrumentationServiceImpl.parseCheckerMethodSignature(
"check$org_example_TestClass$InnerClass$staticMethod",
"check$org_example_TestClass$InnerClass$$staticMethod",
new Type[] { Type.getType(Class.class) }
);

Expand All @@ -225,94 +213,80 @@ public void testParseCheckerMethodSignatureCtorWithArgs() {
assertThat(methodKey, equalTo(new MethodKey("org/example/TestClass", "<init>", List.of("I", "java/lang/String"))));
}

public void testParseCheckerMethodSignatureIncorrectName() {
var exception = assertThrows(
IllegalArgumentException.class,
() -> InstrumentationServiceImpl.parseCheckerMethodSignature("check$staticMethod", new Type[] { Type.getType(Class.class) })
);
public void testParseCheckerMethodSignatureOneDollarSign() {
assertParseCheckerMethodSignatureThrows("has incorrect name format", "check$method", Type.getType(Class.class));
}

assertThat(exception.getMessage(), containsString("has incorrect name format"));
public void testParseCheckerMethodSignatureMissingClass() {
assertParseCheckerMethodSignatureThrows("has incorrect name format", "check$$staticMethod", Type.getType(Class.class));
}

public void testParseCheckerMethodSignatureBlankClass() {
assertParseCheckerMethodSignatureThrows("no class name", "check$$$staticMethod", Type.getType(Class.class));
}

public void testParseCheckerMethodSignatureStaticMethodIncorrectArgumentCount() {
var exception = assertThrows(
IllegalArgumentException.class,
() -> InstrumentationServiceImpl.parseCheckerMethodSignature("check$ClassName$staticMethod", new Type[] {})
);
assertThat(exception.getMessage(), containsString("It must have a first argument of Class<?> type"));
assertParseCheckerMethodSignatureThrows("It must have a first argument of Class<?> type", "check$ClassName$staticMethod");
}

public void testParseCheckerMethodSignatureStaticMethodIncorrectArgumentType() {
var exception = assertThrows(
IllegalArgumentException.class,
() -> InstrumentationServiceImpl.parseCheckerMethodSignature(
"check$ClassName$staticMethod",
new Type[] { Type.getType(String.class) }
)
assertParseCheckerMethodSignatureThrows(
"It must have a first argument of Class<?> type",
"check$ClassName$$staticMethod",
Type.getType(String.class)
);
assertThat(exception.getMessage(), containsString("It must have a first argument of Class<?> type"));
}

public void testParseCheckerMethodSignatureInstanceMethod() {
var methodKey = InstrumentationServiceImpl.parseCheckerMethodSignature(
"check$$instanceMethod",
"check$org_example_TestClass$instanceMethod",
new Type[] { Type.getType(Class.class), Type.getType(TestTargetClass.class) }
);

assertThat(
methodKey,
equalTo(
new MethodKey(
"org/elasticsearch/entitlement/instrumentation/impl/InstrumentationServiceImplTests$TestTargetClass",
"instanceMethod",
List.of()
)
)
);
assertThat(methodKey, equalTo(new MethodKey("org/example/TestClass", "instanceMethod", List.of())));
}

public void testParseCheckerMethodSignatureInstanceMethodWithArgs() {
var methodKey = InstrumentationServiceImpl.parseCheckerMethodSignature(
"check$$instanceMethod",
"check$org_example_TestClass$instanceMethod",
new Type[] { Type.getType(Class.class), Type.getType(TestTargetClass.class), Type.getType("I"), Type.getType(String.class) }
);

assertThat(
methodKey,
equalTo(
new MethodKey(
"org/elasticsearch/entitlement/instrumentation/impl/InstrumentationServiceImplTests$TestTargetClass",
"instanceMethod",
List.of("I", "java/lang/String")
)
)
);
assertThat(methodKey, equalTo(new MethodKey("org/example/TestClass", "instanceMethod", List.of("I", "java/lang/String"))));
}

public void testParseCheckerMethodSignatureInstanceMethodIncorrectArgumentTypes() {
var exception = assertThrows(
IllegalArgumentException.class,
() -> InstrumentationServiceImpl.parseCheckerMethodSignature("check$$instanceMethod", new Type[] { Type.getType(String.class) })
assertParseCheckerMethodSignatureThrows(
"It must have a first argument of Class<?> type",
"check$org_example_TestClass$instanceMethod",
Type.getType(String.class)
);
assertThat(exception.getMessage(), containsString("It must have a first argument of Class<?> type"));
}

public void testParseCheckerMethodSignatureInstanceMethodIncorrectArgumentCount() {
var exception = assertThrows(
IllegalArgumentException.class,
() -> InstrumentationServiceImpl.parseCheckerMethodSignature("check$$instanceMethod", new Type[] { Type.getType(Class.class) })
assertParseCheckerMethodSignatureThrows(
"a second argument of the class containing the method to instrument",
"check$org_example_TestClass$instanceMethod",
Type.getType(Class.class)
);
assertThat(exception.getMessage(), containsString("a second argument of the class containing the method to instrument"));
}

public void testParseCheckerMethodSignatureInstanceMethodIncorrectArgumentTypes2() {
assertParseCheckerMethodSignatureThrows(
"a second argument of the class containing the method to instrument",
"check$org_example_TestClass$instanceMethod",
Type.getType(Class.class),
Type.getType("I")
);
}

private static void assertParseCheckerMethodSignatureThrows(String messageText, String methodName, Type... methodArgs) {
var exception = assertThrows(
IllegalArgumentException.class,
() -> InstrumentationServiceImpl.parseCheckerMethodSignature(
"check$$instanceMethod",
new Type[] { Type.getType(Class.class), Type.getType("I") }
)
() -> InstrumentationServiceImpl.parseCheckerMethodSignature(methodName, methodArgs)
);
assertThat(exception.getMessage(), containsString("a second argument of the class containing the method to instrument"));

assertThat(exception.getMessage(), containsString(messageText));
}

}
Loading

0 comments on commit f34d5f7

Please sign in to comment.