Skip to content

Commit

Permalink
Throw if the caller specified a duplicate param name when calling `De…
Browse files Browse the repository at this point in the history
…bugService#callMethod`
  • Loading branch information
JamesChenX committed Jun 10, 2024
1 parent be5559e commit 3f6a7e3
Showing 1 changed file with 70 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import jakarta.annotation.Nullable;

import org.springframework.beans.factory.NoSuchBeanDefinitionException;
Expand All @@ -42,6 +43,7 @@
import im.turms.server.common.infra.lang.ClassUtil;
import im.turms.server.common.infra.lang.LongUtil;
import im.turms.server.common.infra.lang.MathUtil;
import im.turms.server.common.infra.lang.Pair;
import im.turms.server.common.infra.lang.PrimitiveUtil;
import im.turms.server.common.infra.lang.StringUtil;
import im.turms.server.common.infra.logging.core.logger.Logger;
Expand Down Expand Up @@ -144,60 +146,22 @@ public Mono<Object> callMethod(
// 4. Find method
Method methodToCall;
try {
methodToCall = getTargetMethod(receiverClass, methodName);
methodToCall = findTargetMethod(receiverClass, methodName);
} catch (Exception e) {
return Mono.error(e);
}
ReflectionUtil.setAccessible(methodToCall);
// 5. Prepare arguments
Parameter[] parameters = methodToCall.getParameters();
int paramCount = parameters.length;
int inputParamCount = CollectionUtil.getSize(params);
if (inputParamCount > paramCount) {
return Mono.error(ResponseException.get(ResponseStatusCode.ILLEGAL_ARGUMENT,
"The count of arguments must not exceed "
+ paramCount));
}
Object[] paramValues = new Object[paramCount];
if (inputParamCount > 0) {
boolean hasName = params.getFirst()
.name() != null;
if (hasName) {
Map<String, Parameter> nameToParam =
CollectionUtil.newMapWithExpectedSize(paramCount);
for (Parameter parameter : parameters) {
nameToParam.put(parameter.getName(), parameter);
}
for (int i = 0; i < inputParamCount; i++) {
CreateMethodCallDTO.ParamDTO param = params.get(i);
String name = param.name();
if (name == null) {
throw ResponseException.get(ResponseStatusCode.ILLEGAL_ARGUMENT,
"The parameter at index "
+ i
+ " has not specified a name");
}
Parameter parameter = nameToParam.get(name);
if (parameter == null) {
throw ResponseException.get(ResponseStatusCode.ILLEGAL_ARGUMENT,
"The specified parameter is not found: \""
+ param.name()
+ "\"");
}
paramValues[i] = parseArg(parameter.getType(), param.value());
}
} else {
for (int i = 0; i < inputParamCount; i++) {
CreateMethodCallDTO.ParamDTO param = params.get(i);
Class<?> parameterType = parameters[i].getType();
paramValues[i] = parseArg(parameterType, param.value());
}
}
Object[] arguments;
try {
arguments = prepareArguments(params, methodToCall);
} catch (Exception e) {
return Mono.error(e);
}
// 6. Invoke method
Object returnValue;
try {
returnValue = methodToCall.invoke(receiver, paramValues);
returnValue = methodToCall.invoke(receiver, arguments);
} catch (Exception e) {
return Mono.error(ResponseException.get(ResponseStatusCode.ILLEGAL_ARGUMENT,
"Failed to invoke the method: "
Expand All @@ -213,7 +177,7 @@ public Mono<Object> callMethod(
};
}

private Method getTargetMethod(Class<?> specifiedClass, String methodName) {
private Method findTargetMethod(Class<?> specifiedClass, String methodName) {
int indexOfBrace = methodName.indexOf('(');
boolean useMethodSignature = indexOfBrace >= 0;
Class<?> currentClass = specifiedClass;
Expand Down Expand Up @@ -283,6 +247,66 @@ private Method getTargetMethod(Class<?> specifiedClass, String methodName) {
}
}

private Object[] prepareArguments(
@Nullable List<CreateMethodCallDTO.ParamDTO> inputParams,
Method methodToCall) {
Parameter[] parameters = methodToCall.getParameters();
int paramCount = parameters.length;
int inputParamCount = CollectionUtil.getSize(inputParams);
if (inputParamCount > paramCount) {
throw ResponseException.get(ResponseStatusCode.ILLEGAL_ARGUMENT,
"The count of arguments must not exceed "
+ paramCount);
}
Object[] arguments = new Object[paramCount];
if (inputParamCount == 0) {
return arguments;
}
boolean hasName = inputParams.getFirst()
.name() != null;
if (hasName) {
Set<String> specifiedNames = CollectionUtil.newSetWithExpectedSize(inputParamCount);
Map<String, Pair<Integer, Parameter>> nameToParam =
CollectionUtil.newMapWithExpectedSize(paramCount);
for (int i = 0; i < paramCount; i++) {
Parameter parameter = parameters[i];
nameToParam.put(parameter.getName(), Pair.of(i, parameter));
}
for (int i = 0; i < inputParamCount; i++) {
CreateMethodCallDTO.ParamDTO param = inputParams.get(i);
String name = param.name();
if (name == null) {
throw ResponseException.get(ResponseStatusCode.ILLEGAL_ARGUMENT,
"The parameter at index "
+ i
+ " has not specified a name");
}
Pair<Integer, Parameter> parameter = nameToParam.get(name);
if (parameter == null) {
throw ResponseException.get(ResponseStatusCode.ILLEGAL_ARGUMENT,
"The specified parameter is not found: \""
+ param.name()
+ "\"");
}
if (!specifiedNames.add(name)) {
throw ResponseException.get(ResponseStatusCode.ILLEGAL_ARGUMENT,
"The specified parameter is duplicated: \""
+ name
+ "\"");
}
arguments[parameter.first()] = parseArg(parameter.second()
.getType(), param.value());
}
} else {
for (int i = 0; i < inputParamCount; i++) {
CreateMethodCallDTO.ParamDTO param = inputParams.get(i);
Class<?> parameterType = parameters[i].getType();
arguments[i] = parseArg(parameterType, param.value());
}
}
return arguments;
}

@Nullable
private Object parseArg(Class parameterType, Object arg) {
Class parameterClassToDetect = parameterType;
Expand Down

0 comments on commit 3f6a7e3

Please sign in to comment.