]> source.dussan.org Git - vaadin-framework.git/commitdiff
Use ConnectorBundle for ClientRpc handling (#9371)
authorLeif Åstrand <leif@vaadin.com>
Tue, 21 Aug 2012 09:33:32 +0000 (12:33 +0300)
committerLeif Åstrand <leif@vaadin.com>
Wed, 22 Aug 2012 16:25:31 +0000 (19:25 +0300)
19 files changed:
client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ConnectorBundleLoaderFactory.java
client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java [deleted file]
client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java
client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ClientRpcVisitor.java [new file with mode: 0644]
client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorBundle.java
client/src/com/vaadin/Vaadin.gwt.xml
client/src/com/vaadin/terminal/gwt/client/ApplicationConfiguration.java
client/src/com/vaadin/terminal/gwt/client/WidgetSet.java
client/src/com/vaadin/terminal/gwt/client/communication/GeneratedRpcMethodProvider.java [deleted file]
client/src/com/vaadin/terminal/gwt/client/communication/RpcManager.java
client/src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java [deleted file]
client/src/com/vaadin/terminal/gwt/client/metadata/Method.java
client/src/com/vaadin/terminal/gwt/client/metadata/NoDataException.java [new file with mode: 0644]
client/src/com/vaadin/terminal/gwt/client/metadata/Property.java
client/src/com/vaadin/terminal/gwt/client/metadata/Type.java
client/src/com/vaadin/terminal/gwt/client/metadata/TypeData.java
client/src/com/vaadin/terminal/gwt/client/metadata/TypeDataStore.java
client/src/com/vaadin/terminal/gwt/client/ui/AbstractComponentConnector.java
client/src/com/vaadin/terminal/gwt/client/ui/AbstractConnector.java

index e0c88ced66a817be81edf9948fd9e040553cf063..b6a6e0bff45cc5a497b2da4f872d7cd6452a9077 100644 (file)
@@ -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 (file)
index c6cf28d..0000000
+++ /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("\\.", "_");
-    }
-}
index c7cc7bf7cbd097193005056932e9f64bb982d7aa..83e1c17881475b9b90084b9cf9ab4e99029d9af1 100644 (file)
@@ -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 (file)
index 0000000..2f628b7
--- /dev/null
@@ -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);
+            }
+        }
+    }
+}
index 26e293351c713fdc3ddcb6d78c0d4327980c8024..3302fbc4fabb00209c85002e6c231c8660b9be8e 100644 (file)
@@ -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
index 4bac60b47298e3006c9b861da256fbe6efdcb517..e25c812e5bae18fbc88b2deccd70ba0b463b2aec 100644 (file)
                <when-type-assignable
                        class="com.vaadin.terminal.gwt.client.communication.RpcProxy.RpcProxyCreator" />
        </generate-with>
-
-       <!-- Generate client side RPC manager for server to client RPC -->
-       <generate-with
-               class="com.vaadin.terminal.gwt.widgetsetutils.GeneratedRpcMethodProviderGenerator">
-               <when-type-assignable
-                       class="com.vaadin.terminal.gwt.client.communication.GeneratedRpcMethodProvider" />
-       </generate-with>
        
        <generate-with class="com.vaadin.terminal.gwt.widgetsetutils.ConnectorBundleLoaderFactory">
                <when-type-assignable class="com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader" />
index 8f6697288c444afc6243e92c07daaccf7bb67184..8bb4f37324f0c2a59f6ada46b6bba5660476e930 100644 (file)
@@ -33,6 +33,7 @@ import com.google.gwt.user.client.Window;
 import com.vaadin.shared.ApplicationConstants;
 import com.vaadin.terminal.gwt.client.metadata.BundleLoadCallback;
 import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader;
+import com.vaadin.terminal.gwt.client.metadata.NoDataException;
 import com.vaadin.terminal.gwt.client.metadata.TypeData;
 import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector;
 
