From c7ae45cc2404c2eab557866f310a2bb2130ddffe Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Tue, 15 Oct 2013 09:33:43 +0300 Subject: Validate that the connector is enabled before triggering actions for it (#12743) Automated test enabled only for IE9-IE11 because of #12785 Change-Id: I265e5d1ead3fa56469861c5a98dcc9d0106d1051 --- .../com/vaadin/event/ConnectorActionManager.java | 88 ++++++++++++++++++++++ .../server/communication/ServerRpcHandler.java | 33 +++++--- server/src/com/vaadin/ui/AbstractComponent.java | 5 +- server/src/com/vaadin/ui/Button.java | 2 +- 4 files changed, 116 insertions(+), 12 deletions(-) create mode 100644 server/src/com/vaadin/event/ConnectorActionManager.java (limited to 'server') diff --git a/server/src/com/vaadin/event/ConnectorActionManager.java b/server/src/com/vaadin/event/ConnectorActionManager.java new file mode 100644 index 0000000000..297f78f179 --- /dev/null +++ b/server/src/com/vaadin/event/ConnectorActionManager.java @@ -0,0 +1,88 @@ +/* + * Copyright 2000-2013 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.event; + +import java.util.logging.Logger; + +import com.vaadin.event.Action.Container; +import com.vaadin.server.ClientConnector; +import com.vaadin.server.VariableOwner; +import com.vaadin.server.communication.ServerRpcHandler; +import com.vaadin.ui.Component; + +/** + * An ActionManager connected to a connector. Takes care of verifying that the + * connector can receive events before triggering an action. + *

+ * This is mostly a workaround until shortcut actions are re-implemented in a + * more sensible way. + * + * @since 7.1.8 + * @author Vaadin Ltd + */ +public class ConnectorActionManager extends ActionManager { + + private ClientConnector connector; + + /** + * Initialize an action manager for the given connector. + * + * @param connector + * the owner of this action manager + */ + public ConnectorActionManager(ClientConnector connector) { + super(); + this.connector = connector; + } + + /** + * Initialize an action manager for the given connector using the given + * viewer. + * + * @param connector + * the owner of this action manager + * @param viewer + * the viewer connected + */ + public ConnectorActionManager( + ClientConnector connector, T viewer) { + super(viewer); + this.connector = connector; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.event.ActionManager#handleAction(com.vaadin.event.Action, + * java.lang.Object, java.lang.Object) + */ + @Override + public void handleAction(Action action, Object sender, Object target) { + if (!connector.isConnectorEnabled()) { + getLogger().warning( + ServerRpcHandler.getIgnoredDisabledError("action", + connector)); + return; + } + + super.handleAction(action, sender, target); + } + + private static final Logger getLogger() { + return Logger.getLogger(ConnectorActionManager.class.getName()); + } + +} diff --git a/server/src/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/com/vaadin/server/communication/ServerRpcHandler.java index 3cc85909ee..f14d703454 100644 --- a/server/src/com/vaadin/server/communication/ServerRpcHandler.java +++ b/server/src/com/vaadin/server/communication/ServerRpcHandler.java @@ -182,15 +182,8 @@ public class ServerRpcHandler implements Serializable { } // Connector is disabled, log a warning and move to the next - String msg = "Ignoring RPC call for disabled connector " - + connector.getClass().getName(); - if (connector instanceof Component) { - String caption = ((Component) connector).getCaption(); - if (caption != null) { - msg += ", caption=" + caption; - } - } - getLogger().warning(msg); + getLogger().warning( + getIgnoredDisabledError("RPC call", connector)); continue; } // DragAndDropService has null UI @@ -466,4 +459,26 @@ public class ServerRpcHandler implements Serializable { private static final Logger getLogger() { return Logger.getLogger(ServerRpcHandler.class.getName()); } + + /** + * Generates an error message when the client is trying to to something + * ('what') with a connector which is disabled or invisible. + * + * @since 7.1.8 + * @param connector + * the connector which is disabled (or invisible) + * @return an error message + */ + public static String getIgnoredDisabledError(String what, + ClientConnector connector) { + String msg = "Ignoring " + what + " for disabled connector " + + connector.getClass().getName(); + if (connector instanceof Component) { + String caption = ((Component) connector).getCaption(); + if (caption != null) { + msg += ", caption=" + caption; + } + } + return msg; + } } diff --git a/server/src/com/vaadin/ui/AbstractComponent.java b/server/src/com/vaadin/ui/AbstractComponent.java index 262d47af18..61bcf00ad8 100644 --- a/server/src/com/vaadin/ui/AbstractComponent.java +++ b/server/src/com/vaadin/ui/AbstractComponent.java @@ -27,6 +27,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import com.vaadin.event.ActionManager; +import com.vaadin.event.ConnectorActionManager; import com.vaadin.event.ShortcutListener; import com.vaadin.server.AbstractClientConnector; import com.vaadin.server.ComponentSizeValidator; @@ -90,7 +91,7 @@ public abstract class AbstractComponent extends AbstractClientConnector * Keeps track of the Actions added to this component; the actual * handling/notifying is delegated, usually to the containing window. */ - private ActionManager actionManager; + private ConnectorActionManager actionManager; private boolean visible = true; @@ -929,7 +930,7 @@ public abstract class AbstractComponent extends AbstractClientConnector */ protected ActionManager getActionManager() { if (actionManager == null) { - actionManager = new ActionManager(); + actionManager = new ConnectorActionManager(this); setActionManagerViewer(); } return actionManager; diff --git a/server/src/com/vaadin/ui/Button.java b/server/src/com/vaadin/ui/Button.java index 1bcf802f12..589f30d631 100644 --- a/server/src/com/vaadin/ui/Button.java +++ b/server/src/com/vaadin/ui/Button.java @@ -340,7 +340,7 @@ public class Button extends AbstractComponent implements * No action is taken is the button is disabled. */ public void click() { - if (isEnabled() && !isReadOnly()) { + if (isConnectorEnabled() && !isReadOnly()) { fireClick(); } } -- cgit v1.2.3 From 6c1ba81e0777080a59bad1eba44cc82f185ba6b3 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Wed, 16 Oct 2013 15:31:15 +0300 Subject: Reverted button click() logic check (#12743) The isConnectorEnabled() method should only to be used to check if the client side is allowed to interact with the button, not on the server side (isConnectorEnabled() is false if the component is not attached to a UI) Change-Id: I56cd93a1041432199337148f5c4a1449a825c5bc --- server/src/com/vaadin/ui/Button.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'server') diff --git a/server/src/com/vaadin/ui/Button.java b/server/src/com/vaadin/ui/Button.java index 589f30d631..1bcf802f12 100644 --- a/server/src/com/vaadin/ui/Button.java +++ b/server/src/com/vaadin/ui/Button.java @@ -340,7 +340,7 @@ public class Button extends AbstractComponent implements * No action is taken is the button is disabled. */ public void click() { - if (isConnectorEnabled() && !isReadOnly()) { + if (isEnabled() && !isReadOnly()) { fireClick(); } } -- cgit v1.2.3 From ed50200e9a68c00279cdefa65ccdccd4734d6c9a Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Fri, 18 Oct 2013 13:00:31 +0300 Subject: Fix serialization issue (#12703) Change-Id: Ibdced8cdc3200ccfef2750e32fc8bf8dc544f1ae --- server/src/com/vaadin/server/ErrorHandlingRunnable.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'server') diff --git a/server/src/com/vaadin/server/ErrorHandlingRunnable.java b/server/src/com/vaadin/server/ErrorHandlingRunnable.java index 8ae6ce3d5d..3970a14ee8 100644 --- a/server/src/com/vaadin/server/ErrorHandlingRunnable.java +++ b/server/src/com/vaadin/server/ErrorHandlingRunnable.java @@ -15,6 +15,8 @@ */ package com.vaadin.server; +import java.io.Serializable; + /** * Defines the interface to handle exceptions thrown during the execution of a * FutureAccess. @@ -22,7 +24,7 @@ package com.vaadin.server; * @since 7.1.8 * @author Vaadin Ltd */ -public interface ErrorHandlingRunnable extends Runnable { +public interface ErrorHandlingRunnable extends Runnable, Serializable { /** * Handles exceptions thrown during the execution of a FutureAccess. -- cgit v1.2.3 From dd51b7f73062650cb3d5bb8550a0b088a0ea6595 Mon Sep 17 00:00:00 2001 From: Marc Englund Date: Wed, 9 Oct 2013 15:31:06 +0300 Subject: Added more exception handling to PushHandler (#12578, #11882) PushHandler now catches Exception and calls ErrorHandler more. Change-Id: I7032c00f717b1dae34f4352abc035b1b398c7cfc --- .../vaadin/server/communication/PushHandler.java | 50 ++++++++++-- .../com/vaadin/tests/push/PushErrorHandling.html | 41 ++++++++++ .../com/vaadin/tests/push/PushErrorHandling.java | 93 ++++++++++++++++++++++ 3 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/push/PushErrorHandling.html create mode 100644 uitest/src/com/vaadin/tests/push/PushErrorHandling.java (limited to 'server') diff --git a/server/src/com/vaadin/server/communication/PushHandler.java b/server/src/com/vaadin/server/communication/PushHandler.java index 81dd00084d..b7cc628856 100644 --- a/server/src/com/vaadin/server/communication/PushHandler.java +++ b/server/src/com/vaadin/server/communication/PushHandler.java @@ -31,6 +31,8 @@ import org.atmosphere.cpr.AtmosphereResourceEvent; import org.atmosphere.cpr.AtmosphereResourceEventListenerAdapter; import org.json.JSONException; +import com.vaadin.server.ErrorEvent; +import com.vaadin.server.ErrorHandler; import com.vaadin.server.LegacyCommunicationManager.InvalidUIDLSecurityKeyException; import com.vaadin.server.ServiceException; import com.vaadin.server.ServletPortletHelper; @@ -274,14 +276,52 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter } else { callback.run(resource, ui); } - } catch (IOException e) { - getLogger().log(Level.WARNING, "Error writing a push response", - e); + } catch (final IOException e) { + callErrorHandler(session, e); + } catch (final Exception e) { + SystemMessages msg = service.getSystemMessages( + ServletPortletHelper.findLocale(null, null, + vaadinRequest), vaadinRequest); + sendNotificationAndDisconnect( + resource, + VaadinService.createCriticalNotificationJSON( + msg.getInternalErrorCaption(), + msg.getInternalErrorMessage(), null, + msg.getInternalErrorURL())); + callErrorHandler(session, e); } finally { - session.unlock(); + try { + session.unlock(); + } catch (Exception e) { + getLogger().log(Level.WARNING, + "Error while unlocking session", e); + // can't call ErrorHandler, we (hopefully) don't have a lock + } } } finally { - service.requestEnd(vaadinRequest, null, session); + try { + service.requestEnd(vaadinRequest, null, session); + } catch (Exception e) { + getLogger().log(Level.WARNING, "Error while ending request", e); + + // can't call ErrorHandler, we don't have a lock + } + } + } + + /** + * Call the session's {@link ErrorHandler}, if it has one, with the given + * exception wrapped in an {@link ErrorEvent}. + */ + private void callErrorHandler(VaadinSession session, Exception e) { + try { + ErrorHandler errorHandler = ErrorEvent.findErrorHandler(session); + if (errorHandler != null) { + errorHandler.error(new ErrorEvent(e)); + } + } catch (Exception ex) { + // Let's not allow error handling to cause trouble; log fails + getLogger().log(Level.WARNING, "ErrorHandler call failed", ex); } } diff --git a/uitest/src/com/vaadin/tests/push/PushErrorHandling.html b/uitest/src/com/vaadin/tests/push/PushErrorHandling.html new file mode 100644 index 0000000000..afd3e70771 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/PushErrorHandling.html @@ -0,0 +1,41 @@ + + + + + + +PushErrorHandling + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PushErrorHandling
open/run/PushErrorHandling?restartApplication
clickvaadin=runPushErrorHandling::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VButton[0]/domChild[0]/domChild[0]
assertTextvaadin=runPushErrorHandling::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[2]/VLabel[0]An error! Unable to invoke method click in com.vaadin.shared.ui.button.ButtonServerRpc
mouseClickvaadin=runPushErrorHandling::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[1]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[0]/domChild[0]/domChild[0]26,7
assertTextvaadin=runPushErrorHandling::Root/VNotification[0]/HTML[0]/domChild[0]Internal error
+ + diff --git a/uitest/src/com/vaadin/tests/push/PushErrorHandling.java b/uitest/src/com/vaadin/tests/push/PushErrorHandling.java new file mode 100644 index 0000000000..3074bd3851 --- /dev/null +++ b/uitest/src/com/vaadin/tests/push/PushErrorHandling.java @@ -0,0 +1,93 @@ +package com.vaadin.tests.push; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import com.vaadin.data.util.AbstractInMemoryContainer; +import com.vaadin.data.util.BeanContainer; +import com.vaadin.event.ItemClickEvent; +import com.vaadin.event.ItemClickEvent.ItemClickListener; +import com.vaadin.server.ErrorHandler; +import com.vaadin.server.VaadinRequest; +import com.vaadin.server.VaadinSession; +import com.vaadin.shared.communication.PushMode; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Label; +import com.vaadin.ui.Table; + +public class PushErrorHandling extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + getPushConfiguration().setPushMode(PushMode.AUTOMATIC); + + VaadinSession.getCurrent().setErrorHandler(new ErrorHandler() { + + @Override + public void error(com.vaadin.server.ErrorEvent event) { + addComponent(new Label("An error! " + + event.getThrowable().getMessage())); + System.err.println("An error! " + + event.getThrowable().getMessage()); + } + }); + + final Button button = new Button("Click for NPE!", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + ((String) null).length(); // Null-pointer exception + } + }); + addComponent(button); + + final Table view = new Table("testtable"); + view.setSelectable(true); + view.setMultiSelect(false); + view.setImmediate(true); + view.setSizeFull(); + + view.addItemClickListener(new ItemClickListener() { + + @Override + public void itemClick(ItemClickEvent event) { + BeanContainer metaContainer = new BeanContainer( + AbstractInMemoryContainer.class) { + @Override + public Collection getContainerPropertyIds() { + List cpropIds = new ArrayList(super + .getContainerPropertyIds()); + cpropIds.add("testid"); + return cpropIds; + } + + @Override + public Class getType(Object propertyId) { + ((Object) null).hashCode(); + return super.getType(propertyId); + } + }; + view.setContainerDataSource(metaContainer); + + } + }); + view.addContainerProperty("Column", String.class, "Click for NPE"); + view.addItem(new Object()); + + addComponent(view); + + } + + @Override + protected String getTestDescription() { + return "Error handling should still work w/ push enabled. (Button can be handled properly, table causes internal error)"; + } + + @Override + protected Integer getTicketNumber() { + return 11882; + } +} -- cgit v1.2.3 From ee809e5985d7a438e031c40bed160ac78ae8d0bc Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 21 Oct 2013 16:16:37 +0300 Subject: Revert broken fix and test (#12446) The timeoutInterval variable needs to be part of per-UI state for the code to work correctly. Storing it in a servlet-global MetadataWriter instance is both semantically wrong and a race condition. Also, the test currently throws NPE if assertions are enabled. This reverts commit f595d057951523baf35a797692376dfa5de0bc8d. Change-Id: Ia6d1383b2c112b86ce60c75a3ebb9f10da545d4a --- .../server/communication/UidlRequestHandler.java | 5 +- .../vaadin/server/communication/UidlWriter.java | 32 ++---- .../server/communication/UidlWriterTest.java | 125 --------------------- 3 files changed, 14 insertions(+), 148 deletions(-) delete mode 100644 server/tests/src/com/vaadin/server/communication/UidlWriterTest.java (limited to 'server') diff --git a/server/src/com/vaadin/server/communication/UidlRequestHandler.java b/server/src/com/vaadin/server/communication/UidlRequestHandler.java index f13199e9ae..d52c5e9fe0 100644 --- a/server/src/com/vaadin/server/communication/UidlRequestHandler.java +++ b/server/src/com/vaadin/server/communication/UidlRequestHandler.java @@ -56,7 +56,8 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements private ServerRpcHandler rpcHandler = new ServerRpcHandler(); - private UidlWriter uidlWriter = new UidlWriter(); + public UidlRequestHandler() { + } @Override public boolean synchronizedHandleRequest(VaadinSession session, @@ -145,7 +146,7 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements JSONException { openJsonMessage(writer, response); - uidlWriter.write(ui, writer, repaintAll, false); + new UidlWriter().write(ui, writer, repaintAll, false); closeJsonMessage(writer); } diff --git a/server/src/com/vaadin/server/communication/UidlWriter.java b/server/src/com/vaadin/server/communication/UidlWriter.java index fe7a7d42bf..60933a75c2 100644 --- a/server/src/com/vaadin/server/communication/UidlWriter.java +++ b/server/src/com/vaadin/server/communication/UidlWriter.java @@ -51,14 +51,6 @@ import com.vaadin.ui.UI; */ public class UidlWriter implements Serializable { - private LegacyUidlWriter legacyUidlWriter = new LegacyUidlWriter(); - private SharedStateWriter sharedStateWriter = new SharedStateWriter(); - private ConnectorTypeWriter connectorTypeWriter = new ConnectorTypeWriter(); - private ConnectorHierarchyWriter connectorHierarchyWriter = new ConnectorHierarchyWriter(); - private ClientRpcWriter clientRpcWriter = new ClientRpcWriter(); - private MetadataWriter metadataWriter = new MetadataWriter(); - private ResourceWriter resourceWriter = new ResourceWriter(); - /** * Writes a JSON object containing all pending changes to the given UI. * @@ -87,12 +79,13 @@ public class UidlWriter implements Serializable { // to write out session.getService().runPendingAccessTasks(session); + ArrayList dirtyVisibleConnectors = ui + .getConnectorTracker().getDirtyVisibleConnectors(); + LegacyCommunicationManager manager = session.getCommunicationManager(); // Paints components + ConnectorTracker uiConnectorTracker = ui.getConnectorTracker(); getLogger().log(Level.FINE, "* Creating response to client"); - ConnectorTracker uiConnectorTracker = ui.getConnectorTracker(); - ArrayList dirtyVisibleConnectors = uiConnectorTracker - .getDirtyVisibleConnectors(); getLogger().log( Level.FINE, "Found " + dirtyVisibleConnectors.size() @@ -107,13 +100,10 @@ public class UidlWriter implements Serializable { try { writer.write("\"changes\" : "); - LegacyCommunicationManager manager = session - .getCommunicationManager(); - JsonPaintTarget paintTarget = new JsonPaintTarget(manager, writer, !repaintAll); - legacyUidlWriter.write(ui, writer, paintTarget); + new LegacyUidlWriter().write(ui, writer, paintTarget); paintTarget.close(); writer.write(", "); // close changes @@ -130,7 +120,7 @@ public class UidlWriter implements Serializable { // processing. writer.write("\"state\":"); - sharedStateWriter.write(ui, writer); + new SharedStateWriter().write(ui, writer); writer.write(", "); // close states // TODO This should be optimized. The type only needs to be @@ -139,7 +129,7 @@ public class UidlWriter implements Serializable { // widget mapping writer.write("\"types\":"); - connectorTypeWriter.write(ui, writer, paintTarget); + new ConnectorTypeWriter().write(ui, writer, paintTarget); writer.write(", "); // close states // Send update hierarchy information to the client. @@ -150,7 +140,7 @@ public class UidlWriter implements Serializable { // child to 0 children) writer.write("\"hierarchy\":"); - connectorHierarchyWriter.write(ui, writer); + new ConnectorHierarchyWriter().write(ui, writer); writer.write(", "); // close hierarchy // send server to client RPC calls for components in the UI, in call @@ -160,7 +150,7 @@ public class UidlWriter implements Serializable { // which they were performed, remove the calls from components writer.write("\"rpc\" : "); - clientRpcWriter.write(ui, writer); + new ClientRpcWriter().write(ui, writer); writer.write(", "); // close rpc uiConnectorTracker.markAllConnectorsClean(); @@ -170,11 +160,11 @@ public class UidlWriter implements Serializable { SystemMessages messages = ui.getSession().getService() .getSystemMessages(ui.getLocale(), null); // TODO hilightedConnector - metadataWriter.write(ui, writer, repaintAll, async, messages); + new MetadataWriter().write(ui, writer, repaintAll, async, messages); writer.write(", "); writer.write("\"resources\" : "); - resourceWriter.write(ui, writer, paintTarget); + new ResourceWriter().write(ui, writer, paintTarget); Collection> usedClientConnectors = paintTarget .getUsedClientConnectors(); diff --git a/server/tests/src/com/vaadin/server/communication/UidlWriterTest.java b/server/tests/src/com/vaadin/server/communication/UidlWriterTest.java deleted file mode 100644 index 8dcd6cbdf4..0000000000 --- a/server/tests/src/com/vaadin/server/communication/UidlWriterTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2000-2013 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.server.communication; - -import java.io.IOException; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Locale; - -import org.easymock.EasyMock; -import org.json.JSONException; -import org.json.JSONObject; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.server.ClientConnector; -import com.vaadin.server.LegacyCommunicationManager; -import com.vaadin.server.SystemMessages; -import com.vaadin.server.VaadinRequest; -import com.vaadin.server.VaadinService; -import com.vaadin.server.VaadinSession; -import com.vaadin.server.WrappedSession; -import com.vaadin.ui.ConnectorTracker; -import com.vaadin.ui.UI; - -/** - * - * @since - * @author Vaadin Ltd - */ -public class UidlWriterTest { - - private UI ui; - private UidlWriter uidlWriter; - - @Before - public void setUp() { - SystemMessages messages = EasyMock.createNiceMock(SystemMessages.class); - EasyMock.expect(messages.isSessionExpiredNotificationEnabled()) - .andReturn(true).anyTimes(); - EasyMock.replay(messages); - - VaadinService service = EasyMock.createNiceMock(VaadinService.class); - EasyMock.expect( - service.getSystemMessages(EasyMock.anyObject(Locale.class), - EasyMock.anyObject(VaadinRequest.class))) - .andReturn(messages).anyTimes(); - EasyMock.replay(service); - - LegacyCommunicationManager manager = EasyMock - .createNiceMock(LegacyCommunicationManager.class); - EasyMock.replay(manager); - - WrappedSession wrappedSession = EasyMock - .createNiceMock(WrappedSession.class); - EasyMock.expect(wrappedSession.getMaxInactiveInterval()).andReturn(100) - .times(3).andReturn(200); - - EasyMock.replay(wrappedSession); - - VaadinSession session = EasyMock.createNiceMock(VaadinSession.class); - EasyMock.expect(session.getService()).andReturn(service).anyTimes(); - EasyMock.expect(session.getCommunicationManager()).andReturn(manager) - .anyTimes(); - EasyMock.expect(session.getSession()).andReturn(wrappedSession) - .anyTimes(); - EasyMock.replay(session); - - ConnectorTracker tracker = EasyMock - .createNiceMock(ConnectorTracker.class); - EasyMock.expect(tracker.getDirtyVisibleConnectors()) - .andReturn(new ArrayList()).anyTimes(); - EasyMock.replay(tracker); - - ui = EasyMock.createNiceMock(UI.class); - EasyMock.expect(ui.getSession()).andReturn(session).anyTimes(); - EasyMock.expect(ui.getConnectorTracker()).andReturn(tracker).anyTimes(); - EasyMock.replay(ui); - - uidlWriter = new UidlWriter(); - } - - @Test - public void testMetadataWriterState() throws IOException, JSONException { - - Assert.assertEquals( - "Metadata should contain redirect interval on first write", - 115, getRedirect(uidl(false, false)).optInt("interval")); - Assert.assertNull( - "Metadata should not contain redirect interval on second write", - getRedirect(uidl(false, false))); - Assert.assertEquals( - "Metadata should contain redirect interval on repaintAll", 115, - getRedirect(uidl(true, false)).optInt("interval")); - Assert.assertEquals( - "Metadata should contain redirect interval when changed in session", - 215, getRedirect(uidl(false, false)).optInt("interval")); - } - - private JSONObject uidl(boolean repaintAll, boolean async) - throws IOException, JSONException { - StringWriter writer = new StringWriter(); - uidlWriter.write(ui, writer, repaintAll, async); - return new JSONObject("{" + writer.toString() + "}"); - } - - private JSONObject getRedirect(JSONObject json) throws JSONException { - return json.getJSONObject("meta").optJSONObject("timedRedirect"); - - } -} -- cgit v1.2.3