Browse Source

Refactor how LegacyApplication and VaadinSession are "closed" (#9635)

tags/7.0.0.beta2
Leif Åstrand 11 years ago
parent
commit
6b28dc7bf4

+ 64
- 86
server/src/com/vaadin/LegacyApplication.java View File

@@ -22,16 +22,13 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.vaadin.server.AbstractUIProvider;
import com.vaadin.server.DefaultErrorListener;
import com.vaadin.server.Terminal.ErrorEvent;
import com.vaadin.server.Terminal.ErrorListener;
import com.vaadin.server.VaadinSession;
import com.vaadin.server.WrappedRequest;
import com.vaadin.ui.UI;
import com.vaadin.ui.UI.LegacyWindow;

/**
* A special application designed to help migrating applications from Vaadin 6
@@ -45,19 +42,20 @@ import com.vaadin.ui.UI;
* @since 7.0
*/
@Deprecated
public abstract class LegacyApplication extends AbstractUIProvider implements
ErrorListener {
/**
* Ignore initial / and then get everything up to the next /
*/
private static final Pattern WINDOW_NAME_PATTERN = Pattern
.compile("^/?([^/]+).*");

public abstract class LegacyApplication implements ErrorListener {
private UI.LegacyWindow mainWindow;
private String theme;

private Map<String, UI.LegacyWindow> legacyUINames = new HashMap<String, UI.LegacyWindow>();

private boolean isRunning = true;

/**
* URL where the user is redirected to on application close, or null if
* application is just closed without redirection.
*/
private String logoutURL = null;

/**
* Sets the main window of this application. Setting window as a main window
* of this application also adds the window to this application.
@@ -69,9 +67,7 @@ public abstract class LegacyApplication extends AbstractUIProvider implements
if (this.mainWindow != null) {
throw new IllegalStateException("mainWindow has already been set");
}
if (mainWindow.getSession() == null) {
mainWindow.setSession(VaadinSession.getCurrent());
} else if (mainWindow.getSession() != VaadinSession.getCurrent()) {
if (mainWindow.getSession() != null) {
throw new IllegalStateException(
"mainWindow is attached to another application");
}
@@ -80,7 +76,7 @@ public abstract class LegacyApplication extends AbstractUIProvider implements
// no current UI -> set the main window as the current UI
UI.setCurrent(mainWindow);
}
mainWindow.setApplication(this);
addWindow(mainWindow);
this.mainWindow = mainWindow;
}

@@ -91,36 +87,6 @@ public abstract class LegacyApplication extends AbstractUIProvider implements

protected abstract void init();

@Override
public Class<? extends UI> getUIClass(WrappedRequest request) {
UI uiInstance = getUIInstance(request);
if (uiInstance != null) {
return uiInstance.getClass();
}
return null;
}

@Override
public UI createInstance(WrappedRequest request, Class<? extends UI> type) {
return getUIInstance(request);
}

@Override
public String getTheme(WrappedRequest request, Class<? extends UI> uiClass) {
return theme;
}

@Override
public String getPageTitle(WrappedRequest request,
Class<? extends UI> uiClass) {
UI uiInstance = getUIInstance(request);
if (uiInstance != null) {
return uiInstance.getCaption();
} else {
return super.getPageTitle(request, uiClass);
}
}

/**
* Gets the mainWindow of the application.
*
@@ -138,43 +104,6 @@ public abstract class LegacyApplication extends AbstractUIProvider implements
return mainWindow;
}

private UI getUIInstance(WrappedRequest request) {
String pathInfo = request.getRequestPathInfo();
String name = null;
if (pathInfo != null && pathInfo.length() > 0) {
Matcher matcher = WINDOW_NAME_PATTERN.matcher(pathInfo);
if (matcher.matches()) {
// Skip the initial slash
name = matcher.group(1);
}
}
UI.LegacyWindow window = getWindow(name);
if (window != null) {
return window;
}
return mainWindow;
}

/**
* This implementation simulates the way of finding a window for a request
* by extracting a window name from the requested path and passes that name
* to {@link #getWindow(String)}.
* <p>
* {@inheritDoc}
*/
@Override
public UI getExistingUI(WrappedRequest request) {
UI uiInstance = getUIInstance(request);
if (uiInstance.getUIId() == -1) {
// Not initialized -> Let go through createUIInstance to make it
// initialized
return null;
} else {
UI.setCurrent(uiInstance);
return uiInstance;
}
}

/**
* Sets the application's theme.
* <p>
@@ -289,15 +218,64 @@ public abstract class LegacyApplication extends AbstractUIProvider implements
return VaadinSession.getCurrent();
}

protected void close() {
VaadinSession.getCurrent().close();
public void close() {
isRunning = false;
Collection<LegacyWindow> windows = getWindows();
for (LegacyWindow legacyWindow : windows) {
String logoutUrl = getLogoutURL();
if (logoutUrl == null) {
URL url = getURL();
if (url != null) {
logoutUrl = url.toString();
}
}
if (logoutUrl != null) {
legacyWindow.getPage().setLocation(logoutUrl);
}
legacyWindow.getSession().cleanupUI(legacyWindow);
}
}

public boolean isRunning() {
return VaadinSession.getCurrent().isRunning();
return isRunning;
}

public URL getURL() {
return VaadinSession.getCurrent().getURL();
}

/**
* Returns the URL user is redirected to on application close. If the URL is
* <code>null</code>, the application is closed normally as defined by the
* application running environment.
* <p>
* Desktop application just closes the application window and
* web-application redirects the browser to application main URL.
* </p>
*
* @return the URL.
*
* @deprecated might be refactored or removed before 7.0.0
*/
@Deprecated
public String getLogoutURL() {
return logoutURL;
}

/**
* Sets the URL user is redirected to on application close. If the URL is
* <code>null</code>, the application is closed normally as defined by the
* application running environment: Desktop application just closes the
* application window and web-application redirects the browser to
* application main URL.
*
* @param logoutURL
* the logoutURL to set.
*
* @deprecated might be refactored or removed before 7.0.0
*/
@Deprecated
public void setLogoutURL(String logoutURL) {
this.logoutURL = logoutURL;
}
}

+ 16
- 58
server/src/com/vaadin/server/AbstractCommunicationManager.java View File

@@ -83,6 +83,7 @@ import com.vaadin.ui.Component;
import com.vaadin.ui.ConnectorTracker;
import com.vaadin.ui.HasComponents;
import com.vaadin.ui.UI;
import com.vaadin.ui.UI.LegacyWindow;
import com.vaadin.ui.Window;
import com.vaadin.util.CurrentInstance;

@@ -576,18 +577,11 @@ public abstract class AbstractCommunicationManager implements Serializable {
session.getLock().lock();
try {

// Finds the UI within the session
if (session.isRunning()) {
// Returns if no window found
if (uI == null) {
// This should not happen, no windows exists but
// session is still open.
getLogger().warning("Could not get UI for session");
return;
}
} else {
// session has been closed
endApplication(request, response, session);
// Verify that there's an UI
if (uI == null) {
// This should not happen, no windows exists but
// session is still open.
getLogger().warning("Could not get UI for session");
return;
}

@@ -653,6 +647,16 @@ public abstract class AbstractCommunicationManager implements Serializable {
*
*/
protected void postPaint(UI uI) {
if (uI instanceof LegacyWindow) {
LegacyWindow legacyWindow = (LegacyWindow) uI;
if (!legacyWindow.getApplication().isRunning()) {
// Detach LegacyWindow if it belongs to a closed
// LegacyApplication
legacyWindow.setApplication(null);
legacyWindow.setSession(null);
}
}

// Remove connectors that have been detached from the session during
// handling of the request
uI.getConnectorTracker().cleanConnectorMap();
@@ -752,13 +756,6 @@ public abstract class AbstractCommunicationManager implements Serializable {
WrappedResponse response, Callback callback, boolean repaintAll,
final PrintWriter outWriter, UI uI, boolean analyzeLayouts)
throws PaintException, IOException, JSONException {

// Removes session if it has stopped during variable changes
if (!session.isRunning()) {
endApplication(request, response, session);
return;
}

openJsonMessage(outWriter, response);

// security key
@@ -2177,45 +2174,6 @@ public abstract class AbstractCommunicationManager implements Serializable {
outWriter.print("]"); // Close locales
}

/**
* Ends the Application.
*
* The browser is redirected to the Application logout URL set with
* {@link VaadinSession#setLogoutURL(String)}, or to the application URL if
* no logout URL is given.
*
* @param request
* the request instance.
* @param response
* the response to write to.
* @param application
* the Application to end.
* @throws IOException
* if the writing failed due to input/output error.
*/
private void endApplication(WrappedRequest request,
WrappedResponse response, VaadinSession application)
throws IOException {

String logoutUrl = application.getLogoutURL();
if (logoutUrl == null) {
logoutUrl = application.getURL().toString();
}
// clients JS app is still running, send a special json file to tell
// client that application has quit and where to point browser now
// Set the response type
final OutputStream out = response.getOutputStream();
final PrintWriter outWriter = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(out, "UTF-8")));
openJsonMessage(outWriter, response);
outWriter.print("\"redirect\":{");
outWriter.write("\"url\":\"" + logoutUrl + "\"}");
closeJsonMessage(outWriter);
outWriter.flush();
outWriter.close();
out.flush();
}

protected void closeJsonMessage(PrintWriter outWriter) {
outWriter.print("}]");
}

+ 134
- 0
server/src/com/vaadin/server/LegacyApplicationUIProvider.java View File

@@ -0,0 +1,134 @@
/*
* Copyright 2011 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 java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.vaadin.LegacyApplication;
import com.vaadin.ui.UI;

public abstract class LegacyApplicationUIProvider extends AbstractUIProvider {
/**
* Ignore initial / and then get everything up to the next /
*/
private static final Pattern WINDOW_NAME_PATTERN = Pattern
.compile("^/?([^/]+).*");

@Override
public Class<? extends UI> getUIClass(WrappedRequest request) {
UI uiInstance = getUIInstance(request);
if (uiInstance != null) {
return uiInstance.getClass();
}
return null;
}

@Override
public UI createInstance(WrappedRequest request, Class<? extends UI> type) {
return getUIInstance(request);
}

@Override
public String getTheme(WrappedRequest request, Class<? extends UI> uiClass) {
LegacyApplication application = getApplication();
if (application != null) {
return application.getTheme();
} else {
return null;
}
}

@Override
public String getPageTitle(WrappedRequest request,
Class<? extends UI> uiClass) {
UI uiInstance = getUIInstance(request);
if (uiInstance != null) {
return uiInstance.getCaption();
} else {
return super.getPageTitle(request, uiClass);
}
}

private UI getUIInstance(WrappedRequest request) {
String pathInfo = request.getRequestPathInfo();
String name = null;
if (pathInfo != null && pathInfo.length() > 0) {
Matcher matcher = WINDOW_NAME_PATTERN.matcher(pathInfo);
if (matcher.matches()) {
// Skip the initial slash
name = matcher.group(1);
}
}

LegacyApplication application = getApplication();
if (application == null) {
return null;
}
UI.LegacyWindow window = application.getWindow(name);
if (window != null) {
return window;
}
return application.getMainWindow();
}

/**
* This implementation simulates the way of finding a window for a request
* by extracting a window name from the requested path and passes that name
* to {@link #getWindow(String)}.
* <p>
* {@inheritDoc}
*/
@Override
public UI getExistingUI(WrappedRequest request) {
UI uiInstance = getUIInstance(request);
if (uiInstance == null || uiInstance.getUIId() == -1) {
// Not initialized -> Let go through createUIInstance to make it
// initialized
return null;
} else {
UI.setCurrent(uiInstance);
return uiInstance;
}
}

private LegacyApplication getApplication() {
LegacyApplication application = VaadinSession.getCurrent()
.getAttribute(LegacyApplication.class);
if (application == null) {
application = createApplication();
if (application == null) {
return null;
}
VaadinSession.getCurrent().setAttribute(LegacyApplication.class,
application);
application.doInit();
}

if (application != null && !application.isRunning()) {
VaadinSession.getCurrent().setAttribute(LegacyApplication.class,
null);
// Run again without a current application
return getApplication();
}

return application;
}

protected abstract LegacyApplication createApplication();

}

+ 22
- 13
server/src/com/vaadin/server/LegacyVaadinPortlet.java View File

@@ -24,6 +24,26 @@ import com.vaadin.server.ServletPortletHelper.ApplicationClassException;

public class LegacyVaadinPortlet extends VaadinPortlet {

private static final LegacyApplicationUIProvider provider = new LegacyApplicationUIProvider() {
@Override
protected LegacyApplication createApplication() {
VaadinPortlet portlet = VaadinPortlet.getCurrent();
if (portlet instanceof LegacyVaadinPortlet) {
LegacyVaadinPortlet legacyPortlet = (LegacyVaadinPortlet) portlet;
PortletRequest request = PortletService
.getCurrentPortletRequest();
if (legacyPortlet.shouldCreateApplication(request)) {
try {
return legacyPortlet.getNewApplication(request);
} catch (PortletException e) {
throw new RuntimeException(e);
}
}
}
return null;
}
};

@Override
public void init() throws PortletException {
super.init();
@@ -68,21 +88,10 @@ public class LegacyVaadinPortlet extends VaadinPortlet {

private void onVaadinSessionStarted(WrappedPortletRequest request,
VaadinPortletSession session) throws PortletException {
if (shouldCreateApplication(request)) {
// Must set current before running init()
VaadinSession.setCurrent(session);

// XXX Must update details here so they are available in init.
session.getBrowser().updateRequestDetails(request);

LegacyApplication legacyApplication = getNewApplication(request
.getPortletRequest());
legacyApplication.doInit();
session.addUIProvider(legacyApplication);
}
session.addUIProvider(provider);
}

protected boolean shouldCreateApplication(WrappedPortletRequest request) {
protected boolean shouldCreateApplication(PortletRequest request) {
return true;
}
}

+ 23
- 15
server/src/com/vaadin/server/LegacyVaadinServlet.java View File

@@ -25,6 +25,27 @@ import com.vaadin.server.ServletPortletHelper.ApplicationClassException;

public class LegacyVaadinServlet extends VaadinServlet {

private static final UIProvider provider = new LegacyApplicationUIProvider() {
@Override
protected LegacyApplication createApplication() {

VaadinServlet servlet = VaadinServlet.getCurrent();
if (servlet instanceof LegacyVaadinServlet) {
LegacyVaadinServlet legacyServlet = (LegacyVaadinServlet) servlet;
HttpServletRequest request = ServletService
.getCurrentServletRequest();
try {
if (legacyServlet.shouldCreateApplication(request)) {
return legacyServlet.getNewApplication(request);
}
} catch (ServletException e) {
throw new RuntimeException(e);
}
}
return null;
}
};

@Override
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
@@ -65,27 +86,14 @@ public class LegacyVaadinServlet extends VaadinServlet {
}
}

protected boolean shouldCreateApplication(WrappedHttpServletRequest request)
protected boolean shouldCreateApplication(HttpServletRequest request)
throws ServletException {
return true;
}

private void onVaadinSessionStarted(WrappedRequest wrappedRequest,
VaadinSession session) throws ServletException {
WrappedHttpServletRequest request = WrappedHttpServletRequest
.cast(wrappedRequest);

if (shouldCreateApplication(request)) {
// Must set current before running init()
VaadinSession.setCurrent(session);

// XXX Must update details here so they are available in init.
session.getBrowser().updateRequestDetails(request);

LegacyApplication legacyApplication = getNewApplication(request);
legacyApplication.doInit();
session.addUIProvider(legacyApplication);
}
session.addUIProvider(provider);
}

}

+ 26
- 35
server/src/com/vaadin/server/VaadinPortlet.java View File

@@ -612,34 +612,29 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
UI uI = null;
application.getLock().lock();
try {
if (application.isRunning()) {
switch (requestType) {
case RENDER:
case ACTION:
// Both action requests and render requests are
// ok
// without a UI as they render the initial HTML
// and then do a second request
uI = application
.getUIForRequest(wrappedRequest);
break;
case BROWSER_DETAILS:
// Should not try to find a UI here as the
// combined request details might change the UI
break;
case FILE_UPLOAD:
// no window
break;
case APPLICATION_RESOURCE:
// use main window - should not need any window
// UI = application.getUI();
break;
default:
uI = application
.getUIForRequest(wrappedRequest);
}
// if window not found, not a problem - use null
switch (requestType) {
case RENDER:
case ACTION:
// Both action requests and render requests are ok
// without a UI as they render the initial HTML
// and then do a second request
uI = application.getUIForRequest(wrappedRequest);
break;
case BROWSER_DETAILS:
// Should not try to find a UI here as the
// combined request details might change the UI
break;
case FILE_UPLOAD:
// no window
break;
case APPLICATION_RESOURCE:
// use main window - should not need any window
// UI = application.getUI();
break;
default:
uI = application.getUIForRequest(wrappedRequest);
}
// if window not found, not a problem - use null
} finally {
application.getLock().unlock();
}
@@ -681,14 +676,6 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
wrappedResponse, portletWrapper, uI);
return;
} else {
/*
* Removes the application if it has stopped
*/
if (!application.isRunning()) {
endApplication(request, response, application);
return;
}

handleOtherRequest(wrappedRequest, wrappedResponse,
requestType, application, applicationContext,
applicationManager);
@@ -711,6 +698,10 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
application.cleanupInactiveUIs();
}

if (applicationRunning) {
application.cleanupInactiveUIs();
}

if (application != null) {
requestTimer.stop(application);
}

+ 45
- 6
server/src/com/vaadin/server/VaadinService.java View File

@@ -22,6 +22,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Locale;
import java.util.ServiceLoader;
@@ -34,6 +35,7 @@ import com.vaadin.LegacyApplication;
import com.vaadin.event.EventRouter;
import com.vaadin.server.ServletPortletHelper.ApplicationClassException;
import com.vaadin.server.VaadinSession.SessionStartEvent;
import com.vaadin.ui.UI;
import com.vaadin.util.CurrentInstance;
import com.vaadin.util.ReflectTools;

@@ -51,6 +53,10 @@ public abstract class VaadinService implements Serializable {
VaadinSessionInitializationListener.class,
"vaadinSessionInitialized", VaadinSessionInitializeEvent.class);

private static final Method SESSION_DESTROY_METHOD = ReflectTools
.findMethod(VaadinSessionDestroyListener.class,
"vaadinSessionDestroyed", VaadinSessionDestroyEvent.class);

/**
* @deprecated Only supported for {@link LegacyApplication}.
*/
@@ -253,6 +259,44 @@ public abstract class VaadinService implements Serializable {
listener, SESSION_INIT_METHOD);
}

/**
* Adds a listener that gets notified when a Vaadin session that has been
* initialized for this service is destroyed.
*
* @see #addVaadinSessionInitializationListener(VaadinSessionInitializationListener)
*
* @param listener
* the vaadin session destroy listener
*/
public void addVaadinSessionDestroyListener(
VaadinSessionDestroyListener listener) {
eventRouter.addListener(VaadinSessionDestroyEvent.class, listener,
SESSION_DESTROY_METHOD);
}

public void fireSessionDestroy(VaadinSession vaadinSession) {
for (UI ui : new ArrayList<UI>(vaadinSession.getUIs())) {
vaadinSession.cleanupUI(ui);
}

eventRouter
.fireEvent(new VaadinSessionDestroyEvent(this, vaadinSession));
}

/**
* Removes a Vaadin session destroy listener from this service.
*
* @see #addVaadinSessionDestroyListener(VaadinSessionDestroyListener)
*
* @param listener
* the vaadin session destroy listener
*/
public void removeVaadinSessionDestroyListener(
VaadinSessionDestroyListener listener) {
eventRouter.removeListener(VaadinSessionDestroyEvent.class, listener,
SESSION_DESTROY_METHOD);
}

/**
* Attempts to find a Vaadin session associated with this request.
*
@@ -324,6 +368,7 @@ public abstract class VaadinService implements Serializable {
throw new ServiceException(e);
}

session.setVaadinService(this);
session.storeInSession(request.getWrappedSession());

URL applicationUrl;
@@ -404,7 +449,6 @@ public abstract class VaadinService implements Serializable {
return;
}

application.close();
if (session != null) {
application.removeFromSession();
}
@@ -426,11 +470,6 @@ public abstract class VaadinService implements Serializable {
return null;
}

if (!sessionApplication.isRunning()) {
sessionApplication.removeFromSession();
return null;
}

return sessionApplication;
}


+ 0
- 37
server/src/com/vaadin/server/VaadinServlet.java View File

@@ -41,7 +41,6 @@ import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.vaadin.DefaultDeploymentConfiguration;
import com.vaadin.sass.ScssStylesheet;
@@ -481,13 +480,6 @@ public class VaadinServlet extends HttpServlet implements Constants {
return;
}

// Removes application if it has stopped (maybe by thread or
// transactionlistener)
if (!application.isRunning()) {
endApplication(request, response, application);
return;
}

if (applicationManager.handleApplicationRequest(request, response)) {
return;
}
@@ -1347,35 +1339,6 @@ public class VaadinServlet extends HttpServlet implements Constants {
return u;
}

/**
* Ends the application.
*
* @param request
* the HTTP request.
* @param response
* the HTTP response to write to.
* @param application
* the application to end.
* @throws IOException
* if the writing failed due to input/output error.
*/
private void endApplication(HttpServletRequest request,
HttpServletResponse response, VaadinSession application)
throws IOException {

String logoutUrl = application.getLogoutURL();
if (logoutUrl == null) {
logoutUrl = application.getURL().toString();
}

final HttpSession session = request.getSession();
if (session != null) {
application.removeFromSession();
}

response.sendRedirect(response.encodeRedirectURL(logoutUrl));
}

/**
* Returns the path info; note that this _can_ be different than
* request.getPathInfo(). Examples where this might be useful:

+ 38
- 91
server/src/com/vaadin/server/VaadinSession.java View File

@@ -19,11 +19,11 @@ package com.vaadin.server;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
@@ -37,6 +37,7 @@ import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

import com.vaadin.LegacyApplication;
import com.vaadin.data.util.converter.Converter;
import com.vaadin.data.util.converter.ConverterFactory;
import com.vaadin.data.util.converter.DefaultConverterFactory;
@@ -153,22 +154,11 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
*/
private URL applicationUrl;

/**
* Application status.
*/
private volatile boolean applicationIsRunning = false;

/**
* Default locale of the session.
*/
private Locale locale;

/**
* URL where the user is redirected to on application close, or null if
* application is just closed without redirection.
*/
private String logoutURL = null;

/**
* Session wide error handler which is used by default if an error is left
* unhandled.
@@ -206,6 +196,8 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {

private final Map<String, Object> attributes = new HashMap<String, Object>();

private VaadinService vaadinService;

/**
* @see javax.servlet.http.HttpSessionBindingListener#valueBound(HttpSessionBindingEvent)
*/
@@ -221,7 +213,19 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
public void valueUnbound(HttpSessionBindingEvent event) {
// If we are going to be unbound from the session, the session must be
// closing
close();
if (vaadinService != null) {
vaadinService.fireSessionDestroy(this);
}
}

/**
* Sets the Vaadin service to which this session belongs.
*
* @param vaadinService
* the Vaadin service.
*/
public void setVaadinService(VaadinService vaadinService) {
this.vaadinService = vaadinService;
}

/**
@@ -301,25 +305,6 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
return applicationUrl;
}

/**
* Ends the session.
* <p>
* When the session is closed, close events are fired for its UIs, its state
* is removed from the underlying session, and the browser window is
* redirected to the application logout url set with
* {@link #setLogoutURL(String)}. If the logout url has not been set, the
* browser window is reloaded and the application is restarted.
*
* @deprecated might be refactored or removed before 7.0.0
*/
@Deprecated
public void close() {
applicationIsRunning = false;
for (UI ui : getUIs()) {
ui.fireCleanupEvent();
}
}

/**
* @param underlyingSession
* @return
@@ -389,25 +374,6 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
applicationUrl = event.getApplicationUrl();
configuration = event.getConfiguration();
communicationManager = event.getCommunicationManager();
applicationIsRunning = true;
}

/**
* Tests if the application is running or if it has been finished.
*
* <p>
* Application starts running when its {@link #start(SessionStartEvent)}
* method has been called and stops when the {@link #close()} is called.
* </p>
*
* @return <code>true</code> if the application is running,
* <code>false</code> if not.
*
* @deprecated might be refactored or removed before 7.0.0
*/
@Deprecated
public boolean isRunning() {
return applicationIsRunning;
}

/**
@@ -566,41 +532,6 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
public void windowDetached(WindowDetachEvent event);
}

/**
* Returns the URL user is redirected to on application close. If the URL is
* <code>null</code>, the application is closed normally as defined by the
* application running environment.
* <p>
* Desktop application just closes the application window and
* web-application redirects the browser to application main URL.
* </p>
*
* @return the URL.
*
* @deprecated might be refactored or removed before 7.0.0
*/
@Deprecated
public String getLogoutURL() {
return logoutURL;
}

/**
* Sets the URL user is redirected to on application close. If the URL is
* <code>null</code>, the application is closed normally as defined by the
* application running environment: Desktop application just closes the
* application window and web-application redirects the browser to
* application main URL.
*
* @param logoutURL
* the logoutURL to set.
*
* @deprecated might be refactored or removed before 7.0.0
*/
@Deprecated
public void setLogoutURL(String logoutURL) {
this.logoutURL = logoutURL;
}

/**
* Gets the session's error handler.
*
@@ -1180,18 +1111,34 @@ public class VaadinSession implements HttpSessionBindingListener, Serializable {
*/
@Deprecated
public void cleanupInactiveUIs() {
for (Iterator<UI> i = uIs.values().iterator(); i.hasNext();) {
UI ui = i.next();
for (UI ui : new ArrayList<UI>(uIs.values())) {
if (!isUIAlive(ui)) {
i.remove();
retainOnRefreshUIs.values().remove(ui.getUIId());
ui.fireCleanupEvent();
cleanupUI(ui);
getLogger().fine(
"Closed UI #" + ui.getUIId() + " due to inactivity");
}
}
}

/**
* Called by the framework to remove an UI instance because it has been
* inactive.
*
* @param ui
* the UI to remove
*
* @deprecated Method is declared as public only to support
* {@link LegacyApplication#close()} and will be removed when
* LegacyApplciation support is removed.
*/
@Deprecated
public void cleanupUI(UI ui) {
Integer id = Integer.valueOf(ui.getUIId());
uIs.remove(id);
retainOnRefreshUIs.values().remove(id);
ui.fireCleanupEvent();
}

/**
* Returns the number of seconds that must pass without a valid heartbeat or
* UIDL request being received from a UI before that UI is removed from the

+ 70
- 0
server/src/com/vaadin/server/VaadinSessionDestroyEvent.java View File

@@ -0,0 +1,70 @@
/*
* Copyright 2011 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 java.util.EventObject;

/**
* Event fired when a Vaadin session is no longer in use.
*
* @see VaadinSessionDestroyListener#vaadinSessionDestroyed(VaadinSessionDestroyEvent)
*
* @author Vaadin Ltd
* @since 7.0.0
*/
public class VaadinSessionDestroyEvent extends EventObject {

private final VaadinSession session;

/**
* Creates a new event.
*
* @param service
* the Vaadin service from which the even originates
* @param session
* the Vaadin session that is no longer used
*/
public VaadinSessionDestroyEvent(VaadinService service,
VaadinSession session) {
super(service);
this.session = session;
}

@Override
public VaadinService getSource() {
return (VaadinService) super.getSource();
}

/**
* Gets the Vaadin service from which the even originates.
*
* @return the Vaadin service
*/
public VaadinService getVaadinService() {
return getSource();
}

/**
* Gets the Vaadin session that is no longer used.
*
* @return the Vaadin session
*/
public VaadinSession getVaadinSession() {
return session;
}

}

+ 35
- 0
server/src/com/vaadin/server/VaadinSessionDestroyListener.java View File

@@ -0,0 +1,35 @@
/*
* Copyright 2011 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;

/**
* A listener that gets notified when a Vaadin session is no longer used.
*
* @see VaadinService#addVaadinSessionDestroyListener(VaadinSessionDestroyListener)
*
* @author Vaadin Ltd
* @since 7.0.0
*/
public interface VaadinSessionDestroyListener {
/**
* Called when a Vaadin session is no longer used.
*
* @param event
* the event with details about the destroyed session
*/
public void vaadinSessionDestroyed(VaadinSessionDestroyEvent event);
}

+ 1
- 1
uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java View File

@@ -129,7 +129,7 @@ public class ApplicationRunnerServlet extends LegacyVaadinServlet {
}

@Override
protected boolean shouldCreateApplication(WrappedHttpServletRequest request)
protected boolean shouldCreateApplication(HttpServletRequest request)
throws ServletException {
try {
return LegacyApplication.class.isAssignableFrom(getClassToRun());

+ 3
- 1
uitest/src/com/vaadin/tests/TestForUpload.java View File

@@ -43,6 +43,7 @@ import com.vaadin.ui.Panel;
import com.vaadin.ui.ProgressIndicator;
import com.vaadin.ui.Select;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI.LegacyWindow;
import com.vaadin.ui.Upload;
import com.vaadin.ui.Upload.FinishedEvent;
import com.vaadin.ui.Upload.StartedEvent;
@@ -244,7 +245,8 @@ public class TestForUpload extends CustomComponent implements

@Override
public void buttonClick(ClickEvent event) {
getSession().close();
LegacyWindow window = (LegacyWindow) event.getButton().getUI();
window.getApplication().close();
}
});
main.addComponent(restart);

+ 3
- 1
uitest/src/com/vaadin/tests/application/ApplicationCloseTest.java View File

@@ -5,6 +5,7 @@ import com.vaadin.tests.components.TestBase;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Label;
import com.vaadin.ui.UI.LegacyWindow;

public class ApplicationCloseTest extends TestBase {

@@ -26,7 +27,8 @@ public class ApplicationCloseTest extends TestBase {

@Override
public void buttonClick(ClickEvent event) {
event.getButton().getUI().getSession().close();
LegacyWindow ui = (LegacyWindow) event.getButton().getUI();
ui.getApplication().close();
}
});


+ 1
- 1
uitest/src/com/vaadin/tests/layouts/ComplexGLColumnExpansionWithColSpan.java View File

@@ -73,7 +73,7 @@ public class ComplexGLColumnExpansionWithColSpan extends AbstractTestCase {
restart.addListener(new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
mainLayout.getUI().getSession().close();
close();
}
});


Loading…
Cancel
Save