LI123456mo commented on code in PR #16325:
URL: https://github.com/apache/dubbo/pull/16325#discussion_r3422112275


##########
dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/DescriptorUtils.java:
##########
@@ -99,49 +101,133 @@ public static MethodDescriptor 
findReflectionMethodDescriptor(
                     .get(0);
         } else {
             List<MethodDescriptor> methodDescriptors = 
serviceDescriptor.getMethods(methodName);
-            if (CollectionUtils.isEmpty(methodDescriptors)) {
-                return null;
-            }
-            // In most cases there is only one method
-            if (methodDescriptors.size() == 1) {
-                methodDescriptor = methodDescriptors.get(0);
-            }
-            // generated unary method ,use unary type
-            // Response foo(Request)
-            // void foo(Request,StreamObserver<Response>)
-            if (methodDescriptors.size() == 2) {
-                if (methodDescriptors.get(1).getRpcType() == 
MethodDescriptor.RpcType.SERVER_STREAM) {
-                    methodDescriptor = methodDescriptors.get(0);
-                } else if (methodDescriptors.get(0).getRpcType() == 
MethodDescriptor.RpcType.SERVER_STREAM) {
-                    methodDescriptor = methodDescriptors.get(1);
-                }
-            }
+            methodDescriptor = 
findSingleOrGeneratedUnaryMethodDescriptor(methodDescriptors);
         }
         return methodDescriptor;
     }
 
     public static MethodDescriptor findTripleMethodDescriptor(
             ServiceDescriptor serviceDescriptor, String methodName, 
InputStream rawMessage) throws IOException {
-        MethodDescriptor methodDescriptor = 
findReflectionMethodDescriptor(serviceDescriptor, methodName);
-        if (methodDescriptor == null) {
-            rawMessage.mark(Integer.MAX_VALUE);
-            List<MethodDescriptor> methodDescriptors = 
serviceDescriptor.getMethods(methodName);
-            TripleRequestWrapper request = 
TripleRequestWrapper.parseFrom(rawMessage);
-            String[] paramTypes = request.getArgTypes().toArray(new String[0]);
-            // wrapper mode the method can overload so maybe list
-            for (MethodDescriptor descriptor : methodDescriptors) {
-                // params type is array
-                if (Arrays.equals(descriptor.getCompatibleParamSignatures(), 
paramTypes)) {
-                    methodDescriptor = descriptor;
-                    break;
-                }
+        if (isGeneric(methodName)) {
+            return ServiceDescriptorInternalCache.genericService()
+                    .getMethods(methodName)
+                    .get(0);
+        }
+        if (isEcho(methodName)) {
+            return ServiceDescriptorInternalCache.echoService()
+                    .getMethods(methodName)
+                    .get(0);
+        }
+
+        List<MethodDescriptor> methodDescriptors = 
serviceDescriptor.getMethods(methodName);
+        if (CollectionUtils.isEmpty(methodDescriptors)) {
+            throw new UnimplementedException("method:" + methodName);
+        }
+        if (methodDescriptors.size() == 1) {
+            return methodDescriptors.get(0);
+        }
+
+        TripleRequestWrapper request = parseRequestWrapper(rawMessage);
+        List<String> argTypes = request == null ? null : request.getArgTypes();
+        if (argTypes != null) {
+            MethodDescriptor methodDescriptor =
+                    findMethodDescriptorByParamTypes(methodDescriptors, 
argTypes.toArray(new String[0]));
+            if (methodDescriptor != null) {
+                return methodDescriptor;
             }
-            if (methodDescriptor == null) {
+            if (CollectionUtils.isNotEmpty(argTypes)) {
                 throw new UnimplementedException("method:" + methodName);
             }
+        }
+
+        MethodDescriptor methodDescriptor = 
findGeneratedUnaryMethodDescriptor(methodDescriptors);
+        if (methodDescriptor != null) {
+            return methodDescriptor;
+        }
+        throw new UnimplementedException("method:" + methodName);
+    }
+
+    private static MethodDescriptor findSingleOrGeneratedUnaryMethodDescriptor(
+            List<MethodDescriptor> methodDescriptors) {
+        if (CollectionUtils.isEmpty(methodDescriptors)) {
+            return null;
+        }
+        // In most cases there is only one method
+        if (methodDescriptors.size() == 1) {
+            return methodDescriptors.get(0);
+        }
+        return findGeneratedUnaryMethodDescriptor(methodDescriptors);
+    }
+
+    private static TripleRequestWrapper parseRequestWrapper(InputStream 
rawMessage) throws IOException {
+        rawMessage.mark(Integer.MAX_VALUE);
+        try {
+            return TripleRequestWrapper.parseFrom(rawMessage);
+        } catch (IOException | RuntimeException ignored) {
+            return null;
+        } finally {
             rawMessage.reset();
         }
-        return methodDescriptor;
+    }
+
+    private static MethodDescriptor findMethodDescriptorByParamTypes(
+            List<MethodDescriptor> methodDescriptors, String[] paramTypes) {
+        for (MethodDescriptor descriptor : methodDescriptors) {
+            // wrapper mode the method can overload so maybe list
+            if (Arrays.equals(descriptor.getCompatibleParamSignatures(), 
paramTypes)) {
+                return descriptor;
+            }
+        }
+        return null;
+    }
+
+    private static MethodDescriptor 
findGeneratedUnaryMethodDescriptor(List<MethodDescriptor> methodDescriptors) {
+        // Generated unary methods may expose two Java methods for the same 
RPC:
+        // Response foo(Request)
+        // void foo(Request, StreamObserver<Response>)
+        if (methodDescriptors.size() != 2) {
+            return null;
+        }
+
+        MethodDescriptor unaryMethodDescriptor = null;
+        MethodDescriptor serverStreamMethodDescriptor = null;
+        for (MethodDescriptor descriptor : methodDescriptors) {
+            if (descriptor.getRpcType() == MethodDescriptor.RpcType.UNARY) {
+                unaryMethodDescriptor = descriptor;
+            } else if (descriptor.getRpcType() == 
MethodDescriptor.RpcType.SERVER_STREAM) {
+                serverStreamMethodDescriptor = descriptor;
+            }
+        }
+        if (unaryMethodDescriptor == null || serverStreamMethodDescriptor == 
null) {
+            return null;
+        }
+        if (!Arrays.equals(
+                unaryMethodDescriptor.getParameterClasses(),
+                getServerStreamRequestTypes(serverStreamMethodDescriptor))) {
+            return null;
+        }
+        if (!isSameResponseType(unaryMethodDescriptor, 
serverStreamMethodDescriptor)) {
+            return null;
+        }
+        return unaryMethodDescriptor;
+    }
+
+    private static Class<?>[] getServerStreamRequestTypes(MethodDescriptor 
serverStreamMethodDescriptor) {
+        Class<?>[] parameterClasses = 
serverStreamMethodDescriptor.getParameterClasses();
+        if (parameterClasses.length == 0
+                || 
!StreamObserver.class.isAssignableFrom(parameterClasses[parameterClasses.length 
- 1])) {
+            return null;
+        }
+        return Arrays.copyOf(parameterClasses, parameterClasses.length - 1);
+    }
+
+    private static boolean isSameResponseType(
+            MethodDescriptor unaryMethodDescriptor, MethodDescriptor 
serverStreamMethodDescriptor) {
+        Type[] returnTypes = unaryMethodDescriptor.getReturnTypes();
+        if (returnTypes.length == 0 || !(returnTypes[0] instanceof Class)) {
+            return false;
+        }
+        return returnTypes[0] == 
serverStreamMethodDescriptor.getActualResponseType();

Review Comment:
   Can you check if this changes ca be valid, @skt-shinyruo 
   
   
   Should add: if (serverStreamMethodDescriptor.getActualResponseType() == 
null) return false;
   
   Uses reference equality (==) instead of equals() for Type comparison
   This could fail for wrapped/boxed types or dynamically loaded classes
   Should use .equals() for safer comparison
   
   
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to