* 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: I264d58f373db7ea3258cbc28dfc0fa1ec952723dtags/7.0.0.beta10
@@ -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 |
@@ -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() |
@@ -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); | |||
} |
@@ -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); | |||
} |
@@ -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; | |||
} |
@@ -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); | |||
} |
@@ -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 { |
@@ -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; | |||
} |
@@ -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); | |||
} |