diff options
author | Leif Åstrand <leif@vaadin.com> | 2012-08-21 12:33:32 +0300 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2012-08-22 19:25:31 +0300 |
commit | bcef4d5e716a275f3a3588cd9e50885129d38eb7 (patch) | |
tree | 5bc17a54d1e6a804539793e4fa2a79615b263b73 /client-compiler/src/com/vaadin | |
parent | d51dcf18b8d7f64f763163c5965ca30b8c33070d (diff) | |
download | vaadin-framework-bcef4d5e716a275f3a3588cd9e50885129d38eb7.tar.gz vaadin-framework-bcef4d5e716a275f3a3588cd9e50885129d38eb7.zip |
Use ConnectorBundle for ClientRpc handling (#9371)
Diffstat (limited to 'client-compiler/src/com/vaadin')
5 files changed, 216 insertions, 247 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 e0c88ced66..b6a6e0bff4 100644 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ConnectorBundleLoaderFactory.java +++ b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ConnectorBundleLoaderFactory.java @@ -22,6 +22,8 @@ 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.NotFoundException; import com.google.gwt.core.ext.typeinfo.TypeOracle; import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; @@ -34,6 +36,7 @@ import com.vaadin.terminal.gwt.client.ServerConnector; import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader; 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.StateInitVisitor; @@ -161,6 +164,85 @@ public class ConnectorBundleLoaderFactory extends Generator { writeIdentifiers(w, bundle); writeGwtConstructors(w, bundle); writeReturnTypes(w, bundle); + writeInvokers(w, bundle); + writeParamTypes(w, bundle); + } + + private void writeParamTypes(SourceWriter w, ConnectorBundle bundle) { + Map<JClassType, Set<JMethod>> needsParamTypes = bundle + .getNeedsParamTypes(); + for (Entry<JClassType, Set<JMethod>> entry : needsParamTypes.entrySet()) { + JClassType type = entry.getKey(); + + Set<JMethod> methods = entry.getValue(); + for (JMethod method : methods) { + w.println("store.setParamTypes("); + printClassLiteral(w, type); + w.print(", \""); + w.print(escape(method.getName())); + w.println("\", new Type[] {"); + + for (JType parameter : method.getParameterTypes()) { + ConnectorBundleLoaderFactory.writeTypeCreator(w, parameter); + w.print(", "); + } + + w.println("});"); + + } + } + } + + private void writeInvokers(SourceWriter w, ConnectorBundle bundle) { + Map<JClassType, Set<JMethod>> needsInvoker = bundle.getNeedsInvoker(); + for (Entry<JClassType, Set<JMethod>> entry : needsInvoker.entrySet()) { + JClassType type = entry.getKey(); + + Set<JMethod> methods = entry.getValue(); + for (JMethod method : methods) { + w.print("store.setInvoker("); + printClassLiteral(w, type); + w.print(", \""); + w.print(escape(method.getName())); + w.println("\", new Invoker() {"); + w.indent(); + + w.println("public Object invoke(Object target, Object[] params) {"); + w.indent(); + + JType returnType = method.getReturnType(); + boolean hasReturnType = !"void".equals(returnType + .getQualifiedSourceName()); + if (hasReturnType) { + w.print("return "); + } + + JType[] parameterTypes = method.getParameterTypes(); + + w.print("((" + type.getQualifiedSourceName() + ") target)." + + method.getName() + "("); + for (int i = 0; i < parameterTypes.length; i++) { + JType parameterType = parameterTypes[i]; + if (i != 0) { + w.print(", "); + } + String parameterTypeName = getBoxedTypeName(parameterType); + w.print("(" + parameterTypeName + ") params[" + i + "]"); + } + w.println(");"); + + if (!hasReturnType) { + w.println("return null;"); + } + + w.outdent(); + w.println("}"); + + w.outdent(); + w.println("});"); + + } + } } private void writeReturnTypes(SourceWriter w, ConnectorBundle bundle) { @@ -177,10 +259,9 @@ public class ConnectorBundleLoaderFactory extends Generator { w.print("store.setReturnType("); printClassLiteral(w, type); w.print(", \""); - w.print(method.getName()); + w.print(escape(method.getName())); w.print("\", "); - GeneratedRpcMethodProviderGenerator.writeTypeCreator(w, - method.getReturnType()); + writeTypeCreator(w, method.getReturnType()); w.println(");"); } } @@ -299,7 +380,7 @@ public class ConnectorBundleLoaderFactory extends Generator { throws NotFoundException { List<TypeVisitor> visitors = Arrays.<TypeVisitor> asList( new ConnectorInitVisitor(), new StateInitVisitor(), - new WidgetInitVisitor()); + new WidgetInitVisitor(), new ClientRpcVisitor()); for (TypeVisitor typeVisitor : visitors) { typeVisitor.init(oracle); } @@ -311,4 +392,31 @@ public class ConnectorBundleLoaderFactory extends Generator { return annotation.loadStyle(); } + public static String getBoxedTypeName(JType type) { + if (type.isPrimitive() != null) { + // Used boxed types for primitives + return type.isPrimitive().getQualifiedBoxedSourceName(); + } else { + return type.getErasedType().getQualifiedSourceName(); + } + } + + public static void writeTypeCreator(SourceWriter sourceWriter, JType type) { + String typeName = ConnectorBundleLoaderFactory.getBoxedTypeName(type); + sourceWriter.print("new Type(\"" + typeName + "\", "); + 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(")"); + } + } diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java deleted file mode 100644 index c6cf28db28..0000000000 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java +++ /dev/null @@ -1,223 +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.ArrayList; -import java.util.Date; -import java.util.List; - -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.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.shared.communication.ClientRpc; -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 - * client side classes for executing RPC calls received from the the server. - * - * @since 7.0 - */ -public class GeneratedRpcMethodProviderGenerator extends Generator { - - @Override - public String generate(TreeLogger logger, GeneratorContext context, - String typeName) throws UnableToCompleteException { - - String packageName = null; - String className = null; - try { - TypeOracle typeOracle = context.getTypeOracle(); - - // get classType and save instance variables - JClassType classType = typeOracle.getType(typeName); - packageName = classType.getPackage().getName(); - className = classType.getSimpleSourceName() + "Impl"; - // Generate class source code for SerializerMapImpl - generateClass(logger, context, packageName, className); - } catch (Exception e) { - logger.log(TreeLogger.ERROR, - "SerializerMapGenerator creation failed", e); - } - // return the fully qualifed name of the class generated - return packageName + "." + className; - } - - /** - * Generate source code for RpcManagerImpl - * - * @param logger - * Logger object - * @param context - * Generator context - * @param packageName - * package name for the class to generate - * @param className - * class name for the class to generate - */ - private void generateClass(TreeLogger logger, GeneratorContext context, - String packageName, String className) { - // get print writer that receives the source code - PrintWriter printWriter = null; - printWriter = context.tryCreate(logger, packageName, className); - // print writer if null, source code has ALREADY been generated - if (printWriter == null) { - return; - } - logger.log(Type.INFO, - "Detecting server to client RPC interface types..."); - Date date = new Date(); - TypeOracle typeOracle = context.getTypeOracle(); - JClassType serverToClientRpcType = typeOracle.findType(ClientRpc.class - .getName()); - JClassType[] rpcInterfaceSubtypes = serverToClientRpcType.getSubtypes(); - - // init composer, set class properties, create source writer - ClassSourceFileComposerFactory composer = null; - composer = new ClassSourceFileComposerFactory(packageName, className); - composer.addImport("com.google.gwt.core.client.GWT"); - composer.addImport(RpcMethod.class.getName()); - composer.addImport(ClientRpc.class.getName()); - composer.addImport(com.vaadin.terminal.gwt.client.metadata.Type.class - .getName()); - composer.addImplementedInterface(GeneratedRpcMethodProvider.class - .getName()); - SourceWriter sourceWriter = composer.createSourceWriter(context, - printWriter); - sourceWriter.indent(); - - List<JMethod> rpcMethods = new ArrayList<JMethod>(); - - sourceWriter - .println("public java.util.Collection<RpcMethod> getGeneratedRpcMethods() {"); - sourceWriter.indent(); - - sourceWriter - .println("java.util.ArrayList<RpcMethod> list = new java.util.ArrayList<RpcMethod>();"); - - // iterate over RPC interfaces and create helper methods for each - // interface - for (JClassType type : rpcInterfaceSubtypes) { - if (null == type.isInterface()) { - // only interested in interfaces here, not implementations - continue; - } - - // loop over the methods of the interface and its superinterfaces - // methods - for (JClassType currentType : type.getFlattenedSupertypeHierarchy()) { - for (JMethod method : currentType.getMethods()) { - - // RpcMethod(String interfaceName, String methodName, - // Type... parameterTypes) - sourceWriter.print("list.add(new RpcMethod(\"" - + type.getQualifiedSourceName() + "\", \"" - + method.getName() + "\""); - JType[] parameterTypes = method.getParameterTypes(); - for (JType parameter : parameterTypes) { - sourceWriter.print(", "); - writeTypeCreator(sourceWriter, parameter); - } - sourceWriter.println(") {"); - sourceWriter.indent(); - - sourceWriter - .println("public void applyInvocation(ClientRpc target, Object... parameters) {"); - sourceWriter.indent(); - - sourceWriter.print("((" + type.getQualifiedSourceName() - + ")target)." + method.getName() + "("); - for (int i = 0; i < parameterTypes.length; i++) { - JType parameterType = parameterTypes[i]; - if (i != 0) { - sourceWriter.print(", "); - } - String parameterTypeName = getBoxedTypeName(parameterType); - sourceWriter.print("(" + parameterTypeName - + ") parameters[" + i + "]"); - } - sourceWriter.println(");"); - - sourceWriter.outdent(); - sourceWriter.println("}"); - - sourceWriter.outdent(); - sourceWriter.println("});"); - } - } - } - - sourceWriter.println("return list;"); - - sourceWriter.outdent(); - sourceWriter.println("}"); - sourceWriter.println(); - - // close generated class - sourceWriter.outdent(); - sourceWriter.println("}"); - // commit generated class - context.commit(logger, printWriter); - logger.log(Type.INFO, - "Done. (" + (new Date().getTime() - date.getTime()) / 1000 - + "seconds)"); - - } - - public static void writeTypeCreator(SourceWriter sourceWriter, JType type) { - String typeName = getBoxedTypeName(type); - sourceWriter.print("new Type(\"" + typeName + "\", "); - 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(")"); - } - - public static String getBoxedTypeName(JType type) { - if (type.isPrimitive() != null) { - // Used boxed types for primitives - return type.isPrimitive().getQualifiedBoxedSourceName(); - } else { - return type.getErasedType().getQualifiedSourceName(); - } - } - - private String getInvokeMethodName(JClassType type) { - return "invoke" + type.getQualifiedSourceName().replaceAll("\\.", "_"); - } -} diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java index c7cc7bf7cb..83e1c17881 100644 --- a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java +++ b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java @@ -256,10 +256,10 @@ public class SerializerGenerator extends Generator { JType componentType = type.getComponentType(); sourceWriter.print("value[i] = (" - + GeneratedRpcMethodProviderGenerator + + ConnectorBundleLoaderFactory .getBoxedTypeName(componentType) + ") " + JsonDecoder.class.getName() + ".decodeValue("); - GeneratedRpcMethodProviderGenerator.writeTypeCreator(sourceWriter, + ConnectorBundleLoaderFactory.writeTypeCreator(sourceWriter, componentType); sourceWriter.print(", jsonArray.get(i), null, connection)"); @@ -320,7 +320,7 @@ public class SerializerGenerator extends Generator { // connection)); sourceWriter.print("target." + setterName + "((" + fieldType + ") " + JsonDecoder.class.getName() + ".decodeValue("); - GeneratedRpcMethodProviderGenerator.writeTypeCreator(sourceWriter, + ConnectorBundleLoaderFactory.writeTypeCreator(sourceWriter, setterParameterType); sourceWriter.println(", " + jsonFieldName + ", referenceValue, connection));"); diff --git a/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ClientRpcVisitor.java b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ClientRpcVisitor.java new file mode 100644 index 0000000000..2f628b76cb --- /dev/null +++ b/client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ClientRpcVisitor.java @@ -0,0 +1,39 @@ +/* + * 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 ClientRpcVisitor extends TypeVisitor { + @Override + public void visitClientRpc(TreeLogger logger, JClassType type, + ConnectorBundle bundle) { + Set<? extends JClassType> hierarchy = type + .getFlattenedSupertypeHierarchy(); + for (JClassType subType : hierarchy) { + JMethod[] methods = subType.getMethods(); + for (JMethod method : methods) { + bundle.setNeedsInvoker(type, method); + bundle.setNeedsParamTypes(type, method); + } + } + } +} 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 26e293351c..3302fbc4fa 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,6 +36,8 @@ public class ConnectorBundle { private final Map<JClassType, Set<JMethod>> needsReturnType = new HashMap<JClassType, Set<JMethod>>(); private final Collection<TypeVisitor> visitors; + 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 ConnectorBundle(String name, ConnectorBundle previousBundle, Collection<TypeVisitor> visitors) { @@ -71,18 +73,12 @@ public class ConnectorBundle { public void setIdentifier(JClassType type, String identifier) { if (!hasIdentifier(type, identifier)) { ensureVisited(type); - Set<String> set = identifiers.get(type); - if (set == null) { - set = new HashSet<String>(); - identifiers.put(type, set); - } - set.add(identifier); + addMapping(identifiers, type, identifier); } } private boolean hasIdentifier(JClassType type, String identifier) { - if (identifiers.containsKey(type) - && identifiers.get(type).contains(identifier)) { + if (hasMapping(identifiers, type, identifier)) { return true; } else { return previousBundle != null @@ -142,10 +138,13 @@ public class ConnectorBundle { if (isTypeVisited(type)) { continue; } + + // Mark as visited before visiting to avoid adding to queue again + visitedTypes.add(type); + for (TypeVisitor typeVisitor : visitors) { invokeVisitor(logger, type, typeVisitor); } - visitedTypes.add(type); } } @@ -171,18 +170,12 @@ public class ConnectorBundle { public void setNeedsReturnType(JClassType type, JMethod method) { if (!isNeedsReturnType(type, method)) { ensureVisited(type); - Set<JMethod> set = needsReturnType.get(type); - if (set == null) { - set = new HashSet<JMethod>(); - needsReturnType.put(type, set); - } - set.add(method); + addMapping(needsReturnType, type, method); } } private boolean isNeedsReturnType(JClassType type, JMethod method) { - if (needsReturnType.containsKey(type) - && needsReturnType.get(type).contains(method)) { + if (hasMapping(needsReturnType, type, method)) { return true; } else { return previousBundle != null @@ -223,4 +216,56 @@ public class ConnectorBundle { } } + public void setNeedsInvoker(JClassType type, JMethod method) { + if (!isNeedsInvoker(type, method)) { + ensureVisited(type); + addMapping(needsInvoker, type, method); + } + } + + private <K, V> void addMapping(Map<K, Set<V>> map, K key, V value) { + Set<V> set = map.get(key); + if (set == null) { + set = new HashSet<V>(); + map.put(key, set); + } + set.add(value); + } + + private <K, V> boolean hasMapping(Map<K, Set<V>> map, K key, V value) { + return map.containsKey(key) && map.get(key).contains(value); + } + + private boolean isNeedsInvoker(JClassType type, JMethod method) { + if (hasMapping(needsInvoker, type, method)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsInvoker(type, method); + } + } + + public Map<JClassType, Set<JMethod>> getNeedsInvoker() { + return Collections.unmodifiableMap(needsInvoker); + } + + public void setNeedsParamTypes(JClassType type, JMethod method) { + if (!isNeedsParamTypes(type, method)) { + ensureVisited(type); + addMapping(needsParamTypes, type, method); + } + } + + private boolean isNeedsParamTypes(JClassType type, JMethod method) { + if (hasMapping(needsParamTypes, type, method)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsParamTypes(type, method); + } + } + + public Map<JClassType, Set<JMethod>> getNeedsParamTypes() { + return Collections.unmodifiableMap(needsParamTypes); + } }
\ No newline at end of file |