@@ -398,8 +399,14 @@ public class ApplicationConfiguration implements EntryPoint {
             Integer currentTag = Integer.valueOf(tag);
             while (type == null && currentTag != null) {
                 String serverSideClassNameForTag = getServerSideClassNameForTag(currentTag);
-                type = (Class<? extends ServerConnector>) TypeData
-                        .getClass(serverSideClassNameForTag);
+                if (TypeData.hasIdentifier(serverSideClassNameForTag)) {
+                    try {
+                        type = (Class<? extends ServerConnector>) TypeData
+                                .getClass(serverSideClassNameForTag);
+                    } catch (NoDataException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
                 currentTag = getParentTag(currentTag.intValue());
             }
             if (type == null) {
index 776436f5f04ba6273e8ac7d7718b60ad448f4d58..82453711611901f1a2840852789f3e800e9c7149 100644 (file)
@@ -20,6 +20,7 @@ import com.google.gwt.core.client.GWT;
 import com.vaadin.terminal.gwt.client.communication.HasJavaScriptConnectorHelper;
 import com.vaadin.terminal.gwt.client.metadata.BundleLoadCallback;
 import com.vaadin.terminal.gwt.client.metadata.ConnectorBundleLoader;
+import com.vaadin.terminal.gwt.client.metadata.NoDataException;
 import com.vaadin.terminal.gwt.client.metadata.TypeData;
 import com.vaadin.terminal.gwt.client.ui.UnknownComponentConnector;
 
@@ -60,13 +61,21 @@ public class WidgetSet {
             /*
              * let the auto generated code instantiate this type
              */
-            ServerConnector connector = (ServerConnector) TypeData.getType(
-                    classType).createInstance();
-            if (connector instanceof HasJavaScriptConnectorHelper) {
-                ((HasJavaScriptConnectorHelper) connector)
-                        .getJavascriptConnectorHelper().setTag(tag);
+            try {
+                ServerConnector connector = (ServerConnector) TypeData.getType(
+                        classType).createInstance();
+                if (connector instanceof HasJavaScriptConnectorHelper) {
+                    ((HasJavaScriptConnectorHelper) connector)
+                            .getJavascriptConnectorHelper().setTag(tag);
+                }
+                return connector;
+            } catch (NoDataException e) {
+                throw new IllegalStateException(
+                        "There is no information about "
+                                + classType
+                                + ". Did you remember to compile the right widgetset?",
+                        e);
             }
-            return connector;
         }
     }
 
diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/GeneratedRpcMethodProvider.java b/client/src/com/vaadin/terminal/gwt/client/communication/GeneratedRpcMethodProvider.java
deleted file mode 100644 (file)
index e865dbc..0000000
+++ /dev/null
@@ -1,32 +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.client.communication;
-
-import java.util.Collection;
-
-/**
- * Provides runtime data about client side RPC calls received from the server to
- * the client-side code.
- * 
- * A GWT generator is used to create an implementation of this class at
- * run-time.
- * 
- * @since 7.0
- */
-public interface GeneratedRpcMethodProvider {
-
-    public Collection<RpcMethod> getGeneratedRpcMethods();
-}
index 537cc341857325775066bd6c603eac25ab27816c..45939eb54eb530f343cdeefbdb170bbe3e8f54a5 100644 (file)
 package com.vaadin.terminal.gwt.client.communication;
 
 import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
 
-import com.google.gwt.core.client.GWT;
 import com.google.gwt.json.client.JSONArray;
 import com.google.gwt.json.client.JSONString;
 import com.vaadin.shared.communication.ClientRpc;
@@ -29,6 +26,8 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection;
 import com.vaadin.terminal.gwt.client.ConnectorMap;
 import com.vaadin.terminal.gwt.client.ServerConnector;
 import com.vaadin.terminal.gwt.client.VConsole;
+import com.vaadin.terminal.gwt.client.metadata.Method;
+import com.vaadin.terminal.gwt.client.metadata.NoDataException;
 import com.vaadin.terminal.gwt.client.metadata.Type;
 
 /**
@@ -42,19 +41,6 @@ import com.vaadin.terminal.gwt.client.metadata.Type;
  */
 public class RpcManager {
 
-    private final Map<String, RpcMethod> methodMap = new HashMap<String, RpcMethod>();
-
-    public RpcManager() {
-        GeneratedRpcMethodProvider provider = GWT
-                .create(GeneratedRpcMethodProvider.class);
-        Collection<RpcMethod> methods = provider.getGeneratedRpcMethods();
-        for (RpcMethod rpcMethod : methods) {
-            methodMap.put(
-                    rpcMethod.getInterfaceName() + "."
-                            + rpcMethod.getMethodName(), rpcMethod);
-        }
-    }
-
     /**
      * Perform server to client RPC invocation.
      * 
@@ -63,24 +49,25 @@ public class RpcManager {
      */
     public void applyInvocation(MethodInvocation invocation,
             ServerConnector connector) {
-        String signature = getSignature(invocation);
+        Method method = getMethod(invocation);
 
-        RpcMethod rpcMethod = getRpcMethod(signature);
         Collection<ClientRpc> implementations = connector
                 .getRpcImplementations(invocation.getInterfaceName());
-        for (ClientRpc clientRpc : implementations) {
-            rpcMethod.applyInvocation(clientRpc, invocation.getParameters());
+        try {
+            for (ClientRpc clientRpc : implementations) {
+                method.invoke(clientRpc, invocation.getParameters());
+            }
+        } catch (NoDataException e) {
+            throw new IllegalStateException("There is no information about "
+                    + method.getSignature()
+                    + ". Did you remember to compile the right widgetset?", e);
         }
     }
 
-    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 Method getMethod(MethodInvocation invocation) {
+        Type type = new Type(invocation.getInterfaceName(), null);
+        Method method = type.getMethod(invocation.getMethodName());
+        return method;
     }
 
     private static String getSignature(MethodInvocation invocation) {
@@ -88,7 +75,15 @@ public class RpcManager {
     }
 
     public Type[] getParameterTypes(MethodInvocation invocation) {
-        return getRpcMethod(getSignature(invocation)).getParameterTypes();
+        Method method = getMethod(invocation);
+        Type[] parameterTypes = method.getParameterTypes();
+        if (parameterTypes == null) {
+            throw new IllegalStateException("There is no information about "
+                    + method.getSignature()
+                    + ". Did you remember to compile the right widgetset?");
+
+        }
+        return parameterTypes;
     }
 
     public void parseAndApplyInvocation(JSONArray rpcCall,
diff --git a/client/src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java b/client/src/com/vaadin/terminal/gwt/client/communication/RpcMethod.java
deleted file mode 100644 (file)
index 1759fbb..0000000
+++ /dev/null
@@ -1,47 +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.client.communication;
-
-import com.vaadin.shared.communication.ClientRpc;
-import com.vaadin.terminal.gwt.client.metadata.Type;
-
-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);
-
-}
index f164bc4bcfa44f43c86bb64a040a606f7bcb193d..588e736da3624254730de4f82d053eda99c06fa6 100644 (file)
@@ -22,11 +22,11 @@ public class Method {
         return name;
     }
 
-    public Type getReturnType() {
+    public Type getReturnType() throws NoDataException {
         return TypeDataStore.getReturnType(this);
     }
 
-    public void invoke(Object target, Object... params) {
+    public void invoke(Object target, Object... params) throws NoDataException {
         TypeDataStore.getInvoker(this).invoke(target, params);
     }
 
@@ -46,9 +46,18 @@ public class Method {
         }
     }
 
+    @Override
+    public String toString() {
+        return getSignature();
+    }
+
     @Override
     public int hashCode() {
         return getSignature().hashCode();
     }
 
+    public Type[] getParameterTypes() {
+        return TypeDataStore.getParamTypes(this);
+    }
+
 }
diff --git a/client/src/com/vaadin/terminal/gwt/client/metadata/NoDataException.java b/client/src/com/vaadin/terminal/gwt/client/metadata/NoDataException.java
new file mode 100644 (file)
index 0000000..717b92e
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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.client.metadata;
+
+public class NoDataException extends Exception {
+
+    public NoDataException(String message) {
+        super(message);
+    }
+
+}
index 5f2b1ffb41f8bb6a627c47e972bcc838bc2c1b87..30d864a43f8effa28caf6f54aef6d565e6c0f888 100644 (file)
@@ -13,7 +13,7 @@ public class Property {
         this.name = name;
     }
 
-    public Object getValue(Object bean) {
+    public Object getValue(Object bean) throws NoDataException {
         return TypeDataStore.getGetter(this).invoke(bean, null);
     }
 
index 4fab29644173763a8e4ace5c34467567c33435d4..dfd504983c8d5e55a49a9bc90ce5fd01dbb5f8da 100644 (file)
@@ -25,7 +25,7 @@ public class Type {
         return parameterTypes;
     }
 
-    public Object createInstance() {
+    public Object createInstance() throws NoDataException {
         Invoker invoker = TypeDataStore.getConstructor(this);
         return invoker.invoke(null, null);
     }
@@ -40,7 +40,7 @@ public class Type {
 
     public String getSignature() {
         String string = name;
-        if (parameterTypes != null) {
+        if (parameterTypes != null && parameterTypes.length != 0) {
             string += '<';
             for (int i = 0; i < parameterTypes.length; i++) {
                 if (i != 0) {
index 6ee0b4ede0739821139222f0af14aec193abca59..ec2a8f191cf2f4c601a63e0f8eba1c26aa349823 100644 (file)
@@ -10,11 +10,11 @@ public class TypeData {
         return TypeDataStore.getType(type);
     }
 
-    public static Type getType(String identifier) {
-        return TypeDataStore.getType(getClass(identifier));
+    public static Class<?> getClass(String identifier) throws NoDataException {
+        return TypeDataStore.getClass(identifier);
     }
 
-    public static Class<?> getClass(String identifier) {
-        return TypeDataStore.getClass(identifier);
+    public static boolean hasIdentifier(String identifier) {
+        return TypeDataStore.hasIdentifier(identifier);
     }
 }
index 4b224721e68e2d655d15198e17a9f54932ac4d69..4b99250465a7476b1ff2fae858815a8b3e40bb9f 100644 (file)
@@ -14,6 +14,7 @@ public class TypeDataStore {
 
     private final Map<Method, Type> returnTypes = new HashMap<Method, Type>();
     private final Map<Method, Invoker> invokers = new HashMap<Method, Invoker>();
+    private final Map<Method, Type[]> paramTypes = new HashMap<Method, Type[]>();
 
     private final Map<Property, Invoker> getters = new HashMap<Property, Invoker>();
     private final Map<Property, String> delegateToWidget = new HashMap<Property, String>();
@@ -26,28 +27,55 @@ public class TypeDataStore {
         identifiers.put(identifier, type);
     }
 
-    public static Class<?> getClass(String identifier) {
-        return get().identifiers.get(identifier);
+    public static Class<?> getClass(String identifier) throws NoDataException {
+        Class<?> class1 = get().identifiers.get(identifier);
+        if (class1 == null) {
+            throw new NoDataException("There is not class for identifier "
+                    + identifier);
+        }
+        return class1;
     }
 
     public static Type getType(Class<?> clazz) {
         return new Type(clazz);
     }
 
-    public static Type getReturnType(Method method) {
-        return get().returnTypes.get(method);
+    public static Type getReturnType(Method method) throws NoDataException {
+        Type type = get().returnTypes.get(method);
+        if (type == null) {
+            throw new NoDataException("There is return type for "
+                    + method.getSignature());
+        }
+        return type;
     }
 
-    public static Invoker getInvoker(Method method) {
-        return get().invokers.get(method);
+    public static Invoker getInvoker(Method method) throws NoDataException {
+        Invoker invoker = get().invokers.get(method);
+        if (invoker == null) {
+            throw new NoDataException("There is invoker for "
+                    + method.getSignature());
+        }
+        return invoker;
     }
 
-    public static Invoker getConstructor(Type type) {
-        return get().invokers.get(new Method(type, CONSTRUCTOR_NAME));
+    public static Invoker getConstructor(Type type) throws NoDataException {
+        Invoker invoker = get().invokers
+                .get(new Method(type, CONSTRUCTOR_NAME));
+        if (invoker == null) {
+            throw new NoDataException("There is constructor for "
+                    + type.getSignature());
+        }
+        return invoker;
     }
 
-    public static Invoker getGetter(Property property) {
-        return get().getters.get(property);
+    public static Invoker getGetter(Property property) throws NoDataException {
+        Invoker getter = get().getters.get(property);
+        if (getter == null) {
+            throw new NoDataException("There is getter for "
+                    + property.getSignature());
+        }
+
+        return getter;
     }
 
     public static String getDelegateToWidget(Property property) {
@@ -59,6 +87,23 @@ public class TypeDataStore {
     }
 
     public void setConstructor(Class<?> type, Invoker constructor) {
-        invokers.put(new Method(getType(type), CONSTRUCTOR_NAME), constructor);
+        setInvoker(type, CONSTRUCTOR_NAME, constructor);
+    }
+
+    public void setInvoker(Class<?> type, String methodName, Invoker invoker) {
+        invokers.put(new Method(getType(type), methodName), invoker);
+    }
+
+    public static Type[] getParamTypes(Method method) {
+        return get().paramTypes.get(method);
+    }
+
+    public void setParamTypes(Class<?> type, String methodName,
+            Type[] paramTypes) {
+        this.paramTypes.put(new Method(getType(type), methodName), paramTypes);
+    }
+
+    public static boolean hasIdentifier(String identifier) {
+        return get().identifiers.containsKey(identifier);
     }
 }
index 4f14ee550be09f0517857e3c08471a269b9d374a..faded222606a21425becaecceec5d785c75d06c7 100644 (file)
@@ -37,6 +37,7 @@ import com.vaadin.terminal.gwt.client.UIDL;
 import com.vaadin.terminal.gwt.client.Util;
 import com.vaadin.terminal.gwt.client.VConsole;
 import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
+import com.vaadin.terminal.gwt.client.metadata.NoDataException;
 import com.vaadin.terminal.gwt.client.metadata.Type;
 import com.vaadin.terminal.gwt.client.metadata.TypeData;
 import com.vaadin.terminal.gwt.client.ui.datefield.PopupDateFieldConnector;
@@ -80,9 +81,17 @@ public abstract class AbstractComponentConnector extends AbstractConnector
      */
     protected Widget createWidget() {
         Type type = TypeData.getType(getClass());
-        Type widgetType = type.getMethod("getWidget").getReturnType();
-        Object instance = widgetType.createInstance();
-        return (Widget) instance;
+        try {
+            Type widgetType = type.getMethod("getWidget").getReturnType();
+            Object instance = widgetType.createInstance();
+            return (Widget) instance;
+        } catch (NoDataException e) {
+            throw new IllegalStateException(
+                    "There is no information about the widget for "
+                            + Util.getSimpleName(this)
+                            + ". Did you remember to compile the right widgetset?",
+                    e);
+        }
     }
 
     /**
index 9efa7bad0d7952ddfaf10376c20e811b04f3c204..b861ade0bfbaeeb94f247616bd0577168c3abc00 100644 (file)
@@ -33,6 +33,7 @@ import com.vaadin.terminal.gwt.client.Util;
 import com.vaadin.terminal.gwt.client.VConsole;
 import com.vaadin.terminal.gwt.client.communication.StateChangeEvent;
 import com.vaadin.terminal.gwt.client.communication.StateChangeEvent.StateChangeHandler;
+import com.vaadin.terminal.gwt.client.metadata.NoDataException;
 import com.vaadin.terminal.gwt.client.metadata.Type;
 import com.vaadin.terminal.gwt.client.metadata.TypeData;
 
@@ -268,9 +269,19 @@ public abstract class AbstractConnector implements ServerConnector,
      */
     protected SharedState createState() {
         Type connectorType = TypeData.getType(getClass());
-        Type stateType = connectorType.getMethod("getState").getReturnType();
-        Object stateInstance = stateType.createInstance();
-        return (SharedState) stateInstance;
+        try {
+            Type stateType = connectorType.getMethod("getState")
+                    .getReturnType();
+            Object stateInstance = stateType.createInstance();
+            return (SharedState) stateInstance;
+        } catch (NoDataException e) {
+            throw new IllegalStateException(
+                    "There is no information about the state for "
+                            + Util.getSimpleName(this)
+                            + ". Did you remember to compile the right widgetset?",
+                    e);
+        }
+
     }
 
     @Override