Skip to content

Commit d32ff60

Browse files
kexianjunbeiwei30
authored andcommitted
[Dubbo-2766]Fix 2766 and enhance the invoke command (#2801)
* add getter and setter for ServiceConfig's interfaceName property#2353 * add interfaceName to ignoreAttributeNames and change the unit test * delete the demo source code and update the unit test * unchange ServiceConfig * update unit test * update unit test * fix #2798 and enhance invoke command
1 parent acfc86f commit d32ff60

File tree

5 files changed

+137
-11
lines changed

5 files changed

+137
-11
lines changed

dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/support/command/HelpTelnetHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ public String telnet(Channel channel, String message) {
5959
Help help = handler.getClass().getAnnotation(Help.class);
6060
List<String> row = new ArrayList<String>();
6161
String parameter = " " + extensionLoader.getExtensionName(handler) + " " + (help != null ? help.parameter().replace("\r\n", " ").replace("\n", " ") : "");
62-
row.add(parameter.length() > 50 ? parameter.substring(0, 50) + "..." : parameter);
62+
row.add(parameter.length() > 55 ? parameter.substring(0, 55) + "..." : parameter);
6363
String summary = help != null ? help.summary().replace("\r\n", " ").replace("\n", " ") : "";
64-
row.add(summary.length() > 50 ? summary.substring(0, 50) + "..." : summary);
64+
row.add(summary.length() > 55 ? summary.substring(0, 55) + "..." : summary);
6565
table.add(row);
6666
}
6767
}

dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@
3030
import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;
3131

3232
import com.alibaba.fastjson.JSON;
33+
import com.alibaba.fastjson.JSONObject;
3334

