]> source.dussan.org Git - vaadin-framework.git/commitdiff
Allow customizing client-side push config on server side (#11867)
authorArtur Signell <artur@vaadin.com>
Wed, 5 Jun 2013 11:27:09 +0000 (14:27 +0300)
committerArtur Signell <artur@vaadin.com>
Wed, 5 Jun 2013 12:14:42 +0000 (15:14 +0300)
Change-Id: I212067aa0bd04e3e73844ef57963b5622291986a

16 files changed:
client/src/com/vaadin/client/ApplicationConnection.java
client/src/com/vaadin/client/communication/AtmospherePushConnection.java
client/src/com/vaadin/client/communication/PushConnection.java
client/src/com/vaadin/client/ui/ui/UIConnector.java
server/src/com/vaadin/server/VaadinSession.java
server/src/com/vaadin/server/communication/PushHandler.java
server/src/com/vaadin/server/communication/UIInitHandler.java
server/src/com/vaadin/ui/PushConfiguration.java [new file with mode: 0644]
server/src/com/vaadin/ui/UI.java
shared/src/com/vaadin/shared/ui/ui/Transport.java [new file with mode: 0644]
shared/src/com/vaadin/shared/ui/ui/UIState.java
uitest/src/com/vaadin/tests/push/PushConfiguration.html [new file with mode: 0644]
uitest/src/com/vaadin/tests/push/PushConfigurationTest.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/push/PushConfigurator.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/push/TogglePush.java
uitest/src/com/vaadin/tests/widgetset/client/TestingPushConnection.java

index a3279e56312e1b48688d89426079e8c02dfa7483..ac058b553699aa6a0d52184fa8d9e97505896364 100644 (file)
@@ -95,6 +95,7 @@ import com.vaadin.shared.communication.LegacyChangeVariablesInvocation;
 import com.vaadin.shared.communication.MethodInvocation;
 import com.vaadin.shared.communication.SharedState;
 import com.vaadin.shared.ui.ui.UIConstants;
+import com.vaadin.shared.ui.ui.UIState.PushConfigurationState;
 
 /**
  * This is the client side communication "engine", managing client-server
@@ -3359,9 +3360,11 @@ public class ApplicationConnection {
      *            <code>false</code> to disable the push connection.
      */
     public void setPushEnabled(boolean enabled) {
+        final PushConfigurationState pushState = uIConnector.getState().pushConfiguration;
+
         if (enabled && push == null) {
             push = GWT.create(PushConnection.class);
-            push.init(this, new CommunicationErrorHandler() {
+            push.init(this, pushState, new CommunicationErrorHandler() {
                 @Override
                 public boolean onError(String details, int statusCode) {
                     showCommunicationError(details, statusCode);
@@ -3378,7 +3381,7 @@ public class ApplicationConnection {
                      * the old connection to disconnect, now is the right time
                      * to open a new connection
                      */
-                    if (uIConnector.getState().pushMode.isEnabled()) {
+                    if (pushState.mode.isEnabled()) {
                         setPushEnabled(true);
                     }
 
index 997e84145c9723fb9534ba0d47467c29c291d9ec..f7936f8717dd303b6b43f26c323ede50f39e16bf 100644 (file)
@@ -30,6 +30,7 @@ import com.vaadin.client.VConsole;
 import com.vaadin.shared.ApplicationConstants;
 import com.vaadin.shared.communication.PushConstants;
 import com.vaadin.shared.ui.ui.UIConstants;
+import com.vaadin.shared.ui.ui.UIState.PushConfigurationState;
 
 /**
  * The default {@link PushConnection} implementation that uses Atmosphere for
@@ -133,15 +134,22 @@ public class AtmospherePushConnection implements PushConnection {
      * (non-Javadoc)
      * 
      * @see
-     * com.vaadin.client.communication.PushConenction#init(com.vaadin.client
-     * .ApplicationConnection)
+     * com.vaadin.client.communication.PushConnection#init(ApplicationConnection
+     * , Map<String, String>, CommunicationErrorHandler)
      */
     @Override
     public void init(final ApplicationConnection connection,
+            final PushConfigurationState pushConfiguration,
             CommunicationErrorHandler errorHandler) {
         this.connection = connection;
         this.errorHandler = errorHandler;
 
+        config = createConfig();
+        for (String param : pushConfiguration.parameters.keySet()) {
+            config.setStringValue(param,
+                    pushConfiguration.parameters.get(param));
+        }
+
         runWhenAtmosphereLoaded(new Command() {
             @Override
             public void execute() {
@@ -216,9 +224,6 @@ public class AtmospherePushConnection implements PushConnection {
     }
 
     protected AtmosphereConfiguration getConfig() {
-        if (config == null) {
-            config = createConfig();
-        }
         return config;
     }
 
index a4a3bbc0ccf5c85fda5e098b5ad839e70907c82d..bc2af98f1aa0a7ffbb0bf8b0e0fafd7a273d98c2 100644 (file)
@@ -19,6 +19,7 @@ package com.vaadin.client.communication;
 import com.google.gwt.user.client.Command;
 import com.vaadin.client.ApplicationConnection;
 import com.vaadin.client.ApplicationConnection.CommunicationErrorHandler;
+import com.vaadin.shared.ui.ui.UIState.PushConfigurationState;
 
 /**
  * Represents the client-side endpoint of a bidirectional ("push") communication
@@ -39,6 +40,7 @@ public interface PushConnection {
      *            The ApplicationConnection
      */
     public void init(ApplicationConnection connection,
+            PushConfigurationState pushConfigurationState,
             CommunicationErrorHandler errorHandler);
 
     /**
index 1c2c6ddeb891cd782f1ef8285fcdf32fcc6f96e0..45b0a7ab9d4d4a77af3471a9830a58acb9a58989 100644 (file)
@@ -644,8 +644,9 @@ public class UIConnector extends AbstractSingleComponentContainerConnector
             configurePolling();
         }
 
-        if (stateChangeEvent.hasPropertyChanged("pushMode")) {
-            getConnection().setPushEnabled(getState().pushMode.isEnabled());
+        if (stateChangeEvent.hasPropertyChanged("pushConfiguration")) {
+            getConnection().setPushEnabled(
+                    getState().pushConfiguration.mode.isEnabled());
         }
 
         if (stateChangeEvent.hasPropertyChanged("overlayContainerLabel")) {
index 889eadcd6f96138dfae9ce7ca5e42e1395e4806d..e0a5b51baa9c0ad9c87906e5e97a9fd7b19b5282 100644 (file)
@@ -902,7 +902,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
                 getService().runPendingAccessTasks(this);
 
                 for (UI ui : getUIs()) {
-                    if (ui.getPushMode() == PushMode.AUTOMATIC) {
+                    if (ui.getPushConfiguration().getPushMode() == PushMode.AUTOMATIC) {
                         ui.push();
                     }
                 }
index a44df792211e9533a62b282edf11ac293dbc5b1a..7efcb8fd8cf03ccb3206639809ac84bc9b0c8c46 100644 (file)
@@ -171,7 +171,7 @@ public class PushHandler implements AtmosphereHandler {
     PushEventCallback disconnectCallback = new PushEventCallback() {
         @Override
         public void run(AtmosphereResource resource, UI ui) throws IOException {
-            PushMode pushMode = ui.getPushMode();
+            PushMode pushMode = ui.getPushConfiguration().getPushMode();
             AtmospherePushConnection pushConnection = getConnectionForUI(ui);
 
             String id = resource.uuid();
index 8507bf40cc6704dba7b303f39b1841ebe6d43b70..9807ea6a9fccf719b909ae70d6b595fcc6eeaf52 100644 (file)
@@ -209,7 +209,7 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler {
             pushMode = session.getService().getDeploymentConfiguration()
                     .getPushMode();
         }
-        ui.setPushMode(pushMode);
+        ui.getPushConfiguration().setPushMode(pushMode);
 
         // Set thread local here so it is available in init
         UI.setCurrent(ui);
diff --git a/server/src/com/vaadin/ui/PushConfiguration.java b/server/src/com/vaadin/ui/PushConfiguration.java
new file mode 100644 (file)
index 0000000..a592b39
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * 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.ui;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+
+import com.vaadin.server.VaadinSession;
+import com.vaadin.shared.communication.PushMode;
+import com.vaadin.shared.ui.ui.Transport;
+import com.vaadin.shared.ui.ui.UIState.PushConfigurationState;
+
+/**
+ * Provides method for configuring the push channel.
+ * 
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+public interface PushConfiguration extends Serializable {
+
+    /**
+     * Returns the mode of bidirectional ("push") communication that is used.
+     * 
+     * @return The push mode.
+     */
+    public PushMode getPushMode();
+
+    /**
+     * Sets the mode of bidirectional ("push") communication that should be
+     * used.
+     * <p>
+     * Add-on developers should note that this method is only meant for the
+     * application developer. An add-on should not set the push mode directly,
+     * rather instruct the user to set it.
+     * </p>
+     * 
+     * @param pushMode
+     *            The push mode to use.
+     * 
+     * @throws IllegalArgumentException
+     *             if the argument is null.
+     * @throws IllegalStateException
+     *             if push support is not available.
+     */
+    public void setPushMode(PushMode pushMode);
+
+    /**
+     * Returns the primary transport type for push.
+     * <p>
+     * Note that if you set the transport type using
+     * {@link #setParameter(String, String)} to an unsupported type this method
+     * will return null. Supported types are defined by {@link Transport}.
+     * 
+     * @return The primary transport type
+     */
+    public Transport getTransport();
+
+    /**
+     * Sets the primary transport type for push.
+     * <p>
+     * Note that the new transport type will not be used until the push channel
+     * is disconnected and reconnected if already active.
+     * 
+     * @param transport
+     *            The primary transport type
+     */
+    public void setTransport(Transport transport);
+
+    /**
+     * Returns the fallback transport type for push.
+     * <p>
+     * Note that if you set the transport type using
+     * {@link #setParameter(String, String)} to an unsupported type this method
+     * will return null. Supported types are defined by {@link Transport}.
+     * 
+     * @return The fallback transport type
+     */
+    public Transport getFallbackTransport();
+
+    /**
+     * Sets the fallback transport type for push.
+     * <p>
+     * Note that the new transport type will not be used until the push channel
+     * is disconnected and reconnected if already active.
+     * 
+     * @param fallbackTransport
+     *            The fallback transport type
+     */
+    public void setFallbackTransport(Transport fallbackTransport);
+
+    /**
+     * Returns the given parameter, if set.
+     * <p>
+     * This method provides low level access to push parameters and is typically
+     * not needed for normal application development.
+     * 
+     * @since 7.1
+     * @param parameter
+     *            The parameter name
+     * @return The parameter value or null if not set
+     */
+    public String getParameter(String parameter);
+
+    /**
+     * Returns the parameters which have been defined.
+     * 
+     * @since 7.1
+     * @return A collection of parameter names
+     */
+    public Collection<String> getParameterNames();
+
+    /**
+     * Sets the given parameter.
+     * <p>
+     * This method provides low level access to push parameters and is typically
+     * not needed for normal application development.
+     * 
+     * @since 7.1
+     * @param parameter
+     *            The parameter name
+     * @param value
+     *            The value
+     */
+    public void setParameter(String parameter, String value);
+
+}
+
+class PushConfigurationImpl implements PushConfiguration {
+    private UI ui;
+
+    public PushConfigurationImpl(UI ui) {
+        this.ui = ui;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.vaadin.ui.PushConfiguration#getPushMode()
+     */
+    @Override
+    public PushMode getPushMode() {
+        return getState(false).mode;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * com.vaadin.ui.PushConfiguration#setPushMode(com.vaadin.shared.communication
+     * .PushMode)
+     */
+    @Override
+    public void setPushMode(PushMode pushMode) {
+        if (pushMode == null) {
+            throw new IllegalArgumentException("Push mode cannot be null");
+        }
+
+        if (pushMode.isEnabled()) {
+            VaadinSession session = ui.getSession();
+            if (session != null && !session.getService().ensurePushAvailable()) {
+                throw new IllegalStateException(
+                        "Push is not available. See previous log messages for more information.");
+            }
+        }
+
+        /*
+         * Client-side will open a new connection or disconnect the old
+         * connection, so there's nothing more to do on the server at this
+         * point.
+         */
+        getState().mode = pushMode;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.vaadin.ui.PushConfiguration#getTransport()
+     */
+    @Override
+    public Transport getTransport() {
+        try {
+            return Transport
+                    .valueOf(getParameter(PushConfigurationState.TRANSPORT_PARAM));
+        } catch (IllegalArgumentException e) {
+            return null;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * com.vaadin.ui.PushConfiguration#setTransport(com.vaadin.shared.ui.ui.
+     * Transport)
+     */
+    @Override
+    public void setTransport(Transport transport) {
+        setParameter(PushConfigurationState.TRANSPORT_PARAM,
+                transport.getIdentifier());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.vaadin.ui.PushConfiguration#getFallbackTransport()
+     */
+    @Override
+    public Transport getFallbackTransport() {
+        try {
+            return Transport
+                    .valueOf(getParameter(PushConfigurationState.FALLBACK_TRANSPORT_PARAM));
+        } catch (IllegalArgumentException e) {
+            return null;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * com.vaadin.ui.PushConfiguration#setFallbackTransport(com.vaadin.shared
+     * .ui.ui.Transport)
+     */
+    @Override
+    public void setFallbackTransport(Transport fallbackTransport) {
+        setParameter(PushConfigurationState.FALLBACK_TRANSPORT_PARAM,
+                fallbackTransport.getIdentifier());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.vaadin.ui.PushConfiguration#getParameter(java.lang.String)
+     */
+    @Override
+    public String getParameter(String parameter) {
+        return getState(false).parameters.get(parameter);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.vaadin.ui.PushConfiguration#setParameter(java.lang.String,
+     * java.lang.String)
+     */
+    @Override
+    public void setParameter(String parameter, String value) {
+        getState().parameters.put(parameter, value);
+
+    }
+
+    private PushConfigurationState getState() {
+        return ui.getState().pushConfiguration;
+    }
+
+    private PushConfigurationState getState(boolean markAsDirty) {
+        return ui.getState(markAsDirty).pushConfiguration;
+    }
+
+    @Override
+    public Collection<String> getParameterNames() {
+        return Collections
+                .unmodifiableCollection(ui.getState(false).pushConfiguration.parameters
+                        .keySet());
+    }
+
+}
index 2c6283377a019822a33fbf78383aba0c2a838a3a..6159298a69da113dccdfe9aab8541ae72ea5b208 100644 (file)
@@ -48,7 +48,6 @@ import com.vaadin.server.communication.PushConnection;
 import com.vaadin.shared.Connector;
 import com.vaadin.shared.EventId;
 import com.vaadin.shared.MouseEventDetails;
-import com.vaadin.shared.communication.PushMode;
 import com.vaadin.shared.ui.ui.DebugWindowClientRpc;
 import com.vaadin.shared.ui.ui.DebugWindowServerRpc;
 import com.vaadin.shared.ui.ui.ScrollClientRpc;
@@ -216,6 +215,8 @@ public abstract class UI extends AbstractSingleComponentContainer implements
 
     private TooltipConfiguration tooltipConfiguration = new TooltipConfigurationImpl(
             this);
+    private PushConfiguration pushConfiguration = new PushConfigurationImpl(
+            this);
 
     /**
      * Creates a new empty UI without a caption. The content of the UI must be
@@ -1325,7 +1326,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements
                 return;
             }
 
-            if (!getPushMode().isEnabled()) {
+            if (!getPushConfiguration().getPushMode().isEnabled()) {
                 throw new IllegalStateException("Push not enabled");
             }
 
@@ -1353,7 +1354,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements
      */
     public void setPushConnection(PushConnection pushConnection) {
         // If pushMode is disabled then there should never be a pushConnection
-        assert (getPushMode().isEnabled() || pushConnection == null);
+        assert (getPushConfiguration().getPushMode().isEnabled() || pushConnection == null);
 
         if (pushConnection == this.pushConnection) {
             return;
@@ -1402,51 +1403,13 @@ public abstract class UI extends AbstractSingleComponentContainer implements
     }
 
     /**
-     * Returns the mode of bidirectional ("push") communication that is used in
-     * this UI.
-     * 
-     * @return The push mode.
-     */
-    public PushMode getPushMode() {
-        return getState(false).pushMode;
-    }
-
-    /**
-     * Sets the mode of bidirectional ("push") communication that should be used
-     * in this UI.
-     * <p>
-     * Add-on developers should note that this method is only meant for the
-     * application developer. An add-on should not set the push mode directly,
-     * rather instruct the user to set it.
-     * </p>
+     * Retrieves the object used for configuring the push channel.
      * 
-     * @param pushMode
-     *            The push mode to use.
-     * 
-     * @throws IllegalArgumentException
-     *             if the argument is null.
-     * @throws IllegalStateException
-     *             if push support is not available.
+     * @since 7.1
+     * @return The instance used for push configuration
      */
-    public void setPushMode(PushMode pushMode) {
-        if (pushMode == null) {
-            throw new IllegalArgumentException("Push mode cannot be null");
-        }
-
-        if (pushMode.isEnabled()) {
-            VaadinSession session = getSession();
-            if (session != null && !session.getService().ensurePushAvailable()) {
-                throw new IllegalStateException(
-                        "Push is not available. See previous log messages for more information.");
-            }
-        }
-
-        /*
-         * Client-side will open a new connection or disconnect the old
-         * connection, so there's nothing more to do on the server at this
-         * point.
-         */
-        getState().pushMode = pushMode;
+    public PushConfiguration getPushConfiguration() {
+        return pushConfiguration;
     }
 
     /**
diff --git a/shared/src/com/vaadin/shared/ui/ui/Transport.java b/shared/src/com/vaadin/shared/ui/ui/Transport.java
new file mode 100644 (file)
index 0000000..69d713b
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.shared.ui.ui;
+
+/**
+ * Transport modes for Push
+ * 
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+public enum Transport {
+    /**
+     * Websockets
+     */
+    WEBSOCKET("websocket"),
+    /**
+     * HTTP streaming
+     */
+    STREAMING("streaming");
+
+    /**
+     * The default transport mechanism for push
+     */
+    public static final Transport DEFAULT = Transport.WEBSOCKET;
+
+    /**
+     * The default fallback transport mechanism for push
+     */
+    public static final Transport DEFAULT_FALLBACK = Transport.STREAMING;
+
+    private String identifier;
+
+    private Transport(String identifier) {
+        this.identifier = identifier;
+    }
+
+    public String getIdentifier() {
+        return identifier;
+    }
+
+}
index 177fe2e7bdb83dc8e3f826db9d4470d7b2a86793..e19a87ada979a68ee454b4b0d3e30b24071ad8af 100644 (file)
@@ -17,7 +17,9 @@ package com.vaadin.shared.ui.ui;
 
 import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import com.vaadin.shared.communication.PushMode;
 import com.vaadin.shared.ui.TabIndexState;
@@ -27,8 +29,6 @@ public class UIState extends TabIndexState {
     public LoadingIndicatorConfigurationState loadingIndicatorConfiguration = new LoadingIndicatorConfigurationState();
     public int pollInterval = -1;
 
-    public PushMode pushMode = PushMode.DISABLED;
-
     // Informing users of assistive devices, that the content of this container
     // is announced automatically and does not need to be navigated into
     public String overlayContainerLabel = "This content is announced automatically and does not need to be navigated into.";
@@ -48,6 +48,19 @@ public class UIState extends TabIndexState {
         public int maxWidth = 500;
     }
 
+    public static class PushConfigurationState implements Serializable {
+        public static final String TRANSPORT_PARAM = "transport";
+        public static final String FALLBACK_TRANSPORT_PARAM = "fallbackTransport";
+
+        public PushMode mode = PushMode.DISABLED;
+        public Map<String, String> parameters = new HashMap<String, String>();
+        {
+            parameters.put(TRANSPORT_PARAM, Transport.DEFAULT.getIdentifier());
+            parameters.put(FALLBACK_TRANSPORT_PARAM,
+                    Transport.DEFAULT_FALLBACK.getIdentifier());
+        }
+    }
+
     /**
      * State related to the Page class.
      */
@@ -57,6 +70,11 @@ public class UIState extends TabIndexState {
      */
     public LocaleServiceState localeServiceState = new LocaleServiceState();
 
+    /**
+     * Configuration for the push channel
+     */
+    public PushConfigurationState pushConfiguration = new PushConfigurationState();
+
     {
         primaryStyleName = "v-ui";
         // Default is 1 for legacy reasons
diff --git a/uitest/src/com/vaadin/tests/push/PushConfiguration.html b/uitest/src/com/vaadin/tests/push/PushConfiguration.html
new file mode 100644 (file)
index 0000000..c3786b1
--- /dev/null
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8888/" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<!--Websocket-->
+<tr>
+       <td>open</td>
+       <td>/run/com.vaadin.tests.push.PushConfigurationTest?debug&amp;restartApplication</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertNotText</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td>
+       <td>4</td>
+</tr>
+<tr>
+       <td>select</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[1]/VNativeSelect[0]/domChild[0]</td>
+       <td>label=WEBSOCKET</td>
+</tr>
+<tr>
+       <td>assertNotText</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td>
+       <td>4</td>
+</tr>
+<tr>
+       <td>select</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]</td>
+       <td>label=AUTOMATIC</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[5]/VLabel[0]/domChild[0]</td>
+       <td>*fallbackTransport: streaming*transport: websocket*</td>
+</tr>
+<tr>
+       <td>assertNotText</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td>
+       <td>4</td>
+</tr>
+<tr>
+       <td>waitForText</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td>
+       <td>4</td>
+</tr>
+<!--Use debug console to verify we used the correct transport type-->
+<tr>
+       <td>assertTextPresent</td>
+       <td>Push connection established using websocket</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertTextNotPresent</td>
+       <td>Push connection established using streaming</td>
+       <td>Push connection established using streaming</td>
+</tr>
+<tr>
+       <td>select</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]</td>
+       <td>label=DISABLED</td>
+</tr>
+<!--Streaming-->
+<tr>
+       <td>open</td>
+       <td>/run/com.vaadin.tests.push.PushConfigurationTest?debug&amp;restartApplication</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertNotText</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td>
+       <td>4</td>
+</tr>
+<tr>
+       <td>select</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[1]/VNativeSelect[0]/domChild[0]</td>
+       <td>label=STREAMING</td>
+</tr>
+<tr>
+       <td>assertNotText</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td>
+       <td>4</td>
+</tr>
+<tr>
+       <td>select</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]</td>
+       <td>label=AUTOMATIC</td>
+</tr>
+<tr>
+       <td>assertNotText</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td>
+       <td>4</td>
+</tr>
+<tr>
+       <td>assertText</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[5]/VLabel[0]/domChild[0]</td>
+       <td>*fallbackTransport: streaming*transport: streaming*</td>
+</tr>
+<tr>
+       <td>waitForText</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]</td>
+       <td>4</td>
+</tr>
+<!--Use debug console to verify we used the correct transport type-->
+<tr>
+       <td>assertTextNotPresent</td>
+       <td>Push connection established using websocket</td>
+       <td></td>
+</tr>
+<tr>
+       <td>assertTextPresent</td>
+       <td>Push connection established using streaming</td>
+       <td></td>
+</tr>
+<tr>
+       <td>select</td>
+       <td>vaadin=runcomvaadintestspushPushConfigurationTest::/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]</td>
+       <td>label=DISABLED</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java b/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java
new file mode 100644 (file)
index 0000000..b57e973
--- /dev/null
@@ -0,0 +1,102 @@
+package com.vaadin.tests.push;
+
+import java.util.Date;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import com.vaadin.data.util.ObjectProperty;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Label;
+
+public class PushConfigurationTest extends AbstractTestUI {
+
+    private ObjectProperty<Integer> counter = new ObjectProperty<Integer>(0);
+
+    private ObjectProperty<Integer> counter2 = new ObjectProperty<Integer>(0);
+
+    private final Timer timer = new Timer(true);
+
+    private final TimerTask task = new TimerTask() {
+
+        @Override
+        public void run() {
+            access(new Runnable() {
+                @Override
+                public void run() {
+                    counter2.setValue(counter2.getValue() + 1);
+                }
+            });
+        }
+    };
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        addComponent(new PushConfigurator(this));
+        spacer();
+
+        /*
+         * Client initiated push.
+         */
+        Label lbl = new Label(counter);
+        lbl.setCaption("Client counter (click 'increment' to update):");
+        addComponent(lbl);
+
+        addComponent(new Button("Increment", new Button.ClickListener() {
+
+            @Override
+            public void buttonClick(ClickEvent event) {
+                counter.setValue(counter.getValue() + 1);
+            }
+        }));
+
+        spacer();
+
+        /*
+         * Server initiated push.
+         */
+        lbl = new Label(counter2);
+        lbl.setCaption("Server counter (updates each 1s by server thread) :");
+        addComponent(lbl);
+
+        addComponent(new Button("Reset", new Button.ClickListener() {
+
+            @Override
+            public void buttonClick(ClickEvent event) {
+                counter2.setValue(0);
+            }
+        }));
+    }
+
+    @Override
+    protected String getTestDescription() {
+        return "This test tests the very basic operations of push. "
+                + "It tests that client initiated changes are "
+                + "recieved back to the client as well as server "
+                + "initiated changes are correctly updated to the client.";
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 11494;
+    }
+
+    private void spacer() {
+        addComponent(new Label("<hr/>", ContentMode.HTML));
+    }
+
+    @Override
+    public void attach() {
+        super.attach();
+        timer.scheduleAtFixedRate(task, new Date(), 1000);
+    }
+
+    @Override
+    public void detach() {
+        super.detach();
+        timer.cancel();
+    }
+}
diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurator.java b/uitest/src/com/vaadin/tests/push/PushConfigurator.java
new file mode 100644 (file)
index 0000000..6528366
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * 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.tests.push;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.shared.communication.PushMode;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.shared.ui.ui.Transport;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.NativeSelect;
+import com.vaadin.ui.PushConfiguration;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+
+/**
+ * 
+ * @since 7.1
+ * @author Vaadin Ltd
+ */
+public class PushConfigurator extends VerticalLayout {
+    private NativeSelect pushMode = new NativeSelect("Push mode");
+    private NativeSelect transport = new NativeSelect("Transport");
+    private NativeSelect fallbackTransport = new NativeSelect("Fallback");
+    private TextField parameter = new TextField("Parameter");
+    private TextField value = new TextField("Value");
+    private Button set = new Button("Set");
+    private HorizontalLayout paramValue = new HorizontalLayout();
+    private VerticalLayout vl = new VerticalLayout();
+    private UI ui;
+
+    private Label status = new Label("", ContentMode.PREFORMATTED);
+
+    public PushConfigurator(UI ui) {
+        this.ui = ui;
+        construct();
+        refreshStatus();
+    }
+
+    /**
+     * @since
+     */
+    private void refreshStatus() {
+        PushConfiguration pc = ui.getPushConfiguration();
+        String value = "";
+        ArrayList<String> names = new ArrayList<String>();
+        names.addAll(pc.getParameterNames());
+        Collections.sort(names);
+        for (String param : names) {
+            value += param + ": " + pc.getParameter(param) + "\n";
+        }
+        status.setValue(value);
+    }
+
+    /**
+     * @since
+     */
+    private void construct() {
+        pushMode.addItem(PushMode.DISABLED);
+        pushMode.addItem(PushMode.MANUAL);
+        pushMode.addItem(PushMode.AUTOMATIC);
+
+        for (Transport t : Transport.values()) {
+            transport.addItem(t.toString());
+            fallbackTransport.addItem(t.toString());
+        }
+        transport.addItem("");
+        fallbackTransport.addItem("");
+
+        pushMode.setImmediate(true);
+        transport.setImmediate(true);
+        fallbackTransport.setImmediate(true);
+
+        listeners();
+
+        paramValue.setDefaultComponentAlignment(Alignment.BOTTOM_RIGHT);
+        paramValue.addComponents(parameter, value, set);
+        vl.addComponents(pushMode, transport, fallbackTransport, paramValue,
+                new Label("<hr/>", ContentMode.HTML), status);
+        addComponent(vl);
+
+    }
+
+    /**
+     * @since
+     */
+    private void listeners() {
+        pushMode.addValueChangeListener(new ValueChangeListener() {
+            @Override
+            public void valueChange(ValueChangeEvent event) {
+                ui.getPushConfiguration().setPushMode(
+                        (PushMode) pushMode.getValue());
+                refreshStatus();
+            }
+        });
+
+        transport.addValueChangeListener(new ValueChangeListener() {
+            @Override
+            public void valueChange(ValueChangeEvent event) {
+                Transport t = Transport.valueOf((String) transport.getValue());
+                ui.getPushConfiguration().setTransport(t);
+                refreshStatus();
+            }
+        });
+
+        fallbackTransport.addValueChangeListener(new ValueChangeListener() {
+            @Override
+            public void valueChange(ValueChangeEvent event) {
+                Transport t = Transport.valueOf((String) fallbackTransport
+                        .getValue());
+                ui.getPushConfiguration().setFallbackTransport(t);
+                refreshStatus();
+            }
+        });
+
+        set.addClickListener(new ClickListener() {
+            @Override
+            public void buttonClick(ClickEvent event) {
+                ui.getPushConfiguration().setParameter(parameter.getValue(),
+                        value.getValue());
+                refreshStatus();
+            }
+        });
+
+    }
+}
index 37687260dd38c8ab7dc28dc691b3b05123543046..c0bdc54ee00a2add8b2deb7b390aa6edf328ac36 100644 (file)
@@ -22,19 +22,22 @@ public class TogglePush extends AbstractTestUI {
         updateCounter();
         addComponent(counterLabel);
 
-        setPushMode("disabled".equals(request.getParameter("push")) ? PushMode.DISABLED
-                : PushMode.AUTOMATIC);
+        getPushConfiguration()
+                .setPushMode(
+                        "disabled".equals(request.getParameter("push")) ? PushMode.DISABLED
+                                : PushMode.AUTOMATIC);
 
         CheckBox pushSetting = new CheckBox("Push enabled");
-        pushSetting.setValue(Boolean.valueOf(getPushMode().isEnabled()));
+        pushSetting.setValue(Boolean.valueOf(getPushConfiguration()
+                .getPushMode().isEnabled()));
         pushSetting.setImmediate(true);
         pushSetting.addValueChangeListener(new ValueChangeListener() {
             @Override
             public void valueChange(ValueChangeEvent event) {
                 if (event.getProperty().getValue() == Boolean.TRUE) {
-                    setPushMode(PushMode.AUTOMATIC);
+                    getPushConfiguration().setPushMode(PushMode.AUTOMATIC);
                 } else {
-                    setPushMode(PushMode.DISABLED);
+                    getPushConfiguration().setPushMode(PushMode.DISABLED);
                 }
             }
         });
index e255a5f95a39be248f4bd2b97f438c2de0b75e86..4dae8892e79a6428800149587bbf4c6d2a7faca5 100644 (file)
@@ -4,6 +4,7 @@ import com.google.gwt.user.client.Window;
 import com.vaadin.client.ApplicationConnection;
 import com.vaadin.client.ApplicationConnection.CommunicationErrorHandler;
 import com.vaadin.client.communication.AtmospherePushConnection;
+import com.vaadin.shared.ui.ui.UIState.PushConfigurationState;
 
 public class TestingPushConnection extends AtmospherePushConnection {
 
@@ -11,8 +12,9 @@ public class TestingPushConnection extends AtmospherePushConnection {
 
     @Override
     public void init(ApplicationConnection connection,
+            PushConfigurationState pushConfiguration,
             CommunicationErrorHandler errorHandler) {
-        super.init(connection, errorHandler);
+        super.init(connection, pushConfiguration, errorHandler);
         transport = Window.Location.getParameter("transport");
     }