diff --git
a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java
b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java
index 61e9902296..2047642f24 100644
---
a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java
+++
b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokeTelnetHandler.java
@@ -17,8 +17,8 @@
package org.apache.dubbo.rpc.protocol.dubbo.telnet;
import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.remoting.Channel;
@@ -42,90 +42,13 @@
* InvokeTelnetHandler
*/
@Activate
-@Help(parameter = "[service.]method(args) [-p parameter classes]", summary =
"Invoke the service method.",
+@Help(parameter = "[service.]method(args) ", summary = "Invoke the service
method.",
detail = "Invoke the service method.")
public class InvokeTelnetHandler implements TelnetHandler {
- private static Method findMethod(List<ProviderMethodModel> methods, String
method, List<Object> args,
- Class<?>[] paramTypes) {
- for (ProviderMethodModel model : methods) {
- Method m = model.getMethod();
- if (isMatch(m, args, paramTypes, method)) {
- return m;
- }
- }
- return null;
- }
-
- private static boolean isMatch(Method method, List<Object> args,
Class<?>[] paramClasses, String lookupMethodName) {
- if (!method.getName().equals(lookupMethodName)) {
- return false;
- }
-
- Class<?> types[] = method.getParameterTypes();
- if (types.length != args.size()) {
- return false;
- }
- for (int i = 0; i < types.length; i++) {
- Class<?> type = types[i];
- Object arg = args.get(i);
-
- if (paramClasses != null && type != paramClasses[i]) {
- return false;
- }
- if (arg == null) {
- // if the type is primitive, the method to invoke will cause
NullPointerException definitely
- // so we can offer a specified error message to the invoker in
advance and avoid unnecessary invoking
- if (type.isPrimitive()) {
- throw new NullPointerException(String.format("The type of
No.%d parameter is primitive(%s), " +
- "but the value passed is null.", i + 1,
type.getName()));
- }
-
- // if the type is not primitive, we choose to believe what the
invoker want is a null value
- continue;
- }
-
- if (ReflectUtils.isPrimitive(arg.getClass())) {
- // allow string arg to enum type, @see PojoUtils.realize0()
- if (arg instanceof String && type.isEnum()) {
- continue;
- }
-
- if (!ReflectUtils.isPrimitive(type)) {
- return false;
- }
-
- if (!ReflectUtils.isCompatible(type, arg)) {
- return false;
- }
- } else if (arg instanceof Map) {
- String name = (String) ((Map<?, ?>) arg).get("class");
- if (StringUtils.isNotEmpty(name)) {
- Class<?> cls = ReflectUtils.forName(name);
- if (!type.isAssignableFrom(cls)) {
- return false;
- }
- } else {
- if (arg instanceof JSONObject) {
- try {
- ((JSONObject) arg).toJavaObject(type);
- } catch (Exception ex) {
- return false;
- }
- }
- }
- } else if (arg instanceof Collection) {
- if (!type.isArray() && !type.isAssignableFrom(arg.getClass()))
{
- return false;
- }
- } else {
- if (!type.isAssignableFrom(arg.getClass())) {
- return false;
- }
- }
- }
- return true;
- }
+ public static final String INVOKE_MESSAGE_KEY =
"telnet.invoke.method.message";
+ public static final String INVOKE_METHOD_LIST_KEY =
"telnet.invoke.method.list";
+ public static final String INVOKE_METHOD_PROVIDER_KEY =
"telnet.invoke.method.provider";
@Override
@SuppressWarnings("unchecked")
@@ -136,33 +59,9 @@ public String telnet(Channel channel, String message) {
"invoke com.xxx.XxxService.xxxMethod(1234, \"abcd\",
{\"prop\" : \"value\"})";
}
- StringBuilder buf = new StringBuilder();
String service = (String)
channel.getAttribute(ChangeTelnetHandler.SERVICE_KEY);
- if (!StringUtils.isEmpty(service)) {
- buf.append("Use default service ").append(service).append(".");
- }
int i = message.indexOf("(");
- String originalMessage = message;
- Class<?>[] paramTypes = null;
- if (message.contains("-p")) {
- message = originalMessage.substring(0,
originalMessage.indexOf("-p")).trim();
- String paramClassesString =
originalMessage.substring(originalMessage.indexOf("-p") + 2).trim();
- if (paramClassesString.length() > 0) {
- String[] split = paramClassesString.split("\\s+");
- if (split.length > 0) {
- paramTypes = new Class[split.length];
- for (int j = 0; j < split.length; j++) {
- try {
- paramTypes[j] = Class.forName(split[j]);
- } catch (ClassNotFoundException e) {
- return "Unknown parameter class for name " +
split[j];
- }
- }
-
- }
- }
- }
if (i < 0 || !message.endsWith(")")) {
return "Invalid parameters, format: service.method(args)";
@@ -182,32 +81,44 @@ public String telnet(Channel channel, String message) {
} catch (Throwable t) {
return "Invalid json argument, cause: " + t.getMessage();
}
- if (paramTypes != null) {
- if (paramTypes.length != list.size()) {
- return "Parameter's number does not match the number of
parameter class";
- }
- List<Object> listOfActualClass = new ArrayList<>(list.size());
- for (int ii = 0; ii < list.size(); ii++) {
- if (list.get(ii) instanceof JSONObject) {
- JSONObject jsonObject = (JSONObject) list.get(ii);
-
listOfActualClass.add(jsonObject.toJavaObject(paramTypes[ii]));
- } else {
- listOfActualClass.add(list.get(ii));
- }
- }
- list = listOfActualClass;
- }
-
+ StringBuilder buf = new StringBuilder();
Method invokeMethod = null;
ProviderModel selectedProvider = null;
- for (ProviderModel provider : ApplicationModel.allProviderModels()) {
- if (isServiceMatch(service, provider)) {
- invokeMethod = findMethod(provider.getAllMethods(), method,
list, paramTypes);
- selectedProvider = provider;
- break;
+ if (isInvokedSelectCommand(channel)) {
+ selectedProvider = (ProviderModel)
channel.getAttribute(INVOKE_METHOD_PROVIDER_KEY);
+ invokeMethod = (Method)
channel.getAttribute(SelectTelnetHandler.SELECT_METHOD_KEY);
+ } else {
+ for (ProviderModel provider :
ApplicationModel.allProviderModels()) {
+ if (isServiceMatch(service, provider)) {
+ selectedProvider = provider;
+ List<Method> methodList =
findSameSignatureMethod(provider.getAllMethods(), method, list);
+ if (CollectionUtils.isNotEmpty(methodList)) {
+ if (methodList.size() == 1) {
+ invokeMethod = methodList.get(0);
+ } else {
+ List<Method> matchMethods =
findMatchMethods(methodList, list);
+ if (CollectionUtils.isNotEmpty(matchMethods)) {
+ if (matchMethods.size() == 1) {
+ invokeMethod = matchMethods.get(0);
+ } else { //exist overridden method
+
channel.setAttribute(INVOKE_METHOD_PROVIDER_KEY, provider);
+
channel.setAttribute(INVOKE_METHOD_LIST_KEY, matchMethods);
+ channel.setAttribute(INVOKE_MESSAGE_KEY,
message);
+ printSelectMessage(buf, matchMethods);
+ return buf.toString();
+ }
+ }
+ }
+ }
+ break;
+ }
}
}
+
+ if (!StringUtils.isEmpty(service)) {
+ buf.append("Use default service ").append(service).append(".");
+ }
if (selectedProvider != null) {
if (invokeMethod != null) {
try {
@@ -240,10 +151,111 @@ public String telnet(Channel channel, String message) {
return buf.toString();
}
+
private boolean isServiceMatch(String service, ProviderModel provider) {
return provider.getServiceName().equalsIgnoreCase(service)
||
provider.getServiceInterfaceClass().getSimpleName().equalsIgnoreCase(service)
||
provider.getServiceInterfaceClass().getName().equalsIgnoreCase(service)
|| StringUtils.isEmpty(service);
}
+
+ private List<Method> findSameSignatureMethod(List<ProviderMethodModel>
methods, String lookupMethodName, List<Object> args) {
+ List<Method> sameSignatureMethods = new ArrayList<>();
+ for (ProviderMethodModel model : methods) {
+ Method method = model.getMethod();
+ if (method.getName().equals(lookupMethodName) &&
method.getParameterTypes().length == args.size()) {
+ sameSignatureMethods.add(method);
+ }
+ }
+ return sameSignatureMethods;
+ }
+
+ private List<Method> findMatchMethods(List<Method> methods, List<Object>
args) {
+ List<Method> matchMethod = new ArrayList<>();
+ for (Method method : methods) {
+ if (isMatch(method, args)) {
+ matchMethod.add(method);
+ }
+ }
+ return matchMethod;
+ }
+
+ private static boolean isMatch(Method method, List<Object> args) {
+ Class<?>[] types = method.getParameterTypes();
+ if (types.length != args.size()) {
+ return false;
+ }
+ for (int i = 0; i < types.length; i++) {
+ Class<?> type = types[i];
+ Object arg = args.get(i);
+
+ if (arg == null) {
+ if (type.isPrimitive()) {
+ return false;
+ }
+
+ // if the type is not primitive, we choose to believe what the
invoker want is a null value
+ continue;
+ }
+
+ if (ReflectUtils.isPrimitive(arg.getClass())) {
+ // allow string arg to enum type, @see PojoUtils.realize0()
+ if (arg instanceof String && type.isEnum()) {
+ continue;
+ }
+
+ if (!ReflectUtils.isPrimitive(type)) {
+ return false;
+ }
+
+ if (!ReflectUtils.isCompatible(type, arg)) {
+ return false;
+ }
+ } else if (arg instanceof Map) {
+ String name = (String) ((Map<?, ?>) arg).get("class");
+ if (StringUtils.isNotEmpty(name)) {
+ Class<?> cls = ReflectUtils.forName(name);
+ if (!type.isAssignableFrom(cls)) {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ } else if (arg instanceof Collection) {
+ if (!type.isArray() && !type.isAssignableFrom(arg.getClass()))
{
+ return false;
+ }
+ } else {
+ if (!type.isAssignableFrom(arg.getClass())) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private void printSelectMessage(StringBuilder buf, List<Method> methods) {
+ buf.append("Methods:\r\n");
+ for (int i = 0; i < methods.size(); i++) {
+ Method method = methods.get(i);
+ buf.append((i + 1) + ". " + method.getName() + "(");
+ Class<?>[] parameterTypes = method.getParameterTypes();
+ for (int n = 0; n < parameterTypes.length; n++) {
+ buf.append(parameterTypes[n].getSimpleName());
+ if (n != parameterTypes.length - 1) {
+ buf.append(",");
+ }
+ }
+ buf.append(")\r\n");
+ }
+ buf.append("Please use the select command to select the method you
want to invoke. eg: select 1");
+ }
+
+ private boolean isInvokedSelectCommand(Channel channel) {
+ if (channel.hasAttribute(SelectTelnetHandler.SELECT_KEY)) {
+ channel.removeAttribute(SelectTelnetHandler.SELECT_KEY);
+ return true;
+ }
+ return false;
+ }
}
diff --git
a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/SelectTelnetHandler.java
b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/SelectTelnetHandler.java
new file mode 100644
index 0000000000..ed76ebb391
--- /dev/null
+++
b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/SelectTelnetHandler.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.protocol.dubbo.telnet;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.remoting.Channel;
+import org.apache.dubbo.remoting.telnet.TelnetHandler;
+import org.apache.dubbo.remoting.telnet.support.Help;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * SelectTelnetHandler
+ */
+@Activate
+@Help(parameter = "[index]", summary = "Select the index of the method you
want to invoke.",
+ detail = "Select the index of the method you want to invoke.")
+public class SelectTelnetHandler implements TelnetHandler {
+ public static final String SELECT_METHOD_KEY = "telnet.select.method";
+ public static final String SELECT_KEY = "telnet.select";
+
+ private InvokeTelnetHandler invokeTelnetHandler = new
InvokeTelnetHandler();
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public String telnet(Channel channel, String message) {
+ if (message == null || message.length() == 0) {
+ return "Please input the index of the method you want to invoke,
eg: \r\n select 1";
+ }
+ List<Method> methodList = (List<Method>)
channel.getAttribute(InvokeTelnetHandler.INVOKE_METHOD_LIST_KEY);
+ if (CollectionUtils.isEmpty(methodList)) {
+ return "Please use the invoke command first.";
+ }
+ if (!StringUtils.isInteger(message) || Integer.parseInt(message) < 1
|| Integer.parseInt(message) > methodList.size()) {
+ return "Illegal index ,please input select 1~" + methodList.size();
+ }
+ Method method = methodList.get(Integer.parseInt(message));
+ channel.setAttribute(SELECT_METHOD_KEY, method);
+ channel.setAttribute(SELECT_KEY, Boolean.TRUE);
+ String invokeMessage = (String)
channel.getAttribute(InvokeTelnetHandler.INVOKE_MESSAGE_KEY);
+ return invokeTelnetHandler.telnet(channel, invokeMessage);
+ }
+}
diff --git
a/dubbo-rpc/dubbo-rpc-dubbo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler
b/dubbo-rpc/dubbo-rpc-dubbo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler
index ad5b55f9e0..ef32515fe7 100644
---
a/dubbo-rpc/dubbo-rpc-dubbo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler
+++
b/dubbo-rpc/dubbo-rpc-dubbo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler
@@ -4,4 +4,5 @@
cd=org.apache.dubbo.rpc.protocol.dubbo.telnet.ChangeTelnetHandler
pwd=org.apache.dubbo.rpc.protocol.dubbo.telnet.CurrentTelnetHandler
invoke=org.apache.dubbo.rpc.protocol.dubbo.telnet.InvokeTelnetHandler
trace=org.apache.dubbo.rpc.protocol.dubbo.telnet.TraceTelnetHandler
-count=org.apache.dubbo.rpc.protocol.dubbo.telnet.CountTelnetHandler
\ No newline at end of file
+count=org.apache.dubbo.rpc.protocol.dubbo.telnet.CountTelnetHandler
+select=org.apache.dubbo.rpc.protocol.dubbo.telnet.SelectTelnetHandler
\ No newline at end of file
diff --git
a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java
b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java
index f1752be8ef..4512d29a6a 100644
---
a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java
+++
b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java
@@ -16,8 +16,10 @@
*/
package org.apache.dubbo.rpc.protocol.dubbo.telnet;
+import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.remoting.Channel;
+import org.apache.dubbo.remoting.ChannelHandler;
import org.apache.dubbo.remoting.RemotingException;
import org.apache.dubbo.remoting.telnet.TelnetHandler;
import org.apache.dubbo.rpc.model.ApplicationModel;
@@ -25,23 +27,27 @@
import org.apache.dubbo.rpc.protocol.dubbo.support.DemoService;
import org.apache.dubbo.rpc.protocol.dubbo.support.DemoServiceImpl;
import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils;
-
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import java.net.InetSocketAddress;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
/**
- * CountTelnetHandlerTest.java
+ * InvokeTelnetHandlerTest.java
*/
public class InvokerTelnetHandlerTest {
private static TelnetHandler invoke = new InvokeTelnetHandler();
+ private static TelnetHandler select = new SelectTelnetHandler();
private Channel mockChannel;
@BeforeEach
@@ -56,176 +62,98 @@ public void after() {
@SuppressWarnings("unchecked")
@Test
- public void testInvokeDefaultSService() throws RemotingException {
+ public void testInvokeDefaultService() throws RemotingException {
mockChannel = mock(Channel.class);
-
given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
+
given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
- ProviderModel providerModel = new
ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new
DemoServiceImpl(), DemoService.class);
-
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService",
providerModel);
+ ProviderModel providerModel = new
ProviderModel(DemoService.class.getName(), new DemoServiceImpl(),
DemoService.class);
+ ApplicationModel.initProviderModel(DemoService.class.getName(),
providerModel);
- String result = invoke.telnet(mockChannel, "DemoService.echo(\"ok\")");
+ String result = invoke.telnet(mockChannel, "echo(\"ok\")");
assertTrue(result.contains("result: \"ok\""));
}
@SuppressWarnings("unchecked")
@Test
- public void testInvokeByPassingNullValue() throws RemotingException {
- mockChannel = mock(Channel.class);
-
given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
-
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
-
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
-
- ProviderModel providerModel = new
ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new
DemoServiceImpl(), DemoService.class);
-
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService",
providerModel);
-
- // pass null value to parameter of primitive type
- try {
- invoke.telnet(mockChannel, "DemoService.add(null, 2)");
- fail("It should cause a NullPointerException by the above code.");
- } catch (NullPointerException ex) {
- String message = ex.getMessage();
- assertEquals("The type of No.1 parameter is primitive(int), but
the value passed is null.", message);
- }
-
- try {
- invoke.telnet(mockChannel, "DemoService.add(1, null)");
- fail("It should cause a NullPointerException by the above code.");
- } catch (NullPointerException ex) {
- String message = ex.getMessage();
- assertEquals("The type of No.2 parameter is primitive(long), but
the value passed is null.", message);
- }
-
- // pass null value to parameter of object type
- try {
- invoke.telnet(mockChannel, "DemoService.sayHello(null)");
- } catch (NullPointerException ex) {
- fail("It shouldn't cause a NullPointerException by the above
code.");
- }
- }
-
- @Test
- public void testInvokeByPassingEnumValue() throws RemotingException {
+ public void testInvokeWithSpecifyService() throws RemotingException {
mockChannel = mock(Channel.class);
given(mockChannel.getAttribute("telnet.service")).willReturn(null);
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
- ProviderModel providerModel = new
ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new
DemoServiceImpl(), DemoService.class);
-
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService",
providerModel);
-
- String result = invoke.telnet(mockChannel, "getType(\"High\")");
- assertTrue(result.contains("result: \"High\""));
- }
-
-
- @SuppressWarnings("unchecked")
- @Test
- public void testComplexParamWithoutSpecifyParamType() throws
RemotingException {
- mockChannel = mock(Channel.class);
-
given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
-
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
-
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
-
- ProviderModel providerModel = new
ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new
DemoServiceImpl(), DemoService.class);
-
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService",
providerModel);
+ ProviderModel providerModel = new
ProviderModel(DemoService.class.getName(), new DemoServiceImpl(),
DemoService.class);
+ ApplicationModel.initProviderModel(DemoService.class.getName(),
providerModel);
- // pass json value to parameter of Person type
-
- String result = invoke.telnet(mockChannel,
"DemoService.getPerson({\"name\":\"zhangsan\",\"age\":12,\"class\":\"org.apache.dubbo.rpc.protocol.dubbo.support.Person\"})");
- assertTrue(result.contains("result: 12"));
+ String result = invoke.telnet(mockChannel, "DemoService.echo(\"ok\")");
+ assertTrue(result.contains("result: \"ok\""));
}
@SuppressWarnings("unchecked")
@Test
- public void testComplexParamSpecifyParamType() throws RemotingException {
+ public void testInvokeByPassingNullValue() {
mockChannel = mock(Channel.class);
-
given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
+
given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
- ProviderModel providerModel = new
ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new
DemoServiceImpl(), DemoService.class);
-
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService",
providerModel);
-
- // pass json value to parameter of Person type and specify it's type
- // one parameter with type of Person
- String result = invoke.telnet(mockChannel,
"DemoService.getPerson({\"name\":\"zhangsan\",\"age\":12}) -p
org.apache.dubbo.rpc.protocol.dubbo.support.Person");
- assertTrue(result.contains("result: 12"));
-
- // two parameter with type of Person
- result = invoke.telnet(mockChannel,
"DemoService.getPerson({\"name\":\"zhangsan\",\"age\":12},{\"name\":\"lisi\",\"age\":12})
" +
- "-p org.apache.dubbo.rpc.protocol.dubbo.support.Person " +
- "org.apache.dubbo.rpc.protocol.dubbo.support.Person");
- assertTrue(result.contains("result: 24"));
+ ProviderModel providerModel = new
ProviderModel(DemoService.class.getName(), new DemoServiceImpl(),
DemoService.class);
+ ApplicationModel.initProviderModel(DemoService.class.getName(),
providerModel);
+ try {
+ invoke.telnet(mockChannel, "sayHello(null)");
+ } catch (Exception ex) {
+ assertTrue(ex instanceof NullPointerException);
+ }
}
- @SuppressWarnings("unchecked")
@Test
- public void testComplexParamSpecifyWrongParamType() throws
RemotingException {
+ public void testInvokeByPassingEnumValue() throws RemotingException {
mockChannel = mock(Channel.class);
-
given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
+ given(mockChannel.getAttribute("telnet.service")).willReturn(null);
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
- ProviderModel providerModel = new
ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new
DemoServiceImpl(), DemoService.class);
-
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService",
providerModel);
-
- // pass json value to parameter of Person type
- // wrong name of parameter class
- String result = invoke.telnet(mockChannel,
"DemoService.getPerson({\"name\":\"zhangsan\",\"age\":12}) -p wrongType");
- assertEquals("Unknown parameter class for name wrongType", result);
+ ProviderModel providerModel = new
ProviderModel(DemoService.class.getName(), new DemoServiceImpl(),
DemoService.class);
+ ApplicationModel.initProviderModel(DemoService.class.getName(),
providerModel);
- // wrong number of parameter class
- result = invoke.telnet(mockChannel,
"DemoService.getPerson({\"name\":\"zhangsan\",\"age\":12},{\"name\":\"lisi\",\"age\":12})
" +
- "-p org.apache.dubbo.rpc.protocol.dubbo.support.Person");
- assertEquals("Parameter's number does not match the number of
parameter class", result);
+ String result = invoke.telnet(mockChannel, "getType(\"High\")");
+ assertTrue(result.contains("result: \"High\""));
}
@SuppressWarnings("unchecked")
@Test
- public void testInvokeAutoFindMethod() throws RemotingException {
+ public void testOverriddenMethodWithSpecifyParamType() throws
RemotingException {
mockChannel = mock(Channel.class);
- given(mockChannel.getAttribute("telnet.service")).willReturn(null);
+
given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
- ProviderModel providerModel = new
ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new
DemoServiceImpl(), DemoService.class);
-
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService",
providerModel);
-
- String result = invoke.telnet(mockChannel, "echo(\"ok\")");
- assertTrue(result.contains("result: \"ok\""));
+ ProviderModel providerModel = new
ProviderModel(DemoService.class.getName(), new DemoServiceImpl(),
DemoService.class);
+ ApplicationModel.initProviderModel(DemoService.class.getName(),
providerModel);
+ String result = invoke.telnet(mockChannel,
"getPerson({\"name\":\"zhangsan\",\"age\":12,\"class\":\"org.apache.dubbo.rpc.protocol.dubbo.support.Person\"})");
+ assertTrue(result.contains("result: 12"));
}
@Test
- public void testInvokeJsonParamMethod() throws RemotingException {
- mockChannel = mock(Channel.class);
- given(mockChannel.getAttribute("telnet.service")).willReturn(null);
+ public void testInvokeOverriddenMethodBySelect() throws RemotingException {
+ //create a real instance to keep the attribute values;
+ mockChannel = spy(getChannelInstance());
+
given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
- ProviderModel providerModel = new
ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new
DemoServiceImpl(), DemoService.class);
-
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService",
providerModel);
+ ProviderModel providerModel = new
ProviderModel(DemoService.class.getName(), new DemoServiceImpl(),
DemoService.class);
+ ApplicationModel.initProviderModel(DemoService.class.getName(),
providerModel);
String param = "{\"name\":\"Dubbo\",\"age\":8}";
String result = invoke.telnet(mockChannel, "getPerson(" + param + ")");
+ assertTrue(result.contains("Please use the select command to select
the method you want to invoke. eg: select 1"));
+ result = select.telnet(mockChannel, "1");
+ //result dependent on method order.
assertTrue(result.contains("result: 8") || result.contains("result:
\"Dubbo\""));
}
- @Test
- public void testInvokeSpecifyTypeJsonParamMethod() throws
RemotingException {
- mockChannel = mock(Channel.class);
- given(mockChannel.getAttribute("telnet.service")).willReturn(null);
-
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
-
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
-
- ProviderModel providerModel = new
ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new
DemoServiceImpl(), DemoService.class);
-
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService",
providerModel);
- String param =
"{\"name\":\"Dubbo\",\"age\":8,\"class\":\"org.apache.dubbo.rpc.protocol.dubbo.support.Man\"}";
- String result = invoke.telnet(mockChannel, "getPerson(" + param + ")");
- assertTrue(result.contains("result: \"Dubbo\""));
- }
-
@Test
public void testInvokeMultiJsonParamMethod() throws RemotingException {
mockChannel = mock(Channel.class);
@@ -233,8 +161,8 @@ public void testInvokeMultiJsonParamMethod() throws
RemotingException {
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
- ProviderModel providerModel = new
ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new
DemoServiceImpl(), DemoService.class);
-
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService",
providerModel);
+ ProviderModel providerModel = new
ProviderModel(DemoService.class.getName(), new DemoServiceImpl(),
DemoService.class);
+ ApplicationModel.initProviderModel(DemoService.class.getName(),
providerModel);
String param =
"{\"name\":\"Dubbo\",\"age\":8},{\"name\":\"Apache\",\"age\":20}";
String result = invoke.telnet(mockChannel, "getPerson(" + param + ")");
assertTrue(result.contains("result: 28"));
@@ -254,8 +182,93 @@ public void testMessageNull() throws RemotingException {
public void testInvalidMessage() throws RemotingException {
mockChannel = mock(Channel.class);
given(mockChannel.getAttribute("telnet.service")).willReturn(null);
-
String result = invoke.telnet(mockChannel, "(");
assertEquals("Invalid parameters, format: service.method(args)",
result);
}
+
+ private Channel getChannelInstance() {
+ return new Channel() {
+ private final Map<String, Object> attributes = new
ConcurrentHashMap<String, Object>();
+
+ @Override
+ public InetSocketAddress getRemoteAddress() {
+ return null;
+ }
+
+ @Override
+ public boolean isConnected() {
+ return false;
+ }
+
+ @Override
+ public boolean hasAttribute(String key) {
+ return attributes.containsKey(key);
+ }
+
+ @Override
+ public Object getAttribute(String key) {
+ return attributes.get(key);
+ }
+
+ @Override
+ public void setAttribute(String key, Object value) {
+ if (value == null) { // The null value unallowed in the
ConcurrentHashMap.
+ attributes.remove(key);
+ } else {
+ attributes.put(key, value);
+ }
+ }
+
+ @Override
+ public void removeAttribute(String key) {
+ attributes.remove(key);
+ }
+
+
+ @Override
+ public URL getUrl() {
+ return null;
+ }
+
+ @Override
+ public ChannelHandler getChannelHandler() {
+ return null;
+ }
+
+ @Override
+ public InetSocketAddress getLocalAddress() {
+ return null;
+ }
+
+ @Override
+ public void send(Object message) throws RemotingException {
+
+ }
+
+ @Override
+ public void send(Object message, boolean sent) throws
RemotingException {
+
+ }
+
+ @Override
+ public void close() {
+
+ }
+
+ @Override
+ public void close(int timeout) {
+
+ }
+
+ @Override
+ public void startClose() {
+
+ }
+
+ @Override
+ public boolean isClosed() {
+ return false;
+ }
+ };
+ }
}
diff --git
a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/SelectTelnetHandlerTest.java
b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/SelectTelnetHandlerTest.java
new file mode 100644
index 0000000000..df8bf470ad
--- /dev/null
+++
b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/SelectTelnetHandlerTest.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.protocol.dubbo.telnet;
+
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.remoting.Channel;
+import org.apache.dubbo.remoting.RemotingException;
+import org.apache.dubbo.remoting.telnet.TelnetHandler;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ProviderModel;
+import org.apache.dubbo.rpc.protocol.dubbo.support.DemoService;
+import org.apache.dubbo.rpc.protocol.dubbo.support.DemoServiceImpl;
+import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
+
+/**
+ * SelectTelnetHandlerTest.java
+ */
+public class SelectTelnetHandlerTest {
+
+ private static TelnetHandler select = new SelectTelnetHandler();
+ private Channel mockChannel;
+ List<Method> methods;
+
+ @BeforeEach
+ public void setup() {
+ String methodName = "getPerson";
+ methods = new ArrayList<>();
+ for (Method method : DemoService.class.getMethods()) {
+ if (method.getName().equals(methodName)) {
+ methods.add(method);
+ }
+ }
+
+ ApplicationModel.reset();
+ }
+
+ @AfterEach
+ public void after() {
+ ProtocolUtils.closeAll();
+ }
+
+ @Test
+ public void testInvokeWithoutMethodList() throws RemotingException {
+ mockChannel = mock(Channel.class);
+
given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
+
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
+
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
+
+ ProviderModel providerModel = new
ProviderModel(DemoService.class.getName(), new DemoServiceImpl(),
DemoService.class);
+ ApplicationModel.initProviderModel(DemoService.class.getName(),
providerModel);
+
+ String result = select.telnet(mockChannel, "1");
+ assertTrue(result.contains("Please use the invoke command first."));
+ }
+
+ @Test
+ public void testInvokeWithIllegalMessage() throws RemotingException {
+ mockChannel = mock(Channel.class);
+
given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
+
given(mockChannel.getAttribute(InvokeTelnetHandler.INVOKE_METHOD_LIST_KEY)).willReturn(methods);
+
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
+
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
+
+ ProviderModel providerModel = new
ProviderModel(DemoService.class.getName(), new DemoServiceImpl(),
DemoService.class);
+ ApplicationModel.initProviderModel(DemoService.class.getName(),
providerModel);
+
+ String result = select.telnet(mockChannel, "index");
+ assertTrue(result.contains("Illegal index ,please input select 1"));
+
+ result = select.telnet(mockChannel, "0");
+ assertTrue(result.contains("Illegal index ,please input select 1"));
+
+ result = select.telnet(mockChannel, "1000");
+ assertTrue(result.contains("Illegal index ,please input select 1"));
+ }
+
+ @Test
+ public void testInvokeWithNull() throws RemotingException {
+ mockChannel = mock(Channel.class);
+
given(mockChannel.getAttribute("telnet.service")).willReturn(DemoService.class.getName());
+
given(mockChannel.getAttribute(InvokeTelnetHandler.INVOKE_METHOD_LIST_KEY)).willReturn(methods);
+
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
+
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
+
+ ProviderModel providerModel = new
ProviderModel(DemoService.class.getName(), new DemoServiceImpl(),
DemoService.class);
+ ApplicationModel.initProviderModel(DemoService.class.getName(),
providerModel);
+
+ String result = select.telnet(mockChannel, null);
+ assertTrue(result.contains("Please input the index of the method you
want to invoke"));
+ }
+}
With regards,
Apache Git Services