From dc7e238f2dc9ec6c9faad5ab6dcfdab8f2eaae46 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leif=20=C3=85strand?= Date: Thu, 31 May 2012 16:31:26 +0300 Subject: [PATCH] Refactor RpcManager to provide info about parameter types (#8879) This is an intermediate step towards decoding everything received from the server based on its declared type. --- .../terminal/gwt/DefaultWidgetSet.gwt.xml | 4 +- .../GeneratedRpcMethodProvider.java | 20 +++ .../gwt/client/communication/RpcManager.java | 59 +++++++- .../gwt/client/communication/RpcMethod.java | 32 +++++ .../gwt/client/communication/Type.java | 40 ++++++ ... GeneratedRpcMethodProviderGenerator.java} | 129 +++++++++--------- 6 files changed, 217 insertions(+), 67 deletions(-) create mode 100644 src/com/vaadin/terminal/gwt/client/communication/GeneratedRpcMethodProvider.java create mode 100644 src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java create mode 100644 src/com/vaadin/terminal/gwt/client/communication/Type.java rename src/com/vaadin/terminal/gwt/widgetsetutils/{RpcManagerGenerator.java => GeneratedRpcMethodProviderGenerator.java} (60%) diff --git a/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml b/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml index 74dc78d9b8..daa5e9f24d 100644 --- a/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml +++ b/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml @@ -63,9 +63,9 @@ + class="com.vaadin.terminal.gwt.widgetsetutils.GeneratedRpcMethodProviderGenerator"> + class="com.vaadin.terminal.gwt.client.communication.GeneratedRpcMethodProvider" /> getGeneratedRpcMethods(); +} diff --git a/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java b/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java index 302e6eaa55..1d3447687d 100644 --- a/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java +++ b/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java @@ -4,9 +4,13 @@ package com.vaadin.terminal.gwt.client.communication; -import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import com.google.gwt.core.client.GWT; import com.vaadin.terminal.gwt.client.ConnectorMap; +import com.vaadin.terminal.gwt.client.ServerConnector; /** * Client side RPC manager that can invoke methods based on RPC calls received @@ -17,7 +21,21 @@ import com.vaadin.terminal.gwt.client.ConnectorMap; * * @since 7.0 */ -public interface RpcManager extends Serializable { +public class RpcManager { + + private final Map methodMap = new HashMap(); + + public RpcManager() { + GeneratedRpcMethodProvider provider = GWT + .create(GeneratedRpcMethodProvider.class); + Collection methods = provider.getGeneratedRpcMethods(); + for (RpcMethod rpcMethod : methods) { + methodMap.put( + rpcMethod.getInterfaceName() + "." + + rpcMethod.getMethodName(), rpcMethod); + } + } + /** * Perform server to client RPC invocation. * @@ -28,5 +46,40 @@ public interface RpcManager extends Serializable { * connectors referenced in parameters */ public void applyInvocation(MethodInvocation invocation, - ConnectorMap connectorMap); + ConnectorMap connectorMap) { + ServerConnector connector = connectorMap.getConnector(invocation + .getConnectorId()); + String signature = getSignature(invocation); + if (connector == null) { + throw new IllegalStateException("Target connector (" + + invocation.getConnectorId() + ") not found for RCC to " + + signature); + } + + RpcMethod rpcMethod = getRpcMethod(signature); + Collection implementations = connector + .getRpcImplementations(invocation.getInterfaceName()); + for (ClientRpc clientRpc : implementations) { + rpcMethod.applyInvocation(clientRpc, invocation.getParameters()); + } + } + + private RpcMethod getRpcMethod(String signature) { + RpcMethod rpcMethod = methodMap.get(signature); + if (rpcMethod == null) { + throw new IllegalStateException("There is no information about " + + signature + + ". Did you remember to compile the right widgetset?"); + } + return rpcMethod; + } + + private static String getSignature(MethodInvocation invocation) { + return invocation.getInterfaceName() + "." + invocation.getMethodName(); + } + + public Type[] getParameterTypes(MethodInvocation invocation) { + return getRpcMethod(getSignature(invocation)).getParameterTypes(); + } + } diff --git a/src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java b/src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java new file mode 100644 index 0000000000..abdcf73e2c --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java @@ -0,0 +1,32 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.communication; + +public abstract class RpcMethod { + private String interfaceName; + private String methodName; + private Type[] parameterTypes; + + public RpcMethod(String interfaceName, String methodName, + Type... parameterTypes) { + this.interfaceName = interfaceName; + this.methodName = methodName; + this.parameterTypes = parameterTypes; + } + + public String getInterfaceName() { + return interfaceName; + } + + public String getMethodName() { + return methodName; + } + + public Type[] getParameterTypes() { + return parameterTypes; + } + + public abstract void applyInvocation(ClientRpc target, Object... parameters); + +} diff --git a/src/com/vaadin/terminal/gwt/client/communication/Type.java b/src/com/vaadin/terminal/gwt/client/communication/Type.java new file mode 100644 index 0000000000..dc33f760ff --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/communication/Type.java @@ -0,0 +1,40 @@ +/* +@VaadinApache2LicenseForJavaFiles@ + */ +package com.vaadin.terminal.gwt.client.communication; + +public class Type { + private final String baseTypeName; + private final Type[] parameterTypes; + + public Type(String baseTypeName, Type[] parameterTypes) { + this.baseTypeName = baseTypeName; + this.parameterTypes = parameterTypes; + } + + public String getBaseTypeName() { + return baseTypeName; + } + + public Type[] getParameterTypes() { + return parameterTypes; + } + + @Override + public String toString() { + String string = baseTypeName; + if (parameterTypes != null) { + string += '<'; + for (int i = 0; i < parameterTypes.length; i++) { + if (i != 0) { + string += ','; + } + string += parameterTypes[i].toString(); + } + string += '>'; + } + + return string; + } + +} diff --git a/src/com/vaadin/terminal/gwt/widgetsetutils/RpcManagerGenerator.java b/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java similarity index 60% rename from src/com/vaadin/terminal/gwt/widgetsetutils/RpcManagerGenerator.java rename to src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java index 2899061204..f0db4886e4 100644 --- a/src/com/vaadin/terminal/gwt/widgetsetutils/RpcManagerGenerator.java +++ b/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java @@ -16,15 +16,15 @@ import com.google.gwt.core.ext.TreeLogger.Type; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JParameterizedType; import com.google.gwt.core.ext.typeinfo.JType; import com.google.gwt.core.ext.typeinfo.TypeOracle; import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; import com.google.gwt.user.rebind.SourceWriter; -import com.vaadin.terminal.gwt.client.ServerConnector; -import com.vaadin.terminal.gwt.client.ConnectorMap; import com.vaadin.terminal.gwt.client.communication.ClientRpc; -import com.vaadin.terminal.gwt.client.communication.MethodInvocation; +import com.vaadin.terminal.gwt.client.communication.GeneratedRpcMethodProvider; import com.vaadin.terminal.gwt.client.communication.RpcManager; +import com.vaadin.terminal.gwt.client.communication.RpcMethod; /** * GWT generator that creates an implementation for {@link RpcManager} on the @@ -32,7 +32,7 @@ import com.vaadin.terminal.gwt.client.communication.RpcManager; * * @since 7.0 */ -public class RpcManagerGenerator extends Generator { +public class GeneratedRpcMethodProviderGenerator extends Generator { @Override public String generate(TreeLogger logger, GeneratorContext context, @@ -90,12 +90,24 @@ public class RpcManagerGenerator extends Generator { ClassSourceFileComposerFactory composer = null; composer = new ClassSourceFileComposerFactory(packageName, className); composer.addImport("com.google.gwt.core.client.GWT"); - composer.addImplementedInterface(RpcManager.class.getName()); + composer.addImport(RpcMethod.class.getName()); + composer.addImport(ClientRpc.class.getName()); + composer.addImport(com.vaadin.terminal.gwt.client.communication.Type.class + .getName()); + composer.addImplementedInterface(GeneratedRpcMethodProvider.class + .getName()); SourceWriter sourceWriter = composer.createSourceWriter(context, printWriter); sourceWriter.indent(); - List rpcInterfaces = new ArrayList(); + List rpcMethods = new ArrayList(); + + sourceWriter + .println("public java.util.Collection getGeneratedRpcMethods() {"); + sourceWriter.indent(); + + sourceWriter + .println("java.util.ArrayList list = new java.util.ArrayList();"); // iterate over RPC interfaces and create helper methods for each // interface @@ -104,81 +116,56 @@ public class RpcManagerGenerator extends Generator { // only interested in interfaces here, not implementations continue; } - rpcInterfaces.add(type); - // generate method to call methods of an RPC interface - sourceWriter.println("private void " + getInvokeMethodName(type) - + "(" + MethodInvocation.class.getName() + " invocation, " - + ConnectorMap.class.getName() + " connectorMap) {"); - sourceWriter.indent(); // loop over the methods of the interface and its superinterfaces // methods for (JClassType currentType : type.getFlattenedSupertypeHierarchy()) { for (JMethod method : currentType.getMethods()) { - sourceWriter.println("if (\"" + method.getName() - + "\".equals(invocation.getMethodName())) {"); - sourceWriter.indent(); - // construct parameter string with appropriate casts - String paramString = ""; + + // RpcMethod(String interfaceName, String methodName, + // Type... parameterTypes) + sourceWriter.print("list.add(new RpcMethod(\"" + + type.getQualifiedSourceName() + "\", \"" + + method.getName() + "\""); JType[] parameterTypes = method.getParameterTypes(); - for (int i = 0; i < parameterTypes.length; ++i) { - paramString = paramString + "(" - + parameterTypes[i].getQualifiedSourceName() - + ") invocation.getParameters()[" + i + "]"; - if (i < parameterTypes.length - 1) { - paramString = paramString + ", "; - } + for (JType parameter : parameterTypes) { + sourceWriter.print(", "); + writeTypeCreator(sourceWriter, parameter); } + sourceWriter.println(") {"); + sourceWriter.indent(); + sourceWriter - .println(ServerConnector.class.getName() - + " connector = connectorMap.getConnector(invocation.getConnectorId());"); - sourceWriter - .println("for (" - + ClientRpc.class.getName() - + " rpcImplementation : connector.getRpcImplementations(\"" - + type.getQualifiedSourceName() + "\")) {"); + .println("public void applyInvocation(ClientRpc target, Object... parameters) {"); sourceWriter.indent(); - sourceWriter.println("((" + type.getQualifiedSourceName() - + ") rpcImplementation)." + method.getName() + "(" - + paramString + ");"); + + sourceWriter.print("((" + type.getQualifiedSourceName() + + ")target)." + method.getName() + "("); + for (int i = 0; i < parameterTypes.length; i++) { + JType parameterType = parameterTypes[i]; + if (i != 0) { + sourceWriter.print(", "); + } + sourceWriter.print("(" + + parameterType.getQualifiedSourceName() + + ") parameters[" + i + "]"); + } + sourceWriter.println(");"); + sourceWriter.outdent(); sourceWriter.println("}"); - sourceWriter.println("return;"); + sourceWriter.outdent(); - sourceWriter.println("}"); + sourceWriter.println("});"); } } - - sourceWriter.outdent(); - sourceWriter.println("}"); - - logger.log(Type.DEBUG, - "Constructed helper method for server to client RPC for " - + type.getName()); } - // generate top-level "switch-case" method to select the correct - // previously generated method based on the RPC interface - sourceWriter.println("public void applyInvocation(" - + MethodInvocation.class.getName() + " invocation, " - + ConnectorMap.class.getName() + " connectorMap) {"); - sourceWriter.indent(); + sourceWriter.println("return list;"); - for (JClassType type : rpcInterfaces) { - sourceWriter.println("if (\"" + type.getQualifiedSourceName() - + "\".equals(invocation.getInterfaceName())) {"); - sourceWriter.indent(); - sourceWriter.println(getInvokeMethodName(type) - + "(invocation, connectorMap);"); - sourceWriter.println("return;"); - sourceWriter.outdent(); - sourceWriter.println("}"); - - logger.log(Type.INFO, - "Configured server to client RPC for " + type.getName()); - } sourceWriter.outdent(); sourceWriter.println("}"); + sourceWriter.println(); // close generated class sourceWriter.outdent(); @@ -191,6 +178,24 @@ public class RpcManagerGenerator extends Generator { } + private void writeTypeCreator(SourceWriter sourceWriter, JType type) { + sourceWriter.print("new Type(\"" + + type.getErasedType().getQualifiedSourceName() + "\", "); + JParameterizedType parameterized = type.isParameterized(); + if (parameterized != null) { + sourceWriter.print("new Type[] {"); + JClassType[] typeArgs = parameterized.getTypeArgs(); + for (JClassType jClassType : typeArgs) { + writeTypeCreator(sourceWriter, jClassType); + sourceWriter.print(", "); + } + sourceWriter.print("}"); + } else { + sourceWriter.print("null"); + } + sourceWriter.print(")"); + } + private String getInvokeMethodName(JClassType type) { return "invoke" + type.getQualifiedSourceName().replaceAll("\\.", "_"); } -- 2.39.5