summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorLeif Åstrand <leif@vaadin.com>2013-10-22 09:12:59 +0300
committerLeif Åstrand <leif@vaadin.com>2013-10-22 09:12:59 +0300
commitd70961ff2539aabe99eea22683a8ae77efdc81e5 (patch)
treec3876e2266ace7e90d8dc82e35f22631e2ce29e5 /server
parenta48370a761a6d0b6c54196da0defdb30b47a5bb1 (diff)
parentee809e5985d7a438e031c40bed160ac78ae8d0bc (diff)
downloadvaadin-framework-d70961ff2539aabe99eea22683a8ae77efdc81e5.tar.gz
vaadin-framework-d70961ff2539aabe99eea22683a8ae77efdc81e5.zip
Merge changes from origin/7.1
c7ae45c Validate that the connector is enabled before triggering actions for it (#12743) ce89a75 Created constants for tested browser versions (#12786) f9ea9b3 Allow running tests locally by overriding runLocally() (#12786) e70ba25 Added liferay module for building liferay.zip #12748 7c12694 Add sub directory support to sass test scanner (#12790) 39fdf66 Handle numbers in the same way if they do not have a unit (#12732) 6155d61 Disable fallback in a way compatible with Atmosphere JS 2.0.3 (#12241) f401595 Test for pushing large chunks of data (#12567) d41967d Skip compilation of TB2 tests if tests.tb2.skip is set 6c1ba81 Reverted button click() logic check (#12743) 779c8a0 Disable automated testing on Opera until issues are resolved (#12487, #12367, #12800) 962c1c3 Fix compilation error 7ee11a7 Remove unused test super class (#12786) a4211dc Resolve concurrency issue in running TB3 tests 20c28aa Fixed javadoc 0d36896 Add more hax to make test work with new Atmosphere JS (#12241) ed50200 Fix serialization issue (#12703) dd51b7f Added more exception handling to PushHandler (#12578, #11882) 6f76840 Sass variables can now start with underscore (#12716) ab5b20c Ticket #12727 - Panels get unnecessary scroll bars in WebKit when content is 100% wide. 361ad17 Fixed focus issue in TableMoveFocusWithSelectionTest (#12540) ee809e5 Revert broken fix and test (#12446) Change-Id: I71b6e3c2dc6b02845794df0934ba807d7ccac784
Diffstat (limited to 'server')
-rw-r--r--server/src/com/vaadin/event/ConnectorActionManager.java88
-rw-r--r--server/src/com/vaadin/server/ErrorHandlingRunnable.java4
-rw-r--r--server/src/com/vaadin/server/communication/PushHandler.java50
-rw-r--r--server/src/com/vaadin/server/communication/ServerRpcHandler.java33
-rw-r--r--server/src/com/vaadin/server/communication/UidlRequestHandler.java5
-rw-r--r--server/src/com/vaadin/server/communication/UidlWriter.java32
-rw-r--r--server/src/com/vaadin/ui/AbstractComponent.java5
-rw-r--r--server/tests/src/com/vaadin/server/communication/UidlWriterTest.java125
8 files changed, 177 insertions, 165 deletions
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.
+ * <p>
+ * 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 <T extends Component & Container & VariableOwner> 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/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.
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/server/src/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/com/vaadin/server/communication/ServerRpcHandler.java
index eff9ceebf4..432a9ea893 100644
--- a/server/src/com/vaadin/server/communication/ServerRpcHandler.java
+++ b/server/src/com/vaadin/server/communication/ServerRpcHandler.java
@@ -248,15 +248,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
@@ -495,4 +488,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/server/communication/UidlRequestHandler.java b/server/src/com/vaadin/server/communication/UidlRequestHandler.java
index 2277e1c76f..cf25910fa4 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
protected boolean canHandleRequest(VaadinRequest request) {
@@ -147,7 +148,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 a290eb4846..b46fbbf58a 100644
--- a/server/src/com/vaadin/server/communication/UidlWriter.java
+++ b/server/src/com/vaadin/server/communication/UidlWriter.java
@@ -52,14 +52,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.
*
@@ -88,12 +80,13 @@ public class UidlWriter implements Serializable {
// to write out
session.getService().runPendingAccessTasks(session);
+ ArrayList<ClientConnector> 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<ClientConnector> dirtyVisibleConnectors = uiConnectorTracker
- .getDirtyVisibleConnectors();
getLogger().log(
Level.FINE,
"Found " + dirtyVisibleConnectors.size()
@@ -111,13 +104,10 @@ public class UidlWriter implements Serializable {
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
@@ -134,7 +124,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
@@ -143,7 +133,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.
@@ -154,7 +144,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
@@ -164,7 +154,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();
@@ -174,11 +164,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<Class<? extends ClientConnector>> usedClientConnectors = paintTarget
.getUsedClientConnectors();
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/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<ClientConnector>()).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");
-
- }
-}