summaryrefslogtreecommitdiffstats
path: root/server/src/com
diff options
context:
space:
mode:
authorJonatan Kronqvist <jonatan@vaadin.com>2014-04-14 11:53:11 +0300
committerJonatan Kronqvist <jonatan@vaadin.com>2014-04-14 12:06:05 +0300
commit416e2f97bcaf93e4d2a782149a963fca95b8400e (patch)
treeeac6d22107b7c2d7bf6371e5278078f02bb860e9 /server/src/com
parentd2e24feb09ccba7f3a2f253687488774af2bc340 (diff)
parenteda9edcbde781d29ff5939defb61ba5fb159e206 (diff)
downloadvaadin-framework-416e2f97bcaf93e4d2a782149a963fca95b8400e.tar.gz
vaadin-framework-416e2f97bcaf93e4d2a782149a963fca95b8400e.zip
Merge branch 'master' into 7.2
72d0aa0 Update Window Javadoc based on 7.2 API review changes ee203f5 Apply abstract ordered layout settings for replaced component (#13568) 02998d8 Updated Window API based on 7.2 API review cd94b21 Discourage use of setNeedsLayout while a layout is running (#13542) f374bc7 Make ComboBox always immediate (#4054) aec102a Update 3rd party license information (#13449) 013d32d Remove old widget from tab content on replace (#12931). 3d0ff32 Prevent duplicate detach() calls with push (#13261) a452bad Refactor VaadinPortletRequest extending. (#13551) 55dfd29 Prevent duplicate session destroy events (#12612) 2067d4e Don't allocate unnecessary memory for empty array of Objects in MethodProperty (#10446). 00a9af5 Refactor PushConfigurationTest. Merge: no Change-Id: I6563769a77f91a68cfeadcb3306dd71fe431863c
Diffstat (limited to 'server/src/com')
-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
10 files changed, 343 insertions, 149 deletions
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;
}
/**