From: Henri Sara Date: Wed, 18 Jan 2012 12:23:06 +0000 (+0200) Subject: #8277 Refactor client to server communication in preparation for RPC. X-Git-Tag: 7.0.0.alpha2~440^2~41 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=67f7691fb28cdafa5f6f83e26d47ec69bffa072d;p=vaadin-framework.git #8277 Refactor client to server communication in preparation for RPC. --- diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index af3fcefaf2..a7f146be16 100644 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -36,6 +36,7 @@ import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConfiguration.ErrorMessage; import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize; import com.vaadin.terminal.gwt.client.RenderInformation.Size; +import com.vaadin.terminal.gwt.client.communication.MethodInvocation; import com.vaadin.terminal.gwt.client.ui.Field; import com.vaadin.terminal.gwt.client.ui.VContextMenu; import com.vaadin.terminal.gwt.client.ui.VNotification; @@ -73,6 +74,8 @@ public class ApplicationConnection { private static final String ERROR_CLASSNAME_EXT = "-error"; + public static final String UPDATE_VARIABLE_METHOD = "v"; + public static final char VAR_RECORD_SEPARATOR = '\u001e'; public static final char VAR_FIELD_SEPARATOR = '\u001f'; @@ -106,7 +109,7 @@ public class ApplicationConnection { private final HashMap resourcesMap = new HashMap(); - private final ArrayList pendingVariables = new ArrayList(); + private ArrayList pendingInvocations = new ArrayList(); private WidgetSet widgetSet; @@ -129,7 +132,7 @@ public class ApplicationConnection { private ApplicationConfiguration configuration; /** List of pending variable change bursts that must be submitted in order */ - private final ArrayList> pendingVariableBursts = new ArrayList>(); + private final ArrayList> pendingBursts = new ArrayList>(); /** Timer for automatic refirect to SessionExpiredURL */ private Timer redirectTimer; @@ -750,14 +753,14 @@ public class ApplicationConnection { * change set if it exists. */ private void checkForPendingVariableBursts() { - cleanVariableBurst(pendingVariables); - if (pendingVariableBursts.size() > 0) { - for (Iterator> iterator = pendingVariableBursts + cleanVariableBurst(pendingInvocations); + if (pendingBursts.size() > 0) { + for (Iterator> iterator = pendingBursts .iterator(); iterator.hasNext();) { cleanVariableBurst(iterator.next()); } - ArrayList nextBurst = pendingVariableBursts.get(0); - pendingVariableBursts.remove(0); + ArrayList nextBurst = pendingBursts.get(0); + pendingBursts.remove(0); buildAndSendVariableBurst(nextBurst, false); } } @@ -768,16 +771,13 @@ public class ApplicationConnection { * * @param variableBurst */ - private void cleanVariableBurst(ArrayList variableBurst) { - for (int i = 1; i < variableBurst.size(); i += 2) { - String id = variableBurst.get(i); - id = id.substring(0, id.indexOf(VAR_FIELD_SEPARATOR)); + private void cleanVariableBurst(ArrayList variableBurst) { + for (int i = 1; i < variableBurst.size(); i++) { + String id = variableBurst.get(i).getPaintableId(); if (!getPaintableMap().hasPaintable(id) && !getPaintableMap().isDragAndDropPaintable(id)) { // variable owner does not exist anymore - variableBurst.remove(i - 1); - variableBurst.remove(i - 1); - i -= 2; + variableBurst.remove(i); VConsole.log("Removed variable from removed component: " + id); } } @@ -1108,17 +1108,16 @@ public class ApplicationConnection { private void addVariableToQueue(String paintableId, String variableName, String encodedValue, boolean immediate, char type) { - final String id = paintableId + VAR_FIELD_SEPARATOR + variableName - + VAR_FIELD_SEPARATOR + type; - for (int i = 1; i < pendingVariables.size(); i += 2) { - if ((pendingVariables.get(i)).equals(id)) { - pendingVariables.remove(i - 1); - pendingVariables.remove(i - 1); - break; - } - } - pendingVariables.add(encodedValue); - pendingVariables.add(id); + // TODO could eliminate invocations of same shared variable setter + String param = variableName + VAR_FIELD_SEPARATOR + type + + VAR_FIELD_SEPARATOR + encodedValue; + addMethodInvocationToQueue(paintableId, new MethodInvocation( + paintableId, UPDATE_VARIABLE_METHOD, param), immediate); + } + + private void addMethodInvocationToQueue(String paintableId, + MethodInvocation invocation, boolean immediate) { + pendingInvocations.add(invocation); if (immediate) { sendPendingVariableChanges(); } @@ -1154,15 +1153,12 @@ public class ApplicationConnection { if (applicationRunning) { if (hasActiveRequest()) { // skip empty queues if there are pending bursts to be sent - if (pendingVariables.size() > 0 - || pendingVariableBursts.size() == 0) { - ArrayList burst = (ArrayList) pendingVariables - .clone(); - pendingVariableBursts.add(burst); - pendingVariables.clear(); + if (pendingInvocations.size() > 0 || pendingBursts.size() == 0) { + pendingBursts.add(pendingInvocations); + pendingInvocations = new ArrayList(); } } else { - buildAndSendVariableBurst(pendingVariables, false); + buildAndSendVariableBurst(pendingInvocations, false); } } } @@ -1174,35 +1170,38 @@ public class ApplicationConnection { * at the same time. This is ok as we can assume that DOM will never be * updated after this. * - * @param pendingVariables - * Vector of variable changes to send + * @param pendingInvocations + * List of RPC method invocations to send * @param forceSync * Should we use synchronous request? */ - private void buildAndSendVariableBurst(ArrayList pendingVariables, - boolean forceSync) { + private void buildAndSendVariableBurst( + ArrayList pendingInvocations, boolean forceSync) { final StringBuffer req = new StringBuffer(); - while (!pendingVariables.isEmpty()) { + while (!pendingInvocations.isEmpty()) { if (ApplicationConfiguration.isDebugMode()) { - Util.logVariableBurst(this, pendingVariables); + Util.logVariableBurst(this, pendingInvocations); } - for (int i = 0; i < pendingVariables.size(); i++) { + // TODO use JSON for messages + for (int i = 0; i < pendingInvocations.size(); i++) { if (i > 0) { - if (i % 2 == 0) { - req.append(VAR_RECORD_SEPARATOR); - } else { - req.append(VAR_FIELD_SEPARATOR); - } + req.append(VAR_RECORD_SEPARATOR); } - req.append(pendingVariables.get(i)); + MethodInvocation invocation = pendingInvocations.get(i); + req.append(invocation.getPaintableId()); + req.append(VAR_FIELD_SEPARATOR); + req.append(invocation.getMethodName()); + req.append(VAR_FIELD_SEPARATOR); + // TODO support multiple parameters + req.append(invocation.getParameters()); } - pendingVariables.clear(); - // Append all the busts to this synchronous request - if (forceSync && !pendingVariableBursts.isEmpty()) { - pendingVariables = pendingVariableBursts.get(0); - pendingVariableBursts.remove(0); + pendingInvocations.clear(); + // Append all the bursts to this synchronous request + if (forceSync && !pendingBursts.isEmpty()) { + pendingInvocations = pendingBursts.get(0); + pendingBursts.remove(0); req.append(VAR_BURST_SEPARATOR); } } diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java index 597ca3d49c..2789a73078 100644 --- a/src/com/vaadin/terminal/gwt/client/Util.java +++ b/src/com/vaadin/terminal/gwt/client/Util.java @@ -30,6 +30,7 @@ import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.RenderInformation.FloatSize; +import com.vaadin.terminal.gwt.client.communication.MethodInvocation; public class Util { @@ -936,45 +937,60 @@ public class Util { return idx; } - private static void printPaintablesVariables(ArrayList vars, - String id, ApplicationConnection c) { + private static void printPaintablesInvocations( + ArrayList invocations, String id, + ApplicationConnection c) { VPaintableWidget paintable = (VPaintableWidget) VPaintableMap.get(c) .getPaintable(id); if (paintable != null) { VConsole.log("\t" + id + " (" + paintable.getClass() + ") :"); - for (String[] var : vars) { - VConsole.log("\t\t" + var[1] + " (" + var[2] + ")" + " : " - + var[0]); + for (MethodInvocation invocation : invocations) { + String formattedParams = invocation.getParameters(); + if (ApplicationConnection.UPDATE_VARIABLE_METHOD + .equals(invocation.getMethodName())) { + // if an updateVariable call, format as variable changes + // ensure with limit that also trailing parameters are + // included + String[] split = invocation + .getParameters() + .split(String + .valueOf(ApplicationConnection.VAR_FIELD_SEPARATOR), + 3); + + // unless of correct length, do not reformat + if (split.length == 3) { + // TODO needs to be reworked + // name, type, value + formattedParams = split[0] + " (" + split[1] + ")" + + " : " + split[2]; + } + } + VConsole.log("\t\t" + invocation.getMethodName() + "(" + + formattedParams + ")"); } } } static void logVariableBurst(ApplicationConnection c, - ArrayList loggedBurst) { + ArrayList loggedBurst) { try { VConsole.log("Variable burst to be sent to server:"); String curId = null; - ArrayList vars = new ArrayList(); + ArrayList invocations = new ArrayList(); for (int i = 0; i < loggedBurst.size(); i++) { - String value = loggedBurst.get(i++); - String[] split = loggedBurst - .get(i) - .split(String - .valueOf(ApplicationConnection.VAR_FIELD_SEPARATOR)); - String id = split[0]; + String id = loggedBurst.get(i).getPaintableId(); if (curId == null) { curId = id; } else if (!curId.equals(id)) { - printPaintablesVariables(vars, curId, c); - vars.clear(); + printPaintablesInvocations(invocations, curId, c); + invocations.clear(); curId = id; } - split[0] = value; - vars.add(split); + invocations.add(loggedBurst.get(i)); } - if (!vars.isEmpty()) { - printPaintablesVariables(vars, curId, c); + if (!invocations.isEmpty()) { + printPaintablesInvocations(invocations, curId, c); } } catch (Exception e) { VConsole.error(e); diff --git a/src/com/vaadin/terminal/gwt/client/communication/MethodInvocation.java b/src/com/vaadin/terminal/gwt/client/communication/MethodInvocation.java new file mode 100644 index 0000000000..c07427fc9d --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/communication/MethodInvocation.java @@ -0,0 +1,34 @@ +package com.vaadin.terminal.gwt.client.communication; + +/** + * Information needed by the framework to send an RPC method invocation from the + * client to the server or vice versa. + * + * @since 7.0 + */ +public class MethodInvocation { + + private final String paintableId; + private final String methodName; + private final String parameters; + + // TODO Parameters should be an Object[]? + public MethodInvocation(String paintableId, String methodName, + String parameters) { + this.paintableId = paintableId; + this.methodName = methodName; + this.parameters = parameters; + } + + public String getPaintableId() { + return paintableId; + } + + public String getMethodName() { + return methodName; + } + + public String getParameters() { + return parameters; + } +} \ No newline at end of file diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index 86f2c7a2de..c71bb0ea10 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -123,10 +123,11 @@ public abstract class AbstractCommunicationManager implements private static final String WRITE_SECURITY_TOKEN_FLAG = "writeSecurityToken"; /* Variable records indexes */ - private static final int VAR_PID = 1; - private static final int VAR_NAME = 2; + private static final int VAR_PID = 0; + private static final int VAR_METHOD = 1; + private static final int VAR_VARNAME = 2; private static final int VAR_TYPE = 3; - private static final int VAR_VALUE = 0; + private static final int VAR_VALUE = 4; private static final char VTYPE_PAINTABLE = 'p'; private static final char VTYPE_BOOLEAN = 'b'; @@ -1151,8 +1152,7 @@ public abstract class AbstractCommunicationManager implements for (int bi = 1; bi < bursts.length; bi++) { final String burst = bursts[bi]; - success = handleVariableBurst(request, application2, success, - burst); + success = handleBurst(request, application2, success, burst); // In case that there were multiple bursts, we know that this is // a special synchronous case for closing window. Thus we are @@ -1182,14 +1182,16 @@ public abstract class AbstractCommunicationManager implements return success; } - public boolean handleVariableBurst(Object source, Application app, - boolean success, final String burst) { + public boolean handleBurst(Object source, Application app, boolean success, + final String burst) { // extract variables to two dim string array final String[] tmp = burst.split(String.valueOf(VAR_RECORD_SEPARATOR)); - final String[][] variableRecords = new String[tmp.length][4]; + // TODO support variable number of parameters + final String[][] variableRecords = new String[tmp.length][5]; for (int i = 0; i < tmp.length; i++) { - variableRecords[i] = tmp[i].split(String - .valueOf(VAR_FIELD_SEPARATOR)); + // ensure with limit that also trailing parameters are included + variableRecords[i] = tmp[i].split( + String.valueOf(VAR_FIELD_SEPARATOR), 5); } for (int i = 0; i < variableRecords.length; i++) { @@ -1199,6 +1201,12 @@ public abstract class AbstractCommunicationManager implements nextVariable = variableRecords[i + 1]; } final VariableOwner owner = getVariableOwner(variable[VAR_PID]); + final String methodName = variable[VAR_METHOD]; + if (!ApplicationConnection.UPDATE_VARIABLE_METHOD + .equals(methodName)) { + // TODO handle other RPC calls + continue; + } if (owner != null && owner.isEnabled()) { Map m; if (nextVariable != null @@ -1206,13 +1214,13 @@ public abstract class AbstractCommunicationManager implements // we have more than one value changes in row for // one variable owner, collect them in HashMap m = new HashMap(); - m.put(variable[VAR_NAME], + m.put(variable[VAR_VARNAME], convertVariableValue(variable[VAR_TYPE].charAt(0), variable[VAR_VALUE])); } else { // use optimized single value map m = Collections.singletonMap( - variable[VAR_NAME], + variable[VAR_VARNAME], convertVariableValue(variable[VAR_TYPE].charAt(0), variable[VAR_VALUE])); } @@ -1227,7 +1235,7 @@ public abstract class AbstractCommunicationManager implements } else { nextVariable = null; } - m.put(variable[VAR_NAME], + m.put(variable[VAR_VARNAME], convertVariableValue(variable[VAR_TYPE].charAt(0), variable[VAR_VALUE])); } @@ -1246,7 +1254,7 @@ public abstract class AbstractCommunicationManager implements // Handle special case where window-close is called // after the window has been removed from the // application or the application has closed - if ("close".equals(variable[VAR_NAME]) + if ("close".equals(variable[VAR_VARNAME]) && "true".equals(variable[VAR_VALUE])) { // Silently ignore this continue;