From d0d84ec68f2b786a39bff36d091c9b256c9e42c3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leif=20=C3=85strand?= Date: Tue, 20 Nov 2012 10:44:45 +0200 Subject: [PATCH] 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 --- .../server/AbstractClientConnector.java | 24 +++------ .../server/AbstractCommunicationManager.java | 50 +++++++++++++------ .../server/AbstractJavaScriptExtension.java | 4 +- .../com/vaadin/server/ClientConnector.java | 12 ++++- .../com/vaadin/server/DragAndDropService.java | 2 +- server/src/com/vaadin/server/RpcTarget.java | 38 -------------- .../com/vaadin/server/ServerRpcManager.java | 9 ++-- .../server/ServerRpcMethodInvocation.java | 29 +++-------- .../ui/AbstractJavaScriptComponent.java | 4 +- 9 files changed, 75 insertions(+), 97 deletions(-) delete mode 100644 server/src/com/vaadin/server/RpcTarget.java diff --git a/server/src/com/vaadin/server/AbstractClientConnector.java b/server/src/com/vaadin/server/AbstractClientConnector.java index 2e0b72b08a..3762e90d05 100644 --- a/server/src/com/vaadin/server/AbstractClientConnector.java +++ b/server/src/com/vaadin/server/AbstractClientConnector.java @@ -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, RpcManager> rpcManagerMap = new HashMap, RpcManager>(); + private Map rpcManagerMap = new HashMap(); /** * 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 void registerRpc(T implementation, Class rpcInterfaceType) { - rpcManagerMap.put(rpcInterfaceType, new ServerRpcManager( + protected void registerRpc(T implementation, + Class rpcInterfaceType) { + rpcManagerMap.put(rpcInterfaceType.getName(), new ServerRpcManager( 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 diff --git a/server/src/com/vaadin/server/AbstractCommunicationManager.java b/server/src/com/vaadin/server/AbstractCommunicationManager.java index 834d7d8a17..0655ad6e74 100644 --- a/server/src/com/vaadin/server/AbstractCommunicationManager.java +++ b/server/src/com/vaadin/server/AbstractCommunicationManager.java @@ -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 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() diff --git a/server/src/com/vaadin/server/AbstractJavaScriptExtension.java b/server/src/com/vaadin/server/AbstractJavaScriptExtension.java index 1f67631203..af814e6c19 100644 --- a/server/src/com/vaadin/server/AbstractJavaScriptExtension.java +++ b/server/src/com/vaadin/server/AbstractJavaScriptExtension.java @@ -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 void registerRpc(T implementation, Class rpcInterfaceType) { + protected void registerRpc(T implementation, + Class rpcInterfaceType) { super.registerRpc(implementation, rpcInterfaceType); callbackHelper.registerRpc(rpcInterfaceType); } diff --git a/server/src/com/vaadin/server/ClientConnector.java b/server/src/com/vaadin/server/ClientConnector.java index b38f2a9037..b46ef58fcd 100644 --- a/server/src/com/vaadin/server/ClientConnector.java +++ b/server/src/com/vaadin/server/ClientConnector.java @@ -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); } diff --git a/server/src/com/vaadin/server/DragAndDropService.java b/server/src/com/vaadin/server/DragAndDropService.java index 69ab997b18..a864f8fb16 100644 --- a/server/src/com/vaadin/server/DragAndDropService.java +++ b/server/src/com/vaadin/server/DragAndDropService.java @@ -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; } diff --git a/server/src/com/vaadin/server/RpcTarget.java b/server/src/com/vaadin/server/RpcTarget.java deleted file mode 100644 index c491707995..0000000000 --- a/server/src/com/vaadin/server/RpcTarget.java +++ /dev/null @@ -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); -} diff --git a/server/src/com/vaadin/server/ServerRpcManager.java b/server/src/com/vaadin/server/ServerRpcManager.java index 8ef165e084..c063761c7f 100644 --- a/server/src/com/vaadin/server/ServerRpcManager.java +++ b/server/src/com/vaadin/server/ServerRpcManager.java @@ -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 implements RpcManager { +public class ServerRpcManager implements RpcManager { private final T implementation; private final Class rpcInterface; @@ -80,10 +81,10 @@ public class ServerRpcManager 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 { diff --git a/server/src/com/vaadin/server/ServerRpcMethodInvocation.java b/server/src/com/vaadin/server/ServerRpcMethodInvocation.java index 761db687bb..3af58fa351 100644 --- a/server/src/com/vaadin/server/ServerRpcMethodInvocation.java +++ b/server/src/com/vaadin/server/ServerRpcMethodInvocation.java @@ -29,33 +29,20 @@ public class ServerRpcMethodInvocation extends MethodInvocation { private final Method method; - private Class interfaceClass; + private final Class interfaceClass; - public ServerRpcMethodInvocation(String connectorId, String interfaceName, - String methodName, int parameterCount) { - super(connectorId, interfaceName, methodName); + public ServerRpcMethodInvocation(String connectorId, + Class 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 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) rpcInterface; - } catch (ClassNotFoundException e) { - throw new IllegalArgumentException("The server RPC interface " - + getInterfaceName() + " could not be found", e); - } finally { - - } - } - public Class getInterfaceClass() { return interfaceClass; } diff --git a/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java b/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java index 47420334d7..91547dc79f 100644 --- a/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java +++ b/server/src/com/vaadin/ui/AbstractJavaScriptComponent.java @@ -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 void registerRpc(T implementation, Class rpcInterfaceType) { + protected void registerRpc(T implementation, + Class rpcInterfaceType) { super.registerRpc(implementation, rpcInterfaceType); callbackHelper.registerRpc(rpcInterfaceType); } -- 2.39.5