]> source.dussan.org Git - vaadin-framework.git/commitdiff
Only support one Application per session (#9402)
authorLeif Åstrand <leif@vaadin.com>
Wed, 5 Sep 2012 07:42:27 +0000 (10:42 +0300)
committerLeif Åstrand <leif@vaadin.com>
Wed, 5 Sep 2012 08:39:36 +0000 (11:39 +0300)
server/src/com/vaadin/server/ApplicationContext.java
server/src/com/vaadin/server/PortletApplicationContext2.java
server/src/com/vaadin/server/ServletApplicationContext.java
server/src/com/vaadin/server/VaadinPortlet.java
server/src/com/vaadin/server/VaadinServlet.java
uitest/src/com/vaadin/tests/application/ApplicationCloseTest.java

index 85a77241d949971effbda72cc4ae17d385b8c77f..0b317486e49522832a18d2bf7d459b3cbc89388d 100644 (file)
 package com.vaadin.server;
 
 import java.io.Serializable;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -43,11 +39,11 @@ import com.vaadin.Application;
 public abstract class ApplicationContext implements HttpSessionBindingListener,
         Serializable {
 
-    protected final HashSet<Application> applications = new HashSet<Application>();
+    private Application application;
 
     protected WebBrowser browser = new WebBrowser();
 
-    protected HashMap<Application, AbstractCommunicationManager> applicationToAjaxAppMgrMap = new HashMap<Application, AbstractCommunicationManager>();
+    private AbstractCommunicationManager communicationManager;
 
     private long totalSessionTime = 0;
 
@@ -70,22 +66,7 @@ public abstract class ApplicationContext implements HttpSessionBindingListener,
     public void valueUnbound(HttpSessionBindingEvent event) {
         // If we are going to be unbound from the session, the session must be
         // closing
-        try {
-            while (!applications.isEmpty()) {
-                final Application app = applications.iterator().next();
-                app.close();
-                removeApplication(app);
-            }
-        } catch (Exception e) {
-            // This should never happen but is possible with rare
-            // configurations (e.g. robustness tests). If you have one
-            // thread doing HTTP socket write and another thread trying to
-            // remove same application here. Possible if you got e.g. session
-            // lifetime 1 min but socket write may take longer than 1 min.
-            // FIXME: Handle exception
-            getLogger().log(Level.SEVERE,
-                    "Could not remove application, leaking memory.", e);
-        }
+        removeApplication();
     }
 
     /**
@@ -102,19 +83,36 @@ public abstract class ApplicationContext implements HttpSessionBindingListener,
     }
 
     /**
-     * Returns a collection of all the applications in this context.
+     * Returns the applications in this context.
      * 
-     * Each application context contains all active applications for one user.
+     * Each application context contains the application for one user.
      * 
-     * @return A collection containing all the applications in this context.
+     * @return The application of this context, or <code>null</code> if there is
+     *         no application
      */
-    public Collection<Application> getApplications() {
-        return Collections.unmodifiableCollection(applications);
+    public Application getApplication() {
+        return application;
     }
 
-    protected void removeApplication(Application application) {
-        applications.remove(application);
-        applicationToAjaxAppMgrMap.remove(application);
+    public void removeApplication() {
+        if (application == null) {
+            return;
+        }
+        try {
+            application.close();
+        } catch (Exception e) {
+            // This should never happen but is possible with rare
+            // configurations (e.g. robustness tests). If you have one
+            // thread doing HTTP socket write and another thread trying to
+            // remove same application here. Possible if you got e.g. session
+            // lifetime 1 min but socket write may take longer than 1 min.
+            // FIXME: Handle exception
+            getLogger().log(Level.SEVERE,
+                    "Could not close application, leaking memory.", e);
+        } finally {
+            application = null;
+            communicationManager = null;
+        }
     }
 
     /**
@@ -168,4 +166,17 @@ public abstract class ApplicationContext implements HttpSessionBindingListener,
         this.session = session;
     }
 
+    public AbstractCommunicationManager getApplicationManager() {
+        return communicationManager;
+    }
+
+    public void setApplication(Application application,
+            AbstractCommunicationManager communicationManager) {
+        if (this.application != null) {
+            removeApplication();
+        }
+        this.application = application;
+        this.communicationManager = communicationManager;
+    }
+
 }
\ No newline at end of file
index f157dc9ae6a71daa85cbd05e310a02469aa7b2ee..63f02ac4ec757cba9a6ee48f602b16fe1ec4e5d9 100644 (file)
@@ -57,32 +57,12 @@ public class PortletApplicationContext2 extends ApplicationContext {
 
     protected Map<Application, Set<PortletListener>> portletListeners = new HashMap<Application, Set<PortletListener>>();
 
-    protected HashMap<String, Application> portletWindowIdToApplicationMap = new HashMap<String, Application>();
-
     private final Map<String, QName> eventActionDestinationMap = new HashMap<String, QName>();
     private final Map<String, Serializable> eventActionValueMap = new HashMap<String, Serializable>();
 
     private final Map<String, String> sharedParameterActionNameMap = new HashMap<String, String>();
     private final Map<String, String> sharedParameterActionValueMap = new HashMap<String, String>();
 
-    protected PortletCommunicationManager getApplicationManager(
-            Application application) {
-        PortletCommunicationManager mgr = (PortletCommunicationManager) applicationToAjaxAppMgrMap
-                .get(application);
-
-        if (mgr == null) {
-            // Creates a new manager
-            mgr = createPortletCommunicationManager(application);
-            applicationToAjaxAppMgrMap.put(application, mgr);
-        }
-        return mgr;
-    }
-
-    protected PortletCommunicationManager createPortletCommunicationManager(
-            Application application) {
-        return new PortletCommunicationManager(application);
-    }
-
     public static PortletApplicationContext2 getApplicationContext(
             PortletSession session) {
         Object cxattr = session.getAttribute(PortletApplicationContext2.class
@@ -103,23 +83,6 @@ public class PortletApplicationContext2 extends ApplicationContext {
         return cx;
     }
 
-    @Override
-    protected void removeApplication(Application application) {
-        super.removeApplication(application);
-        // values() is backed by map, removes the key-value pair from the map
-        portletWindowIdToApplicationMap.values().remove(application);
-    }
-
-    protected void addApplication(Application application,
-            String portletWindowId) {
-        applications.add(application);
-        portletWindowIdToApplicationMap.put(portletWindowId, application);
-    }
-
-    public Application getApplicationForWindowId(String portletWindowId) {
-        return portletWindowIdToApplicationMap.get(portletWindowId);
-    }
-
     public PortletSession getPortletSession() {
         WrappedSession wrappedSession = getSession();
         PortletSession session = ((WrappedPortletSession) wrappedSession)
index 910051a26b2943f301a107884064d6b1eb4bf837..a1f5a816241c550369c28e381c405b7be86a37a6 100644 (file)
@@ -23,7 +23,6 @@ import javax.servlet.http.HttpSession;
 import javax.servlet.http.HttpSessionBindingEvent;
 import javax.servlet.http.HttpSessionBindingListener;
 
-import com.vaadin.Application;
 import com.vaadin.util.CurrentInstance;
 
 /**
@@ -125,30 +124,4 @@ public class ServletApplicationContext extends ApplicationContext {
         cx.setSession(new WrappedHttpSession(session));
         return cx;
     }
-
-    protected void addApplication(Application application) {
-        applications.add(application);
-    }
-
-    /**
-     * Gets communication manager for an application.
-     * 
-     * If this application has not been running before, a new manager is
-     * created.
-     * 
-     * @param application
-     * @return CommunicationManager
-     */
-    public CommunicationManager getApplicationManager(Application application,
-            VaadinServlet servlet) {
-        CommunicationManager mgr = (CommunicationManager) applicationToAjaxAppMgrMap
-                .get(application);
-
-        if (mgr == null) {
-            // Creates new manager
-            mgr = servlet.createCommunicationManager(application);
-            applicationToAjaxAppMgrMap.put(application, mgr);
-        }
-        return mgr;
-    }
 }
index 5fb2340bc8133d71e2834c29a93a8b01a610e7bb..2bec4249ede1e4521318b2d437a618d397c80591 100644 (file)
@@ -478,8 +478,8 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
                 PortletApplicationContext2 applicationContext = getApplicationContext(request
                         .getPortletSession());
 
-                PortletCommunicationManager applicationManager = applicationContext
-                        .getApplicationManager(application);
+                PortletCommunicationManager applicationManager = (PortletCommunicationManager) applicationContext
+                        .getApplicationManager();
 
                 if (requestType == RequestType.CONNECTOR_RESOURCE) {
                     applicationManager.serveConnectorResource(wrappedRequest,
@@ -805,7 +805,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
             throws IOException {
         final PortletSession session = request.getPortletSession();
         if (session != null) {
-            getApplicationContext(session).removeApplication(application);
+            getApplicationContext(session).removeApplication();
         }
         // Do not send any redirects when running inside a portlet.
     }
@@ -863,16 +863,17 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
         application.close();
         if (session != null) {
             PortletApplicationContext2 context = getApplicationContext(session);
-            context.removeApplication(application);
+            context.removeApplication();
         }
     }
 
     private Application createApplication(PortletRequest request)
-            throws PortletException, MalformedURLException {
+            throws PortletException {
         Application newApplication = getNewApplication(request);
         final PortletApplicationContext2 context = getApplicationContext(request
                 .getPortletSession());
-        context.addApplication(newApplication, request.getWindowID());
+        context.setApplication(newApplication, new PortletCommunicationManager(
+                newApplication));
         return newApplication;
     }
 
@@ -888,8 +889,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
         }
 
         PortletApplicationContext2 context = getApplicationContext(session);
-        Application application = context.getApplicationForWindowId(request
-                .getWindowID());
+        Application application = context.getApplication();
         if (application == null) {
             return null;
         }
@@ -897,7 +897,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants {
             return application;
         }
         // application found but not running
-        context.removeApplication(application);
+        context.removeApplication();
 
         return null;
     }
index 62fb8ba71e92b0ab3942fb8fb28f18a355973d66..af66a3496e11b349cc0f513bf7495870f6a9fda6 100644 (file)
@@ -31,7 +31,6 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Enumeration;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.Locale;
 import java.util.Properties;
 import java.util.logging.Level;
@@ -322,8 +321,8 @@ public class VaadinServlet extends HttpServlet implements Constants {
              */
             ServletApplicationContext webApplicationContext = getApplicationContext(request
                     .getSession());
-            CommunicationManager applicationManager = webApplicationContext
-                    .getApplicationManager(application, this);
+            CommunicationManager applicationManager = (CommunicationManager) webApplicationContext
+                    .getApplicationManager();
 
             if (requestType == RequestType.CONNECTOR_RESOURCE) {
                 applicationManager.serveConnectorResource(request, response);
@@ -726,7 +725,8 @@ public class VaadinServlet extends HttpServlet implements Constants {
 
         final ServletApplicationContext context = getApplicationContext(request
                 .getSession());
-        context.addApplication(newApplication);
+        context.setApplication(newApplication,
+                createCommunicationManager(newApplication));
 
         return newApplication;
     }
@@ -1334,30 +1334,19 @@ public class VaadinServlet extends HttpServlet implements Constants {
 
         ServletApplicationContext context = getApplicationContext(session);
 
-        // Gets application list for the session.
-        final Collection<Application> applications = context.getApplications();
-
-        // Search for the application (using the application URI) from the list
-        for (final Iterator<Application> i = applications.iterator(); i
-                .hasNext();) {
-            final Application sessionApplication = i.next();
-            final String sessionApplicationPath = sessionApplication.getURL()
-                    .getPath();
-            String requestApplicationPath = getApplicationUrl(request)
-                    .getPath();
-
-            if (requestApplicationPath.equals(sessionApplicationPath)) {
-                // Found a running application
-                if (sessionApplication.isRunning()) {
-                    return sessionApplication;
-                }
-                // Application has stopped, so remove it before creating a new
-                // application
-                getApplicationContext(session).removeApplication(
-                        sessionApplication);
-                break;
-            }
+        Application sessionApplication = context.getApplication();
+
+        if (sessionApplication == null) {
+            return null;
+        }
+
+        if (sessionApplication.isRunning()) {
+            // Found a running application
+            return sessionApplication;
         }
+        // Application has stopped, so remove it before creating a new
+        // application
+        getApplicationContext(session).removeApplication();
 
         // Existing application not found
         return null;
@@ -1386,7 +1375,7 @@ public class VaadinServlet extends HttpServlet implements Constants {
 
         final HttpSession session = request.getSession();
         if (session != null) {
-            getApplicationContext(session).removeApplication(application);
+            getApplicationContext(session).removeApplication();
         }
 
         response.sendRedirect(response.encodeRedirectURL(logoutUrl));
@@ -1439,7 +1428,7 @@ public class VaadinServlet extends HttpServlet implements Constants {
         application.close();
         if (session != null) {
             ServletApplicationContext context = getApplicationContext(session);
-            context.removeApplication(application);
+            context.removeApplication();
         }
     }
 
index 1f5f0dc6919f57f695e49c43ccc2abf45c2e796e..f2fe90f4b141d7191aa81ff38285501bd0db2947 100644 (file)
@@ -1,6 +1,5 @@
 package com.vaadin.tests.application;
 
-import com.vaadin.Application;
 import com.vaadin.shared.ui.label.ContentMode;
 import com.vaadin.tests.components.TestBase;
 import com.vaadin.ui.Button;
@@ -15,9 +14,9 @@ public class ApplicationCloseTest extends TestBase {
     protected void setup() {
         Label applications = new Label("Applications in session: <br/>",
                 ContentMode.XHTML);
-        for (Application a : getContext().getApplications()) {
-            applications.setValue(applications.getValue() + "App: " + a
-                    + "<br/>");
+        if (getContext().getApplication() != null) {
+            applications.setValue(applications.getValue() + "App: "
+                    + getContext().getApplication() + "<br/>");
         }
         applications.setValue(applications.getValue() + "<br/><br/>");