aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WebContent/license.html11
-rw-r--r--client/src/com/vaadin/client/LayoutManager.java37
-rw-r--r--client/src/com/vaadin/client/ui/VAccordion.java1
-rwxr-xr-xscripts/automerge7.sh4
-rw-r--r--server/src/com/vaadin/data/util/MethodProperty.java26
-rw-r--r--server/src/com/vaadin/server/VaadinPortlet.java228
-rw-r--r--server/src/com/vaadin/server/VaadinService.java12
-rw-r--r--server/src/com/vaadin/server/VaadinSession.java82
-rw-r--r--server/src/com/vaadin/server/communication/AtmospherePushConnection.java10
-rw-r--r--server/src/com/vaadin/server/communication/PushHandler.java78
-rw-r--r--server/src/com/vaadin/ui/AbstractOrderedLayout.java10
-rw-r--r--server/src/com/vaadin/ui/ComboBox.java14
-rw-r--r--server/src/com/vaadin/ui/UI.java3
-rw-r--r--server/src/com/vaadin/ui/Window.java29
-rw-r--r--server/tests/src/com/vaadin/data/util/MethodPropertyMemoryConsumption.java145
-rw-r--r--server/tests/src/com/vaadin/server/VaadinGateInRequestTests.java39
-rw-r--r--server/tests/src/com/vaadin/server/VaadinHttpAndPortletRequestTests.java140
-rw-r--r--server/tests/src/com/vaadin/server/VaadinLiferayRequestTests.java39
-rw-r--r--server/tests/src/com/vaadin/server/VaadinPortletTests.java94
-rw-r--r--server/tests/src/com/vaadin/server/VaadinServiceTest.java22
-rw-r--r--server/tests/src/com/vaadin/server/VaadinWebSpherePortalRequestTests.java39
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/LayoutSettingsOnReplace.java85
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/window/WindowTest.java53
-rw-r--r--uitest/src/com/vaadin/tests/components/accordion/AccordionAddTab.java72
-rw-r--r--uitest/src/com/vaadin/tests/components/accordion/AccordionAddTabTest.java48
-rw-r--r--uitest/src/com/vaadin/tests/push/PushConfigurationLongPollingTest.java58
-rw-r--r--uitest/src/com/vaadin/tests/push/PushConfigurationStreamingTest.java57
-rw-r--r--uitest/src/com/vaadin/tests/push/PushConfigurationTest.java138
-rw-r--r--uitest/src/com/vaadin/tests/push/PushConfigurationWebSocketTest.java58
-rw-r--r--uitest/src/com/vaadin/tests/push/PushConfigurator.java1
30 files changed, 1373 insertions, 260 deletions
diff --git a/WebContent/license.html b/WebContent/license.html
index 0f9a573041..d984717773 100644
--- a/WebContent/license.html
+++ b/WebContent/license.html
@@ -99,7 +99,7 @@
<!-- In vaadin-shared-deps -->
<tr>
<td>JSON</td>
- <td><a href="licenses/the-json-license.txt">The JSON License</a></td>
+ <td><a href="licenses/apache-license-version-2-0.txt">Apache License, Version 2.0</a></td>
</tr>
<!-- Used by vaadin-server -->
@@ -135,6 +135,11 @@
<td>FontAwesome</td>
<td><a href="licenses/OFL.txt">SIL OFL 1.1</a></td>
</tr>
+ <!-- The extracted vaadin-sass-compiler -->
+ <tr>
+ <td>Vaadin Sass Compiler</td>
+ <td><a href="licenses/apache-license-version-2-0.txt">Apache License, Version 2.0</a></td>
+ </tr>
</tbody>
</table>
@@ -182,6 +187,10 @@
<td>Apache Jakarta Regexp</td>
<td><a href="licenses/apache-license-version-2-0.txt">Apache License, Version 2.0</a></td>
</tr>
+ <tr>
+ <td>Apache Mime4j</td>
+ <td><a href="licenses/apache-license-version-2-0.txt">Apache License, Version 2.0</a></td>
+ </tr>
<!-- The Mime4j does not appear to be used anywhere. Remove if necessary.
<tr>
diff --git a/client/src/com/vaadin/client/LayoutManager.java b/client/src/com/vaadin/client/LayoutManager.java
index fbf540273f..69f3f08144 100644
--- a/client/src/com/vaadin/client/LayoutManager.java
+++ b/client/src/com/vaadin/client/LayoutManager.java
@@ -20,6 +20,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.logging.Logger;
import com.google.gwt.core.client.Duration;
import com.google.gwt.core.client.JsArrayString;
@@ -827,6 +828,12 @@ public class LayoutManager {
/**
* Marks that a ManagedLayout should be layouted in the next layout phase
* even if none of the elements managed by the layout have been resized.
+ * <p>
+ * This method should not be invoked during a layout phase since it only
+ * controls what will happen in the beginning of the next phase. If you want
+ * to explicitly cause some layout to be considered in an ongoing layout
+ * phase, you should use {@link #setNeedsMeasure(ComponentConnector)}
+ * instead.
*
* @param layout
* the managed layout that should be layouted
@@ -840,14 +847,25 @@ public class LayoutManager {
* Marks that a ManagedLayout should be layouted horizontally in the next
* layout phase even if none of the elements managed by the layout have been
* resized horizontally.
- *
+ * <p>
* For SimpleManagedLayout which is always layouted in both directions, this
* has the same effect as {@link #setNeedsLayout(ManagedLayout)}.
+ * <p>
+ * This method should not be invoked during a layout phase since it only
+ * controls what will happen in the beginning of the next phase. If you want
+ * to explicitly cause some layout to be considered in an ongoing layout
+ * phase, you should use {@link #setNeedsMeasure(ComponentConnector)}
+ * instead.
*
* @param layout
* the managed layout that should be layouted
*/
public final void setNeedsHorizontalLayout(ManagedLayout layout) {
+ if (isLayoutRunning()) {
+ getLogger()
+ .warning(
+ "setNeedsHorizontalLayout should not be run while a layout phase is in progress.");
+ }
needsHorizontalLayout.add(layout.getConnectorId());
}
@@ -855,14 +873,25 @@ public class LayoutManager {
* Marks that a ManagedLayout should be layouted vertically in the next
* layout phase even if none of the elements managed by the layout have been
* resized vertically.
- *
+ * <p>
* For SimpleManagedLayout which is always layouted in both directions, this
* has the same effect as {@link #setNeedsLayout(ManagedLayout)}.
+ * <p>
+ * This method should not be invoked during a layout phase since it only
+ * controls what will happen in the beginning of the next phase. If you want
+ * to explicitly cause some layout to be considered in an ongoing layout
+ * phase, you should use {@link #setNeedsMeasure(ComponentConnector)}
+ * instead.
*
* @param layout
* the managed layout that should be layouted
*/
public final void setNeedsVerticalLayout(ManagedLayout layout) {
+ if (isLayoutRunning()) {
+ getLogger()
+ .warning(
+ "setNeedsVerticalLayout should not be run while a layout phase is in progress.");
+ }
needsVerticalLayout.add(layout.getConnectorId());
}
@@ -1609,4 +1638,8 @@ public class LayoutManager {
protected void cleanMeasuredSizes() {
}
+ private static Logger getLogger() {
+ return Logger.getLogger(LayoutManager.class.getName());
+ }
+
}
diff --git a/client/src/com/vaadin/client/ui/VAccordion.java b/client/src/com/vaadin/client/ui/VAccordion.java
index cba08d8e6b..d348e6863b 100644
--- a/client/src/com/vaadin/client/ui/VAccordion.java
+++ b/client/src/com/vaadin/client/ui/VAccordion.java
@@ -277,6 +277,7 @@ public class VAccordion extends VTabsheetBase {
public void replaceWidget(Widget newWidget) {
if (getWidgetCount() > 1) {
Widget oldWidget = getWidget(1);
+ remove(oldWidget);
widgets.remove(oldWidget);
}
add(newWidget, content);
diff --git a/scripts/automerge7.sh b/scripts/automerge7.sh
index 3349d8d622..abc577f6b9 100755
--- a/scripts/automerge7.sh
+++ b/scripts/automerge7.sh
@@ -1,8 +1,8 @@
#!/bin/bash
IGNORE=7.0
-FROM=7.1
-TO=7.2
+FROM=7.2
+TO=master
IGNORE_HEAD=origin/$IGNORE
FROM_HEAD=origin/$FROM
diff --git a/server/src/com/vaadin/data/util/MethodProperty.java b/server/src/com/vaadin/data/util/MethodProperty.java
index 0464d50b62..d7323d872f 100644
--- a/server/src/com/vaadin/data/util/MethodProperty.java
+++ b/server/src/com/vaadin/data/util/MethodProperty.java
@@ -19,6 +19,7 @@ package com.vaadin.data.util;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -85,6 +86,10 @@ public class MethodProperty<T> extends AbstractProperty<T> {
*/
private transient Class<? extends T> type;
+ private static final Object[] DEFAULT_GET_ARGS = new Object[0];
+
+ private static final Object[] DEFAULT_SET_ARGS = new Object[1];
+
/* Special serialization to handle method references */
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
@@ -120,8 +125,9 @@ public class MethodProperty<T> extends AbstractProperty<T> {
Class<T> class1 = (Class<T>) SerializerHelper.readClass(in);
type = class1;
instance = in.readObject();
- setArgs = (Object[]) in.readObject();
- getArgs = (Object[]) in.readObject();
+ Object[] setArgs = (Object[]) in.readObject();
+ Object[] getArgs = (Object[]) in.readObject();
+ setArguments(getArgs, setArgs, setArgumentIndex);
String name = (String) in.readObject();
Class<?>[] paramTypes = SerializerHelper.readClassArray(in);
if (name != null) {
@@ -219,7 +225,7 @@ public class MethodProperty<T> extends AbstractProperty<T> {
type = (Class<T>) returnType;
}
- setArguments(new Object[] {}, new Object[] { null }, 0);
+ setArguments(DEFAULT_GET_ARGS, DEFAULT_SET_ARGS, 0);
this.instance = instance;
}
@@ -627,13 +633,15 @@ public class MethodProperty<T> extends AbstractProperty<T> {
*/
public void setArguments(Object[] getArgs, Object[] setArgs,
int setArgumentIndex) {
- this.getArgs = new Object[getArgs.length];
- for (int i = 0; i < getArgs.length; i++) {
- this.getArgs[i] = getArgs[i];
+ if (getArgs.length == 0) {
+ this.getArgs = DEFAULT_GET_ARGS;
+ } else {
+ this.getArgs = Arrays.copyOf(getArgs, getArgs.length);
}
- this.setArgs = new Object[setArgs.length];
- for (int i = 0; i < setArgs.length; i++) {
- this.setArgs[i] = setArgs[i];
+ if (Arrays.equals(setArgs, DEFAULT_SET_ARGS)) {
+ this.setArgs = DEFAULT_SET_ARGS;
+ } else {
+ this.setArgs = Arrays.copyOf(setArgs, setArgs.length);
}
this.setArgumentIndex = setArgumentIndex;
}
diff --git a/server/src/com/vaadin/server/VaadinPortlet.java b/server/src/com/vaadin/server/VaadinPortlet.java
index 4c34b0aedb..b3ce238e72 100644
--- a/server/src/com/vaadin/server/VaadinPortlet.java
+++ b/server/src/com/vaadin/server/VaadinPortlet.java
@@ -29,6 +29,7 @@ import javax.portlet.ActionResponse;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.GenericPortlet;
+import javax.portlet.PortalContext;
import javax.portlet.PortletConfig;
import javax.portlet.PortletContext;
import javax.portlet.PortletException;
@@ -51,61 +52,83 @@ import com.vaadin.util.CurrentInstance;
* Portlet 2.0 base class. This replaces the servlet in servlet/portlet 1.0
* deployments and handles various portlet requests from the browser.
*
- * TODO Document me!
- *
- * @author peholmst
+ * @author Vaadin Ltd
*/
public class VaadinPortlet extends GenericPortlet implements Constants,
Serializable {
/**
- * @deprecated As of 7.0. Will likely change or be removed in a future
- * version
+ * Base class for portlet requests that need access to HTTP servlet
+ * requests.
*/
- @Deprecated
- public static final String RESOURCE_URL_ID = "APP";
-
- public static class VaadinHttpAndPortletRequest extends
+ public static abstract class VaadinHttpAndPortletRequest extends
VaadinPortletRequest {
+ /**
+ * Constructs a new {@link VaadinHttpAndPortletRequest}.
+ *
+ * @since 7.2
+ * @param request
+ * {@link PortletRequest} to be wrapped
+ * @param vaadinService
+ * {@link VaadinPortletService} associated with this request
+ */
public VaadinHttpAndPortletRequest(PortletRequest request,
- HttpServletRequest originalRequest,
VaadinPortletService vaadinService) {
super(request, vaadinService);
- this.originalRequest = originalRequest;
}
- private final HttpServletRequest originalRequest;
+ private HttpServletRequest originalRequest;
+
+ /**
+ * Returns the original HTTP servlet request for this portlet request.
+ *
+ * @since 7.2
+ * @param request
+ * {@link PortletRequest} used to
+ * @return the original HTTP servlet request
+ */
+ protected abstract HttpServletRequest getServletRequest(
+ PortletRequest request);
+
+ private HttpServletRequest getOriginalRequest() {
+ if (originalRequest == null) {
+ PortletRequest request = getRequest();
+ originalRequest = getServletRequest(request);
+ }
+
+ return originalRequest;
+ }
@Override
public String getParameter(String name) {
String parameter = super.getParameter(name);
if (parameter == null) {
- parameter = originalRequest.getParameter(name);
+ parameter = getOriginalRequest().getParameter(name);
}
return parameter;
}
@Override
public String getRemoteAddr() {
- return originalRequest.getRemoteAddr();
+ return getOriginalRequest().getRemoteAddr();
}
@Override
public String getRemoteHost() {
- return originalRequest.getRemoteHost();
+ return getOriginalRequest().getRemoteHost();
}
@Override
public int getRemotePort() {
- return originalRequest.getRemotePort();
+ return getOriginalRequest().getRemotePort();
}
@Override
public String getHeader(String name) {
String header = super.getHeader(name);
if (header == null) {
- header = originalRequest.getHeader(name);
+ header = getOriginalRequest().getHeader(name);
}
return header;
}
@@ -114,7 +137,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
public Enumeration<String> getHeaderNames() {
Enumeration<String> headerNames = super.getHeaderNames();
if (headerNames == null) {
- headerNames = originalRequest.getHeaderNames();
+ headerNames = getOriginalRequest().getHeaderNames();
}
return headerNames;
}
@@ -123,7 +146,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
public Enumeration<String> getHeaders(String name) {
Enumeration<String> headers = super.getHeaders(name);
if (headers == null) {
- headers = originalRequest.getHeaders(name);
+ headers = getOriginalRequest().getHeaders(name);
}
return headers;
}
@@ -132,64 +155,21 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
public Map<String, String[]> getParameterMap() {
Map<String, String[]> parameterMap = super.getParameterMap();
if (parameterMap == null) {
- parameterMap = originalRequest.getParameterMap();
+ parameterMap = getOriginalRequest().getParameterMap();
}
return parameterMap;
}
}
- public static class VaadinGateinRequest extends VaadinHttpAndPortletRequest {
- public VaadinGateinRequest(PortletRequest request,
- VaadinPortletService vaadinService) {
- super(request, getOriginalRequest(request), vaadinService);
- }
-
- private static final HttpServletRequest getOriginalRequest(
- PortletRequest request) {
- try {
- Method getRealReq = request.getClass().getMethod(
- "getRealRequest");
- HttpServletRequestWrapper origRequest = (HttpServletRequestWrapper) getRealReq
- .invoke(request);
- return origRequest;
- } catch (Exception e) {
- throw new IllegalStateException("GateIn request not detected",
- e);
- }
- }
- }
-
- // Intentionally internal, will be refactored out in 7.2.
- static class WebSpherePortalRequest extends VaadinHttpAndPortletRequest {
-
- public WebSpherePortalRequest(PortletRequest request,
- VaadinPortletService vaadinService) {
- super(request, getServletRequest(request), vaadinService);
- }
-
- private static HttpServletRequest getServletRequest(
- PortletRequest request) {
- try {
- Class<?> portletUtils = Class
- .forName("com.ibm.ws.portletcontainer.portlet.PortletUtils");
- Method getHttpServletRequest = portletUtils.getMethod(
- "getHttpServletRequest", PortletRequest.class);
-
- return (HttpServletRequest) getHttpServletRequest.invoke(null,
- request);
- } catch (Exception e) {
- throw new IllegalStateException(
- "WebSphere Portal request not detected.");
- }
- }
- }
-
+ /**
+ * Portlet request for Liferay.
+ */
public static class VaadinLiferayRequest extends
VaadinHttpAndPortletRequest {
public VaadinLiferayRequest(PortletRequest request,
VaadinPortletService vaadinService) {
- super(request, getOriginalRequest(request), vaadinService);
+ super(request, vaadinService);
}
@Override
@@ -219,7 +199,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
* @throws Exception
* @return return value of the invoked method
*/
- private static Object invokeStaticLiferayMethod(String className,
+ private Object invokeStaticLiferayMethod(String className,
String methodName, Object argument, String parameterClassName)
throws Exception {
Thread currentThread = Thread.currentThread();
@@ -251,8 +231,8 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
}
}
- private static HttpServletRequest getOriginalRequest(
- PortletRequest request) {
+ @Override
+ protected HttpServletRequest getServletRequest(PortletRequest request) {
try {
// httpRequest = PortalUtil.getHttpServletRequest(request);
HttpServletRequest httpRequest = (HttpServletRequest) invokeStaticLiferayMethod(
@@ -272,10 +252,68 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
e);
}
}
+ }
+ /**
+ * Portlet request for GateIn.
+ */
+ public static class VaadinGateInRequest extends VaadinHttpAndPortletRequest {
+ public VaadinGateInRequest(PortletRequest request,
+ VaadinPortletService vaadinService) {
+ super(request, vaadinService);
+ }
+
+ @Override
+ protected HttpServletRequest getServletRequest(PortletRequest request) {
+ try {
+ Method getRealReq = request.getClass().getMethod(
+ "getRealRequest");
+ HttpServletRequestWrapper origRequest = (HttpServletRequestWrapper) getRealReq
+ .invoke(request);
+ return origRequest;
+ } catch (Exception e) {
+ throw new IllegalStateException("GateIn request not detected",
+ e);
+ }
+ }
+ }
+
+ /**
+ * Portlet request for WebSphere Portal.
+ */
+ public static class VaadinWebSpherePortalRequest extends
+ VaadinHttpAndPortletRequest {
+
+ public VaadinWebSpherePortalRequest(PortletRequest request,
+ VaadinPortletService vaadinService) {
+ super(request, vaadinService);
+ }
+
+ @Override
+ protected HttpServletRequest getServletRequest(PortletRequest request) {
+ try {
+ Class<?> portletUtils = Class
+ .forName("com.ibm.ws.portletcontainer.portlet.PortletUtils");
+ Method getHttpServletRequest = portletUtils.getMethod(
+ "getHttpServletRequest", PortletRequest.class);
+
+ return (HttpServletRequest) getHttpServletRequest.invoke(null,
+ request);
+ } catch (Exception e) {
+ throw new IllegalStateException(
+ "WebSphere Portal request not detected.");
+ }
+ }
}
/**
+ * @deprecated As of 7.0. Will likely change or be removed in a future
+ * version
+ */
+ @Deprecated
+ public static final String RESOURCE_URL_ID = "APP";
+
+ /**
* This portlet parameter is used to add styles to the main element. E.g
* "height:500px" generates a style="height:500px" to the main element.
*
@@ -443,50 +481,26 @@ public class VaadinPortlet extends GenericPortlet implements Constants,
*
* @param request
* The original PortletRequest
- * @return A wrapped version of the PorletRequest
+ * @return A wrapped version of the PortletRequest
*/
protected VaadinPortletRequest createVaadinRequest(PortletRequest request) {
- if (isLiferay(request)) {
- return new VaadinLiferayRequest(request, getService());
- } else if (isGateIn(request)) {
- return new VaadinGateinRequest(request, getService());
- } else if (isWebSphere(request)) {
- return new WebSpherePortalRequest(request, getService());
- } else {
+ PortalContext portalContext = request.getPortalContext();
+ String portalInfo = portalContext.getPortalInfo().toLowerCase().trim();
+ VaadinPortletService service = getService();
- return new VaadinPortletRequest(request, getService());
+ if (portalInfo.contains("gatein")) {
+ return new VaadinGateInRequest(request, service);
}
- }
-
- /**
- * Returns true if the portlet request is from Liferay.
- *
- * @param request
- * @return True if Liferay, false otherwise
- */
- private static boolean isLiferay(PortletRequest request) {
- String portalInfo = request.getPortalContext().getPortalInfo()
- .toLowerCase();
- return portalInfo.contains("liferay");
- }
- /**
- * Returns true if the portlet request if from GateIn
- *
- * @param request
- * @return True if GateIn, false otherwise
- */
- private static boolean isGateIn(PortletRequest request) {
- String portalInfo = request.getPortalContext().getPortalInfo()
- .toLowerCase();
- return portalInfo.contains("gatein");
- }
+ if (portalInfo.contains("liferay")) {
+ return new VaadinLiferayRequest(request, service);
+ }
- private static boolean isWebSphere(PortletRequest request) {
- String portalInfo = request.getPortalContext().getPortalInfo()
- .toLowerCase();
+ if (portalInfo.contains("websphere portal")) {
+ return new VaadinWebSpherePortalRequest(request, service);
+ }
- return portalInfo.contains("websphere portal");
+ return new VaadinPortletRequest(request, service);
}
private VaadinPortletResponse createVaadinResponse(PortletResponse response) {
diff --git a/server/src/com/vaadin/server/VaadinService.java b/server/src/com/vaadin/server/VaadinService.java
index ba1224568a..b96e284e6e 100644
--- a/server/src/com/vaadin/server/VaadinService.java
+++ b/server/src/com/vaadin/server/VaadinService.java
@@ -53,6 +53,7 @@ import org.json.JSONObject;
import com.vaadin.annotations.PreserveOnRefresh;
import com.vaadin.event.EventRouter;
import com.vaadin.server.VaadinSession.FutureAccess;
+import com.vaadin.server.VaadinSession.State;
import com.vaadin.server.communication.FileUploadHandler;
import com.vaadin.server.communication.HeartbeatHandler;
import com.vaadin.server.communication.PublishedFileHandler;
@@ -446,7 +447,10 @@ public abstract class VaadinService implements Serializable {
session.accessSynchronously(new Runnable() {
@Override
public void run() {
- if (!session.isClosing()) {
+ if (session.getState() == State.CLOSED) {
+ return;
+ }
+ if (session.getState() == State.OPEN) {
closeSession(session);
}
ArrayList<UI> uis = new ArrayList<UI>(session.getUIs());
@@ -472,6 +476,8 @@ public abstract class VaadinService implements Serializable {
// destroy listeners
eventRouter.fireEvent(new SessionDestroyEvent(
VaadinService.this, session), session.getErrorHandler());
+
+ session.setState(State.CLOSED);
}
});
}
@@ -1127,7 +1133,7 @@ public abstract class VaadinService implements Serializable {
closeInactiveUIs(session);
removeClosedUIs(session);
} else {
- if (!session.isClosing()) {
+ if (session.getState() == State.OPEN) {
closeSession(session);
if (session.getSession() != null) {
getLogger().log(Level.FINE, "Closing inactive session {0}",
@@ -1279,7 +1285,7 @@ public abstract class VaadinService implements Serializable {
* @return true if the session is active, false if it could be closed.
*/
private boolean isSessionActive(VaadinSession session) {
- if (session.isClosing() || session.getSession() == null) {
+ if (session.getState() != State.OPEN || session.getSession() == null) {
return false;
} else {
long now = System.currentTimeMillis();
diff --git a/server/src/com/vaadin/server/VaadinSession.java b/server/src/com/vaadin/server/VaadinSession.java
index 134a026788..ac518c1902 100644
--- a/server/src/com/vaadin/server/VaadinSession.java
+++ b/server/src/com/vaadin/server/VaadinSession.java
@@ -167,6 +167,33 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
}
/**
+ * The lifecycle state of a VaadinSession.
+ *
+ * @since 7.2
+ */
+ public enum State {
+ /**
+ * The session is active and accepting client requests.
+ */
+ OPEN,
+ /**
+ * The {@link VaadinSession#close() close} method has been called; the
+ * session will be closed as soon as the current request ends.
+ */
+ CLOSING,
+ /**
+ * The session is closed; all the {@link UI}s have been removed and
+ * {@link SessionDestroyListener}s have been called.
+ */
+ CLOSED;
+
+ private boolean isValidChange(State newState) {
+ return (this == OPEN && newState == CLOSING)
+ || (this == CLOSING && newState == CLOSED);
+ }
+ }
+
+ /**
* The name of the parameter that is by default used in e.g. web.xml to
* define the name of the default {@link UI} class.
*/
@@ -225,7 +252,7 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
private long lastRequestTimestamp = System.currentTimeMillis();
- private boolean closing = false;
+ private State state = State.OPEN;
private transient WrappedSession session;
@@ -279,24 +306,20 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
} else if (VaadinService.getCurrentRequest() != null
&& getCurrent() == this) {
assert hasLock();
- /*
- * Ignore if the session is being moved to a different backing
- * session or if GAEVaadinServlet is doing its normal cleanup.
- */
+ // Ignore if the session is being moved to a different backing
+ // session or if GAEVaadinServlet is doing its normal cleanup.
if (getAttribute(VaadinService.PRESERVE_UNBOUND_SESSION_ATTRIBUTE) == Boolean.TRUE) {
return;
}
// There is still a request in progress for this session. The
// session will be destroyed after the response has been written.
- if (!isClosing()) {
+ if (getState() == State.OPEN) {
close();
}
} else {
- /*
- * We are not in a request related to this session so we can
- * immediately destroy it
- */
+ // We are not in a request related to this session so we can destroy
+ // it as soon as we acquire the lock.
service.fireSessionDestroy(this);
}
session = null;
@@ -1226,19 +1249,52 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
*/
public void close() {
assert hasLock();
- closing = true;
+ state = State.CLOSING;
}
/**
- * Returns whether this session is marked to be closed.
+ * Returns whether this session is marked to be closed. Note that this
+ * method also returns true if the session is actually already closed.
*
* @see #close()
*
+ * @deprecated As of 7.2, use
+ * <code>{@link #getState() getState() != State.OPEN}</code>
+ * instead.
+ *
* @return true if this session is marked to be closed, false otherwise
*/
+ @Deprecated
public boolean isClosing() {
assert hasLock();
- return closing;
+ return state == State.CLOSING || state == State.CLOSED;
+ }
+
+ /**
+ * Returns the lifecycle state of this session.
+ *
+ * @since 7.2
+ * @return the current state
+ */
+ public State getState() {
+ assert hasLock();
+ return state;
+ }
+
+ /**
+ * Sets the lifecycle state of this session. The allowed transitions are
+ * OPEN to CLOSING and CLOSING to CLOSED.
+ *
+ * @since 7.2
+ * @param state
+ * the new state
+ */
+ protected void setState(State state) {
+ assert hasLock();
+ assert this.state.isValidChange(state) : "Invalid session state change "
+ + this.state + "->" + state;
+
+ this.state = state;
}
private static final Logger getLogger() {
diff --git a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java
index 65ea43ddd4..a4290a31cf 100644
--- a/server/src/com/vaadin/server/communication/AtmospherePushConnection.java
+++ b/server/src/com/vaadin/server/communication/AtmospherePushConnection.java
@@ -260,6 +260,16 @@ public class AtmospherePushConnection implements PushConnection {
@Override
public void disconnect() {
assert isConnected();
+
+ if (resource.isResumed()) {
+ // Calling disconnect may end up invoking it again via
+ // resource.resume and PushHandler.onResume. Bail out here if
+ // the resource is already resumed; this is a bit hacky and should
+ // be implemented in a better way in 7.2.
+ resource = null;
+ return;
+ }
+
if (outgoingMessage != null) {
// Wait for the last message to be sent before closing the
// connection (assumes that futures are completed in order)
diff --git a/server/src/com/vaadin/server/communication/PushHandler.java b/server/src/com/vaadin/server/communication/PushHandler.java
index 1557ae9b19..e028968494 100644
--- a/server/src/com/vaadin/server/communication/PushHandler.java
+++ b/server/src/com/vaadin/server/communication/PushHandler.java
@@ -365,7 +365,83 @@ public class PushHandler extends AtmosphereResourceEventListenerAdapter {
}
private void disconnect(AtmosphereResourceEvent event) {
- callWithUi(event.getResource(), disconnectCallback);
+ // We don't want to use callWithUi here, as it assumes there's a client
+ // request active and does requestStart and requestEnd among other
+ // things.
+
+ AtmosphereResource resource = event.getResource();
+ VaadinServletRequest vaadinRequest = new VaadinServletRequest(
+ resource.getRequest(), service);
+ VaadinSession session = null;
+
+ try {
+ session = service.findVaadinSession(vaadinRequest);
+ } catch (ServiceException e) {
+ getLogger().log(Level.SEVERE,
+ "Could not get session. This should never happen", e);
+ return;
+ } catch (SessionExpiredException e) {
+ getLogger()
+ .log(Level.SEVERE,
+ "Session expired before push was disconnected. This should never happen",
+ e);
+ return;
+ }
+
+ UI ui = null;
+ session.lock();
+ try {
+ VaadinSession.setCurrent(session);
+ // Sets UI.currentInstance
+ ui = service.findUI(vaadinRequest);
+ if (ui == null) {
+ getLogger().log(Level.SEVERE,
+ "Could not get UI. This should never happen");
+ return;
+ }
+
+ PushMode pushMode = ui.getPushConfiguration().getPushMode();
+ AtmospherePushConnection pushConnection = getConnectionForUI(ui);
+
+ String id = resource.uuid();
+
+ if (pushConnection == null) {
+ getLogger()
+ .log(Level.WARNING,
+ "Could not find push connection to close: {0} with transport {1}",
+ new Object[] { id, resource.transport() });
+ } else {
+ if (!pushMode.isEnabled()) {
+ /*
+ * The client is expected to close the connection after push
+ * mode has been set to disabled.
+ */
+ getLogger().log(Level.FINER,
+ "Connection closed for resource {0}", id);
+ } else {
+ /*
+ * Unexpected cancel, e.g. if the user closes the browser
+ * tab.
+ */
+ getLogger()
+ .log(Level.FINER,
+ "Connection unexpectedly closed for resource {0} with transport {1}",
+ new Object[] { id, resource.transport() });
+ }
+ ui.setPushConnection(null);
+ }
+
+ } catch (final Exception e) {
+ callErrorHandler(session, e);
+ } finally {
+ 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
+ }
+ }
}
/**
diff --git a/server/src/com/vaadin/ui/AbstractOrderedLayout.java b/server/src/com/vaadin/ui/AbstractOrderedLayout.java
index c9eb756daa..f5fd4d7bfc 100644
--- a/server/src/com/vaadin/ui/AbstractOrderedLayout.java
+++ b/server/src/com/vaadin/ui/AbstractOrderedLayout.java
@@ -213,8 +213,12 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements
if (oldLocation == -1) {
addComponent(newComponent);
} else if (newLocation == -1) {
+ Alignment alignment = getComponentAlignment(oldComponent);
+ float expandRatio = getExpandRatio(oldComponent);
+
removeComponent(oldComponent);
addComponent(newComponent, oldLocation);
+ applyLayoutSettings(newComponent, alignment, expandRatio);
} else {
// Both old and new are in the layout
if (oldLocation > newLocation) {
@@ -444,4 +448,10 @@ public abstract class AbstractOrderedLayout extends AbstractLayout implements
defaultComponentAlignment = defaultAlignment;
}
+ private void applyLayoutSettings(Component target, Alignment alignment,
+ float expandRatio) {
+ setComponentAlignment(target, alignment);
+ setExpandRatio(target, expandRatio);
+ }
+
}
diff --git a/server/src/com/vaadin/ui/ComboBox.java b/server/src/com/vaadin/ui/ComboBox.java
index 5fb2f81011..da29618efe 100644
--- a/server/src/com/vaadin/ui/ComboBox.java
+++ b/server/src/com/vaadin/ui/ComboBox.java
@@ -103,22 +103,30 @@ public class ComboBox extends AbstractSelect implements
private boolean textInputAllowed = true;
public ComboBox() {
- setNewItemsAllowed(false);
+ initDefaults();
}
public ComboBox(String caption, Collection<?> options) {
super(caption, options);
- setNewItemsAllowed(false);
+ initDefaults();
}
public ComboBox(String caption, Container dataSource) {
super(caption, dataSource);
- setNewItemsAllowed(false);
+ initDefaults();
}
public ComboBox(String caption) {
super(caption);
+ initDefaults();
+ }
+
+ /**
+ * Initialize the ComboBox with default settings
+ */
+ private void initDefaults() {
setNewItemsAllowed(false);
+ setImmediate(true);
}
/**
diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java
index 5fbd654dcf..3ae0aea6f7 100644
--- a/server/src/com/vaadin/ui/UI.java
+++ b/server/src/com/vaadin/ui/UI.java
@@ -53,6 +53,7 @@ import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinService;
import com.vaadin.server.VaadinServlet;
import com.vaadin.server.VaadinSession;
+import com.vaadin.server.VaadinSession.State;
import com.vaadin.server.communication.PushConnection;
import com.vaadin.shared.Connector;
import com.vaadin.shared.EventId;
@@ -1162,7 +1163,7 @@ public abstract class UI extends AbstractSingleComponentContainer implements
public void close() {
closing = true;
- boolean sessionExpired = (session == null || session.isClosing());
+ boolean sessionExpired = (session == null || session.getState() != State.OPEN);
getRpcProxy(UIClientRpc.class).uiClosed(sessionExpired);
if (getPushConnection() != null) {
// Push the Rpc to the client. The connection will be closed when
diff --git a/server/src/com/vaadin/ui/Window.java b/server/src/com/vaadin/ui/Window.java
index 022adc6373..11a6fde853 100644
--- a/server/src/com/vaadin/ui/Window.java
+++ b/server/src/com/vaadin/ui/Window.java
@@ -18,9 +18,6 @@ package com.vaadin.ui;
import java.io.Serializable;
import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
import java.util.Map;
import com.vaadin.event.FieldEvents.BlurEvent;
@@ -1017,15 +1014,15 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
* window. Text contained in these components will be read by assistive
* devices when it is opened.
*
- * @param connectors
- * with the components to use as description
+ * @param components
+ * the components to use as description
*/
- public void setAssistiveDescription(Connector... connectors) {
- if (connectors == null) {
+ public void setAssistiveDescription(Component... components) {
+ if (components == null) {
throw new IllegalArgumentException(
"Parameter connectors must be non-null");
} else {
- getState().contentDescription = connectors;
+ getState().contentDescription = components;
}
}
@@ -1034,11 +1031,19 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier,
* contained in these components will be read by assistive devices when the
* window is opened.
*
- * @return list of previously set components
+ * @return array of previously set components
*/
- public List<Connector> getAssistiveDescription() {
- return Collections.unmodifiableList(Arrays
- .asList(getState().contentDescription));
+ public Component[] getAssistiveDescription() {
+ Connector[] contentDescription = getState().contentDescription;
+ if (contentDescription == null) {
+ return null;
+ }
+
+ Component[] target = new Component[contentDescription.length];
+ System.arraycopy(contentDescription, 0, target, 0,
+ contentDescription.length);
+
+ return target;
}
/**
diff --git a/server/tests/src/com/vaadin/data/util/MethodPropertyMemoryConsumption.java b/server/tests/src/com/vaadin/data/util/MethodPropertyMemoryConsumption.java
new file mode 100644
index 0000000000..caff33cf50
--- /dev/null
+++ b/server/tests/src/com/vaadin/data/util/MethodPropertyMemoryConsumption.java
@@ -0,0 +1,145 @@
+/*
+ * 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.data.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test for MethodProperty: don't allocate unnecessary Object arrays.
+ *
+ * @since 7.2
+ * @author Vaadin Ltd
+ */
+public class MethodPropertyMemoryConsumption {
+
+ @Test
+ public void testSetArguments() throws NoSuchFieldException,
+ SecurityException, IllegalArgumentException, IllegalAccessException {
+ TestBean bean = new TestBean();
+ TestMethodProperty<String> property = new TestMethodProperty<String>(
+ bean, "name");
+ Object[] getArgs = property.getGetArgs();
+ Object[] setArgs = property.getSetArgs();
+
+ Field getArgsField = TestMethodProperty.class
+ .getDeclaredField("getArgs");
+ getArgsField.setAccessible(true);
+
+ Field setArgsField = TestMethodProperty.class
+ .getDeclaredField("setArgs");
+ setArgsField.setAccessible(true);
+
+ Assert.assertSame("setArguments method sets non-default instance"
+ + " of empty Object array for getArgs",
+ getArgsField.get(property), getArgs);
+
+ Assert.assertSame("setArguments method sets non-default instance"
+ + " of empty Object array for setArgs",
+ setArgsField.get(property), setArgs);
+ }
+
+ @Test
+ public void testDefaultCtor() {
+ TestBean bean = new TestBean();
+ TestMethodProperty<String> property = new TestMethodProperty<String>(
+ bean, "name");
+
+ Object[] getArgs = property.getGetArgs();
+ Object[] setArgs = property.getSetArgs();
+
+ TestBean otherBean = new TestBean();
+ TestMethodProperty<String> otherProperty = new TestMethodProperty<String>(
+ otherBean, "name");
+ Assert.assertSame("setArguments method uses different instance"
+ + " of empty Object array for getArgs", getArgs,
+ otherProperty.getGetArgs());
+ Assert.assertSame("setArguments method uses different instance"
+ + " of empty Object array for setArgs", setArgs,
+ otherProperty.getSetArgs());
+ }
+
+ @Test
+ public void testDefaultArgsSerialization() throws IOException,
+ ClassNotFoundException {
+ TestBean bean = new TestBean();
+ TestMethodProperty<String> property = new TestMethodProperty<String>(
+ bean, "name");
+
+ ByteArrayOutputStream sourceOutStream = new ByteArrayOutputStream();
+ ObjectOutputStream outStream = new ObjectOutputStream(sourceOutStream);
+ outStream.writeObject(property);
+
+ ObjectInputStream inputStream = new ObjectInputStream(
+ new ByteArrayInputStream(sourceOutStream.toByteArray()));
+ Object red = inputStream.readObject();
+ TestMethodProperty<?> deserialized = (TestMethodProperty<?>) red;
+
+ Assert.assertNotNull("Deseriliation doesn't call setArguments method",
+ deserialized.getGetArgs());
+ Assert.assertNotNull("Deseriliation doesn't call setArguments method",
+ deserialized.getSetArgs());
+
+ }
+
+ public static class TestMethodProperty<T> extends MethodProperty<T> {
+
+ public TestMethodProperty(Object instance, String beanPropertyName) {
+ super(instance, beanPropertyName);
+ }
+
+ @Override
+ public void setArguments(Object[] getArgs, Object[] setArgs,
+ int setArgumentIndex) {
+ super.setArguments(getArgs, setArgs, setArgumentIndex);
+ this.getArgs = getArgs;
+ this.setArgs = setArgs;
+ }
+
+ Object[] getGetArgs() {
+ return getArgs;
+ }
+
+ Object[] getSetArgs() {
+ return setArgs;
+ }
+
+ private transient Object[] getArgs;
+ private transient Object[] setArgs;
+ }
+
+ public static class TestBean implements Serializable {
+
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ }
+}
diff --git a/server/tests/src/com/vaadin/server/VaadinGateInRequestTests.java b/server/tests/src/com/vaadin/server/VaadinGateInRequestTests.java
new file mode 100644
index 0000000000..017613661e
--- /dev/null
+++ b/server/tests/src/com/vaadin/server/VaadinGateInRequestTests.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import com.vaadin.server.VaadinPortlet.VaadinGateInRequest;
+
+public class VaadinGateInRequestTests extends
+ VaadinHttpAndPortletRequestTests<VaadinGateInRequest> {
+
+ @Override
+ protected VaadinGateInRequest createSut() {
+
+ VaadinGateInRequest request = new VaadinGateInRequest(portletRequest,
+ vaadinPortletService);
+
+ // Although partial mocking can be considered a code smell,
+ // here it's actually quite useful to mock reflection calls.
+ VaadinGateInRequest spy = spy(request);
+ doReturn(servletRequest).when(spy).getServletRequest(portletRequest);
+
+ return spy;
+ }
+}
diff --git a/server/tests/src/com/vaadin/server/VaadinHttpAndPortletRequestTests.java b/server/tests/src/com/vaadin/server/VaadinHttpAndPortletRequestTests.java
new file mode 100644
index 0000000000..01d501c4fb
--- /dev/null
+++ b/server/tests/src/com/vaadin/server/VaadinHttpAndPortletRequestTests.java
@@ -0,0 +1,140 @@
+/*
+ * 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;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Enumeration;
+import java.util.Map;
+
+import javax.portlet.PortletRequest;
+import javax.servlet.http.HttpServletRequest;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.vaadin.server.VaadinPortlet.VaadinHttpAndPortletRequest;
+import com.vaadin.server.VaadinPortletService;
+
+//Have to ignore this class - otherwise JUnit tries to instantiate it...
+@Ignore
+public abstract class VaadinHttpAndPortletRequestTests<T extends VaadinHttpAndPortletRequest> {
+
+ protected VaadinHttpAndPortletRequest sut;
+ protected HttpServletRequest servletRequest;
+ protected PortletRequest portletRequest;
+ protected VaadinPortletService vaadinPortletService;
+
+ protected abstract T createSut();
+
+ @Before
+ public void setup() {
+ portletRequest = mock(PortletRequest.class);
+ vaadinPortletService = mock(VaadinPortletService.class);
+ servletRequest = mock(HttpServletRequest.class);
+
+ sut = createSut();
+ }
+
+ @Test
+ public void parameterIsFetchedFromServletRequest() {
+ when(servletRequest.getParameter("foo")).thenReturn("bar");
+
+ String parameter = sut.getParameter("foo");
+
+ assertThat(parameter, is("bar"));
+ }
+
+ @Test
+ public void originalParameterIsOverridden() {
+ when(servletRequest.getParameter("foo")).thenReturn("braa");
+ when(portletRequest.getParameter("foo")).thenReturn("bar");
+
+ String parameter = sut.getParameter("foo");
+
+ assertThat(parameter, is("bar"));
+ }
+
+ @Test
+ public void remoteAddressIsFetchedFromServletRequest() {
+ when(servletRequest.getRemoteAddr()).thenReturn("foo");
+
+ String remoteAddr = sut.getRemoteAddr();
+
+ assertThat(remoteAddr, is("foo"));
+ }
+
+ @Test
+ public void remoteHostIsFetchedFromServletRequest() {
+ when(servletRequest.getRemoteHost()).thenReturn("foo");
+
+ String remoteHost = sut.getRemoteHost();
+
+ assertThat(remoteHost, is("foo"));
+ }
+
+ @Test
+ public void remotePortIsFetchedFromServletRequest() {
+ when(servletRequest.getRemotePort()).thenReturn(12345);
+
+ int remotePort = sut.getRemotePort();
+
+ assertThat(remotePort, is(12345));
+ }
+
+ @Test
+ public void headerIsFetchedFromServletRequest() {
+ when(servletRequest.getHeader("foo")).thenReturn("bar");
+
+ String header = sut.getHeader("foo");
+
+ assertThat(header, is("bar"));
+ }
+
+ @Test
+ public void headerNamesAreFetchedFromServletRequest() {
+ Enumeration expectedHeaderNames = mock(Enumeration.class);
+ when(servletRequest.getHeaderNames()).thenReturn(expectedHeaderNames);
+
+ Enumeration<String> actualHeaderNames = sut.getHeaderNames();
+
+ assertThat(actualHeaderNames, is(expectedHeaderNames));
+ }
+
+ @Test
+ public void headersAreFetchedFromServletRequest() {
+ Enumeration expectedHeaders = mock(Enumeration.class);
+ when(servletRequest.getHeaders("foo")).thenReturn(expectedHeaders);
+
+ Enumeration<String> actualHeaders = sut.getHeaders("foo");
+
+ assertThat(actualHeaders, is(expectedHeaders));
+ }
+
+ @Test
+ public void parameterMapIsFetchedFromServletRequest() {
+ Map expectedParameterMap = mock(Map.class);
+ when(servletRequest.getParameterMap()).thenReturn(expectedParameterMap);
+
+ Map<String, String[]> actualParameterMap = sut.getParameterMap();
+
+ assertThat(actualParameterMap, is(expectedParameterMap));
+ }
+}
diff --git a/server/tests/src/com/vaadin/server/VaadinLiferayRequestTests.java b/server/tests/src/com/vaadin/server/VaadinLiferayRequestTests.java
new file mode 100644
index 0000000000..074941a556
--- /dev/null
+++ b/server/tests/src/com/vaadin/server/VaadinLiferayRequestTests.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import com.vaadin.server.VaadinPortlet.VaadinLiferayRequest;
+
+public class VaadinLiferayRequestTests extends
+ VaadinHttpAndPortletRequestTests<VaadinLiferayRequest> {
+
+ @Override
+ protected VaadinLiferayRequest createSut() {
+
+ VaadinLiferayRequest request = new VaadinLiferayRequest(portletRequest,
+ vaadinPortletService);
+
+ // Although partial mocking can be considered a code smell,
+ // here it's actually quite useful to mock reflection calls.
+ VaadinLiferayRequest spy = spy(request);
+ doReturn(servletRequest).when(spy).getServletRequest(portletRequest);
+
+ return spy;
+ }
+} \ No newline at end of file
diff --git a/server/tests/src/com/vaadin/server/VaadinPortletTests.java b/server/tests/src/com/vaadin/server/VaadinPortletTests.java
new file mode 100644
index 0000000000..93f8fd0778
--- /dev/null
+++ b/server/tests/src/com/vaadin/server/VaadinPortletTests.java
@@ -0,0 +1,94 @@
+/*
+ * 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;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import javax.portlet.PortalContext;
+import javax.portlet.PortletRequest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.server.VaadinPortlet.VaadinGateInRequest;
+import com.vaadin.server.VaadinPortlet.VaadinLiferayRequest;
+import com.vaadin.server.VaadinPortlet.VaadinWebSpherePortalRequest;
+
+public class VaadinPortletTests {
+
+ private VaadinPortlet sut;
+ private PortletRequest portletRequest;
+ private PortalContext portalContext;
+
+ @Before
+ public void setup() {
+ sut = new VaadinPortlet();
+
+ portletRequest = mock(PortletRequest.class);
+ portalContext = mock(PortalContext.class);
+
+ when(portletRequest.getPortalContext()).thenReturn(portalContext);
+ }
+
+ private void mockPortalInfo(String name) {
+ when(portalContext.getPortalInfo()).thenReturn(name);
+ }
+
+ private VaadinPortletRequest createRequest() {
+ VaadinPortletRequest request = sut.createVaadinRequest(portletRequest);
+ return request;
+ }
+
+ @Test
+ public void gateInRequestIsCreated() {
+ mockPortalInfo("gatein");
+
+ VaadinPortletRequest request = createRequest();
+
+ assertThat(request, instanceOf(VaadinGateInRequest.class));
+ }
+
+ @Test
+ public void liferayRequestIsCreated() {
+ mockPortalInfo("liferay");
+
+ VaadinPortletRequest request = createRequest();
+
+ assertThat(request, instanceOf(VaadinLiferayRequest.class));
+ }
+
+ @Test
+ public void webspherePortalRequestIsCreated() {
+ mockPortalInfo("websphere portal");
+
+ VaadinPortletRequest request = createRequest();
+
+ assertThat(request, instanceOf(VaadinWebSpherePortalRequest.class));
+ }
+
+ @Test
+ public void defaultPortletRequestIsCreated() {
+ mockPortalInfo("foobar");
+
+ VaadinPortletRequest request = createRequest();
+
+ assertThat(request, instanceOf(VaadinPortletRequest.class));
+ }
+
+}
diff --git a/server/tests/src/com/vaadin/server/VaadinServiceTest.java b/server/tests/src/com/vaadin/server/VaadinServiceTest.java
index cead5df79c..77eb155378 100644
--- a/server/tests/src/com/vaadin/server/VaadinServiceTest.java
+++ b/server/tests/src/com/vaadin/server/VaadinServiceTest.java
@@ -29,6 +29,16 @@ import org.junit.Test;
*/
public class VaadinServiceTest {
+ private class TestSessionDestroyListener implements SessionDestroyListener {
+
+ int callCount = 0;
+
+ @Override
+ public void sessionDestroy(SessionDestroyEvent event) {
+ callCount++;
+ }
+ }
+
@Test
public void testFireSessionDestroy() throws ServletException {
ServletConfig servletConfig = new MockServletConfig();
@@ -36,6 +46,10 @@ public class VaadinServiceTest {
servlet.init(servletConfig);
VaadinService service = servlet.getService();
+ TestSessionDestroyListener listener = new TestSessionDestroyListener();
+
+ service.addSessionDestroyListener(listener);
+
MockVaadinSession vaadinSession = new MockVaadinSession(service);
service.fireSessionDestroy(vaadinSession);
Assert.assertEquals(
@@ -45,9 +59,11 @@ public class VaadinServiceTest {
vaadinSession.valueUnbound(EasyMock
.createMock(HttpSessionBindingEvent.class));
- org.junit.Assert.assertEquals(
- "'fireSessionDestroy' method may not call 'close' "
- + "method for closing session", 1,
+ Assert.assertEquals("'fireSessionDestroy' method may not call 'close' "
+ + "method for closing session", 1,
vaadinSession.getCloseCount());
+
+ Assert.assertEquals("SessionDestroyListeners not called exactly once",
+ 1, listener.callCount);
}
}
diff --git a/server/tests/src/com/vaadin/server/VaadinWebSpherePortalRequestTests.java b/server/tests/src/com/vaadin/server/VaadinWebSpherePortalRequestTests.java
new file mode 100644
index 0000000000..0da85c7111
--- /dev/null
+++ b/server/tests/src/com/vaadin/server/VaadinWebSpherePortalRequestTests.java
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import com.vaadin.server.VaadinPortlet.VaadinWebSpherePortalRequest;
+
+public class VaadinWebSpherePortalRequestTests extends
+ VaadinHttpAndPortletRequestTests<VaadinWebSpherePortalRequest> {
+
+ @Override
+ protected VaadinWebSpherePortalRequest createSut() {
+
+ VaadinWebSpherePortalRequest request = new VaadinWebSpherePortalRequest(
+ portletRequest, vaadinPortletService);
+
+ // Although partial mocking can be considered a code smell,
+ // here it's actually quite useful to mock reflection calls.
+ VaadinWebSpherePortalRequest spy = spy(request);
+ doReturn(servletRequest).when(spy).getServletRequest(portletRequest);
+
+ return spy;
+ }
+} \ No newline at end of file
diff --git a/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/LayoutSettingsOnReplace.java b/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/LayoutSettingsOnReplace.java
new file mode 100644
index 0000000000..0af21d8cb8
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/abstractorderedlayout/LayoutSettingsOnReplace.java
@@ -0,0 +1,85 @@
+/*
+ * 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.server.component.abstractorderedlayout;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.ui.AbstractComponent;
+import com.vaadin.ui.AbstractOrderedLayout;
+import com.vaadin.ui.Alignment;
+
+/**
+ * Tests for abstract layout settings which should be preserved on replace
+ * component
+ *
+ * @since 7.2
+ * @author Vaadin Ltd
+ */
+public class LayoutSettingsOnReplace {
+
+ @Test
+ public void testExpandRatio() {
+ AbstractOrderedLayout layout = new AbstractOrderedLayout() {
+ };
+
+ AbstractComponent first = new AbstractComponent() {
+ };
+ AbstractComponent second = new AbstractComponent() {
+ };
+
+ layout.addComponent(first);
+ layout.addComponent(second);
+
+ int ratio = 2;
+ layout.setExpandRatio(first, ratio);
+ layout.setExpandRatio(second, 1);
+
+ AbstractComponent replace = new AbstractComponent() {
+ };
+ layout.replaceComponent(first, replace);
+
+ Assert.assertEquals("Expand ratio for replaced component is not "
+ + "the same as for previous one", ratio,
+ layout.getExpandRatio(replace), 0.0001);
+ }
+
+ @Test
+ public void testAlignment() {
+ AbstractOrderedLayout layout = new AbstractOrderedLayout() {
+ };
+
+ AbstractComponent first = new AbstractComponent() {
+ };
+ AbstractComponent second = new AbstractComponent() {
+ };
+
+ layout.addComponent(first);
+ layout.addComponent(second);
+
+ Alignment alignment = Alignment.BOTTOM_RIGHT;
+ layout.setComponentAlignment(first, alignment);
+ layout.setComponentAlignment(second, Alignment.MIDDLE_CENTER);
+
+ AbstractComponent replace = new AbstractComponent() {
+ };
+ layout.replaceComponent(first, replace);
+
+ Assert.assertEquals("Alignment for replaced component is not "
+ + "the same as for previous one", alignment,
+ layout.getComponentAlignment(replace));
+ }
+}
diff --git a/server/tests/src/com/vaadin/tests/server/component/window/WindowTest.java b/server/tests/src/com/vaadin/tests/server/component/window/WindowTest.java
new file mode 100644
index 0000000000..2cd19ee153
--- /dev/null
+++ b/server/tests/src/com/vaadin/tests/server/component/window/WindowTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.server.component.window;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Window;
+
+public class WindowTest {
+
+ public Window window;
+
+ @Before
+ public void setup() {
+ window = new Window();
+ }
+
+ @Test
+ public void testAssistiveDescription() {
+ Label l1 = new Label("label 1");
+ Button b2 = new Button("button 2");
+ window.setAssistiveDescription(l1, b2);
+
+ Assert.assertEquals(2, window.getAssistiveDescription().length);
+ Assert.assertEquals(l1, window.getAssistiveDescription()[0]);
+ Assert.assertEquals(b2, window.getAssistiveDescription()[1]);
+
+ // Modifying return value must not change actual value
+ window.getAssistiveDescription()[0] = null;
+
+ Assert.assertEquals(2, window.getAssistiveDescription().length);
+ Assert.assertEquals(l1, window.getAssistiveDescription()[0]);
+ Assert.assertEquals(b2, window.getAssistiveDescription()[1]);
+
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/accordion/AccordionAddTab.java b/uitest/src/com/vaadin/tests/components/accordion/AccordionAddTab.java
new file mode 100644
index 0000000000..da0ad3685a
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/accordion/AccordionAddTab.java
@@ -0,0 +1,72 @@
+/*
+ * 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.components.accordion;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Accordion;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Panel;
+import com.vaadin.ui.TabSheet.Tab;
+import com.vaadin.ui.VerticalLayout;
+
+/**
+ * Test UI for Accordion: old widget should be removed from the tab.
+ *
+ * @since 7.2
+ * @author Vaadin Ltd
+ */
+public class AccordionAddTab extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final Accordion tabs = new Accordion();
+ addComponent(tabs);
+ tabs.setHeight(500, Unit.PIXELS);
+ Button remove = new Button("Remove 'First'");
+ final Tab me = tabs.addTab(addTab("First"));
+ remove.addClickListener(new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ tabs.removeTab(me);
+ Tab tab = tabs.addTab(addTab("Next"));
+ tabs.setSelectedTab(tab);
+ }
+ });
+ addComponent(remove);
+ }
+
+ private Component addTab(String tag) {
+ VerticalLayout layout = new VerticalLayout();
+ layout.addComponent(new Label("On tab: " + tag));
+ return new Panel(tag, layout);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Remove previous widget in the accordion tab when content is replaced";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 11367;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/accordion/AccordionAddTabTest.java b/uitest/src/com/vaadin/tests/components/accordion/AccordionAddTabTest.java
new file mode 100644
index 0000000000..68aa61cc87
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/accordion/AccordionAddTabTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.components.accordion;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+/**
+ * Test for Accordion : replace widget in tab should remove old widget.
+ *
+ * @since 7.2
+ * @author Vaadin Ltd
+ */
+public class AccordionAddTabTest extends MultiBrowserTest {
+
+ @Test
+ public void testRemoveAndAdd() {
+ openTestURL();
+
+ WebElement button = driver.findElement(By.className("v-button"));
+ button.click();
+
+ List<WebElement> panels = driver.findElements(By.className("v-panel"));
+
+ Assert.assertEquals("Found two widgets inside one tab after "
+ + "subsequent tab removal and addition", 1, panels.size());
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurationLongPollingTest.java b/uitest/src/com/vaadin/tests/push/PushConfigurationLongPollingTest.java
new file mode 100644
index 0000000000..c0503d5240
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/push/PushConfigurationLongPollingTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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 static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.remote.DesiredCapabilities;
+import org.openqa.selenium.support.ui.Select;
+
+public class PushConfigurationLongPollingTest extends PushConfigurationTest {
+
+ @Override
+ public List<DesiredCapabilities> getBrowsersToTest() {
+ List<DesiredCapabilities> browsers = super.getBrowsersToTest();
+
+ browsers.remove(Browser.IE8.getDesiredCapabilities());
+
+ return browsers;
+ }
+
+ @Test
+ public void testLongPolling() throws InterruptedException {
+ new Select(getTransportSelect()).selectByVisibleText("LONG_POLLING");
+ new Select(getPushModeSelect()).selectByVisibleText("AUTOMATIC");
+
+ assertThat(getStatusText(),
+ containsString("fallbackTransport: long-polling"));
+ assertThat(getStatusText(), containsString("transport: long-polling"));
+
+ waitForServerCounterToUpdate();
+
+ // Use debug console to verify we used the correct transport type
+ assertThat(
+ driver.getPageSource(),
+ containsString("Push connection established using long-polling"));
+
+ new Select(getPushModeSelect()).selectByVisibleText("DISABLED");
+
+ }
+
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurationStreamingTest.java b/uitest/src/com/vaadin/tests/push/PushConfigurationStreamingTest.java
new file mode 100644
index 0000000000..46fcc5f44b
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/push/PushConfigurationStreamingTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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 static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.remote.DesiredCapabilities;
+import org.openqa.selenium.support.ui.Select;
+
+public class PushConfigurationStreamingTest extends PushConfigurationTest {
+
+ @Override
+ public List<DesiredCapabilities> getBrowsersToTest() {
+ List<DesiredCapabilities> browsers = super.getBrowsersToTest();
+
+ browsers.remove(Browser.IE8.getDesiredCapabilities());
+
+ return browsers;
+ }
+
+ @Test
+ public void testStreaming() throws InterruptedException {
+ new Select(getTransportSelect()).selectByVisibleText("STREAMING");
+ new Select(getPushModeSelect()).selectByVisibleText("AUTOMATIC");
+
+ assertThat(getStatusText(),
+ containsString("fallbackTransport: long-polling"));
+ assertThat(getStatusText(), containsString("transport: streaming"));
+
+ waitForServerCounterToUpdate();
+
+ // Use debug console to verify we used the correct transport type
+ assertThat(
+ driver.getPageSource(),
+ not(containsString("Push connection established using websocket")));
+ assertThat(driver.getPageSource(),
+ containsString("Push connection established using streaming"));
+ }
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java b/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java
index d7ffb47bbc..20399fc67e 100644
--- a/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java
+++ b/uitest/src/com/vaadin/tests/push/PushConfigurationTest.java
@@ -17,139 +17,71 @@ package com.vaadin.tests.push;
import static org.junit.Assert.assertEquals;
-import org.junit.Assert;
-import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.Select;
-import com.vaadin.tests.tb3.WebsocketTest;
+import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
-public class PushConfigurationTest extends WebsocketTest {
+@TestCategory("push")
+abstract class PushConfigurationTest extends MultiBrowserTest {
- @Test
- public void testWebsocketAndStreaming() throws InterruptedException {
- setDebug(true);
- openTestURL();
- // Websocket
- verifyPushDisabled();
- new Select(getTransportSelect()).selectByVisibleText("WEBSOCKET");
- new Select(getPushModeSelect()).selectByVisibleText("AUTOMATIC");
- Assert.assertTrue(vaadinElement(
- "/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[5]/VLabel[0]/domChild[0]")
- .getText()
- .matches(
- "^[\\s\\S]*fallbackTransport: streaming[\\s\\S]*transport: websocket[\\s\\S]*$"));
- int counter = getServerCounter();
- final int waitCounter = counter + 2;
- waitUntil(new ExpectedCondition<Boolean>() {
-
- @Override
- public Boolean apply(WebDriver input) {
- return (getServerCounter() >= waitCounter);
- }
- });
-
- // Use debug console to verify we used the correct transport type
- Assert.assertTrue(driver.getPageSource().contains(
- "Push connection established using websocket"));
- Assert.assertFalse(driver.getPageSource().contains(
- "Push connection established using streaming"));
-
- new Select(getPushModeSelect()).selectByVisibleText("DISABLED");
-
- // Streaming
- driver.get(getTestUrl());
- verifyPushDisabled();
-
- new Select(getTransportSelect()).selectByVisibleText("STREAMING");
- new Select(getPushModeSelect()).selectByVisibleText("AUTOMATIC");
- Assert.assertTrue(vaadinElement(
- "/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[5]/VLabel[0]/domChild[0]")
- .getText()
- .matches(
- "^[\\s\\S]*fallbackTransport: streaming[\\s\\S]*transport: streaming[\\s\\S]*$"));
-
- counter = getServerCounter();
- for (int second = 0;; second++) {
- if (second >= 5) {
- Assert.fail("timeout");
- }
- if (getServerCounter() >= (counter + 2)) {
- break;
- }
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- }
- }
-
- // Use debug console to verify we used the correct transport type
- Assert.assertFalse(driver.getPageSource().contains(
- "Push connection established using websocket"));
- Assert.assertTrue(driver.getPageSource().contains(
- "Push connection established using streaming"));
+ @Override
+ public void setup() throws Exception {
+ super.setup();
+ openTestURL();
+ disablePush();
}
- @Test
- public void testLongPolling() throws InterruptedException {
- setDebug(true);
- openTestURL();
- verifyPushDisabled();
- new Select(getTransportSelect()).selectByVisibleText("LONG_POLLING");
- new Select(getPushModeSelect()).selectByVisibleText("AUTOMATIC");
- Assert.assertTrue(vaadinElement(
- "/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[5]/VLabel[0]/domChild[0]")
- .getText()
- .matches(
- "^[\\s\\S]*fallbackTransport: streaming[\\s\\S]*transport: long-polling[\\s\\S]*$"));
- int counter = getServerCounter();
- final int waitCounter = counter + 2;
- waitUntil(new ExpectedCondition<Boolean>() {
+ @Override
+ protected String getDeploymentPath() {
+ return "/run/" + PushConfiguration.class.getCanonicalName()
+ + "?restartApplication&debug";
+ }
- @Override
- public Boolean apply(WebDriver input) {
- return (getServerCounter() >= waitCounter);
- }
- });
+ protected String getStatusText() {
+ WebElement statusLabel = vaadinElementById("status");
- // Use debug console to verify we used the correct transport type
- Assert.assertTrue(driver.getPageSource().contains(
- "Push connection established using long-polling"));
- Assert.assertFalse(driver.getPageSource().contains(
- "Push connection established using streaming"));
+ return statusLabel.getText();
+ }
+ protected void disablePush() throws InterruptedException {
new Select(getPushModeSelect()).selectByVisibleText("DISABLED");
- }
-
- /**
- * Verifies that push is currently not enabled.
- *
- * @throws InterruptedException
- */
- private void verifyPushDisabled() throws InterruptedException {
int counter = getServerCounter();
sleep(2000);
assertEquals("Server count changed without push enabled", counter,
getServerCounter());
}
- private WebElement getPushModeSelect() {
+ protected WebElement getPushModeSelect() {
return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VNativeSelect[0]/domChild[0]");
}
- private WebElement getTransportSelect() {
+ protected WebElement getTransportSelect() {
return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[0]/VVerticalLayout[0]/Slot[1]/VNativeSelect[0]/domChild[0]");
}
- private int getServerCounter() {
+ protected int getServerCounter() {
return Integer.parseInt(getServerCounterElement().getText());
}
- private WebElement getServerCounterElement() {
+ protected WebElement getServerCounterElement() {
return vaadinElement("/VVerticalLayout[0]/Slot[1]/VVerticalLayout[0]/Slot[5]/VLabel[0]");
}
+
+ protected void waitForServerCounterToUpdate() {
+ int counter = getServerCounter();
+ final int waitCounter = counter + 2;
+ waitUntil(new ExpectedCondition<Boolean>() {
+
+ @Override
+ public Boolean apply(WebDriver input) {
+ return (getServerCounter() >= waitCounter);
+ }
+ });
+ }
} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurationWebSocketTest.java b/uitest/src/com/vaadin/tests/push/PushConfigurationWebSocketTest.java
new file mode 100644
index 0000000000..c8308e72f1
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/push/PushConfigurationWebSocketTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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 static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.remote.DesiredCapabilities;
+import org.openqa.selenium.support.ui.Select;
+
+public class PushConfigurationWebSocketTest extends PushConfigurationTest {
+
+ @Override
+ public List<DesiredCapabilities> getBrowsersToTest() {
+
+ List<DesiredCapabilities> browsers = super.getBrowsersToTest();
+ browsers.remove(Browser.IE8.getDesiredCapabilities());
+ browsers.remove(Browser.IE9.getDesiredCapabilities());
+
+ return browsers;
+ }
+
+ @Test
+ public void testWebsocket() throws InterruptedException {
+ new Select(getTransportSelect()).selectByVisibleText("WEBSOCKET");
+ new Select(getPushModeSelect()).selectByVisibleText("AUTOMATIC");
+
+ assertThat(getStatusText(),
+ containsString("fallbackTransport: long-polling"));
+ assertThat(getStatusText(), containsString("transport: websocket"));
+
+ waitForServerCounterToUpdate();
+
+ // Use debug console to verify we used the correct transport type
+ assertThat(driver.getPageSource(),
+ containsString("Push connection established using websocket"));
+ assertThat(
+ driver.getPageSource(),
+ not(containsString("Push connection established using streaming")));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/push/PushConfigurator.java b/uitest/src/com/vaadin/tests/push/PushConfigurator.java
index 6528366b59..6dbe130b73 100644
--- a/uitest/src/com/vaadin/tests/push/PushConfigurator.java
+++ b/uitest/src/com/vaadin/tests/push/PushConfigurator.java
@@ -101,6 +101,7 @@ public class PushConfigurator extends VerticalLayout {
paramValue.setDefaultComponentAlignment(Alignment.BOTTOM_RIGHT);
paramValue.addComponents(parameter, value, set);
+ status.setId("status");
vl.addComponents(pushMode, transport, fallbackTransport, paramValue,
new Label("<hr/>", ContentMode.HTML), status);
addComponent(vl);