]> source.dussan.org Git - vaadin-framework.git/commitdiff
Less restrictive RPC interface detection in registerRpc (#10945)
authorvandeti <tvanderwee@gmail.com>
Sat, 4 Apr 2015 12:55:00 +0000 (14:55 +0200)
committerVaadin Code Review <review@vaadin.com>
Thu, 28 May 2015 12:43:59 +0000 (12:43 +0000)
Change-Id: I664740523b35b64b0fd0c4fdc21597a2245537cd

server/src/com/vaadin/server/AbstractClientConnector.java
server/tests/src/com/vaadin/server/AbstractClientConnectorTest.java [new file with mode: 0644]

index 87b61c96231b8ffcc9842bc7a2ca4e07d92be55e..0655b482edc30325f416e2598f13078831ffc28c 100644 (file)
@@ -180,22 +180,40 @@ public abstract class AbstractClientConnector implements ClientConnector,
      *            RPC interface implementation. Also used to deduce the type.
      */
     protected <T extends ServerRpc> void registerRpc(T implementation) {
+        // Search upwards until an interface is found. It must be found as T
+        // extends ServerRpc
         Class<?> cls = implementation.getClass();
-        Class<?>[] interfaces = cls.getInterfaces();
-        while (interfaces.length == 0) {
-            // Search upwards until an interface is found. It must be found as T
-            // extends ServerRpc
+        Class<ServerRpc> serverRpcClass = getServerRpcInterface(cls);
+
+        while (cls != null && serverRpcClass == null) {
             cls = cls.getSuperclass();
-            interfaces = cls.getInterfaces();
+            serverRpcClass = getServerRpcInterface(cls);
         }
-        if (interfaces.length != 1
-                || !(ServerRpc.class.isAssignableFrom(interfaces[0]))) {
+
+        if (serverRpcClass == null) {
             throw new RuntimeException(
-                    "Use registerRpc(T implementation, Class<T> rpcInterfaceType) if the Rpc implementation implements more than one interface");
+                    "No interface T extends ServerRpc found in the class hierarchy.");
+        }
+
+        registerRpc(implementation, serverRpcClass);
+    }
+
+    @SuppressWarnings("unchecked")
+    private Class<ServerRpc> getServerRpcInterface(Class<?> implementationClass) {
+        Class<ServerRpc> serverRpcClass = null;
+        if (implementationClass != null) {
+            for (Class<?> candidateInterface : implementationClass
+                    .getInterfaces()) {
+                if (ServerRpc.class.isAssignableFrom(candidateInterface)) {
+                    if (serverRpcClass != null) {
+                        throw new RuntimeException(
+                                "Use registerRpc(T implementation, Class<T> rpcInterfaceType) if the Rpc implementation implements more than one interface");
+                    }
+                    serverRpcClass = (Class<ServerRpc>) candidateInterface;
+                }
+            }
         }
-        @SuppressWarnings("unchecked")
-        Class<T> type = (Class<T>) interfaces[0];
-        registerRpc(implementation, type);
+        return serverRpcClass;
     }
 
     /**
diff --git a/server/tests/src/com/vaadin/server/AbstractClientConnectorTest.java b/server/tests/src/com/vaadin/server/AbstractClientConnectorTest.java
new file mode 100644 (file)
index 0000000..96ca82a
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ * 
+ * Licensed 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 com.vaadin.server;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.vaadin.shared.MouseEventDetails;
+import com.vaadin.shared.communication.FieldRpc.BlurServerRpc;
+import com.vaadin.shared.ui.ClickRpc;
+
+/**
+ * We test that AbstractClientConnector has a suitable isThis method which is
+ * needed to correctly perform an equals check between a proxy and it's
+ * underlying instance.
+ * 
+ * @author Vaadin Ltd
+ */
+public class AbstractClientConnectorTest {
+
+    @Test
+    public void registerRPCMultiInterfaceTest() {
+        AbstractClientConnector mock = mock(AbstractClientConnector.class);
+        MultiServerRpcMock implementation = new MultiServerRpcMock();
+        Mockito.doCallRealMethod().when(mock).registerRpc(implementation);
+        try {
+            mock.registerRpc(implementation);
+            Assert.fail("expected exception");
+        } catch (Exception expected) {
+            Assert.assertEquals(
+                    expected.getMessage(),
+                    "Use registerRpc(T implementation, Class<T> rpcInterfaceType) if the Rpc implementation implements more than one interface");
+        }
+    }
+
+    @Test
+    public void registerRPCInterfaceTest() {
+        AbstractClientConnector mock = mock(AbstractClientConnector.class);
+        ServerRpcMock implementation = new ServerRpcMock();
+        Mockito.doCallRealMethod().when(mock).registerRpc(implementation);
+        mock.registerRpc(implementation);
+        verify(mock, times(1)).registerRpc(implementation, ClickRpc.class);
+    }
+
+    @Test
+    public void registerRPCInterfaceLastTest() {
+        AbstractClientConnector mock = mock(AbstractClientConnector.class);
+        ServerRpcLastMock implementation = new ServerRpcLastMock();
+        Mockito.doCallRealMethod().when(mock).registerRpc(implementation);
+        mock.registerRpc(implementation);
+        verify(mock, times(1)).registerRpc(implementation, ClickRpc.class);
+    }
+
+    private class ServerRpcLastMock implements Comparable<ServerRpcLastMock>,
+            ClickRpc {
+        private static final long serialVersionUID = -2822356895755286180L;
+
+        @Override
+        public void click(MouseEventDetails mouseDetails) {
+        }
+
+        @Override
+        public int compareTo(ServerRpcLastMock o) {
+            return 0;
+        }
+
+    }
+
+    private class ServerRpcMock implements ClickRpc {
+        private static final long serialVersionUID = 2822356895755286180L;
+
+        @Override
+        public void click(MouseEventDetails mouseDetails) {
+        }
+
+    }
+
+    private class MultiServerRpcMock implements ClickRpc, BlurServerRpc {
+
+        private static final long serialVersionUID = -7611999715560330373L;
+
+        @Override
+        public void blur() {
+
+        }
+
+        @Override
+        public void click(MouseEventDetails mouseDetails) {
+
+        }
+
+    }
+
+}