com.vaadin.server.ServerRpcManager Maven / Gradle / Ivy
/*
* Copyright (C) 2000-2024 Vaadin Ltd
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See for the full
* license.
*/
package com.vaadin.server;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.vaadin.shared.communication.ServerRpc;
/**
* Server side RPC manager that handles RPC calls coming from the client.
*
* Each RPC target (typically a {@link ClientConnector}) should have its
* own instance of {@link ServerRpcManager} if it wants to receive RPC calls
* from the client.
*
* @since 7.0
*/
public class ServerRpcManager implements Serializable {
private final T implementation;
private final Class rpcInterface;
/**
* Wrapper exception for exceptions which occur during invocation of an RPC
* call.
*
* @author Vaadin Ltd
* @since 7.0
*
*/
public static class RpcInvocationException extends Exception {
public RpcInvocationException() {
super();
}
public RpcInvocationException(String message, Throwable cause) {
super(message, cause);
}
public RpcInvocationException(String message) {
super(message);
}
public RpcInvocationException(Throwable cause) {
super(cause);
}
}
private static final Map, Class>> BOXED_TYPES = new HashMap<>();
static {
try {
Class>[] boxClasses = new Class>[] { Boolean.class, Byte.class,
Short.class, Character.class, Integer.class, Long.class,
Float.class, Double.class };
for (Class> boxClass : boxClasses) {
Field typeField = boxClass.getField("TYPE");
Class> primitiveType = (Class>) typeField.get(boxClass);
BOXED_TYPES.put(primitiveType, boxClass);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Create a RPC manager for an RPC target.
*
* @param implementation
* RPC interface implementation for the target
* @param rpcInterface
* RPC interface type
*/
public ServerRpcManager(T implementation, Class rpcInterface) {
this.implementation = implementation;
this.rpcInterface = rpcInterface;
}
/**
* Invoke a method in a server side RPC target class. This method is to be
* used by the RPC framework and unit testing tools only.
*
* @param target
* non-null target of the RPC call
* @param invocation
* method invocation to perform
* @throws RpcInvocationException
*/
public static void applyInvocation(ClientConnector target,
ServerRpcMethodInvocation invocation)
throws RpcInvocationException {
ServerRpcManager> manager = target
.getRpcManager(invocation.getInterfaceName());
if (manager != null) {
manager.applyInvocation(invocation);
} else {
getLogger().log(Level.WARNING,
"RPC call received for RpcTarget {0} ({1}) but the target has not registered any RPC interfaces",
new Object[] { target.getClass().getName(),
invocation.getConnectorId() });
}
}
/**
* Returns the RPC interface implementation for the RPC target.
*
* @return RPC interface implementation
*/
protected T getImplementation() {
return implementation;
}
/**
* Returns the RPC interface type managed by this RPC manager instance.
*
* @return RPC interface type
*/
public Class getRpcInterface() {
return rpcInterface;
}
/**
* Invoke a method in a server side RPC target class. This method is to be
* used by the RPC framework and unit testing tools only.
*
* @param invocation
* method invocation to perform
*/
public void applyInvocation(ServerRpcMethodInvocation invocation)
throws RpcInvocationException {
Method method = invocation.getMethod();
Object[] arguments = invocation.getParameters();
try {
method.invoke(implementation, arguments);
} catch (Exception e) {
throw new RpcInvocationException(
"Unable to invoke method " + invocation.getMethodName()
+ " in " + invocation.getInterfaceName(),
e);
}
}
private static Logger getLogger() {
return Logger.getLogger(ServerRpcManager.class.getName());
}
/**
* Returns an RPC proxy for a given client to server RPC interface for the
* given component or extension.
*
* @param connector
* the connector for which to the RPC proxy
* @param rpcInterface
* the RPC interface type
*
* @return a server RPC handler which can be used to invoke RPC methods
* @since 8.0
*/
public static T getRpcProxy(ClientConnector connector,
final Class rpcInterface) {
@SuppressWarnings("unchecked")
ServerRpcManager rpcManager = (ServerRpcManager) connector
.getRpcManager(rpcInterface.getName());
if (rpcManager == null) {
return null;
}
return rpcManager.getImplementation();
}
}