aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvandeti <tvanderwee@gmail.com>2015-04-04 14:55:00 +0200
committerVaadin Code Review <review@vaadin.com>2015-05-28 12:43:59 +0000
commitfdd6a9d9d00fbb0e94c96226744deab563b1cd63 (patch)
treefee7f9715385723347acca0057b0f8690fb601a9
parent3b7ddf8aa06379a09ff534ae1a89977164937b89 (diff)
downloadvaadin-framework-fdd6a9d9d00fbb0e94c96226744deab563b1cd63.tar.gz
vaadin-framework-fdd6a9d9d00fbb0e94c96226744deab563b1cd63.zip
Less restrictive RPC interface detection in registerRpc (#10945)
Change-Id: I664740523b35b64b0fd0c4fdc21597a2245537cd
-rw-r--r--server/src/com/vaadin/server/AbstractClientConnector.java40
-rw-r--r--server/tests/src/com/vaadin/server/AbstractClientConnectorTest.java112
2 files changed, 141 insertions, 11 deletions
diff --git a/server/src/com/vaadin/server/AbstractClientConnector.java b/server/src/com/vaadin/server/AbstractClientConnector.java
index 87b61c9623..0655b482ed 100644
--- a/server/src/com/vaadin/server/AbstractClientConnector.java
+++ b/server/src/com/vaadin/server/AbstractClientConnector.java
@@ -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
index 0000000000..96ca82a0b3
--- /dev/null
+++ b/server/tests/src/com/vaadin/server/AbstractClientConnectorTest.java
@@ -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) {
+
+ }
+
+ }
+
+}