Browse Source

Less restrictive RPC interface detection in registerRpc (#10945)

Change-Id: I664740523b35b64b0fd0c4fdc21597a2245537cd
tags/7.5.0.beta2
vandeti 9 years ago
parent
commit
fdd6a9d9d0

+ 29
- 11
server/src/com/vaadin/server/AbstractClientConnector.java View 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;
}

/**

+ 112
- 0
server/tests/src/com/vaadin/server/AbstractClientConnectorTest.java View File

@@ -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) {

}

}

}

Loading…
Cancel
Save