Browse Source

Only process RPC invocation if there's a handler for it (#10134)

* RpcManagers lookup by String instead of Class to avoid loading the
class sent by the client
* Some generics tightened to only accept ServerRpc instances
* Remove RpcTarget as it is only supported for ClientConnector

Change-Id: I264d58f373db7ea3258cbc28dfc0fa1ec952723d
tags/7.0.0.beta10
Leif Åstrand 11 years ago
parent
commit
d0d84ec68f

+ 8
- 16
server/src/com/vaadin/server/AbstractClientConnector.java View File

@@ -55,10 +55,10 @@ import com.vaadin.ui.UI;
public abstract class AbstractClientConnector implements ClientConnector,
MethodEventSource {
/**
* A map from client to server RPC interface class to the RPC call manager
* that handles incoming RPC calls for that interface.
* A map from client to server RPC interface class name to the RPC call
* manager that handles incoming RPC calls for that interface.
*/
private Map<Class<?>, RpcManager> rpcManagerMap = new HashMap<Class<?>, RpcManager>();
private Map<String, RpcManager> rpcManagerMap = new HashMap<String, RpcManager>();

/**
* A map from server to client RPC interface class to the RPC proxy that
@@ -122,8 +122,9 @@ public abstract class AbstractClientConnector implements ClientConnector,
* RPC interface class for which the implementation should be
* registered
*/
protected <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) {
rpcManagerMap.put(rpcInterfaceType, new ServerRpcManager<T>(
protected <T extends ServerRpc> void registerRpc(T implementation,
Class<T> rpcInterfaceType) {
rpcManagerMap.put(rpcInterfaceType.getName(), new ServerRpcManager<T>(
implementation, rpcInterfaceType));
}

@@ -333,18 +334,9 @@ public abstract class AbstractClientConnector implements ClientConnector,
requestRepaint();
}

/**
* @see RpcTarget#getRpcManager(Class)
*
* @param rpcInterface
* RPC interface for which a call was made
* @return RPC Manager handling calls for the interface
*
* @since 7.0
*/
@Override
public RpcManager getRpcManager(Class<?> rpcInterface) {
return rpcManagerMap.get(rpcInterface);
public RpcManager getRpcManager(String rpcInterfaceName) {
return rpcManagerMap.get(rpcInterfaceName);
}

@Override

+ 36
- 14
server/src/com/vaadin/server/AbstractCommunicationManager.java View File

@@ -75,6 +75,7 @@ import com.vaadin.shared.JavaScriptConnectorState;
import com.vaadin.shared.Version;
import com.vaadin.shared.communication.LegacyChangeVariablesInvocation;
import com.vaadin.shared.communication.MethodInvocation;
import com.vaadin.shared.communication.ServerRpc;
import com.vaadin.shared.communication.SharedState;
import com.vaadin.shared.communication.UidlValue;
import com.vaadin.shared.ui.ui.UIConstants;
@@ -1662,17 +1663,6 @@ public abstract class AbstractCommunicationManager implements Serializable {
final ClientConnector connector = getConnector(uI,
invocation.getConnectorId());

if (connector == null) {
getLogger().log(
Level.WARNING,
"RPC call to " + invocation.getInterfaceName()
+ "." + invocation.getMethodName()
+ " received for connector "
+ invocation.getConnectorId()
+ " but no such connector could be found");
continue;
}

if (!enabledConnectors.contains(connector)) {

if (invocation instanceof LegacyChangeVariablesInvocation) {
@@ -1790,8 +1780,9 @@ public abstract class AbstractCommunicationManager implements Serializable {
MethodInvocation invocation = parseInvocation(invocationJson,
previousInvocation, connectorTracker);
if (invocation != null) {
// Can be null iff the invocation was a legacy invocation and it
// was merged with the previous one
// Can be null if the invocation was a legacy invocation and it
// was merged with the previous one or if the invocation was
// rejected because of an error.
invocations.add(invocation);
previousInvocation = invocation;
}
@@ -1806,6 +1797,15 @@ public abstract class AbstractCommunicationManager implements Serializable {
String interfaceName = invocationJson.getString(1);
String methodName = invocationJson.getString(2);

if (connectorTracker.getConnector(connectorId) == null) {
getLogger().log(
Level.WARNING,
"RPC call to " + interfaceName + "." + methodName
+ " received for connector " + connectorId
+ " but no such connector could be found");
return null;
}

JSONArray parametersJson = invocationJson.getJSONArray(3);

if (LegacyChangeVariablesInvocation.isLegacyVariableChange(
@@ -1855,8 +1855,30 @@ public abstract class AbstractCommunicationManager implements Serializable {
String connectorId, String interfaceName, String methodName,
JSONArray parametersJson, ConnectorTracker connectorTracker)
throws JSONException {
ClientConnector connector = connectorTracker.getConnector(connectorId);

RpcManager rpcManager = connector.getRpcManager(interfaceName);
if (!(rpcManager instanceof ServerRpcManager)) {
/*
* Security: Don't even decode the json parameters if no RpcManager
* corresponding to the received method invocation has been
* registered.
*/
getLogger().warning(
"Ignoring RPC call to " + interfaceName + "." + methodName
+ " in connector " + connector.getClass().getName()
+ "(" + connectorId
+ ") as no RPC implementation is regsitered");
return null;
}

// Use interface from RpcManager instead of loading the class based on
// the string name to avoid problems with OSGi
Class<? extends ServerRpc> rpcInterface = ((ServerRpcManager<?>) rpcManager)
.getRpcInterface();

ServerRpcMethodInvocation invocation = new ServerRpcMethodInvocation(
connectorId, interfaceName, methodName, parametersJson.length());
connectorId, rpcInterface, methodName, parametersJson.length());

Object[] parameters = new Object[parametersJson.length()];
Type[] declaredRpcMethodParameterTypes = invocation.getMethod()

+ 3
- 1
server/src/com/vaadin/server/AbstractJavaScriptExtension.java View File

@@ -17,6 +17,7 @@
package com.vaadin.server;

import com.vaadin.shared.JavaScriptExtensionState;
import com.vaadin.shared.communication.ServerRpc;
import com.vaadin.ui.JavaScriptFunction;

/**
@@ -125,7 +126,8 @@ public abstract class AbstractJavaScriptExtension extends AbstractExtension {
this);

@Override
protected <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) {
protected <T extends ServerRpc> void registerRpc(T implementation,
Class<T> rpcInterfaceType) {
super.registerRpc(implementation, rpcInterfaceType);
callbackHelper.registerRpc(rpcInterfaceType);
}

+ 11
- 1
server/src/com/vaadin/server/ClientConnector.java View File

@@ -36,7 +36,7 @@ import com.vaadin.ui.UI;
* @since 7.0.0
*
*/
public interface ClientConnector extends Connector, RpcTarget {
public interface ClientConnector extends Connector {
/**
* Returns the list of pending server to client RPC calls and clears the
* list.
@@ -239,4 +239,14 @@ public interface ClientConnector extends Connector, RpcTarget {
*/
public boolean handleConnectorRequest(VaadinRequest request,
VaadinResponse response, String path) throws IOException;

/**
* Returns the RPC manager instance to use when receiving calls for an RPC
* interface.
*
* @param rpcInterfaceName
* name of the interface for which the call was made
* @return RpcManager or null if none found for the interface
*/
public RpcManager getRpcManager(String rpcInterfaceName);
}

+ 1
- 1
server/src/com/vaadin/server/DragAndDropService.java View File

@@ -252,7 +252,7 @@ public class DragAndDropService implements VariableOwner, ClientConnector {
}

@Override
public RpcManager getRpcManager(Class<?> rpcInterface) {
public RpcManager getRpcManager(String interfaceName) {
// TODO Use rpc for drag'n'drop
return null;
}

+ 0
- 38
server/src/com/vaadin/server/RpcTarget.java View File

@@ -1,38 +0,0 @@
/*
* Copyright 2011 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 java.io.Serializable;

/**
* Marker interface for server side classes that can receive RPC calls.
*
* This plays a role similar to that of {@link VariableOwner}.
*
* @since 7.0
*/
public interface RpcTarget extends Serializable {
/**
* Returns the RPC manager instance to use when receiving calls for an RPC
* interface.
*
* @param rpcInterface
* interface for which the call was made
* @return RpcManager or null if none found for the interface
*/
public RpcManager getRpcManager(Class<?> rpcInterface);
}

+ 5
- 4
server/src/com/vaadin/server/ServerRpcManager.java View File

@@ -24,6 +24,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;

import com.vaadin.shared.Connector;
import com.vaadin.shared.communication.ServerRpc;

/**
* Server side RPC manager that handles RPC calls coming from the client.
@@ -34,7 +35,7 @@ import com.vaadin.shared.Connector;
*
* @since 7.0
*/
public class ServerRpcManager<T> implements RpcManager {
public class ServerRpcManager<T extends ServerRpc> implements RpcManager {

private final T implementation;
private final Class<T> rpcInterface;
@@ -80,10 +81,10 @@ public class ServerRpcManager<T> implements RpcManager {
* method invocation to perform
* @throws RpcInvocationException
*/
public static void applyInvocation(RpcTarget target,
public static void applyInvocation(ClientConnector target,
ServerRpcMethodInvocation invocation) throws RpcInvocationException {
RpcManager manager = target.getRpcManager(invocation
.getInterfaceClass());
RpcManager manager = target
.getRpcManager(invocation.getInterfaceName());
if (manager != null) {
manager.applyInvocation(invocation);
} else {

+ 8
- 21
server/src/com/vaadin/server/ServerRpcMethodInvocation.java View File

@@ -29,33 +29,20 @@ public class ServerRpcMethodInvocation extends MethodInvocation {

private final Method method;

private Class<? extends ServerRpc> interfaceClass;
private final Class<? extends ServerRpc> interfaceClass;

public ServerRpcMethodInvocation(String connectorId, String interfaceName,
String methodName, int parameterCount) {
super(connectorId, interfaceName, methodName);
public ServerRpcMethodInvocation(String connectorId,
Class<? extends ServerRpc> interfaceClass, String methodName,
int parameterCount) {
super(connectorId, interfaceClass.getName(), methodName);

assert ServerRpc.class.isAssignableFrom(interfaceClass);
this.interfaceClass = interfaceClass;

interfaceClass = findClass();
method = findInvocationMethod(interfaceClass, methodName,
parameterCount);
}

private Class<? extends ServerRpc> findClass() {
try {
Class<?> rpcInterface = Class.forName(getInterfaceName());
if (!ServerRpc.class.isAssignableFrom(rpcInterface)) {
throw new IllegalArgumentException("The interface "
+ getInterfaceName() + "is not a server RPC interface.");
}
return (Class<? extends ServerRpc>) rpcInterface;
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("The server RPC interface "
+ getInterfaceName() + " could not be found", e);
} finally {

}
}

public Class<? extends ServerRpc> getInterfaceClass() {
return interfaceClass;
}

+ 3
- 1
server/src/com/vaadin/ui/AbstractJavaScriptComponent.java View File

@@ -16,6 +16,7 @@
package com.vaadin.ui;

import com.vaadin.server.JavaScriptCallbackHelper;
import com.vaadin.shared.communication.ServerRpc;
import com.vaadin.shared.ui.JavaScriptComponentState;

/**
@@ -128,7 +129,8 @@ public abstract class AbstractJavaScriptComponent extends AbstractComponent {
this);

@Override
protected <T> void registerRpc(T implementation, Class<T> rpcInterfaceType) {
protected <T extends ServerRpc> void registerRpc(T implementation,
Class<T> rpcInterfaceType) {
super.registerRpc(implementation, rpcInterfaceType);
callbackHelper.registerRpc(rpcInterfaceType);
}

Loading…
Cancel
Save