summaryrefslogtreecommitdiffstats
path: root/client-compiler
diff options
context:
space:
mode:
Diffstat (limited to 'client-compiler')
-rw-r--r--client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/ConnectorBundleLoaderFactory.java116
-rw-r--r--client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/GeneratedRpcMethodProviderGenerator.java223
-rw-r--r--client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/SerializerGenerator.java6
-rw-r--r--client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ClientRpcVisitor.java39
-rw-r--r--client-compiler/src/com/vaadin/terminal/gwt/widgetsetutils/metadata/ConnectorBundle.java79
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