diff options
Diffstat (limited to 'server/src/com')
10 files changed, 89 insertions, 40 deletions
diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java index 39329c32ce..34c9b5b767 100644 --- a/server/src/com/vaadin/server/Constants.java +++ b/server/src/com/vaadin/server/Constants.java @@ -126,6 +126,7 @@ public interface Constants { static final String SERVLET_PARAMETER_PUSH_MODE = "pushMode"; static final String SERVLET_PARAMETER_UI_PROVIDER = "UIProvider"; static final String SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING = "legacyPropertyToString"; + static final String SERVLET_PARAMETER_SYNC_ID_CHECK = "syncIdCheck"; // Configurable parameter names static final String PARAMETER_VAADIN_RESOURCES = "Resources"; diff --git a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java index e72b411720..fd14c3cd3f 100644 --- a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java +++ b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java @@ -51,6 +51,13 @@ public class DefaultDeploymentConfiguration implements DeploymentConfiguration { */ public static final LegacyProperyToStringMode DEFAULT_LEGACY_PROPERTY_TO_STRING = LegacyProperyToStringMode.WARNING; + /** + * Default value for {@link #isSyncIdCheckEnabled()} = {@value} . + * + * @since 7.3 + */ + public static final boolean DEFAULT_SYNC_ID_CHECK = true; + private final Properties initParameters; private boolean productionMode; private boolean xsrfProtectionEnabled; @@ -60,6 +67,7 @@ public class DefaultDeploymentConfiguration implements DeploymentConfiguration { private PushMode pushMode; private final Class<?> systemPropertyBaseClass; private LegacyProperyToStringMode legacyPropertyToStringMode; + private boolean syncIdCheck; /** * Create a new deployment configuration instance. @@ -83,6 +91,7 @@ public class DefaultDeploymentConfiguration implements DeploymentConfiguration { checkCloseIdleSessions(); checkPushMode(); checkLegacyPropertyToString(); + checkSyncIdCheck(); } private void checkLegacyPropertyToString() { @@ -238,6 +247,16 @@ public class DefaultDeploymentConfiguration implements DeploymentConfiguration { /** * {@inheritDoc} * <p> + * The default value is <code>true</code>. + */ + @Override + public boolean isSyncIdCheckEnabled() { + return syncIdCheck; + } + + /** + * {@inheritDoc} + * <p> * The default mode is {@link PushMode#DISABLED}. */ @Override @@ -321,6 +340,12 @@ public class DefaultDeploymentConfiguration implements DeploymentConfiguration { } } + private void checkSyncIdCheck() { + syncIdCheck = getApplicationOrSystemProperty( + Constants.SERVLET_PARAMETER_SYNC_ID_CHECK, + Boolean.toString(DEFAULT_SYNC_ID_CHECK)).equals("true"); + } + private Logger getLogger() { return Logger.getLogger(getClass().getName()); } diff --git a/server/src/com/vaadin/server/DeploymentConfiguration.java b/server/src/com/vaadin/server/DeploymentConfiguration.java index b600d01cbd..fcfeecc31f 100644 --- a/server/src/com/vaadin/server/DeploymentConfiguration.java +++ b/server/src/com/vaadin/server/DeploymentConfiguration.java @@ -85,6 +85,17 @@ public interface DeploymentConfiguration extends Serializable { public boolean isXsrfProtectionEnabled(); /** + * Returns whether sync id checking is enabled. The sync id is used to + * gracefully handle situations when the client sends a message to a + * connector that has recently been removed on the server. + * + * @since 7.3 + * @return <code>true</code> if sync id checking is enabled; + * <code>false</code> otherwise + */ + public boolean isSyncIdCheckEnabled(); + + /** * Returns the time resources can be cached in the browsers, in seconds. * * @return The resource cache time. diff --git a/server/src/com/vaadin/server/VaadinPortletRequest.java b/server/src/com/vaadin/server/VaadinPortletRequest.java index e1b521d57f..93e06d7f45 100644 --- a/server/src/com/vaadin/server/VaadinPortletRequest.java +++ b/server/src/com/vaadin/server/VaadinPortletRequest.java @@ -247,7 +247,7 @@ public class VaadinPortletRequest extends PortletRequestWrapper implements * * @return the current portlet request instance if available, otherwise * <code>null</code> - * + * @since 7.3 */ public static PortletRequest getCurrentPortletRequest() { return VaadinPortletService.getCurrentPortletRequest(); @@ -262,7 +262,7 @@ public class VaadinPortletRequest extends PortletRequestWrapper implements * * @return the current Vaadin portlet request instance if available, * otherwise <code>null</code> - * + * @since 7.3 */ public static VaadinPortletRequest getCurrent() { return VaadinPortletService.getCurrentRequest(); diff --git a/server/src/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/com/vaadin/server/communication/ServerRpcHandler.java index 89d87567d7..36bfc8bcc6 100644 --- a/server/src/com/vaadin/server/communication/ServerRpcHandler.java +++ b/server/src/com/vaadin/server/communication/ServerRpcHandler.java @@ -75,10 +75,16 @@ public class ServerRpcHandler implements Serializable { private final int syncId; private final JSONObject json; - public RpcRequest(String jsonString) throws JSONException { + public RpcRequest(String jsonString, VaadinRequest request) + throws JSONException { json = new JSONObject(jsonString); csrfToken = json.getString(ApplicationConstants.CSRF_TOKEN); - syncId = json.getInt(ApplicationConstants.SERVER_SYNC_ID); + if (request.getService().getDeploymentConfiguration() + .isSyncIdCheckEnabled()) { + syncId = json.getInt(ApplicationConstants.SERVER_SYNC_ID); + } else { + syncId = -1; + } invocations = new JSONArray( json.getString(ApplicationConstants.RPC_INVOCATIONS)); } @@ -157,7 +163,7 @@ public class ServerRpcHandler implements Serializable { return; } - RpcRequest rpcRequest = new RpcRequest(changeMessage); + RpcRequest rpcRequest = new RpcRequest(changeMessage, request); // Security: double cookie submission pattern unless disabled by // property diff --git a/server/src/com/vaadin/server/communication/UidlWriter.java b/server/src/com/vaadin/server/communication/UidlWriter.java index 00522e2aa5..9d55f7e197 100644 --- a/server/src/com/vaadin/server/communication/UidlWriter.java +++ b/server/src/com/vaadin/server/communication/UidlWriter.java @@ -37,6 +37,7 @@ import com.vaadin.server.JsonPaintTarget; import com.vaadin.server.LegacyCommunicationManager; import com.vaadin.server.LegacyCommunicationManager.ClientCache; import com.vaadin.server.SystemMessages; +import com.vaadin.server.VaadinService; import com.vaadin.server.VaadinSession; import com.vaadin.shared.ApplicationConstants; import com.vaadin.ui.ConnectorTracker; @@ -75,10 +76,11 @@ public class UidlWriter implements Serializable { public void write(UI ui, Writer writer, boolean repaintAll, boolean async) throws IOException, JSONException { VaadinSession session = ui.getSession(); + VaadinService service = session.getService(); // Purge pending access calls as they might produce additional changes // to write out - session.getService().runPendingAccessTasks(session); + service.runPendingAccessTasks(session); ArrayList<ClientConnector> dirtyVisibleConnectors = ui .getConnectorTracker().getDirtyVisibleConnectors(); @@ -99,8 +101,12 @@ public class UidlWriter implements Serializable { uiConnectorTracker.setWritingResponse(true); try { + + int syncId = service.getDeploymentConfiguration() + .isSyncIdCheckEnabled() ? uiConnectorTracker + .getCurrentSyncId() : -1; writer.write("\"" + ApplicationConstants.SERVER_SYNC_ID + "\": " - + uiConnectorTracker.getCurrentSyncId() + ", "); + + syncId + ", "); writer.write("\"changes\" : "); diff --git a/server/src/com/vaadin/ui/AbstractSplitPanel.java b/server/src/com/vaadin/ui/AbstractSplitPanel.java index 1c69ebf87e..09f881cf46 100644 --- a/server/src/com/vaadin/ui/AbstractSplitPanel.java +++ b/server/src/com/vaadin/ui/AbstractSplitPanel.java @@ -335,7 +335,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { * @return position of the splitter */ public float getSplitPosition() { - return getSplitterState().position; + return getSplitterState(false).position; } /** @@ -358,7 +358,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { * Allowed units are UNITS_PERCENTAGE and UNITS_PIXELS */ public void setMinSplitPosition(float pos, Unit unit) { - setSplitPositionLimits(pos, unit, getSplitterState().maxPosition, + setSplitPositionLimits(pos, unit, getSplitterState(false).maxPosition, posMaxUnit); } @@ -369,7 +369,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { * @return the minimum position of the splitter */ public float getMinSplitPosition() { - return getSplitterState().minPosition; + return getSplitterState(false).minPosition; } /** @@ -392,8 +392,8 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { * Allowed units are UNITS_PERCENTAGE and UNITS_PIXELS */ public void setMaxSplitPosition(float pos, Unit unit) { - setSplitPositionLimits(getSplitterState().minPosition, posMinUnit, pos, - unit); + setSplitPositionLimits(getSplitterState(false).minPosition, posMinUnit, + pos, unit); } /** @@ -403,7 +403,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { * @return the maximum position of the splitter */ public float getMaxSplitPosition() { - return getSplitterState().maxPosition; + return getSplitterState(false).maxPosition; } /** @@ -467,7 +467,7 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { * @return <code>true</code> if locked, <code>false</code> otherwise. */ public boolean isLocked() { - return getSplitterState().locked; + return getSplitterState(false).locked; } /** @@ -540,6 +540,10 @@ public abstract class AbstractSplitPanel extends AbstractComponentContainer { } private SplitterState getSplitterState() { - return getState(false).splitterState; + return ((AbstractSplitPanelState) super.getState()).splitterState; + } + + private SplitterState getSplitterState(boolean markAsDirty) { + return ((AbstractSplitPanelState) super.getState(markAsDirty)).splitterState; } } diff --git a/server/src/com/vaadin/ui/ConnectorTracker.java b/server/src/com/vaadin/ui/ConnectorTracker.java index f7eae0013a..c0f973106b 100644 --- a/server/src/com/vaadin/ui/ConnectorTracker.java +++ b/server/src/com/vaadin/ui/ConnectorTracker.java @@ -774,7 +774,7 @@ public class ConnectorTracker implements Serializable { * concurrently or not. * @param lastSyncIdSeenByClient * the most recent sync id the client has seen at the time the - * request was sent + * request was sent, or -1 to ignore potential problems * @return <code>true</code> if the connector was removed before the client * had a chance to react to it. */ @@ -784,7 +784,8 @@ public class ConnectorTracker implements Serializable { assert getConnector(connectorId) == null : "Connector " + connectorId + " is still attached"; - boolean clientRequestIsTooOld = lastSyncIdSeenByClient < currentSyncId; + boolean clientRequestIsTooOld = lastSyncIdSeenByClient < currentSyncId + && lastSyncIdSeenByClient != -1; if (clientRequestIsTooOld) { /* * The headMap call is present here because we're only interested in @@ -823,6 +824,9 @@ public class ConnectorTracker implements Serializable { * packet is sent. If the state has changed on the server side since that, * the server can try to adjust the way it handles the actions from the * client side. + * <p> + * The sync id value <code>-1</code> is ignored to facilitate testing with + * pre-recorded requests. * * @see #setWritingResponse(boolean) * @see #connectorWasPresentAsRequestWasSent(String, long) @@ -846,6 +850,9 @@ public class ConnectorTracker implements Serializable { * Entries that both client and server agree upon are removed. Since * argument is the last sync id that the client has seen from the server, we * know that entries earlier than that cannot cause any problems anymore. + * <p> + * The sync id value <code>-1</code> is ignored to facilitate testing with + * pre-recorded requests. * * @see #connectorWasPresentAsRequestWasSent(String, long) * @since 7.2 @@ -854,6 +861,12 @@ public class ConnectorTracker implements Serializable { * server. */ public void cleanConcurrentlyRemovedConnectorIds(int lastSyncIdSeenByClient) { + if (lastSyncIdSeenByClient == -1) { + // Sync id checking is not in use, so we should just clear the + // entire map to avoid leaking memory + syncIdToUnregisteredConnectorIds.clear(); + return; + } /* * We remove all entries _older_ than the one reported right now, * because the remaining still contain components that might cause diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index 4bde8a95b3..a72cbe5c30 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -549,6 +549,8 @@ public abstract class UI extends AbstractSingleComponentContainer implements private boolean resizeLazy = false; + private String theme; + private Navigator navigator; private PushConnection pushConnection = null; @@ -631,7 +633,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements this.embedId = embedId; // Actual theme - used for finding CustomLayout templates - getState(false).theme = request.getParameter("theme"); + theme = request.getParameter("theme"); getPage().init(request); @@ -1133,31 +1135,12 @@ public abstract class UI extends AbstractSingleComponentContainer implements } /** - * Gets the theme currently in use by this UI + * Gets the theme that was used when the UI was initialized. * * @return the theme name */ public String getTheme() { - return getState(false).theme; - } - - /** - * Sets the theme currently in use by this UI - * <p> - * Calling this method will remove the old theme (CSS file) from the - * application and add the new theme. - * <p> - * Note that this method is NOT SAFE to call in a portal environment or - * other environment where there are multiple UIs on the same page. The old - * CSS file will be removed even if there are other UIs on the page which - * are still using it. - * - * @since - * @param theme - * The new theme name - */ - public void setTheme(String theme) { - getState().theme = theme; + return theme; } /** diff --git a/server/src/com/vaadin/ui/themes/ValoTheme.java b/server/src/com/vaadin/ui/themes/ValoTheme.java index 51e2e283f2..63fa13dce4 100644 --- a/server/src/com/vaadin/ui/themes/ValoTheme.java +++ b/server/src/com/vaadin/ui/themes/ValoTheme.java @@ -38,7 +38,7 @@ import com.vaadin.ui.Table.ColumnHeaderMode; * * TODO link to Sass API documentation * - * @since 7.3.0 + * @since 7.3 * @author Vaadin Ltd */ public class ValoTheme { |