3435
import java.lang.reflect.Method;
36+
import java.util.ArrayList;
3537
import java.util.Collection;
3638
import java.util.List;
3739
import java.util.Map;
@@ -40,28 +42,32 @@
4042
* InvokeTelnetHandler
4143
*/
4244
@Activate
43-
@Help(parameter = "[service.]method(args)", summary = "Invoke the service method.", detail = "Invoke the service method.")
45+
@Help(parameter = "[service.]method(args) [-p parameter classes]", summary = "Invoke the service method.", detail = "Invoke the service method.")
4446
public class InvokeTelnetHandler implements TelnetHandler {
4547

46-
private static Method findMethod(Exporter<?> exporter, String method, List<Object> args) {
48+
private static Method findMethod(Exporter<?> exporter, String method, List<Object> args, Class<?>[] paramClases) {
4749
Invoker<?> invoker = exporter.getInvoker();
4850
Method[] methods = invoker.getInterface().getMethods();
4951
for (Method m : methods) {
50-
if (m.getName().equals(method) && isMatch(m.getParameterTypes(), args)) {
52+
if (m.getName().equals(method) && isMatch(m.getParameterTypes(), args, paramClases)) {
5153
return m;
5254
}
5355
}
5456
return null;
5557
}
5658

57-
private static boolean isMatch(Class<?>[] types, List<Object> args) {
59+
private static boolean isMatch(Class<?>[] types, List<Object> args, Class<?>[] paramClasses) {
5860
if (types.length != args.size()) {
5961
return false;
6062
}
6163
for (int i = 0; i < types.length; i++) {
6264
Class<?> type = types[i];
6365
Object arg = args.get(i);
6466

67+
if (paramClasses != null && type != paramClasses[i]) {
68+
return false;
69+
}
70+
6571
if (arg == null) {
6672
// if the type is primitive, the method to invoke will cause NullPointerException definitely
6773
// so we can offer a specified error message to the invoker in advance and avoid unnecessary invoking
@@ -83,8 +89,8 @@ private static boolean isMatch(Class<?>[] types, List<Object> args) {
8389
if (!ReflectUtils.isPrimitive(type)) {
8490
return false;
8591
}
86-
Class<?> boxedType = ReflectUtils.getBoxedClass(type);
87-
if (boxedType != arg.getClass()) {
92+
93+
if (!ReflectUtils.isCompatible(type, arg)) {
8894
return false;
8995
}
9096
} else if (arg instanceof Map) {
@@ -121,6 +127,26 @@ public String telnet(Channel channel, String message) {
121127
buf.append("Use default service " + service + ".\r\n");
122128
}
123129
int i = message.indexOf("(");
130+
String originalMessage = message;
131+
Class<?>[] paramClasses = null;
132+
if (message.contains("-p")) {
133+
message = originalMessage.substring(0, originalMessage.indexOf("-p")).trim();
134+
String paramClassesString = originalMessage.substring(originalMessage.indexOf("-p") + 2).trim();
135+
if (paramClassesString.length() > 0) {
136+
String[] split = paramClassesString.split("\\s+");
137+
if (split.length > 0) {
138+
paramClasses = new Class[split.length];
139+
for (int j = 0; j < split.length; j++) {
140+
try {
141+
paramClasses[j] = Class.forName(split[j]);
142+
} catch (ClassNotFoundException e) {
143+
return "Unknown parameter class for name " + split[j];
144+
}
145+
}
146+
147+
}
148+
}
149+
}
124150
if (i < 0 || !message.endsWith(")")) {
125151
return "Invalid parameters, format: service.method(args)";
126152
}
@@ -137,11 +163,26 @@ public String telnet(Channel channel, String message) {
137163
} catch (Throwable t) {
138164
return "Invalid json argument, cause: " + t.getMessage();
139165
}
166+
if (paramClasses != null) {
167+
if (paramClasses.length != list.size()) {
168+
return "Parameter's number does not match the number of parameter class";
169+
}
170+
List<Object> listOfActualClass = new ArrayList<>(list.size());
171+
for (int ii = 0; ii < list.size(); ii++) {
172+
if (list.get(ii) instanceof JSONObject) {
173+
JSONObject jsonObject = (JSONObject) list.get(ii);
174+
listOfActualClass.add(jsonObject.toJavaObject(paramClasses[ii]));
175+
} else {
176+
listOfActualClass.add(list.get(ii));
177+
}
178+
}
179+
list = listOfActualClass;
180+
}
140181
Invoker<?> invoker = null;
141182
Method invokeMethod = null;
142183
for (Exporter<?> exporter : DubboProtocol.getDubboProtocol().getExporters()) {
143184
if (service == null || service.length() == 0) {
144-
invokeMethod = findMethod(exporter, method, list);
185+
invokeMethod = findMethod(exporter, method, list, paramClasses);
145186
if (invokeMethod != null) {
146187
invoker = exporter.getInvoker();
147188
break;
@@ -150,7 +191,7 @@ public String telnet(Channel channel, String message) {
150191
if (service.equals(exporter.getInvoker().getInterface().getSimpleName())
151192
|| service.equals(exporter.getInvoker().getInterface().getName())
152193
|| service.equals(exporter.getInvoker().getUrl().getPath())) {
153-
invokeMethod = findMethod(exporter, method, list);
194+
invokeMethod = findMethod(exporter, method, list, paramClasses);
154195
invoker = exporter.getInvoker();
155196
break;
156197
}
@@ -179,5 +220,4 @@ public String telnet(Channel channel, String message) {
179220
}
180221
return buf.toString();
181222
}
182-
183223
}

dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,8 @@ public interface DemoService {
5959

6060
long add(int a, long b);
6161

62+
int getPerson(Person person);
63+
64+
int getPerson(Person person1, Person perso2);
65+
6266
}

dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/DemoServiceImpl.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,14 @@ public long add(int a, long b) {
107107
return a + b;
108108
}
109109

110+
@Override
111+
public int getPerson(Person person) {
112+
return 1;
113+
}
114+
115+
@Override
116+
public int getPerson(Person person1, Person perso2) {
117+
return 2;
118+
}
119+
110120
}

dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,78 @@ public void testInvokeByPassingEnumValue() throws RemotingException {
125125
}
126126

127127

128+
@SuppressWarnings("unchecked")
129+
@Test
130+
public void testComplexParamWithoutSpecifyParamType() throws RemotingException {
131+
mockInvoker = mock(Invoker.class);
132+
given(mockInvoker.getInterface()).willReturn(DemoService.class);
133+
given(mockInvoker.getUrl()).willReturn(URL.valueOf("dubbo://127.0.0.1:20886/demo"));
134+
given(mockInvoker.invoke(any(Invocation.class))).willReturn(new RpcResult("ok"));
135+
mockChannel = mock(Channel.class);
136+
given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
137+
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
138+
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
139+
140+
DubboProtocol.getDubboProtocol().export(mockInvoker);
141+
142+
// pass json value to parameter of Person type
143+
144+
String result = invoke.telnet(mockChannel, "DemoService.getPerson({\"name\":\"zhangsan\",\"age\":12})");
145+
assertTrue(result.contains("No such method getPerson in service DemoService"));
146+
}
147+
148+
@SuppressWarnings("unchecked")
149+
@Test
150+
public void testComplexParamSpecifyParamType() throws RemotingException {
151+
mockInvoker = mock(Invoker.class);
152+
given(mockInvoker.getInterface()).willReturn(DemoService.class);
153+
given(mockInvoker.getUrl()).willReturn(URL.valueOf("dubbo://127.0.0.1:20886/demo"));
154+
given(mockInvoker.invoke(any(Invocation.class))).willReturn(new RpcResult("ok"));
155+
mockChannel = mock(Channel.class);
156+
given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
157+
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
158+
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
159+
160+
DubboProtocol.getDubboProtocol().export(mockInvoker);
161+
162+
// pass json value to parameter of Person type and specify it's type
163+
// one parameter with type of Person
164+
String result = invoke.telnet(mockChannel, "DemoService.getPerson({\"name\":\"zhangsan\",\"age\":12}) -p org.apache.dubbo.rpc.protocol.dubbo.support.Person");
165+
assertTrue(result.contains("Use default service org.apache.dubbo.rpc.protocol.dubbo.support.DemoService.\r\n\"ok\"\r\n"));
166+
167+
// two parameter with type of Person
168+
result = invoke.telnet(mockChannel, "DemoService.getPerson({\"name\":\"zhangsan\",\"age\":12},{\"name\":\"lisi\",\"age\":12}) " +
169+
"-p org.apache.dubbo.rpc.protocol.dubbo.support.Person " +
170+
"org.apache.dubbo.rpc.protocol.dubbo.support.Person");
171+
assertTrue(result.contains("Use default service org.apache.dubbo.rpc.protocol.dubbo.support.DemoService.\r\n\"ok\"\r\n"));
172+
}
173+
174+
@SuppressWarnings("unchecked")
175+
@Test
176+
public void testComplexParamSpecifyWrongParamType() throws RemotingException {
177+
mockInvoker = mock(Invoker.class);
178+
given(mockInvoker.getInterface()).willReturn(DemoService.class);
179+
given(mockInvoker.getUrl()).willReturn(URL.valueOf("dubbo://127.0.0.1:20886/demo"));
180+
given(mockInvoker.invoke(any(Invocation.class))).willReturn(new RpcResult("ok"));
181+
mockChannel = mock(Channel.class);
182+
given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
183+
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
184+
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
185+
186+
DubboProtocol.getDubboProtocol().export(mockInvoker);
187+
188+
// pass json value to parameter of Person type
189+
// wrong name of parameter class
190+
String result = invoke.telnet(mockChannel, "DemoService.getPerson({\"name\":\"zhangsan\",\"age\":12}) -p wrongType");
191+
assertEquals("Unknown parameter class for name wrongType", result);
192+
193+
// wrong number of parameter class
194+
result = invoke.telnet(mockChannel, "DemoService.getPerson({\"name\":\"zhangsan\",\"age\":12},{\"name\":\"lisi\",\"age\":12}) " +
195+
"-p org.apache.dubbo.rpc.protocol.dubbo.support.Person");
196+
assertEquals("Parameter's number does not match the number of parameter class", result);
197+
}
198+
199+
128200
@SuppressWarnings("unchecked")
129201
@Test
130202
public void testInvokeAutoFindMethod() throws RemotingException {

0 commit comments

Comments
 (0)