]> source.dussan.org Git - vaadin-framework.git/commitdiff
Only process RPC invocation if there's a handler for it (#10134) 98/298/1
authorLeif Åstrand <leif@vaadin.com>
Tue, 20 Nov 2012 08:44:45 +0000 (10:44 +0200)
committerLeif Åstrand <leif@vaadin.com>
Tue, 20 Nov 2012 08:47:09 +0000 (10:47 +0200)
* 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/src/com/vaadin/server/AbstractClientConnector.java
server/src/com/vaadin/server/AbstractCommunicationManager.java
server/src/com/vaadin/server/AbstractJavaScriptExtension.java
server/src/com/vaadin/server/ClientConnector.java
server/src/com/vaadin/server/DragAndDropService.java
server/src/com/vaadin/server/RpcTarget.java [deleted file]
server/src/com/vaadin/server/ServerRpcManager.java
server/src/com/vaadin/server/ServerRpcMethodInvocation.java
server/src/com/vaadin/ui/AbstractJavaScriptComponent.java

index 2e0b72b08a129c2975a55cc3e71dcc56e8f15510..3762e90d05a2f184bf02fdfefd525b6e1680e613 100644 (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
index 834d7d8a17377f78a8af5d73c5fff498e412b285..0655ad6e740f311034e3d04a6ef84a654188c4a3 100644 (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()
index 1f67631203b3282212762b39a9fc6509a8547b5e..af814e6c19271b8b4187f249e8f7fe39d97a164e 100644 (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);
     }
index b38f2a9037da945dcfaa7f8840df1f2484ef2d29..b46ef58fcd7a7daec61e3eca1f4b5813211d59b0 100644 (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);
 }
index 69ab997b1858d6c297b466db6ea10ff39be9273e..a864f8fb16791f09df9f90001c40622e78e5f063 100644 (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;
     }
diff --git a/server/src/com/vaadin/server/RpcTarget.java b/server/src/com/vaadin/server/RpcTarget.java
deleted file mode 100644 (file)
index c491707..0000000
+++ /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);
-}
index 8ef165e084eb25c26667799922aa6914c37170bf..c063761c7f311448778b87d92041cd3e0bd51339 100644 (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 {
index 761db687bbedcf369bd03996658fbf179b5bfd53..3af58fa351e00adfc8416728bf23326f8af6cad2 100644 (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;
     }
index 47420334d7ea234619a42e5b379896b5519fecdd..91547dc79faadb1d89c17fb757dd93c6a12b4deb 100644 (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);
     }