Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ public interface MethodDescriptor {

Class<?>[] getParameterClasses();

/**
* Retrieves the generic parameter types of the method.
* <p>
* For parameterized parameters like {@code List<Byte>}, this returns the
* {@link java.lang.reflect.ParameterizedType} instead of just the raw {@code Class}.
*
* @return the generic parameter types
*/
default Type[] getGenericParameterTypes() {
return getParameterClasses();
}

Class<?> getReturnClass();

Type[] getReturnTypes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public class ReflectionMethodDescriptor implements MethodDescriptor {
public final String methodName;
private final String[] compatibleParamSignatures;
private final Class<?>[] parameterClasses;
private final Type[] genericParameterTypes;
private final Class<?> returnClass;
private final Type[] returnTypes;
private final String paramDesc;
Expand All @@ -57,6 +58,7 @@ public ReflectionMethodDescriptor(Method method) {
this.method = method;
this.methodName = method.getName();
this.parameterClasses = method.getParameterTypes();
this.genericParameterTypes = method.getGenericParameterTypes();
this.returnClass = method.getReturnType();
Type[] returnTypesResult;
try {
Expand Down Expand Up @@ -149,6 +151,11 @@ public Class<?>[] getParameterClasses() {
return parameterClasses;
}

@Override
public Type[] getGenericParameterTypes() {
return genericParameterTypes;
}

@Override
public String getParamDesc() {
return paramDesc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
import org.apache.dubbo.rpc.model.MethodDescriptor.RpcType;
import org.apache.dubbo.rpc.support.DemoService;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -89,6 +92,47 @@ void addAttribute() {
Assertions.assertEquals(attr, method.getAttribute(attr));
}

@Test
void getGenericParameterTypes_nonGeneric() {
Type[] types = method.getGenericParameterTypes();
Assertions.assertEquals(1, types.length);
Assertions.assertEquals(String.class, types[0]);
}

@Test
void getGenericParameterTypes_withGenericParam() throws NoSuchMethodException {
ReflectionMethodDescriptor md =
new ReflectionMethodDescriptor(DemoService.class.getDeclaredMethod("processBytes", List.class));
Type[] genericTypes = md.getGenericParameterTypes();
Class<?>[] rawTypes = md.getParameterClasses();

Assertions.assertEquals(1, genericTypes.length);
Assertions.assertEquals(List.class, rawTypes[0]);
Assertions.assertInstanceOf(ParameterizedType.class, genericTypes[0]);

ParameterizedType pt = (ParameterizedType) genericTypes[0];
Assertions.assertEquals(List.class, pt.getRawType());
Assertions.assertEquals(Byte.class, pt.getActualTypeArguments()[0]);
}

@Test
void getGenericParameterTypes_mixedParams() throws NoSuchMethodException {
ReflectionMethodDescriptor md = new ReflectionMethodDescriptor(
DemoService.class.getDeclaredMethod("processMultiple", String.class, List.class, Map.class));
Type[] genericTypes = md.getGenericParameterTypes();
Class<?>[] rawTypes = md.getParameterClasses();

Assertions.assertEquals(3, genericTypes.length);
// String param: generic type == raw type
Assertions.assertSame(rawTypes[0], genericTypes[0]);
// List<Short>: generic type is ParameterizedType
Assertions.assertInstanceOf(ParameterizedType.class, genericTypes[1]);
Assertions.assertEquals(Short.class, ((ParameterizedType) genericTypes[1]).getActualTypeArguments()[0]);
// Map<String, Byte>: generic type is ParameterizedType
Assertions.assertInstanceOf(ParameterizedType.class, genericTypes[2]);
Assertions.assertEquals(Byte.class, ((ParameterizedType) genericTypes[2]).getActualTypeArguments()[1]);
}

@Test
void testEquals() {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
*/
package org.apache.dubbo.rpc.support;

import java.util.List;
import java.util.Map;

public interface DemoService {
String sayHello(String name);

void processBytes(List<Byte> data);

void processMultiple(String name, List<Short> values, Map<String, Byte> mapping);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,18 @@
*/
package org.apache.dubbo.rpc.support;

import java.util.List;
import java.util.Map;

public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
return "hello " + name;
}

@Override
public void processBytes(List<Byte> data) {}

@Override
public void processMultiple(String name, List<Short> values, Map<String, Byte> mapping) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
Expand Down Expand Up @@ -80,6 +81,8 @@ public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Dec

protected final FrameworkModel frameworkModel;

private Type[] genericParameterTypes;

protected final transient Supplier<CallbackServiceCodec> callbackServiceCodecFactory;

private static final boolean CHECK_SERIALIZATION =
Expand Down Expand Up @@ -237,6 +240,7 @@ protected Class<?>[] drawPts(String path, String version, String desc, Class<?>[
MethodDescriptor methodDescriptor = serviceDescriptor.getMethod(getMethodName(), desc);
if (methodDescriptor != null) {
pts = methodDescriptor.getParameterClasses();
this.genericParameterTypes = methodDescriptor.getGenericParameterTypes();
this.setReturnTypes(methodDescriptor.getReturnTypes());

// switch TCCL
Expand Down Expand Up @@ -271,10 +275,15 @@ protected Class<?>[] drawPts(String path, String version, String desc, Class<?>[
}

protected Object[] drawArgs(ObjectInput in, Class<?>[] pts) throws IOException, ClassNotFoundException {
Object[] args;
args = new Object[pts.length];
Object[] args = new Object[pts.length];
for (int i = 0; i < args.length; i++) {
args[i] = in.readObject(pts[i]);
if (genericParameterTypes != null
&& i < genericParameterTypes.length
&& genericParameterTypes[i] != pts[i]) {
args[i] = in.readObject(pts[i], genericParameterTypes[i]);
} else {
args[i] = in.readObject(pts[i]);
}
}
return args;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ public ReflectionPackableMethod(

// server
this.responsePack = new WrapResponsePack(serialization, url, serializeName, actualResponseType);
this.requestUnpack = new WrapRequestUnpack(serialization, url, allSerialize, actualRequestTypes);
this.requestUnpack = new WrapRequestUnpack(
serialization, url, allSerialize, actualRequestTypes, method.getGenericParameterTypes());
}
this.allSerialize = allSerialize;
}
Expand Down Expand Up @@ -473,16 +474,20 @@ private class WrapRequestUnpack implements WrapperUnPack {

private final Class<?>[] actualRequestTypes;

private final Type[] genericParameterTypes;

private final Collection<String> allSerialize;

private WrapRequestUnpack(
MultipleSerialization serialization,
URL url,
Collection<String> allSerialize,
Class<?>[] actualRequestTypes) {
Class<?>[] actualRequestTypes,
Type[] genericParameterTypes) {
this.serialization = serialization;
this.url = url;
this.actualRequestTypes = actualRequestTypes;
this.genericParameterTypes = genericParameterTypes;
this.allSerialize = allSerialize;
}

Expand Down Expand Up @@ -510,7 +515,14 @@ private Object[] deserializeFromWrapper(TripleCustomerProtocolWrapper.TripleRequ
for (int i = 0; i < wrapper.getArgs().size(); i++) {
ByteArrayInputStream bais =
new ByteArrayInputStream(wrapper.getArgs().get(i));
ret[i] = serialization.deserialize(url, wrapper.getSerializeType(), actualRequestTypes[i], bais);
if (genericParameterTypes != null
&& i < genericParameterTypes.length
&& genericParameterTypes[i] != actualRequestTypes[i]) {
ret[i] = serialization.deserialize(
url, wrapper.getSerializeType(), actualRequestTypes[i], genericParameterTypes[i], bais);
} else {
ret[i] = serialization.deserialize(url, wrapper.getSerializeType(), actualRequestTypes[i], bais);
}
}
return ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;

public class DefaultMultipleSerialization implements MultipleSerialization {

Expand All @@ -46,6 +47,17 @@ public Object deserialize(URL url, String serializeType, Class<?> clz, InputStre
return in.readObject(clz);
}

@Override
public Object deserialize(URL url, String serializeType, Class<?> clz, Type type, InputStream os)
throws IOException, ClassNotFoundException {
serializeType = convertHessian(serializeType);
final Serialization serialization = url.getOrDefaultFrameworkModel()
.getExtensionLoader(Serialization.class)
.getExtension(serializeType);
final ObjectInput in = serialization.deserialize(null, os);
return in.readObject(clz, type);
}

private String convertHessian(String ser) {
if (ser.equals("hessian4")) {
return "hessian2";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;

@SPI(scope = ExtensionScope.FRAMEWORK)
public interface MultipleSerialization {
Expand All @@ -31,4 +32,9 @@ public interface MultipleSerialization {

Object deserialize(URL url, String serializeType, Class<?> clz, InputStream os)
throws IOException, ClassNotFoundException;

default Object deserialize(URL url, String serializeType, Class<?> clz, Type type, InputStream os)
throws IOException, ClassNotFoundException {
return deserialize(url, serializeType, clz, os);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Objects;

Expand Down Expand Up @@ -119,16 +120,43 @@ public <T> T readObject(Class<T> cls) throws IOException, ClassNotFoundException
}

@Override
@SuppressWarnings("unchecked")
public <T> T readObject(Class<T> cls, Type type) throws IOException, ClassNotFoundException {
if (!Objects.equals(
mH2i.getSerializerFactory().getClassLoader(),
Thread.currentThread().getContextClassLoader())) {
mH2i.setSerializerFactory(hessian2FactoryManager.getSerializerFactory(
Thread.currentThread().getContextClassLoader()));
}
if (type instanceof ParameterizedType) {
Type[] typeArgs = ((ParameterizedType) type).getActualTypeArguments();
Class<?>[] expectedTypes = new Class<?>[typeArgs.length];
boolean hasExpectedType = false;
for (int i = 0; i < typeArgs.length; i++) {
if (typeArgs[i] instanceof Class && isPrimitive((Class<?>) typeArgs[i])) {
expectedTypes[i] = (Class<?>) typeArgs[i];
hasExpectedType = true;
}
}
if (hasExpectedType) {
return (T) mH2i.readObject(cls, expectedTypes);
}
}
return readObject(cls);
}

private static boolean isPrimitive(Class<?> type) {
return type.isPrimitive()
|| type == Boolean.class
|| type == Character.class
|| type == Byte.class
|| type == Short.class
|| type == Integer.class
|| type == Long.class
|| type == Float.class
|| type == Double.class;
}

public InputStream readInputStream() throws IOException {
return mH2i.readInputStream();
}
Expand Down
Loading
Loading