summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2012-06-14 22:57:28 +0300
committerLeif Åstrand <leif@vaadin.com>2012-06-14 22:57:28 +0300
commit51ce4a2535146a3b8861bd02f655c18d9a397522 (patch)
tree2c4421863c5255b1595111c6e968b0a84f1c9f4b /src/com
parent72c0f66e2aa588acbb517e6d9b482c7a75faf9f1 (diff)
downloadvaadin-framework-51ce4a2535146a3b8861bd02f655c18d9a397522.tar.gz
vaadin-framework-51ce4a2535146a3b8861bd02f655c18d9a397522.zip
Implement js rpc proxy objects and wildcard rpc support (#8888)
Diffstat (limited to 'src/com')
-rw-r--r--src/com/vaadin/terminal/AbstractJavaScriptExtension.java7
-rw-r--r--src/com/vaadin/terminal/JavaScriptCallbackHelper.java22
-rw-r--r--src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java133
-rw-r--r--src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java5
-rw-r--r--src/com/vaadin/terminal/gwt/client/JavaScriptExtensionState.java10
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java5
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentState.java11
-rw-r--r--src/com/vaadin/ui/AbstractJavaScriptComponent.java7
8 files changed, 176 insertions, 24 deletions
diff --git a/src/com/vaadin/terminal/AbstractJavaScriptExtension.java b/src/com/vaadin/terminal/AbstractJavaScriptExtension.java
index 22c8dd4561..a2f8019858 100644
--- a/src/com/vaadin/terminal/AbstractJavaScriptExtension.java
+++ b/src/com/vaadin/terminal/AbstractJavaScriptExtension.java
@@ -11,6 +11,13 @@ public class AbstractJavaScriptExtension extends AbstractExtension {
private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper(
this);
+ @Override
+ protected <T> void registerRpc(T implementation,
+ java.lang.Class<T> rpcInterfaceType) {
+ super.registerRpc(implementation, rpcInterfaceType);
+ callbackHelper.registerRpc(rpcInterfaceType);
+ }
+
protected void registerCallback(String functionName,
JavaScriptCallback javaScriptCallback) {
callbackHelper.registerCallback(functionName, javaScriptCallback);
diff --git a/src/com/vaadin/terminal/JavaScriptCallbackHelper.java b/src/com/vaadin/terminal/JavaScriptCallbackHelper.java
index c1da8b36ba..eabbcf4925 100644
--- a/src/com/vaadin/terminal/JavaScriptCallbackHelper.java
+++ b/src/com/vaadin/terminal/JavaScriptCallbackHelper.java
@@ -7,7 +7,9 @@ package com.vaadin.terminal;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import com.vaadin.external.json.JSONArray;
import com.vaadin.external.json.JSONException;
@@ -75,4 +77,24 @@ public class JavaScriptCallbackHelper {
connector.requestRepaint();
}
+ public void registerRpc(Class<?> rpcInterfaceType) {
+ if (rpcInterfaceType == JavaScriptCallbackRpc.class) {
+ // Ignore
+ return;
+ }
+ Map<String, Set<String>> rpcInterfaces = getConnectorState()
+ .getRpcInterfaces();
+ String interfaceName = rpcInterfaceType.getName();
+ if (!rpcInterfaces.containsKey(interfaceName)) {
+ Set<String> methodNames = new HashSet<String>();
+
+ for (Method method : rpcInterfaceType.getMethods()) {
+ methodNames.add(method.getName());
+ }
+
+ rpcInterfaces.put(interfaceName, methodNames);
+ connector.requestRepaint();
+ }
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java b/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java
index d07cf0036c..77adcd4217 100644
--- a/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java
+++ b/src/com/vaadin/terminal/gwt/client/JavaScriptConnectorHelper.java
@@ -5,6 +5,10 @@
package com.vaadin.terminal.gwt.client;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import com.google.gwt.core.client.JavaScriptObject;
@@ -18,6 +22,8 @@ public class JavaScriptConnectorHelper {
public interface JavaScriptConnectorState {
public Set<String> getCallbackNames();
+
+ public Map<String, Set<String>> getRpcInterfaces();
}
private final ServerConnector connector;
@@ -25,26 +31,80 @@ public class JavaScriptConnectorHelper {
.createObject();
private final JavaScriptObject rpcMap = JavaScriptObject.createObject();
+ private final Map<String, JavaScriptObject> rpcObjects = new HashMap<String, JavaScriptObject>();
+ private final Map<String, Set<String>> rpcMethods = new HashMap<String, Set<String>>();
+
private JavaScriptObject connectorWrapper;
private int tag;
+ private boolean inited = false;
+
public JavaScriptConnectorHelper(ServerConnector connector) {
this.connector = connector;
+
+ // Wildcard rpc object
+ rpcObjects.put("", JavaScriptObject.createObject());
+
connector.addStateChangeHandler(new StateChangeHandler() {
public void onStateChanged(StateChangeEvent stateChangeEvent) {
JavaScriptObject wrapper = getConnectorWrapper();
+ JavaScriptConnectorState state = getConnectorState();
- for (String callback : getConnectorState().getCallbackNames()) {
+ for (String callback : state.getCallbackNames()) {
ensureCallback(JavaScriptConnectorHelper.this, wrapper,
callback);
}
+ for (Entry<String, Set<String>> entry : state
+ .getRpcInterfaces().entrySet()) {
+ String rpcName = entry.getKey();
+ String jsName = getJsInterfaceName(rpcName);
+ if (!rpcObjects.containsKey(jsName)) {
+ Set<String> methods = entry.getValue();
+ rpcObjects.put(jsName,
+ createRpcObject(rpcName, methods));
+
+ // Init all methods for wildcard rpc
+ for (String method : methods) {
+ JavaScriptObject wildcardRpcObject = rpcObjects
+ .get("");
+ Set<String> interfaces = rpcMethods.get(method);
+ if (interfaces == null) {
+ interfaces = new HashSet<String>();
+ rpcMethods.put(method, interfaces);
+ attachRpcMethod(wildcardRpcObject, null, method);
+ }
+ interfaces.add(rpcName);
+ }
+ }
+ }
+
+ // Init after setting up callbacks & rpc
+ if (!inited) {
+ init();
+ inited = true;
+ }
+
fireNativeStateChange(wrapper);
}
});
}
- public boolean init() {
+ private static String getJsInterfaceName(String rpcName) {
+ return rpcName.replace('$', '.');
+ }
+
+ protected JavaScriptObject createRpcObject(String iface, Set<String> methods) {
+ JavaScriptObject object = JavaScriptObject.createObject();
+
+ for (String method : methods) {
+ attachRpcMethod(object, iface, method);
+ }
+
+ return object;
+ }
+
+ private boolean init() {
ApplicationConfiguration conf = connector.getConnection()
.getConfiguration();
ArrayList<String> attemptedNames = new ArrayList<String>();
@@ -94,7 +154,7 @@ public class JavaScriptConnectorHelper {
protected JavaScriptObject createConnectorWrapper() {
return createConnectorWrapper(this, nativeState, rpcMap,
- connector.getConnectorId());
+ connector.getConnectorId(), rpcObjects);
}
private static native void fireNativeStateChange(
@@ -107,7 +167,8 @@ public class JavaScriptConnectorHelper {
private static native JavaScriptObject createConnectorWrapper(
JavaScriptConnectorHelper h, JavaScriptObject nativeState,
- JavaScriptObject registeredRpc, String connectorId)
+ JavaScriptObject registeredRpc, String connectorId,
+ Map<String, JavaScriptObject> rpcObjects)
/*-{
return {
'getConnectorId': function() {
@@ -116,12 +177,18 @@ public class JavaScriptConnectorHelper {
'getState': function() {
return nativeState;
},
- 'getRpcProxyFunction': function(iface, method) {
- return $entry(function() {
- h.@com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper::fireRpc(Ljava/lang/String;Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;)(iface, method, arguments);
- });
+ 'getRpcProxy': function(iface) {
+ if (!iface) {
+ iface = '';
+ }
+ return rpcObjects.@java.util.Map::get(Ljava/lang/Object;)(iface);
},
'registerRpc': function(iface, rpcHandler) {
+ //registerRpc(handler) -> registerRpc('', handler);
+ if (!rpcHandler) {
+ rpcHandler = iface;
+ iface = '';
+ }
if (!registeredRpc[iface]) {
registeredRpc[iface] = [];
}
@@ -130,8 +197,21 @@ public class JavaScriptConnectorHelper {
};
}-*/;
+ private native void attachRpcMethod(JavaScriptObject rpc, String iface,
+ String method)
+ /*-{
+ var self = this;
+ rpc[method] = $entry(function() {
+ self.@com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper::fireRpc(Ljava/lang/String;Ljava/lang/String;Lcom/google/gwt/core/client/JsArray;)(iface, method, arguments);
+ });
+ }-*/;
+
private void fireRpc(String iface, String method,
JsArray<JavaScriptObject> arguments) {
+ if (iface == null) {
+ iface = findWildcardInterface(method);
+ }
+
JSONArray argumentsArray = new JSONArray(arguments);
Object[] parameters = new Object[arguments.length()];
for (int i = 0; i < parameters.length; i++) {
@@ -142,6 +222,29 @@ public class JavaScriptConnectorHelper {
parameters), true);
}
+ private String findWildcardInterface(String method) {
+ Set<String> interfaces = rpcMethods.get(method);
+ if (interfaces.size() == 1) {
+ return interfaces.iterator().next();
+ } else {
+ // TODO Resolve conflicts using argument count and types
+ String interfaceList = "";
+ for (String iface : interfaces) {
+ if (interfaceList.length() != 0) {
+ interfaceList += ", ";
+ }
+ interfaceList += getJsInterfaceName(iface);
+ }
+
+ throw new IllegalStateException(
+ "Can not call method "
+ + method
+ + " for wildcard rpc proxy because the function is defined for multiple rpc interfaces: "
+ + interfaceList
+ + ". Retrieve a rpc proxy for a specific interface using getRpcProxy(interfaceName) to use the function.");
+ }
+ }
+
private void fireCallback(String name, JsArray<JavaScriptObject> arguments) {
MethodInvocation invocation = new MethodInvocation(
connector.getConnectorId(),
@@ -181,18 +284,20 @@ public class JavaScriptConnectorHelper {
public void invokeJsRpc(MethodInvocation invocation,
JSONArray parametersJson) {
- if ("com.vaadin.ui.JavaScript$JavaScriptCallbackRpc".equals(invocation
- .getInterfaceName())
- && "call".equals(invocation.getMethodName())) {
+ String iface = invocation.getInterfaceName();
+ String method = invocation.getMethodName();
+ if ("com.vaadin.ui.JavaScript$JavaScriptCallbackRpc".equals(iface)
+ && "call".equals(method)) {
String callbackName = parametersJson.get(0).isString()
.stringValue();
JavaScriptObject arguments = parametersJson.get(1).isArray()
.getJavaScriptObject();
invokeCallback(getConnectorWrapper(), callbackName, arguments);
} else {
- invokeJsRpc(rpcMap, invocation.getInterfaceName(),
- invocation.getMethodName(),
- parametersJson.getJavaScriptObject());
+ JavaScriptObject arguments = parametersJson.getJavaScriptObject();
+ invokeJsRpc(rpcMap, iface, method, arguments);
+ // Also invoke wildcard interface
+ invokeJsRpc(rpcMap, "", method, arguments);
}
}
diff --git a/src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java b/src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java
index 47aa7eab28..e3dafab9bd 100644
--- a/src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java
+++ b/src/com/vaadin/terminal/gwt/client/JavaScriptExtension.java
@@ -15,11 +15,6 @@ public class JavaScriptExtension extends AbstractExtensionConnector implements
private final JavaScriptConnectorHelper helper = new JavaScriptConnectorHelper(
this);
- @Override
- protected void init() {
- helper.init();
- }
-
public JavaScriptConnectorHelper getJavascriptConnectorHelper() {
return helper;
}
diff --git a/src/com/vaadin/terminal/gwt/client/JavaScriptExtensionState.java b/src/com/vaadin/terminal/gwt/client/JavaScriptExtensionState.java
index fecf24d450..e7bfbc4bb2 100644
--- a/src/com/vaadin/terminal/gwt/client/JavaScriptExtensionState.java
+++ b/src/com/vaadin/terminal/gwt/client/JavaScriptExtensionState.java
@@ -4,7 +4,9 @@
package com.vaadin.terminal.gwt.client;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import com.vaadin.terminal.gwt.client.JavaScriptConnectorHelper.JavaScriptConnectorState;
@@ -14,6 +16,7 @@ public class JavaScriptExtensionState extends SharedState implements
JavaScriptConnectorState {
private Set<String> callbackNames = new HashSet<String>();
+ private Map<String, Set<String>> rpcInterfaces = new HashMap<String, Set<String>>();
public Set<String> getCallbackNames() {
return callbackNames;
@@ -23,4 +26,11 @@ public class JavaScriptExtensionState extends SharedState implements
this.callbackNames = callbackNames;
}
+ public Map<String, Set<String>> getRpcInterfaces() {
+ return rpcInterfaces;
+ }
+
+ public void setRpcInterfaces(Map<String, Set<String>> rpcInterfaces) {
+ this.rpcInterfaces = rpcInterfaces;
+ }
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java
index ecab58bb9a..47afe95771 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentConnector.java
@@ -29,11 +29,6 @@ public class JavaScriptComponentConnector extends AbstractComponentConnector
}
};
- @Override
- protected void init() {
- helper.init();
- }
-
private static native void addGetWidgetElement(
JavaScriptObject connectorWrapper, Element element)
/*-{
diff --git a/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentState.java b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentState.java
index bc8ed08bba..6728f85ec9 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentState.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/JavaScriptComponentState.java
@@ -4,7 +4,9 @@
package com.vaadin.terminal.gwt.client.ui;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import com.vaadin.terminal.gwt.client.ComponentState;
@@ -14,6 +16,7 @@ public class JavaScriptComponentState extends ComponentState implements
JavaScriptConnectorState {
private Set<String> callbackNames = new HashSet<String>();
+ private Map<String, Set<String>> rpcInterfaces = new HashMap<String, Set<String>>();
public Set<String> getCallbackNames() {
return callbackNames;
@@ -23,4 +26,12 @@ public class JavaScriptComponentState extends ComponentState implements
this.callbackNames = callbackNames;
}
+ public Map<String, Set<String>> getRpcInterfaces() {
+ return rpcInterfaces;
+ }
+
+ public void setRpcInterfaces(Map<String, Set<String>> rpcInterfaces) {
+ this.rpcInterfaces = rpcInterfaces;
+ }
+
}
diff --git a/src/com/vaadin/ui/AbstractJavaScriptComponent.java b/src/com/vaadin/ui/AbstractJavaScriptComponent.java
index e5759a1efc..343caf4abb 100644
--- a/src/com/vaadin/ui/AbstractJavaScriptComponent.java
+++ b/src/com/vaadin/ui/AbstractJavaScriptComponent.java
@@ -10,6 +10,13 @@ public class AbstractJavaScriptComponent extends AbstractComponent {
private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper(
this);
+ @Override
+ protected <T> void registerRpc(T implementation,
+ java.lang.Class<T> rpcInterfaceType) {
+ super.registerRpc(implementation, rpcInterfaceType);
+ callbackHelper.registerRpc(rpcInterfaceType);
+ }
+
protected void registerCallback(String functionName,
JavaScriptCallback javascriptCallback) {
callbackHelper.registerCallback(functionName, javascriptCallback);