diff options
author | Leif Åstrand <leif@vaadin.com> | 2012-08-21 16:51:33 +0300 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2012-08-22 19:25:32 +0300 |
commit | e345e1820aa0e0fe551cca86d6d28b906beb8937 (patch) | |
tree | a063cfb43b58c931a891c1454dd3a4fead1f05fa /client-compiler | |
parent | b3a2c24e88456d958af9804f940ff9bfc2621fae (diff) | |
download | vaadin-framework-e345e1820aa0e0fe551cca86d6d28b906beb8937.tar.gz vaadin-framework-e345e1820aa0e0fe551cca86d6d28b906beb8937.zip |
Use ConnectorBundle for ServerRpc handling (#9371)
Diffstat (limited to 'client-compiler')
5 files changed, 201 insertions, 301 deletions
diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ConnectorBundleLoaderFactory.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ConnectorBundleLoaderFactory.java index 8cb04d9370..9f830d4a8d 100644 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ConnectorBundleLoaderFactory.java +++ b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ConnectorBundleLoaderFactory.java @@ -28,17 +28,22 @@ import com.google.gwt.core.ext.typeinfo.NotFoundException; 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.shared.annotations.Delayed; import com.vaadin.shared.communication.ClientRpc; import com.vaadin.shared.communication.ServerRpc; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.Connect.LoadStyle; import com.vaadin.terminal.gwt.client.ServerConnector; import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader; +import com.vaadin.terminal.gwt.client.metadata.InvokationHandler; +import com.vaadin.terminal.gwt.client.metadata.ProxyHandler; +import com.vaadin.terminal.gwt.client.metadata.TypeData; import com.vaadin.terminal.gwt.client.metadata.TypeDataBundle; import com.vaadin.terminal.gwt.client.metadata.TypeDataStore; import com.vaadin.terminal.gwt.widgetsetutils.metadata.ClientRpcVisitor; import com.vaadin.terminal.gwt.widgetsetutils.metadata.ConnectorBundle; import com.vaadin.terminal.gwt.widgetsetutils.metadata.ConnectorInitVisitor; +import com.vaadin.terminal.gwt.widgetsetutils.metadata.ServerRpcVisitor; import com.vaadin.terminal.gwt.widgetsetutils.metadata.StateInitVisitor; import com.vaadin.terminal.gwt.widgetsetutils.metadata.TypeVisitor; import com.vaadin.terminal.gwt.widgetsetutils.metadata.WidgetInitVisitor; @@ -166,6 +171,112 @@ public class ConnectorBundleLoaderFactory extends Generator { writeReturnTypes(w, bundle); writeInvokers(w, bundle); writeParamTypes(w, bundle); + writeProxys(w, bundle); + wirteDelayedInfo(w, bundle); + } + + private void wirteDelayedInfo(SourceWriter w, ConnectorBundle bundle) { + Map<JClassType, Set<JMethod>> needsDelayedInfo = bundle + .getNeedsDelayedInfo(); + Set<Entry<JClassType, Set<JMethod>>> entrySet = needsDelayedInfo + .entrySet(); + for (Entry<JClassType, Set<JMethod>> entry : entrySet) { + JClassType type = entry.getKey(); + Set<JMethod> methods = entry.getValue(); + for (JMethod method : methods) { + Delayed annotation = method.getAnnotation(Delayed.class); + if (annotation != null) { + w.print("store.setDelayed("); + printClassLiteral(w, type); + w.print(", \""); + w.print(escape(method.getName())); + w.println("\");"); + + if (annotation.lastonly()) { + w.print("store.setLastonly("); + printClassLiteral(w, type); + w.print(", \""); + w.print(escape(method.getName())); + w.println("\");"); + } + } + } + } + } + + private void writeProxys(SourceWriter w, ConnectorBundle bundle) { + Set<JClassType> needsProxySupport = bundle.getNeedsProxySupport(); + for (JClassType type : needsProxySupport) { + w.print("store.setProxyHandler("); + printClassLiteral(w, type); + w.print(", new "); + w.print(ProxyHandler.class.getCanonicalName()); + w.println("() {"); + w.indent(); + + w.println("public Object createProxy(final " + + InvokationHandler.class.getName() + " handler) {"); + w.indent(); + + w.print("return new "); + w.print(type.getQualifiedSourceName()); + w.println("() {"); + w.indent(); + + JMethod[] methods = type.getOverridableMethods(); + for (JMethod method : methods) { + if (method.isAbstract()) { + w.print("public "); + w.print(method.getReturnType().getQualifiedSourceName()); + w.print(" "); + w.print(method.getName()); + w.print("("); + + JType[] types = method.getParameterTypes(); + for (int i = 0; i < types.length; i++) { + if (i != 0) { + w.print(", "); + } + w.print(types[i].getQualifiedSourceName()); + w.print(" p"); + w.print(Integer.toString(i)); + } + + w.println(") {"); + w.indent(); + + if (!method.getReturnType().getQualifiedSourceName() + .equals("void")) { + w.print("return "); + } + + w.print("handler.invoke(this, "); + w.print(TypeData.class.getCanonicalName()); + w.print(".getType("); + printClassLiteral(w, type); + w.print(").getMethod(\""); + w.print(escape(method.getName())); + w.print("\"), new Object [] {"); + for (int i = 0; i < types.length; i++) { + w.print("p" + i + ", "); + } + w.println("});"); + + w.outdent(); + w.println("}"); + } + } + + w.outdent(); + w.println("};"); + + w.outdent(); + w.println("}"); + + w.outdent(); + w.println("});"); + + } } private void writeParamTypes(SourceWriter w, ConnectorBundle bundle) { @@ -176,11 +287,11 @@ public class ConnectorBundleLoaderFactory extends Generator { Set<JMethod> methods = entry.getValue(); for (JMethod method : methods) { - w.println("store.setParamTypes("); + w.print("store.setParamTypes("); printClassLiteral(w, type); w.print(", \""); w.print(escape(method.getName())); - w.println("\", new Type[] {"); + w.print("\", new Type[] {"); for (JType parameter : method.getParameterTypes()) { ConnectorBundleLoaderFactory.writeTypeCreator(w, parameter); @@ -272,7 +383,7 @@ public class ConnectorBundleLoaderFactory extends Generator { for (JClassType type : constructors) { w.print("store.setConstructor("); printClassLiteral(w, type); - w.print(", new Invoker() {"); + w.println(", new Invoker() {"); w.indent(); w.println("public Object invoke(Object target, Object[] params) {"); @@ -380,7 +491,8 @@ public class ConnectorBundleLoaderFactory extends Generator { throws NotFoundException { List<TypeVisitor> visitors = Arrays.<TypeVisitor> asList( new ConnectorInitVisitor(), new StateInitVisitor(), - new WidgetInitVisitor(), new ClientRpcVisitor()); + new WidgetInitVisitor(), new ClientRpcVisitor(), + new ServerRpcVisitor()); for (TypeVisitor typeVisitor : visitors) { typeVisitor.init(oracle); } diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/RpcProxyCreatorGenerator.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/RpcProxyCreatorGenerator.java deleted file mode 100644 index eccc6461c9..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/RpcProxyCreatorGenerator.java +++ /dev/null @@ -1,138 +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.terminal.gwt.widgetsetutils; - -import java.io.PrintWriter; -import java.util.Date; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.core.ext.Generator; -import com.google.gwt.core.ext.GeneratorContext; -import com.google.gwt.core.ext.TreeLogger; -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.TypeOracle; -import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; -import com.google.gwt.user.rebind.SourceWriter; -import com.vaadin.shared.communication.ServerRpc; -import com.vaadin.terminal.gwt.client.ServerConnector; -import com.vaadin.terminal.gwt.client.communication.InitializableServerRpc; -import com.vaadin.terminal.gwt.client.communication.RpcProxy.RpcProxyCreator; - -public class RpcProxyCreatorGenerator extends Generator { - - @Override - public String generate(TreeLogger logger, GeneratorContext ctx, - String requestedClassName) throws UnableToCompleteException { - logger.log(TreeLogger.DEBUG, "Running RpcProxyCreatorGenerator"); - TypeOracle typeOracle = ctx.getTypeOracle(); - assert (typeOracle != null); - - JClassType requestedType = typeOracle.findType(requestedClassName); - if (requestedType == null) { - logger.log(TreeLogger.ERROR, "Unable to find metadata for type '" - + requestedClassName + "'", null); - throw new UnableToCompleteException(); - } - String packageName = requestedType.getPackage().getName(); - String className = requestedType.getSimpleSourceName() + "Impl"; - - createType(logger, ctx, packageName, className); - return packageName + "." + className; - } - - private void createType(TreeLogger logger, GeneratorContext context, - String packageName, String className) { - ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory( - packageName, className); - - PrintWriter printWriter = context.tryCreate(logger, - composer.getCreatedPackage(), - composer.getCreatedClassShortName()); - if (printWriter == null) { - // print writer is null if source code has already been generated - return; - } - Date date = new Date(); - TypeOracle typeOracle = context.getTypeOracle(); - - // init composer, set class properties, create source writer - composer.addImport(GWT.class.getCanonicalName()); - composer.addImport(ServerRpc.class.getCanonicalName()); - composer.addImport(ServerConnector.class.getCanonicalName()); - composer.addImport(InitializableServerRpc.class.getCanonicalName()); - composer.addImport(IllegalArgumentException.class.getCanonicalName()); - composer.addImplementedInterface(RpcProxyCreator.class - .getCanonicalName()); - - SourceWriter sourceWriter = composer.createSourceWriter(context, - printWriter); - sourceWriter.indent(); - - sourceWriter - .println("public <T extends ServerRpc> T create(Class<T> rpcInterface, ServerConnector connector) {"); - sourceWriter.indent(); - - sourceWriter - .println("if (rpcInterface == null || connector == null) {"); - sourceWriter.indent(); - sourceWriter - .println("throw new IllegalArgumentException(\"RpcInterface and/or connector cannot be null\");"); - sourceWriter.outdent(); - - JClassType initializableInterface = typeOracle.findType(ServerRpc.class - .getCanonicalName()); - - for (JClassType rpcType : initializableInterface.getSubtypes()) { - String rpcClassName = rpcType.getQualifiedSourceName(); - if (InitializableServerRpc.class.getCanonicalName().equals( - rpcClassName)) { - // InitializableClientToServerRpc is a special marker interface - // that should not get a generated class - continue; - } - sourceWriter.println("} else if (rpcInterface == " + rpcClassName - + ".class) {"); - sourceWriter.indent(); - sourceWriter.println(rpcClassName + " rpc = GWT.create(" - + rpcClassName + ".class);"); - sourceWriter.println("((" + InitializableServerRpc.class.getName() - + ") rpc).initRpc(connector);"); - sourceWriter.println("return (T) rpc;"); - sourceWriter.outdent(); - } - - sourceWriter.println("} else {"); - sourceWriter.indent(); - sourceWriter - .println("throw new IllegalArgumentException(\"No RpcInterface of type \"+ rpcInterface.getName() + \" was found.\");"); - sourceWriter.outdent(); - // End of if - sourceWriter.println("}"); - // End of method - sourceWriter.println("}"); - - // close generated class - sourceWriter.outdent(); - sourceWriter.println("}"); - // commit generated class - context.commit(logger, printWriter); - logger.log(Type.INFO, composer.getCreatedClassName() + " created in " - + (new Date().getTime() - date.getTime()) / 1000 + "seconds"); - - } -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/RpcProxyGenerator.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/RpcProxyGenerator.java deleted file mode 100644 index 6d322c734e..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/RpcProxyGenerator.java +++ /dev/null @@ -1,159 +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.terminal.gwt.widgetsetutils; - -import java.io.PrintWriter; - -import com.google.gwt.core.ext.Generator; -import com.google.gwt.core.ext.GeneratorContext; -import com.google.gwt.core.ext.TreeLogger; -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.JParameter; -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.shared.annotations.Delayed; -import com.vaadin.shared.communication.MethodInvocation; -import com.vaadin.shared.communication.ServerRpc; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.ServerConnector; -import com.vaadin.terminal.gwt.client.communication.InitializableServerRpc; - -/** - * GWT generator that creates client side proxy classes for making RPC calls - * from the client to the server. - * - * GWT.create() calls for interfaces extending {@link ServerRpc} are affected, - * and a proxy implementation is created. Note that the init(...) method of the - * proxy must be called before the proxy is used. - * - * @since 7.0 - */ -public class RpcProxyGenerator extends Generator { - @Override - public String generate(TreeLogger logger, GeneratorContext ctx, - String requestedClassName) throws UnableToCompleteException { - logger.log(TreeLogger.DEBUG, "Running RpcProxyGenerator", null); - - TypeOracle typeOracle = ctx.getTypeOracle(); - assert (typeOracle != null); - - JClassType requestedType = typeOracle.findType(requestedClassName); - if (requestedType == null) { - logger.log(TreeLogger.ERROR, "Unable to find metadata for type '" - + requestedClassName + "'", null); - throw new UnableToCompleteException(); - } - - String generatedClassName = "ServerRpc_" - + requestedType.getName().replaceAll("[$.]", "_"); - - JClassType initializableInterface = typeOracle - .findType(InitializableServerRpc.class.getCanonicalName()); - - ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory( - requestedType.getPackage().getName(), generatedClassName); - composer.addImplementedInterface(requestedType.getQualifiedSourceName()); - composer.addImplementedInterface(initializableInterface - .getQualifiedSourceName()); - composer.addImport(MethodInvocation.class.getCanonicalName()); - - PrintWriter printWriter = ctx.tryCreate(logger, - composer.getCreatedPackage(), - composer.getCreatedClassShortName()); - if (printWriter != null) { - logger.log(Type.INFO, "Generating client proxy for RPC interface '" - + requestedType.getQualifiedSourceName() + "'"); - SourceWriter writer = composer.createSourceWriter(ctx, printWriter); - - // constructor - writer.println("public " + generatedClassName + "() {}"); - - // initialization etc. - writeCommonFieldsAndMethods(logger, writer, typeOracle); - - // actual proxy methods forwarding calls to the server - writeRemoteProxyMethods(logger, writer, typeOracle, requestedType, - requestedType.isClassOrInterface().getInheritableMethods()); - - // End of class - writer.outdent(); - writer.println("}"); - - ctx.commit(logger, printWriter); - } - - return composer.getCreatedClassName(); - } - - private void writeCommonFieldsAndMethods(TreeLogger logger, - SourceWriter writer, TypeOracle typeOracle) { - JClassType applicationConnectionClass = typeOracle - .findType(ApplicationConnection.class.getCanonicalName()); - - // fields - writer.println("private " + ServerConnector.class.getName() - + " connector;"); - - // init method from the RPC interface - writer.println("public void initRpc(" + ServerConnector.class.getName() - + " connector) {"); - writer.indent(); - writer.println("this.connector = connector;"); - writer.outdent(); - writer.println("}"); - } - - private static void writeRemoteProxyMethods(TreeLogger logger, - SourceWriter writer, TypeOracle typeOracle, - JClassType requestedType, JMethod[] methods) { - for (JMethod m : methods) { - writer.print(m.getReadableDeclaration(false, false, false, false, - true)); - writer.println(" {"); - writer.indent(); - - Delayed delayedAnnotation = m.getAnnotation(Delayed.class); - boolean delayed = delayedAnnotation != null; - boolean lastonly = delayed && delayedAnnotation.lastonly(); - - writer.print("this.connector.getConnection().addMethodInvocationToQueue(new MethodInvocation(this.connector.getConnectorId(), \"" - + requestedType.getQualifiedBinaryName() + "\", \""); - writer.print(m.getName()); - writer.print("\", new Object[] {"); - // new Object[] { ... } for parameters - autoboxing etc. by the - // compiler - JParameter[] parameters = m.getParameters(); - boolean first = true; - for (JParameter p : parameters) { - if (!first) { - writer.print(", "); - } - first = false; - - writer.print(p.getName()); - } - writer.println("}), " + delayed + ", " + lastonly + ");"); - - writer.outdent(); - writer.println("}"); - } - } -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorBundle.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorBundle.java index 3302fbc4fa..e93c72aa2f 100644 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorBundle.java +++ b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorBundle.java @@ -36,8 +36,11 @@ public class ConnectorBundle { private final Map<JClassType, Set<JMethod>> needsReturnType = new HashMap<JClassType, Set<JMethod>>(); private final Collection<TypeVisitor> visitors; + + private final Set<JClassType> needsProxySupport = new HashSet<JClassType>(); private final Map<JClassType, Set<JMethod>> needsInvoker = new HashMap<JClassType, Set<JMethod>>(); private final Map<JClassType, Set<JMethod>> needsParamTypes = new HashMap<JClassType, Set<JMethod>>(); + private final Map<JClassType, Set<JMethod>> needsDelayedInfo = new HashMap<JClassType, Set<JMethod>>(); private ConnectorBundle(String name, ConnectorBundle previousBundle, Collection<TypeVisitor> visitors) { @@ -268,4 +271,44 @@ public class ConnectorBundle { public Map<JClassType, Set<JMethod>> getNeedsParamTypes() { return Collections.unmodifiableMap(needsParamTypes); } + + public void setNeedsProxySupport(JClassType type) { + if (!isNeedsProxySupport(type)) { + ensureVisited(type); + needsProxySupport.add(type); + } + } + + private boolean isNeedsProxySupport(JClassType type) { + if (needsProxySupport.contains(type)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsProxySupport(type); + } + } + + public Set<JClassType> getNeedsProxySupport() { + return Collections.unmodifiableSet(needsProxySupport); + } + + public void setNeedsDelayedInfo(JClassType type, JMethod method) { + if (!isNeedsDelayedInfo(type, method)) { + ensureVisited(type); + addMapping(needsDelayedInfo, type, method); + } + } + + private boolean isNeedsDelayedInfo(JClassType type, JMethod method) { + if (hasMapping(needsDelayedInfo, type, method)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsDelayedInfo(type, method); + } + } + + public Map<JClassType, Set<JMethod>> getNeedsDelayedInfo() { + return Collections.unmodifiableMap(needsDelayedInfo); + } }
\ No newline at end of file diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ServerRpcVisitor.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ServerRpcVisitor.java new file mode 100644 index 0000000000..5505c70dc3 --- /dev/null +++ b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ServerRpcVisitor.java @@ -0,0 +1,42 @@ +/* + * 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.terminal.gwt.widgetsetutils.metadata; + +import java.util.Set; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; + +public class ServerRpcVisitor extends TypeVisitor { + @Override + public void visitServerRpc(TreeLogger logger, JClassType type, + ConnectorBundle bundle) { + bundle.setNeedsProxySupport(type); + + Set<? extends JClassType> superTypes = type + .getFlattenedSupertypeHierarchy(); + for (JClassType subType : superTypes) { + if (subType.isInterface() != null) { + JMethod[] methods = subType.getMethods(); + for (JMethod method : methods) { + bundle.setNeedsDelayedInfo(type, method); + } + } + } + } +} |