diff options
author | Leif Åstrand <leif@vaadin.com> | 2012-09-05 15:42:02 +0300 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2012-09-05 15:42:02 +0300 |
commit | de3ac989c85451767510917822463353bcab71cd (patch) | |
tree | 48a991db5d3a700e99e37d53df4fa7902bbb780b /server/src | |
parent | 8bdaf8732e660d1b9595c9d503999022320b0314 (diff) | |
download | vaadin-framework-de3ac989c85451767510917822463353bcab71cd.tar.gz vaadin-framework-de3ac989c85451767510917822463353bcab71cd.zip |
Change LegacyApplication to be a UIProvider (#9402)
Diffstat (limited to 'server/src')
-rw-r--r-- | server/src/com/vaadin/Application.java | 184 | ||||
-rw-r--r-- | server/src/com/vaadin/server/AbstractUIProvider.java | 5 | ||||
-rw-r--r-- | server/src/com/vaadin/server/LegacyVaadinPortlet.java | 62 | ||||
-rw-r--r-- | server/src/com/vaadin/server/LegacyVaadinServlet.java | 63 | ||||
-rw-r--r-- | server/src/com/vaadin/server/ServletPortletHelper.java | 38 | ||||
-rw-r--r-- | server/src/com/vaadin/server/UIProvider.java | 19 | ||||
-rw-r--r-- | server/src/com/vaadin/server/VaadinPortlet.java | 49 | ||||
-rw-r--r-- | server/src/com/vaadin/server/VaadinServlet.java | 67 |
8 files changed, 342 insertions, 145 deletions
diff --git a/server/src/com/vaadin/Application.java b/server/src/com/vaadin/Application.java index 745d0ad784..634f96bfe1 100644 --- a/server/src/com/vaadin/Application.java +++ b/server/src/com/vaadin/Application.java @@ -58,6 +58,8 @@ import com.vaadin.server.GlobalResourceHandler; import com.vaadin.server.RequestHandler; import com.vaadin.server.ServletApplicationContext; import com.vaadin.server.Terminal; +import com.vaadin.server.Terminal.ErrorEvent; +import com.vaadin.server.Terminal.ErrorListener; import com.vaadin.server.UIProvider; import com.vaadin.server.VaadinServlet; import com.vaadin.server.VariableOwner; @@ -152,7 +154,8 @@ public class Application implements Terminal.ErrorListener, Serializable { * @since 7.0 */ @Deprecated - public static class LegacyApplication extends Application { + public static abstract class LegacyApplication extends AbstractUIProvider + implements ErrorListener { /** * Ignore initial / and then get everything up to the next / */ @@ -177,8 +180,8 @@ public class Application implements Terminal.ErrorListener, Serializable { "mainWindow has already been set"); } if (mainWindow.getApplication() == null) { - mainWindow.setApplication(this); - } else if (mainWindow.getApplication() != this) { + mainWindow.setApplication(Application.getCurrent()); + } else if (mainWindow.getApplication() != Application.getCurrent()) { throw new IllegalStateException( "mainWindow is attached to another application"); } @@ -190,45 +193,44 @@ public class Application implements Terminal.ErrorListener, Serializable { this.mainWindow = mainWindow; } + public void doInit() { + Application.getCurrent().setErrorHandler(this); + init(); + } + + protected abstract void init(); + @Override - public void start(ApplicationStartEvent event) { - super.start(event); - addUIProvider(new AbstractUIProvider() { - @Override - public Class<? extends UI> getUIClass(Application application, - WrappedRequest request) { - if (application == LegacyApplication.this) { - UI uiInstance = getUIInstance(request); - if (uiInstance != null) { - return uiInstance.getClass(); - } - } - return null; - } + public Class<? extends UI> getUIClass(Application application, + WrappedRequest request) { + UI uiInstance = getUIInstance(request); + if (uiInstance != null) { + return uiInstance.getClass(); + } + return null; + } - @Override - public UI createInstance(Application application, - Class<? extends UI> type, WrappedRequest request) { - return getUIInstance(request); - } + @Override + public UI createInstance(Application application, + Class<? extends UI> type, WrappedRequest request) { + return getUIInstance(request); + } - @Override - public String getThemeForUI(WrappedRequest request, - Class<? extends UI> uiClass) { - return theme; - } + @Override + public String getThemeForUI(WrappedRequest request, + Class<? extends UI> uiClass) { + return theme; + } - @Override - public String getPageTitleForUI(WrappedRequest request, - Class<? extends UI> uiClass) { - UI uiInstance = getUIInstance(request); - if (uiInstance != null) { - return uiInstance.getCaption(); - } else { - return super.getPageTitleForUI(request, uiClass); - } - } - }); + @Override + public String getPageTitleForUI(WrappedRequest request, + Class<? extends UI> uiClass) { + UI uiInstance = getUIInstance(request); + if (uiInstance != null) { + return uiInstance.getCaption(); + } else { + return super.getPageTitleForUI(request, uiClass); + } } /** @@ -273,7 +275,7 @@ public class Application implements Terminal.ErrorListener, Serializable { * {@inheritDoc} */ @Override - public UI getUIForRequest(WrappedRequest request) { + public UI getExistingUI(WrappedRequest request) { UI uiInstance = getUIInstance(request); if (uiInstance.getUIId() == -1) { // Not initialized -> Let go through createUIInstance to make it @@ -352,7 +354,7 @@ public class Application implements Terminal.ErrorListener, Serializable { } legacyUINames.put(uI.getName(), uI); - uI.setApplication(this); + uI.setApplication(Application.getCurrent()); } /** @@ -389,6 +391,27 @@ public class Application implements Terminal.ErrorListener, Serializable { public Collection<UI.LegacyWindow> getWindows() { return Collections.unmodifiableCollection(legacyUINames.values()); } + + @Override + public void terminalError(ErrorEvent event) { + Application.getCurrent().terminalError(event); + } + + public ApplicationContext getContext() { + return Application.getCurrent().getContext(); + } + + protected void close() { + Application.getCurrent().close(); + } + + public boolean isRunning() { + return Application.getCurrent().isRunning(); + } + + public URL getURL() { + return Application.getCurrent().getURL(); + } } /** @@ -1854,39 +1877,10 @@ public class Application implements Terminal.ErrorListener, Serializable { Integer uiId = getUIId(request); synchronized (this) { - BrowserDetails browserDetails = request.getBrowserDetails(); - boolean hasBrowserDetails = browserDetails != null - && browserDetails.getUriFragment() != null; - uI = uIs.get(uiId); - Class<? extends UI> uiClass = null; - - if (uI == null && hasBrowserDetails - && !retainOnRefreshUIs.isEmpty()) { - uiClass = getUIClass(request); - - // Check for a known UI - - @SuppressWarnings("null") - String windowName = browserDetails.getWindowName(); - Integer retainedUIId = retainOnRefreshUIs.get(windowName); - - if (retainedUIId != null) { - UI retainedUI = uIs.get(retainedUIId); - // We've had the same UI instance in a window with this - // name, but should we still use it? - if (retainedUI.getClass() == uiClass) { - uiId = retainedUIId; - uI = retainedUI; - } else { - getLogger().info( - "Not using retained UI in " + windowName - + " because retained UI was of type " - + retainedUIId.getClass() + " but " - + uiClass - + " is expected for the request."); - } - } + + if (uI == null) { + uI = findExistingUi(request); } } // end synchronized block @@ -1896,6 +1890,48 @@ public class Application implements Terminal.ErrorListener, Serializable { return uI; } + private UI findExistingUi(WrappedRequest request) { + // Check if some UI provider has an existing UI available + for (int i = uiProviders.size() - 1; i >= 0; i--) { + UIProvider provider = uiProviders.get(i); + UI existingUi = provider.getExistingUI(request); + if (existingUi != null) { + return existingUi; + } + } + + BrowserDetails browserDetails = request.getBrowserDetails(); + boolean hasBrowserDetails = browserDetails != null + && browserDetails.getUriFragment() != null; + + if (hasBrowserDetails && !retainOnRefreshUIs.isEmpty()) { + // Check for a known UI + + @SuppressWarnings("null") + String windowName = browserDetails.getWindowName(); + Integer retainedUIId = retainOnRefreshUIs.get(windowName); + + if (retainedUIId != null) { + Class<? extends UI> expectedUIClass = getUIClass(request); + UI retainedUI = uIs.get(retainedUIId); + // We've had the same UI instance in a window with this + // name, but should we still use it? + if (retainedUI.getClass() == expectedUIClass) { + return retainedUI; + } else { + getLogger().info( + "Not using retained UI in " + windowName + + " because retained UI was of type " + + retainedUIId.getClass() + " but " + + expectedUIClass + + " is expected for the request."); + } + } + } + + return null; + } + public UI createUI(WrappedRequest request) { Class<? extends UI> uiClass = getUIClass(request); @@ -2167,4 +2203,8 @@ public class Application implements Terminal.ErrorListener, Serializable { return globalResourceHandler; } + public Collection<UIProvider> getUIProviders() { + return Collections.unmodifiableCollection(uiProviders); + } + } diff --git a/server/src/com/vaadin/server/AbstractUIProvider.java b/server/src/com/vaadin/server/AbstractUIProvider.java index 49f8e3ec77..c7a137ebbd 100644 --- a/server/src/com/vaadin/server/AbstractUIProvider.java +++ b/server/src/com/vaadin/server/AbstractUIProvider.java @@ -115,4 +115,9 @@ public abstract class AbstractUIProvider implements UIProvider { return titleAnnotation.value(); } } + + @Override + public UI getExistingUI(WrappedRequest request) { + return null; + } } diff --git a/server/src/com/vaadin/server/LegacyVaadinPortlet.java b/server/src/com/vaadin/server/LegacyVaadinPortlet.java new file mode 100644 index 0000000000..036242a0c2 --- /dev/null +++ b/server/src/com/vaadin/server/LegacyVaadinPortlet.java @@ -0,0 +1,62 @@ +/* + * 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 javax.portlet.PortletException; +import javax.portlet.PortletRequest; + +import com.vaadin.Application; +import com.vaadin.Application.LegacyApplication; +import com.vaadin.server.ServletPortletHelper.ApplicationClassException; + +public class LegacyVaadinPortlet extends VaadinPortlet { + + protected Class<? extends LegacyApplication> getApplicationClass() + throws ClassNotFoundException { + try { + return ServletPortletHelper + .getLegacyApplicationClass(getDeploymentConfiguration()); + } catch (ApplicationClassException e) { + throw new RuntimeException(e); + } + } + + protected LegacyApplication getNewApplication(PortletRequest request) + throws PortletException { + try { + Class<? extends LegacyApplication> applicationClass = getApplicationClass(); + return applicationClass.newInstance(); + } catch (Exception e) { + throw new PortletException(e); + } + } + + @Override + protected Application createApplication(PortletRequest request) + throws PortletException { + Application application = super.createApplication(request); + + // Must set current before running init() + Application.setCurrent(application); + + LegacyApplication legacyApplication = getNewApplication(request); + legacyApplication.doInit(); + application.addUIProvider(legacyApplication); + + return application; + } +} diff --git a/server/src/com/vaadin/server/LegacyVaadinServlet.java b/server/src/com/vaadin/server/LegacyVaadinServlet.java new file mode 100644 index 0000000000..f53e9d4bf0 --- /dev/null +++ b/server/src/com/vaadin/server/LegacyVaadinServlet.java @@ -0,0 +1,63 @@ +/* + * 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 javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +import com.vaadin.Application; +import com.vaadin.Application.LegacyApplication; +import com.vaadin.server.ServletPortletHelper.ApplicationClassException; + +public class LegacyVaadinServlet extends VaadinServlet { + + protected Class<? extends LegacyApplication> getApplicationClass() + throws ClassNotFoundException { + try { + return ServletPortletHelper + .getLegacyApplicationClass(getDeploymentConfiguration()); + } catch (ApplicationClassException e) { + throw new RuntimeException(e); + } + } + + protected LegacyApplication getNewApplication(HttpServletRequest request) + throws ServletException { + try { + Class<? extends LegacyApplication> applicationClass = getApplicationClass(); + return applicationClass.newInstance(); + } catch (Exception e) { + throw new ServletException(e); + } + } + + @Override + protected Application createApplication(HttpServletRequest request) + throws ServletException { + Application application = super.createApplication(request); + + // Must set current before running init() + Application.setCurrent(application); + + LegacyApplication legacyApplication = getNewApplication(request); + legacyApplication.doInit(); + application.addUIProvider(legacyApplication); + + return application; + } + +} diff --git a/server/src/com/vaadin/server/ServletPortletHelper.java b/server/src/com/vaadin/server/ServletPortletHelper.java index 26913d8ba8..18fbb66114 100644 --- a/server/src/com/vaadin/server/ServletPortletHelper.java +++ b/server/src/com/vaadin/server/ServletPortletHelper.java @@ -4,6 +4,7 @@ import java.io.Serializable; import java.util.Properties; import com.vaadin.Application; +import com.vaadin.Application.LegacyApplication; import com.vaadin.shared.ApplicationConstants; import com.vaadin.ui.UI; @@ -41,28 +42,22 @@ class ServletPortletHelper implements Serializable { } } - static Class<? extends Application> getApplicationClass( + static Class<? extends LegacyApplication> getLegacyApplicationClass( DeploymentConfiguration deploymentConfiguration) throws ApplicationClassException { Properties initParameters = deploymentConfiguration .getApplicationConfiguration().getInitParameters(); String applicationParameter = initParameters.getProperty("application"); - String uiParameter = initParameters - .getProperty(Application.UI_PARAMETER); ClassLoader classLoader = deploymentConfiguration.getClassLoader(); if (applicationParameter == null) { - - // Validate the parameter value - verifyUIClass(uiParameter, classLoader); - - // Application can be used if a valid rootLayout is defined - return Application.class; + throw new ApplicationClassException( + "No \"application\" init parameter found"); } try { - return (Class<? extends Application>) classLoader - .loadClass(applicationParameter); + return classLoader.loadClass(applicationParameter).asSubclass( + LegacyApplication.class); } catch (final ClassNotFoundException e) { throw new ApplicationClassException( "Failed to load application class: " + applicationParameter, @@ -138,4 +133,25 @@ class ServletPortletHelper implements Serializable { ApplicationConstants.HEARTBEAT_REQUEST_PATH); } + public static void initDefaultUIProvider(Application application, + DeploymentConfiguration deploymentConfiguration) + throws ApplicationClassException { + String uiProperty = deploymentConfiguration + .getApplicationConfiguration().getInitParameters() + .getProperty(Application.UI_PARAMETER); + if (uiProperty != null) { + verifyUIClass(uiProperty, deploymentConfiguration.getClassLoader()); + application.addUIProvider(new DefaultUIProvider()); + } + } + + public static void checkUiProviders(Application newApplication) + throws ApplicationClassException { + if (newApplication.getUIProviders().isEmpty()) { + throw new ApplicationClassException( + "No UIProvider has been added to the application and there is no \"" + + Application.UI_PARAMETER + "\" init parameter."); + } + } + } diff --git a/server/src/com/vaadin/server/UIProvider.java b/server/src/com/vaadin/server/UIProvider.java index 60b79cdbb9..6a45b06c63 100644 --- a/server/src/com/vaadin/server/UIProvider.java +++ b/server/src/com/vaadin/server/UIProvider.java @@ -78,4 +78,23 @@ public interface UIProvider { public String getThemeForUI(WrappedRequest request, Class<? extends UI> uiClass); + /** + * Finds an existing {@link UI} for a request. + * <p> + * Implementations should take care to not return an UI instance that might + * be used in some other browser as that might cause synchronization issues + * when changes from one browser window are not present in the other. + * <p> + * If no UI provider returns an existing UI, the framework does also check + * the window.name for an existing instance with + * {@link #isUiPreserved(WrappedRequest, Class)} before falling back to + * bootstrapping and creating a new UI instance. + * + * @param request + * the request for which a UI is desired + * @return a UI belonging to the request, or <code>null</code> if this UI + * provider doesn't have an existing UI for the request. + */ + public UI getExistingUI(WrappedRequest request); + } diff --git a/server/src/com/vaadin/server/VaadinPortlet.java b/server/src/com/vaadin/server/VaadinPortlet.java index bf8fb5dc84..eae01e9369 100644 --- a/server/src/com/vaadin/server/VaadinPortlet.java +++ b/server/src/com/vaadin/server/VaadinPortlet.java @@ -814,7 +814,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants { if (restartApplication) { closeApplication(application, request.getPortletSession(false)); - return createApplication(request); + return createAndRegisterApplication(request); } else if (closeApplication) { closeApplication(application, request.getPortletSession(false)); return null; @@ -826,7 +826,7 @@ public class VaadinPortlet extends GenericPortlet implements Constants { // No existing application was found if (requestCanCreateApplication) { - return createApplication(request); + return createAndRegisterApplication(request); } else { throw new SessionExpiredException(); } @@ -845,9 +845,16 @@ public class VaadinPortlet extends GenericPortlet implements Constants { } } - private Application createApplication(PortletRequest request) + private Application createAndRegisterApplication(PortletRequest request) throws PortletException { - Application newApplication = getNewApplication(request); + Application newApplication = createApplication(request); + + try { + ServletPortletHelper.checkUiProviders(newApplication); + } catch (ApplicationClassException e) { + throw new PortletException(e); + } + final PortletApplicationContext2 context = getApplicationContext(request .getPortletSession()); context.setApplication(newApplication, new PortletCommunicationManager( @@ -855,6 +862,20 @@ public class VaadinPortlet extends GenericPortlet implements Constants { return newApplication; } + protected Application createApplication(PortletRequest request) + throws PortletException { + Application application = new Application(); + + try { + ServletPortletHelper.initDefaultUIProvider(application, + getDeploymentConfiguration()); + } catch (ApplicationClassException e) { + throw new PortletException(e); + } + + return application; + } + private Application getExistingApplication(PortletRequest request, boolean allowSessionCreation) throws MalformedURLException, SessionExpiredException { @@ -880,26 +901,6 @@ public class VaadinPortlet extends GenericPortlet implements Constants { return null; } - protected Class<? extends Application> getApplicationClass() - throws ApplicationClassException { - return ServletPortletHelper - .getApplicationClass(getDeploymentConfiguration()); - } - - protected Application getNewApplication(PortletRequest request) - throws PortletException { - try { - final Application application = getApplicationClass().newInstance(); - return application; - } catch (final IllegalAccessException e) { - throw new PortletException("getNewApplication failed", e); - } catch (final InstantiationException e) { - throw new PortletException("getNewApplication failed", e); - } catch (final ApplicationClassException e) { - throw new PortletException("getNewApplication failed", e); - } - } - private void handleServiceException(WrappedPortletRequest request, WrappedPortletResponse response, Application application, Throwable e) throws IOException, PortletException { diff --git a/server/src/com/vaadin/server/VaadinServlet.java b/server/src/com/vaadin/server/VaadinServlet.java index ba19072503..8f33382110 100644 --- a/server/src/com/vaadin/server/VaadinServlet.java +++ b/server/src/com/vaadin/server/VaadinServlet.java @@ -603,7 +603,7 @@ public class VaadinServlet extends HttpServlet implements Constants { if (restartApplication) { closeApplication(application, request.getSession(false)); - return createApplication(request); + return createAndRegisterApplication(request); } else if (closeApplication) { closeApplication(application, request.getSession(false)); return null; @@ -619,7 +619,7 @@ public class VaadinServlet extends HttpServlet implements Constants { * If the request is such that it should create a new application if * one as not found, we do that. */ - return createApplication(request); + return createAndRegisterApplication(request); } else { /* * The application was not found and a new one should not be @@ -630,6 +630,24 @@ public class VaadinServlet extends HttpServlet implements Constants { } + private Application createAndRegisterApplication(HttpServletRequest request) + throws ServletException { + Application newApplication = createApplication(request); + + try { + ServletPortletHelper.checkUiProviders(newApplication); + } catch (ApplicationClassException e) { + throw new ServletException(e); + } + + final ServletApplicationContext context = getApplicationContext(request + .getSession()); + context.setApplication(newApplication, + createCommunicationManager(newApplication)); + + return newApplication; + } + /** * Check if the request should create an application if an existing * application is not found. @@ -699,14 +717,16 @@ public class VaadinServlet extends HttpServlet implements Constants { * @throws ServletException * @throws MalformedURLException */ - private Application createApplication(HttpServletRequest request) - throws ServletException, MalformedURLException { - Application newApplication = getNewApplication(request); + protected Application createApplication(HttpServletRequest request) + throws ServletException { + Application newApplication = new Application(); - final ServletApplicationContext context = getApplicationContext(request - .getSession()); - context.setApplication(newApplication, - createCommunicationManager(newApplication)); + try { + ServletPortletHelper.initDefaultUIProvider(newApplication, + getDeploymentConfiguration()); + } catch (ApplicationClassException e) { + throw new ServletException(e); + } return newApplication; } @@ -849,35 +869,6 @@ public class VaadinServlet extends HttpServlet implements Constants { } /** - * Creates a new application for the given request. - * - * @param request - * the HTTP request. - * @return A new Application instance. - * @throws ServletException - */ - protected Application getNewApplication(HttpServletRequest request) - throws ServletException { - - // Creates a new application instance - try { - Class<? extends Application> applicationClass = ServletPortletHelper - .getApplicationClass(getDeploymentConfiguration()); - - final Application application = applicationClass.newInstance(); - application.addUIProvider(new DefaultUIProvider()); - - return application; - } catch (final IllegalAccessException e) { - throw new ServletException("getNewApplication failed", e); - } catch (final InstantiationException e) { - throw new ServletException("getNewApplication failed", e); - } catch (ApplicationClassException e) { - throw new ServletException("getNewApplication failed", e); - } - } - - /** * Starts the application if it is not already running. * * @param request |